@@ -413,10 +413,24 @@ class GlobalISelEmitter final : public GlobalISelMatchTableExecutorEmitter {
413
413
importExplicitUseRenderers (action_iterator InsertPt, RuleMatcher &M,
414
414
BuildMIAction &DstMIBuilder,
415
415
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
+
420
434
Error importDefaultOperandRenderers (action_iterator InsertPt, RuleMatcher &M,
421
435
BuildMIAction &DstMIBuilder,
422
436
const DAGDefaultOperand &DefaultOp) const ;
@@ -1190,159 +1204,207 @@ Error GlobalISelEmitter::importChildMatcher(
1190
1204
return failedImport (" Src pattern child is an unsupported kind" );
1191
1205
}
1192
1206
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 ();
1196
1211
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 ();
1203
1217
}
1204
1218
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 ();
1226
1221
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 ();
1232
1225
}
1233
1226
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 ();
1253
1230
}
1254
1231
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 ();
1270
1238
}
1271
1239
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));
1281
1241
}
1282
1242
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 ();
1286
1245
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));
1290
1248
1291
1249
std::optional<LLTCodeGen> OpTyOrNone;
1250
+ ArrayRef<TypeSetByHwMode> ChildTypes = N.getExtTypes ();
1292
1251
if (ChildTypes.front ().isMachineValueType ())
1293
1252
OpTyOrNone = MVTToLLT (ChildTypes.front ().getMachineValueType ().SimpleTy );
1253
+
1254
+ // TODO: Remove this check. Types in the destination DAG should not matter.
1294
1255
if (!OpTyOrNone)
1295
- return failedImport (" Dst operand has an unsupported type" );
1256
+ return failedImport (" node has unsupported type " + to_string (N) );
1296
1257
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" );
1301
1263
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
+ }
1311
1269
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 ();
1314
1275
}
1315
1276
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 ();
1320
1283
}
1284
+ }
1321
1285
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" );
1327
1290
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 ();
1333
1315
}
1334
1316
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.
1337
1325
}
1338
1326
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);
1344
1360
}
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));
1346
1408
}
1347
1409
1348
1410
// / Generates code that builds the resulting instruction(s) from the destination
@@ -1597,11 +1659,9 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
1597
1659
dyn_cast<DefInit>(SubRegChild.getLeafValue ())) {
1598
1660
CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx (SubRegInit->getDef ());
1599
1661
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
+
1605
1665
DstMIBuilder.addRenderer <SubRegIndexRenderer>(SubIdx);
1606
1666
}
1607
1667
}
@@ -1666,11 +1726,10 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
1666
1726
continue ;
1667
1727
}
1668
1728
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
+
1674
1733
++Child;
1675
1734
}
1676
1735
0 commit comments