@@ -413,10 +413,24 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
413413 importExplicitUseRenderers (action_iterator InsertPt, RuleMatcher &M,
414414 BuildMIAction &DstMIBuilder,
415415 const TreePatternNode &Dst) const ;
416- Expected<action_iterator>
417- importExplicitUseRenderer (action_iterator InsertPt, RuleMatcher &Rule,
418- BuildMIAction &DstMIBuilder,
419- const TreePatternNode &Dst) const ;
416+
417+ Error importNamedNodeRenderer (RuleMatcher &M, BuildMIAction &MIBuilder,
418+ const TreePatternNode &N) const ;
419+
420+ Error importLeafNodeRenderer (RuleMatcher &M, BuildMIAction &MIBuilder,
421+ const TreePatternNode &N) const ;
422+
423+ Error importXFormNodeRenderer (RuleMatcher &M, BuildMIAction &MIBuilder,
424+ const TreePatternNode &N) const ;
425+
426+ Error importInstructionNodeRenderer (RuleMatcher &M, BuildMIAction &MIBuilder,
427+ const TreePatternNode &N,
428+ action_iterator &InsertPt) const ;
429+
430+ Error importNodeRenderer (RuleMatcher &M, BuildMIAction &MIBuilder,
431+ const TreePatternNode &N,
432+ action_iterator &InsertPt) const ;
433+
420434 Error importDefaultOperandRenderers (action_iterator InsertPt, RuleMatcher &M,
421435 BuildMIAction &DstMIBuilder,
422436 const DAGDefaultOperand &DefaultOp) const ;
@@ -1190,159 +1204,207 @@ Error GlobalISelEmitter::importChildMatcher(
11901204 return failedImport (" Src pattern child is an unsupported kind" );
11911205}
11921206
1193- Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer (
1194- action_iterator InsertPt, RuleMatcher &Rule, BuildMIAction &DstMIBuilder,
1195- const TreePatternNode &Dst) const {
1207+ // Equivalent of MatcherGen::EmitResultOfNamedOperand.
1208+ Error GlobalISelEmitter::importNamedNodeRenderer (
1209+ RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N) const {
1210+ StringRef NodeName = N.getName ();
11961211
1197- const auto &SubOperand = Rule.getComplexSubOperand (Dst.getName ());
1198- if (SubOperand) {
1199- DstMIBuilder.addRenderer <RenderComplexPatternOperand>(
1200- *std::get<0 >(*SubOperand), Dst.getName (), std::get<1 >(*SubOperand),
1201- std::get<2 >(*SubOperand));
1202- return InsertPt;
1212+ if (auto SubOperand = M.getComplexSubOperand (NodeName)) {
1213+ auto [ComplexPatternRec, RendererID, SubOperandIdx] = *SubOperand;
1214+ MIBuilder.addRenderer <RenderComplexPatternOperand>(
1215+ *ComplexPatternRec, NodeName, RendererID, SubOperandIdx);
1216+ return Error::success ();
12031217 }
12041218
1205- if (!Dst.isLeaf ()) {
1206- if (Dst.getOperator ()->isSubClassOf (" SDNodeXForm" )) {
1207- auto &Child = Dst.getChild (0 );
1208- auto I = SDNodeXFormEquivs.find (Dst.getOperator ());
1209- if (I != SDNodeXFormEquivs.end ()) {
1210- const Record *XFormOpc = Dst.getOperator ()->getValueAsDef (" Opcode" );
1211- if (XFormOpc->getName () == " timm" ) {
1212- // If this is a TargetConstant, there won't be a corresponding
1213- // instruction to transform. Instead, this will refer directly to an
1214- // operand in an instruction's operand list.
1215- DstMIBuilder.addRenderer <CustomOperandRenderer>(*I->second ,
1216- Child.getName ());
1217- } else {
1218- DstMIBuilder.addRenderer <CustomRenderer>(*I->second , Child.getName ());
1219- }
1220-
1221- return InsertPt;
1222- }
1223- return failedImport (" SDNodeXForm " + Child.getName () +
1224- " has no custom renderer" );
1225- }
1219+ if (!N.isLeaf ()) {
1220+ StringRef OperatorName = N.getOperator ()->getName ();
12261221
1227- // We accept 'bb' here. It's an operator because BasicBlockSDNode isn't
1228- // inline, but in MI it's just another operand.
1229- if (Dst.getOperator ()->getName () == " bb" ) {
1230- DstMIBuilder.addRenderer <CopyRenderer>(Dst.getName ());
1231- return InsertPt;
1222+ if (OperatorName == " imm" ) {
1223+ MIBuilder.addRenderer <CopyConstantAsImmRenderer>(NodeName);
1224+ return Error::success ();
12321225 }
12331226
1234- // Similarly, imm is an operator in TreePatternNode's view but must be
1235- // rendered as operands.
1236- // FIXME: The target should be able to choose sign-extended when appropriate
1237- // (e.g. on Mips).
1238- if (Dst.getOperator ()->getName () == " timm" ) {
1239- DstMIBuilder.addRenderer <CopyRenderer>(Dst.getName ());
1240- return InsertPt;
1241- }
1242- if (Dst.getOperator ()->getName () == " tframeindex" ) {
1243- DstMIBuilder.addRenderer <CopyRenderer>(Dst.getName ());
1244- return InsertPt;
1245- }
1246- if (Dst.getOperator ()->getName () == " imm" ) {
1247- DstMIBuilder.addRenderer <CopyConstantAsImmRenderer>(Dst.getName ());
1248- return InsertPt;
1249- }
1250- if (Dst.getOperator ()->getName () == " fpimm" ) {
1251- DstMIBuilder.addRenderer <CopyFConstantAsFPImmRenderer>(Dst.getName ());
1252- return InsertPt;
1227+ if (OperatorName == " fpimm" ) {
1228+ MIBuilder.addRenderer <CopyFConstantAsFPImmRenderer>(NodeName);
1229+ return Error::success ();
12531230 }
12541231
1255- if (Dst.getOperator ()->isSubClassOf (" Instruction" )) {
1256- auto OpTy = getInstResultType (Dst, Target);
1257- if (!OpTy)
1258- return OpTy.takeError ();
1259-
1260- unsigned TempRegID = Rule.allocateTempRegID ();
1261- InsertPt =
1262- Rule.insertAction <MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID);
1263- DstMIBuilder.addRenderer <TempRegRenderer>(TempRegID);
1264-
1265- auto InsertPtOrError = createAndImportSubInstructionRenderer (
1266- ++InsertPt, Rule, Dst, TempRegID);
1267- if (auto Error = InsertPtOrError.takeError ())
1268- return std::move (Error);
1269- return InsertPtOrError.get ();
1232+ // TODO: 'imm' and 'fpimm' are the only nodes that need special treatment.
1233+ // Remove this check and add CopyRenderer unconditionally for other nodes.
1234+ if (OperatorName == " bb" || OperatorName == " timm" ||
1235+ OperatorName == " tframeindex" ) {
1236+ MIBuilder.addRenderer <CopyRenderer>(NodeName);
1237+ return Error::success ();
12701238 }
12711239
1272- return failedImport (" Dst pattern child isn't a leaf node or an MBB" +
1273- llvm::to_string (Dst));
1274- }
1275-
1276- // It could be a specific immediate in which case we should just check for
1277- // that immediate.
1278- if (const IntInit *ChildIntInit = dyn_cast<IntInit>(Dst.getLeafValue ())) {
1279- DstMIBuilder.addRenderer <ImmRenderer>(ChildIntInit->getValue ());
1280- return InsertPt;
1240+ return failedImport (" node has unsupported operator " + to_string (N));
12811241 }
12821242
1283- // Otherwise, we're looking for a bog-standard RegisterClass operand.
1284- if (auto *ChildDefInit = dyn_cast<DefInit>(Dst.getLeafValue ())) {
1285- auto *ChildRec = ChildDefInit->getDef ();
1243+ if (const auto *DI = dyn_cast<DefInit>(N.getLeafValue ())) {
1244+ const Record *R = DI->getDef ();
12861245
1287- ArrayRef<TypeSetByHwMode> ChildTypes = Dst.getExtTypes ();
1288- if (ChildTypes.size () != 1 )
1289- return failedImport (" Dst pattern child has multiple results" );
1246+ if (N.getNumResults () != 1 )
1247+ return failedImport (" node does not have one result " + to_string (N));
12901248
12911249 std::optional<LLTCodeGen> OpTyOrNone;
1250+ ArrayRef<TypeSetByHwMode> ChildTypes = N.getExtTypes ();
12921251 if (ChildTypes.front ().isMachineValueType ())
12931252 OpTyOrNone = MVTToLLT (ChildTypes.front ().getMachineValueType ().SimpleTy );
1253+
1254+ // TODO: Remove this check. Types in the destination DAG should not matter.
12941255 if (!OpTyOrNone)
1295- return failedImport (" Dst operand has an unsupported type" );
1256+ return failedImport (" node has unsupported type " + to_string (N) );
12961257
1297- if (ChildRec->isSubClassOf (" Register" )) {
1298- DstMIBuilder.addRenderer <AddRegisterRenderer>(Target, ChildRec);
1299- return InsertPt;
1300- }
1258+ if (R->isSubClassOf (" ComplexPattern" )) {
1259+ auto I = ComplexPatternEquivs.find (R);
1260+ if (I == ComplexPatternEquivs.end ())
1261+ return failedImport (" ComplexPattern " + R->getName () +
1262+ " does not have GISel equivalent" );
13011263
1302- if (ChildRec->isSubClassOf (" RegisterClass" ) ||
1303- ChildRec->isSubClassOf (" RegisterOperand" ) ||
1304- ChildRec->isSubClassOf (" ValueType" )) {
1305- if (ChildRec->isSubClassOf (" RegisterOperand" ) &&
1306- !ChildRec->isValueUnset (" GIZeroRegister" )) {
1307- DstMIBuilder.addRenderer <CopyOrAddZeroRegRenderer>(
1308- Dst.getName (), ChildRec->getValueAsDef (" GIZeroRegister" ));
1309- return InsertPt;
1310- }
1264+ const OperandMatcher &OM = M.getOperandMatcher (NodeName);
1265+ MIBuilder.addRenderer <RenderComplexPatternOperand>(
1266+ *I->second , NodeName, OM.getAllocatedTemporariesBaseID ());
1267+ return Error::success ();
1268+ }
13111269
1312- DstMIBuilder.addRenderer <CopyRenderer>(Dst.getName ());
1313- return InsertPt;
1270+ if (R->isSubClassOf (" RegisterOperand" ) &&
1271+ !R->isValueUnset (" GIZeroRegister" )) {
1272+ MIBuilder.addRenderer <CopyOrAddZeroRegRenderer>(
1273+ NodeName, R->getValueAsDef (" GIZeroRegister" ));
1274+ return Error::success ();
13141275 }
13151276
1316- if (ChildRec->isSubClassOf (" SubRegIndex" )) {
1317- CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx (ChildRec);
1318- DstMIBuilder.addRenderer <ImmRenderer>(SubIdx->EnumValue );
1319- return InsertPt;
1277+ // TODO: All special cases are handled above. Remove this check and add
1278+ // CopyRenderer unconditionally.
1279+ if (R->isSubClassOf (" RegisterClass" ) ||
1280+ R->isSubClassOf (" RegisterOperand" ) || R->isSubClassOf (" ValueType" )) {
1281+ MIBuilder.addRenderer <CopyRenderer>(NodeName);
1282+ return Error::success ();
13201283 }
1284+ }
13211285
1322- if (ChildRec->isSubClassOf (" ComplexPattern" )) {
1323- const auto &ComplexPattern = ComplexPatternEquivs.find (ChildRec);
1324- if (ComplexPattern == ComplexPatternEquivs.end ())
1325- return failedImport (
1326- " SelectionDAG ComplexPattern not mapped to GlobalISel" );
1286+ // TODO: Change this to assert and move to the beginning of the function.
1287+ if (!M.hasOperand (NodeName))
1288+ return failedImport (" could not find node $" + NodeName +
1289+ " in the source DAG" );
13271290
1328- const OperandMatcher &OM = Rule.getOperandMatcher (Dst.getName ());
1329- DstMIBuilder.addRenderer <RenderComplexPatternOperand>(
1330- *ComplexPattern->second , Dst.getName (),
1331- OM.getAllocatedTemporariesBaseID ());
1332- return InsertPt;
1291+ // TODO: Remove this check and add CopyRenderer unconditionally.
1292+ // TODO: Handle nodes with multiple results (provided they can reach here).
1293+ if (isa<UnsetInit>(N.getLeafValue ())) {
1294+ MIBuilder.addRenderer <CopyRenderer>(NodeName);
1295+ return Error::success ();
1296+ }
1297+
1298+ return failedImport (" unsupported node " + to_string (N));
1299+ }
1300+
1301+ // Equivalent of MatcherGen::EmitResultLeafAsOperand.
1302+ Error GlobalISelEmitter::importLeafNodeRenderer (
1303+ RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N) const {
1304+ if (const auto *II = dyn_cast<IntInit>(N.getLeafValue ())) {
1305+ MIBuilder.addRenderer <ImmRenderer>(II->getValue ());
1306+ return Error::success ();
1307+ }
1308+
1309+ if (const auto *DI = dyn_cast<DefInit>(N.getLeafValue ())) {
1310+ const Record *R = DI->getDef ();
1311+
1312+ if (R->isSubClassOf (" Register" )) {
1313+ MIBuilder.addRenderer <AddRegisterRenderer>(Target, R);
1314+ return Error::success ();
13331315 }
13341316
1335- return failedImport (
1336- " Dst pattern child def is an unsupported tablegen class" );
1317+ if (R->isSubClassOf (" SubRegIndex" )) {
1318+ const CodeGenSubRegIndex *SubRegIndex = CGRegs.getSubRegIdx (R);
1319+ MIBuilder.addRenderer <ImmRenderer>(SubRegIndex->EnumValue );
1320+ return Error::success ();
1321+ }
1322+
1323+ // There are also RegisterClass / RegisterOperand operands of REG_SEQUENCE /
1324+ // COPY_TO_REGCLASS, but these instructions are currently handled elsewhere.
13371325 }
13381326
1339- // Handle the case where the MVT/register class is omitted in the dest pattern
1340- // but MVT exists in the source pattern.
1341- if (isa<UnsetInit>(Dst.getLeafValue ()) && Rule.hasOperand (Dst.getName ())) {
1342- DstMIBuilder.addRenderer <CopyRenderer>(Dst.getName ());
1343- return InsertPt;
1327+ return failedImport (" unrecognized node " + to_string (N));
1328+ }
1329+
1330+ // Equivalent of MatcherGen::EmitResultSDNodeXFormAsOperand.
1331+ Error GlobalISelEmitter::importXFormNodeRenderer (
1332+ RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N) const {
1333+ const Record *XFormRec = N.getOperator ();
1334+ auto I = SDNodeXFormEquivs.find (XFormRec);
1335+ if (I == SDNodeXFormEquivs.end ())
1336+ return failedImport (" SDNodeXForm " + XFormRec->getName () +
1337+ " does not have GISel equivalent" );
1338+
1339+ // TODO: Fail to import if GISDNodeXForm does not have RendererFn.
1340+ // This currently results in a fatal error in emitRenderOpcodes.
1341+ const Record *XFormEquivRec = I->second ;
1342+
1343+ // The node to apply the transformation function to.
1344+ // FIXME: The node may not have a name and may be a leaf. It should be
1345+ // rendered first, like any other nodes. This may or may not require
1346+ // introducing a temporary register, and we can't tell that without
1347+ // inspecting the node (possibly recursively). This is a general drawback
1348+ // of appending renderers directly to BuildMIAction.
1349+ const TreePatternNode &Node = N.getChild (0 );
1350+ StringRef NodeName = Node.getName ();
1351+
1352+ const Record *XFormOpc = CGP.getSDNodeTransform (XFormRec).first ;
1353+ if (XFormOpc->getName () == " timm" ) {
1354+ // If this is a TargetConstant, there won't be a corresponding
1355+ // instruction to transform. Instead, this will refer directly to an
1356+ // operand in an instruction's operand list.
1357+ MIBuilder.addRenderer <CustomOperandRenderer>(*XFormEquivRec, NodeName);
1358+ } else {
1359+ MIBuilder.addRenderer <CustomRenderer>(*XFormEquivRec, NodeName);
13441360 }
1345- return failedImport (" Dst pattern child is an unsupported kind" );
1361+
1362+ return Error::success ();
1363+ }
1364+
1365+ // Equivalent of MatcherGen::EmitResultInstructionAsOperand.
1366+ Error GlobalISelEmitter::importInstructionNodeRenderer (
1367+ RuleMatcher &M, BuildMIAction &MIBuilder, const TreePatternNode &N,
1368+ action_iterator &InsertPt) const {
1369+ Expected<LLTCodeGen> OpTy = getInstResultType (N, Target);
1370+ if (!OpTy)
1371+ return OpTy.takeError ();
1372+
1373+ // TODO: See the comment in importXFormNodeRenderer. We rely on the node
1374+ // requiring a temporary register, which prevents us from using this
1375+ // function on the root of the destination DAG.
1376+ unsigned TempRegID = M.allocateTempRegID ();
1377+ InsertPt = M.insertAction <MakeTempRegisterAction>(InsertPt, *OpTy, TempRegID);
1378+ MIBuilder.addRenderer <TempRegRenderer>(TempRegID);
1379+
1380+ auto InsertPtOrError =
1381+ createAndImportSubInstructionRenderer (++InsertPt, M, N, TempRegID);
1382+ if (!InsertPtOrError)
1383+ return InsertPtOrError.takeError ();
1384+
1385+ InsertPt = *InsertPtOrError;
1386+ return Error::success ();
1387+ }
1388+
1389+ // Equivalent of MatcherGen::EmitResultOperand.
1390+ Error GlobalISelEmitter::importNodeRenderer (RuleMatcher &M,
1391+ BuildMIAction &MIBuilder,
1392+ const TreePatternNode &N,
1393+ action_iterator &InsertPt) const {
1394+ if (N.hasName ())
1395+ return importNamedNodeRenderer (M, MIBuilder, N);
1396+
1397+ if (N.isLeaf ())
1398+ return importLeafNodeRenderer (M, MIBuilder, N);
1399+
1400+ if (N.getOperator ()->isSubClassOf (" SDNodeXForm" ))
1401+ return importXFormNodeRenderer (M, MIBuilder, N);
1402+
1403+ if (N.getOperator ()->isSubClassOf (" Instruction" ))
1404+ return importInstructionNodeRenderer (M, MIBuilder, N, InsertPt);
1405+
1406+ // Should not reach here.
1407+ return failedImport (" unrecognized node " + llvm::to_string (N));
13461408}
13471409
13481410// / Generates code that builds the resulting instruction(s) from the destination
@@ -1597,11 +1659,9 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
15971659 dyn_cast<DefInit>(SubRegChild.getLeafValue ())) {
15981660 CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx (SubRegInit->getDef ());
15991661
1600- auto InsertPtOrError =
1601- importExplicitUseRenderer (InsertPt, M, DstMIBuilder, ValChild);
1602- if (auto Error = InsertPtOrError.takeError ())
1603- return std::move (Error);
1604- InsertPt = InsertPtOrError.get ();
1662+ if (Error Err = importNodeRenderer (M, DstMIBuilder, ValChild, InsertPt))
1663+ return Err;
1664+
16051665 DstMIBuilder.addRenderer <SubRegIndexRenderer>(SubIdx);
16061666 }
16071667 }
@@ -1666,11 +1726,10 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
16661726 continue ;
16671727 }
16681728
1669- auto InsertPtOrError = importExplicitUseRenderer (InsertPt, M, DstMIBuilder,
1670- Dst.getChild (Child));
1671- if (auto Error = InsertPtOrError.takeError ())
1672- return std::move (Error);
1673- InsertPt = InsertPtOrError.get ();
1729+ if (Error Err =
1730+ importNodeRenderer (M, DstMIBuilder, Dst.getChild (Child), InsertPt))
1731+ return Err;
1732+
16741733 ++Child;
16751734 }
16761735
0 commit comments