llvm.org GIT mirror llvm / 3bbcbfa
[GlobalISel][TableGen] Fix handling of default operands When looping through a destination pattern's operands to decide how many default operands we need to introduce, we used to count the "expanded" number of operands. So if one default operand would be rendered as 2 values, we'd count it as 2 operands, when in fact it needs to count as only 1 operand regardless of how many values it expands to. This turns out to be a problem only in some very specific cases, e.g. when we have one operand with multiple default values followed by more operands with default values (see the new test). In such a situation we'd stop looping before looking at all the operands, and then error out assuming that we don't have enough default operands to make up the shortfall. At the moment this only affects ARM. The patch removes the loop counting default operands entirely and assumes that we'll have to introduce values for any default operand that we find (i.e. we're assuming it cannot be given as a child at all). It also extracts the code for adding renderers for default operands into a helper method. Differential Revision: https://reviews.llvm.org/D33031 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@303240 91177308-0d34-0410-b5e6-96231b3b80d8 Diana Picus 3 years ago
2 changed file(s) with 86 addition(s) and 49 deletion(s). Raw diff Collapse all Expand all
386386 def XORlike : I<(outs GPR32:$dst), (ins m1Z:$src2, GPR32:$src1),
387387 [(set GPR32:$dst, (xor GPR32:$src1, -4))]>;
388388
389 //===- Test a simple pattern with multiple operands with defaults. --------===//
390 //
391
392 // CHECK-LABEL: if ([&]() {
393 // CHECK-NEXT: MachineInstr &MI0 = I;
394 // CHECK-NEXT: if (MI0.getNumOperands() < 3)
395 // CHECK-NEXT: return false;
396 // CHECK-NEXT: if ((MI0.getOpcode() == TargetOpcode::G_XOR) &&
397 // CHECK-NEXT: ((/* dst */ (MRI.getType(MI0.getOperand(0).getReg()) == (LLT::scalar(32))) &&
398 // CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(MI0.getOperand(0).getReg(), MRI, TRI))))) &&
399 // CHECK-NEXT: ((/* src1 */ (MRI.getType(MI0.getOperand(1).getReg()) == (LLT::scalar(32))) &&
400 // CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(MI0.getOperand(1).getReg(), MRI, TRI))))) &&
401 // CHECK-NEXT: ((/* Operand 2 */ (MRI.getType(MI0.getOperand(2).getReg()) == (LLT::scalar(32))) &&
402 // CHECK-NEXT: (isOperandImmEqual(MI0.getOperand(2), -5, MRI))))) {
403 // CHECK-NEXT: // (xor:i32 GPR32:i32:$src1, -5:i32) => (XORManyDefaults:i32 GPR32:i32:$src1)
404 // CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::XORManyDefaults));
405 // CHECK-NEXT: MIB.add(MI0.getOperand(0)/*dst*/);
406 // CHECK-NEXT: MIB.addImm(-1);
407 // CHECK-NEXT: MIB.addReg(MyTarget::R0);
408 // CHECK-NEXT: MIB.addReg(MyTarget::R0);
409 // CHECK-NEXT: MIB.add(MI0.getOperand(1)/*src1*/);
410 // CHECK-NEXT: for (const auto *FromMI : {&MI0, })
411 // CHECK-NEXT: for (const auto &MMO : FromMI->memoperands())
412 // CHECK-NEXT: MIB.addMemOperand(MMO);
413 // CHECK-NEXT: I.eraseFromParent();
414 // CHECK-NEXT: MachineInstr &NewI = *MIB;
415 // CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);
416 // CHECK-NEXT: return true;
417 // CHECK-NEXT: }
418 // CHECK-NEXT: return false;
419 // CHECK-NEXT: }()) { return true; }
420
421 // The -5 is just to distinguish it from the other cases.
422 def XORManyDefaults : I<(outs GPR32:$dst), (ins m1Z:$src3, Z:$src2, GPR32:$src1),
423 [(set GPR32:$dst, (xor GPR32:$src1, -5))]>;
424
389425 //===- Test a simple pattern with constant immediate operands. ------------===//
390426 //
391427 // This must precede the 3-register variants because constant immediates have
12411241 Error importExplicitUseRenderer(BuildMIAction &DstMIBuilder,
12421242 TreePatternNode *DstChild,
12431243 const InstructionMatcher &InsnMatcher) const;
1244 Error importDefaultOperandRenderers(BuildMIAction &DstMIBuilder,
1245 DagInit *DefaultOps) const;
12441246 Error
12451247 importImplicitDefRenderers(BuildMIAction &DstMIBuilder,
12461248 const std::vector &ImplicitDefs) const;
15081510 DstMIBuilder.addRenderer(InsnMatcher, DstIOperand.Name);
15091511 }
15101512
1511 // Figure out which operands need defaults inserted. Operands that subclass
1512 // OperandWithDefaultOps are considered from left to right until we have
1513 // enough operands to render the instruction.
1514 SmallSet DefaultOperands;
1515 unsigned DstINumUses = DstI.Operands.size() - DstI.Operands.NumDefs;
1516 unsigned NumDefaultOperands = 0;
1517 for (unsigned I = 0; I < DstINumUses &&
1518 DstINumUses > Dst->getNumChildren() + NumDefaultOperands;
1519 ++I) {
1520 const auto &DstIOperand = DstI.Operands[DstI.Operands.NumDefs + I];
1521 if (DstIOperand.Rec->isSubClassOf("OperandWithDefaultOps")) {
1522 DefaultOperands.insert(I);
1523 NumDefaultOperands +=
1524 DstIOperand.Rec->getValueAsDag("DefaultOps")->getNumArgs();
1525 }
1526 }
1527 if (DstINumUses > Dst->getNumChildren() + DefaultOperands.size())
1528 return failedImport("Insufficient operands supplied and default ops "
1529 "couldn't make up the shortfall");
1530 if (DstINumUses < Dst->getNumChildren() + DefaultOperands.size())
1531 return failedImport("Too many operands supplied");
1532
15331513 // Render the explicit uses.
15341514 unsigned Child = 0;
1515 unsigned DstINumUses = DstI.Operands.size() - DstI.Operands.NumDefs;
1516 unsigned NumDefaultOps = 0;
15351517 for (unsigned I = 0; I != DstINumUses; ++I) {
1536 // If we need to insert default ops here, then do so.
1537 if (DefaultOperands.count(I)) {
1538 const auto &DstIOperand = DstI.Operands[DstI.Operands.NumDefs + I];
1539
1518 const auto &DstIOperand = DstI.Operands[DstI.Operands.NumDefs + I];
1519
1520 // If the operand has default values, introduce them now.
1521 // FIXME: Until we have a decent test case that dictates we should do
1522 // otherwise, we're going to assume that operands with default values cannot
1523 // be specified in the patterns. Therefore, adding them will not cause us to
1524 // end up with too many rendered operands.
1525 if (DstIOperand.Rec->isSubClassOf("OperandWithDefaultOps")) {
15401526 DagInit *DefaultOps = DstIOperand.Rec->getValueAsDag("DefaultOps");
1541 for (const auto *DefaultOp : DefaultOps->args()) {
1542 // Look through ValueType operators.
1543 if (const DagInit *DefaultDagOp = dyn_cast(DefaultOp)) {
1544 if (const DefInit *DefaultDagOperator =
1545 dyn_cast(DefaultDagOp->getOperator())) {
1546 if (DefaultDagOperator->getDef()->isSubClassOf("ValueType"))
1547 DefaultOp = DefaultDagOp->getArg(0);
1548 }
1549 }
1550
1551 if (const DefInit *DefaultDefOp = dyn_cast(DefaultOp)) {
1552 DstMIBuilder.addRenderer(DefaultDefOp->getDef());
1553 continue;
1554 }
1555
1556 if (const IntInit *DefaultIntOp = dyn_cast(DefaultOp)) {
1557 DstMIBuilder.addRenderer(DefaultIntOp->getValue());
1558 continue;
1559 }
1560
1561 return failedImport("Could not add default op");
1562 }
1563
1527 if (auto Error = importDefaultOperandRenderers(DstMIBuilder, DefaultOps))
1528 return std::move(Error);
1529 ++NumDefaultOps;
15641530 continue;
15651531 }
15661532
15701536 ++Child;
15711537 }
15721538
1539 if (NumDefaultOps + Dst->getNumChildren() != DstINumUses)
1540 return failedImport("Expected " + std::to_string(DstINumUses) +
1541 " used operands but found " +
1542 std::to_string(Dst->getNumChildren()) +
1543 " explicit ones and " + std::to_string(NumDefaultOps) +
1544 " default ones");
1545
15731546 return DstMIBuilder;
1547 }
1548
1549 Error GlobalISelEmitter::importDefaultOperandRenderers(
1550 BuildMIAction &DstMIBuilder, DagInit *DefaultOps) const {
1551 for (const auto *DefaultOp : DefaultOps->args()) {
1552 // Look through ValueType operators.
1553 if (const DagInit *DefaultDagOp = dyn_cast(DefaultOp)) {
1554 if (const DefInit *DefaultDagOperator =
1555 dyn_cast(DefaultDagOp->getOperator())) {
1556 if (DefaultDagOperator->getDef()->isSubClassOf("ValueType"))
1557 DefaultOp = DefaultDagOp->getArg(0);
1558 }
1559 }
1560
1561 if (const DefInit *DefaultDefOp = dyn_cast(DefaultOp)) {
1562 DstMIBuilder.addRenderer(DefaultDefOp->getDef());
1563 continue;
1564 }
1565
1566 if (const IntInit *DefaultIntOp = dyn_cast(DefaultOp)) {
1567 DstMIBuilder.addRenderer(DefaultIntOp->getValue());
1568 continue;
1569 }
1570
1571 return failedImport("Could not add default op");
1572 }
1573
1574 return Error::success();
15741575 }
15751576
15761577 Error GlobalISelEmitter::importImplicitDefRenderers(