@@ -231,6 +231,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
231
231
Register buildZerosVal (const SPIRVType *ResType, MachineInstr &I) const ;
232
232
Register buildOnesVal (bool AllOnes, const SPIRVType *ResType,
233
233
MachineInstr &I) const ;
234
+
235
+ bool wrapIntoSpecConstantOp (MachineInstr &I,
236
+ SmallVector<Register> &CompositeArgs) const ;
234
237
};
235
238
236
239
} // end anonymous namespace
@@ -1249,6 +1252,24 @@ static unsigned getArrayComponentCount(MachineRegisterInfo *MRI,
1249
1252
return N;
1250
1253
}
1251
1254
1255
+ // Return true if the type represents a constant register
1256
+ static bool isConstReg (MachineRegisterInfo *MRI, SPIRVType *OpDef) {
1257
+ if (OpDef->getOpcode () == SPIRV::ASSIGN_TYPE &&
1258
+ OpDef->getOperand (1 ).isReg ()) {
1259
+ if (SPIRVType *RefDef = MRI->getVRegDef (OpDef->getOperand (1 ).getReg ()))
1260
+ OpDef = RefDef;
1261
+ }
1262
+ return OpDef->getOpcode () == TargetOpcode::G_CONSTANT ||
1263
+ OpDef->getOpcode () == TargetOpcode::G_FCONSTANT;
1264
+ }
1265
+
1266
+ // Return true if the virtual register represents a constant
1267
+ static bool isConstReg (MachineRegisterInfo *MRI, Register OpReg) {
1268
+ if (SPIRVType *OpDef = MRI->getVRegDef (OpReg))
1269
+ return isConstReg (MRI, OpDef);
1270
+ return false ;
1271
+ }
1272
+
1252
1273
bool SPIRVInstructionSelector::selectSplatVector (Register ResVReg,
1253
1274
const SPIRVType *ResType,
1254
1275
MachineInstr &I) const {
@@ -1266,16 +1287,7 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg,
1266
1287
1267
1288
// check if we may construct a constant vector
1268
1289
Register OpReg = I.getOperand (OpIdx).getReg ();
1269
- bool IsConst = false ;
1270
- if (SPIRVType *OpDef = MRI->getVRegDef (OpReg)) {
1271
- if (OpDef->getOpcode () == SPIRV::ASSIGN_TYPE &&
1272
- OpDef->getOperand (1 ).isReg ()) {
1273
- if (SPIRVType *RefDef = MRI->getVRegDef (OpDef->getOperand (1 ).getReg ()))
1274
- OpDef = RefDef;
1275
- }
1276
- IsConst = OpDef->getOpcode () == TargetOpcode::G_CONSTANT ||
1277
- OpDef->getOpcode () == TargetOpcode::G_FCONSTANT;
1278
- }
1290
+ bool IsConst = isConstReg (MRI, OpReg);
1279
1291
1280
1292
if (!IsConst && N < 2 )
1281
1293
report_fatal_error (
@@ -1628,6 +1640,48 @@ bool SPIRVInstructionSelector::selectGEP(Register ResVReg,
1628
1640
return Res.constrainAllUses (TII, TRI, RBI);
1629
1641
}
1630
1642
1643
+ // Maybe wrap a value into OpSpecConstantOp
1644
+ bool SPIRVInstructionSelector::wrapIntoSpecConstantOp (
1645
+ MachineInstr &I, SmallVector<Register> &CompositeArgs) const {
1646
+ bool Result = true ;
1647
+ unsigned Lim = I.getNumExplicitOperands ();
1648
+ for (unsigned i = I.getNumExplicitDefs () + 1 ; i < Lim; ++i) {
1649
+ Register OpReg = I.getOperand (i).getReg ();
1650
+ SPIRVType *OpDefine = MRI->getVRegDef (OpReg);
1651
+ SPIRVType *OpType = GR.getSPIRVTypeForVReg (OpReg);
1652
+ if (!OpDefine || !OpType || isConstReg (MRI, OpDefine) ||
1653
+ OpDefine->getOpcode () == TargetOpcode::G_ADDRSPACE_CAST) {
1654
+ // The case of G_ADDRSPACE_CAST inside spv_const_composite() is processed
1655
+ // by selectAddrSpaceCast()
1656
+ CompositeArgs.push_back (OpReg);
1657
+ continue ;
1658
+ }
1659
+ MachineFunction *MF = I.getMF ();
1660
+ Register WrapReg = GR.find (OpDefine, MF);
1661
+ if (WrapReg.isValid ()) {
1662
+ CompositeArgs.push_back (WrapReg);
1663
+ continue ;
1664
+ }
1665
+ // Create a new register for the wrapper
1666
+ WrapReg = MRI->createVirtualRegister (&SPIRV::IDRegClass);
1667
+ GR.add (OpDefine, MF, WrapReg);
1668
+ CompositeArgs.push_back (WrapReg);
1669
+ // Decorate the wrapper register and generate a new instruction
1670
+ MRI->setType (WrapReg, LLT::pointer (0 , 32 ));
1671
+ GR.assignSPIRVTypeToVReg (OpType, WrapReg, *MF);
1672
+ MachineBasicBlock &BB = *I.getParent ();
1673
+ Result = BuildMI (BB, I, I.getDebugLoc (), TII.get (SPIRV::OpSpecConstantOp))
1674
+ .addDef (WrapReg)
1675
+ .addUse (GR.getSPIRVTypeID (OpType))
1676
+ .addImm (static_cast <uint32_t >(SPIRV::Opcode::Bitcast))
1677
+ .addUse (OpReg)
1678
+ .constrainAllUses (TII, TRI, RBI);
1679
+ if (!Result)
1680
+ break ;
1681
+ }
1682
+ return Result;
1683
+ }
1684
+
1631
1685
bool SPIRVInstructionSelector::selectIntrinsic (Register ResVReg,
1632
1686
const SPIRVType *ResType,
1633
1687
MachineInstr &I) const {
@@ -1666,17 +1720,21 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
1666
1720
case Intrinsic::spv_const_composite: {
1667
1721
// If no values are attached, the composite is null constant.
1668
1722
bool IsNull = I.getNumExplicitDefs () + 1 == I.getNumExplicitOperands ();
1669
- unsigned Opcode =
1670
- IsNull ? SPIRV::OpConstantNull : SPIRV::OpConstantComposite;
1723
+ // Select a proper instruction.
1724
+ unsigned Opcode = SPIRV::OpConstantNull;
1725
+ SmallVector<Register> CompositeArgs;
1726
+ if (!IsNull) {
1727
+ Opcode = SPIRV::OpConstantComposite;
1728
+ if (!wrapIntoSpecConstantOp (I, CompositeArgs))
1729
+ return false ;
1730
+ }
1671
1731
auto MIB = BuildMI (BB, I, I.getDebugLoc (), TII.get (Opcode))
1672
1732
.addDef (ResVReg)
1673
1733
.addUse (GR.getSPIRVTypeID (ResType));
1674
1734
// skip type MD node we already used when generated assign.type for this
1675
1735
if (!IsNull) {
1676
- for (unsigned i = I.getNumExplicitDefs () + 1 ;
1677
- i < I.getNumExplicitOperands (); ++i) {
1678
- MIB.addUse (I.getOperand (i).getReg ());
1679
- }
1736
+ for (Register OpReg : CompositeArgs)
1737
+ MIB.addUse (OpReg);
1680
1738
}
1681
1739
return MIB.constrainAllUses (TII, TRI, RBI);
1682
1740
}
0 commit comments