@@ -231,6 +231,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
231231 Register buildZerosVal (const SPIRVType *ResType, MachineInstr &I) const ;
232232 Register buildOnesVal (bool AllOnes, const SPIRVType *ResType,
233233 MachineInstr &I) const ;
234+
235+ bool wrapIntoSpecConstantOp (MachineInstr &I,
236+ SmallVector<Register> &CompositeArgs) const ;
234237};
235238
236239} // end anonymous namespace
@@ -1249,6 +1252,24 @@ static unsigned getArrayComponentCount(MachineRegisterInfo *MRI,
12491252 return N;
12501253}
12511254
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+
12521273bool SPIRVInstructionSelector::selectSplatVector (Register ResVReg,
12531274 const SPIRVType *ResType,
12541275 MachineInstr &I) const {
@@ -1266,16 +1287,7 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg,
12661287
12671288 // check if we may construct a constant vector
12681289 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);
12791291
12801292 if (!IsConst && N < 2 )
12811293 report_fatal_error (
@@ -1628,6 +1640,48 @@ bool SPIRVInstructionSelector::selectGEP(Register ResVReg,
16281640 return Res.constrainAllUses (TII, TRI, RBI);
16291641}
16301642
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+
16311685bool SPIRVInstructionSelector::selectIntrinsic (Register ResVReg,
16321686 const SPIRVType *ResType,
16331687 MachineInstr &I) const {
@@ -1666,17 +1720,21 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
16661720 case Intrinsic::spv_const_composite: {
16671721 // If no values are attached, the composite is null constant.
16681722 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+ }
16711731 auto MIB = BuildMI (BB, I, I.getDebugLoc (), TII.get (Opcode))
16721732 .addDef (ResVReg)
16731733 .addUse (GR.getSPIRVTypeID (ResType));
16741734 // skip type MD node we already used when generated assign.type for this
16751735 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);
16801738 }
16811739 return MIB.constrainAllUses (TII, TRI, RBI);
16821740 }
0 commit comments