Index: include/llvm/Target/GlobalISel/SelectionDAGCompat.td =================================================================== --- include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -42,4 +42,10 @@ def : GINodeEquiv; def : GINodeEquiv; +def : GINodeEquiv; +def : GINodeEquiv; +def : GINodeEquiv; +def : GINodeEquiv; +def : GINodeEquiv; + def : GINodeEquiv; Index: lib/Target/AArch64/AArch64InstructionSelector.cpp =================================================================== --- lib/Target/AArch64/AArch64InstructionSelector.cpp +++ lib/Target/AArch64/AArch64InstructionSelector.cpp @@ -153,29 +153,8 @@ } case AArch64::FPRRegBankID: switch (OpSize) { - case 32: - switch (GenericOpc) { - case TargetOpcode::G_FADD: - return AArch64::FADDSrr; - case TargetOpcode::G_FSUB: - return AArch64::FSUBSrr; - case TargetOpcode::G_FMUL: - return AArch64::FMULSrr; - case TargetOpcode::G_FDIV: - return AArch64::FDIVSrr; - default: - return GenericOpc; - } case 64: switch (GenericOpc) { - case TargetOpcode::G_FADD: - return AArch64::FADDDrr; - case TargetOpcode::G_FSUB: - return AArch64::FSUBDrr; - case TargetOpcode::G_FMUL: - return AArch64::FMULDrr; - case TargetOpcode::G_FDIV: - return AArch64::FDIVDrr; case TargetOpcode::G_OR: return AArch64::ORRv8i8; default: @@ -718,11 +697,6 @@ return constrainSelectedInstRegOperands(I, TII, TRI, RBI); } - case TargetOpcode::G_FADD: - case TargetOpcode::G_FSUB: - case TargetOpcode::G_FMUL: - case TargetOpcode::G_FDIV: - case TargetOpcode::G_OR: case TargetOpcode::G_SHL: case TargetOpcode::G_LSHR: Index: test/TableGen/GlobalISelEmitter.td =================================================================== --- test/TableGen/GlobalISelEmitter.td +++ test/TableGen/GlobalISelEmitter.td @@ -27,7 +27,8 @@ //===- Test a simple pattern with regclass operands. ----------------------===// -// CHECK: if ((I.getOpcode() == TargetOpcode::G_ADD) && +// CHECK: if (true && +// CHECK-NEXT: (I.getOpcode() == TargetOpcode::G_ADD) && // CHECK-NEXT: (((MRI.getType(I.getOperand(0).getReg()) == (LLT::scalar(32))) && // CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(I.getOperand(0).getReg(), MRI, TRI))))) && // CHECK-NEXT: (((MRI.getType(I.getOperand(1).getReg()) == (LLT::scalar(32))) && @@ -46,7 +47,8 @@ //===- Test a pattern with an MBB operand. --------------------------------===// -// CHECK: if ((I.getOpcode() == TargetOpcode::G_BR) && +// CHECK: if (true && +// CHECK-NEXT: (I.getOpcode() == TargetOpcode::G_BR) && // CHECK-NEXT: (((I.getOperand(0).isMBB())))) { // CHECK-NEXT: // (br (bb:Other):$target) => (BR (bb:Other):$target) @@ -57,3 +59,25 @@ def BR : I<(outs), (ins unknown:$target), [(br bb:$target)]>; + +//===- Test a pattern with a predicate. -----------------------------------===// + +// CHECK: if ((STI.getFeatureBits()[MyTarget::FeatureFancyBR_A]) && +// CHECK-NEXT: (STI.getFeatureBits()[MyTarget::FeatureFancyBR_A]) && +// CHECK-NEXT: (I.getOpcode() == TargetOpcode::G_BR) && +// CHECK-NEXT: (((I.getOperand(0).isMBB())))) { + +// CHECK-NEXT: // (br (bb:Other):$target) => (FancyBR (bb:Other):$target) +// CHECK-NEXT: I.setDesc(TII.get(MyTarget::FancyBR)); +// CHECK-NEXT: constrainSelectedInstRegOperands(I, TII, TRI, RBI); +// CHECK-NEXT: return true; +// CHECK-NEXT: } + +def HasFancyBR_A : Predicate<"HasFancyBR_A">, + AssemblerPredicate<"FeatureFancyBR_A", "fancy-br-a">; +def HasFancyBR_B : Predicate<"HasFancyBR_B">, + AssemblerPredicate<"FeatureFancyBR_A", "fancy-br-a">; + +def FancyBR : I<(outs), (ins unknown:$target), + [(br bb:$target)]>, + Requires<[HasFancyBR_A, HasFancyBR_B]>; Index: utils/TableGen/GlobalISelEmitter.cpp =================================================================== --- utils/TableGen/GlobalISelEmitter.cpp +++ utils/TableGen/GlobalISelEmitter.cpp @@ -283,6 +283,33 @@ } }; +/// Generates code to check a predicate on a rule. +/// +/// Typical predicates include: +/// * The subtarget has some feature flag. +/// * The function has a certain attribute (e.g., minsize). +class RulePredicateMatcher { +public: + virtual ~RulePredicateMatcher() {} + + /// Emit a C++ expression that tests whether the rule matches the + /// (context-insensitive) predicate. + virtual void emitCxxPredicateExpr(raw_ostream &OS) const = 0; +}; + +/// Generates code to check a subtarget feature. +class SubtargetFeatureRuleMatcher : public RulePredicateMatcher { +protected: + std::string Feature; + +public: + SubtargetFeatureRuleMatcher(std::string Feature) : Feature(Feature) {} + + void emitCxxPredicateExpr(raw_ostream &OS) const override { + OS << "STI.getFeatureBits()[" << Feature << "]"; + } +}; + //===- Actions ------------------------------------------------------------===// /// An action taken when all Matcher predicates succeeded for a parent rule. @@ -324,8 +351,17 @@ } }; -/// Generates code to check that a match rule matches. -class RuleMatcher { +/// Generates code to check that a match rule matches, and that a set of +/// rule-level predicates match. +/// +/// Typical predicates include: +/// * The subtarget has some feature flag. +/// * The function has a certain attribute (e.g., minsize). +/// +/// This currently supports a single match position but could be extended to +/// support multiple positions to support div/rem fusion or load-multiple +/// instructions. +class RuleMatcher : public PredicateListMatcher { /// A list of matchers that all need to succeed for the current rule to match. /// FIXME: This currently supports a single match position but could be /// extended to support multiple positions to support div/rem fusion or @@ -364,7 +400,10 @@ // %elt0(s32), %elt1(s32) = TGT_LOAD_PAIR %ptr // on some targets but we don't need to make use of that yet. assert(Matchers.size() == 1 && "Cannot handle multi-root matchers yet"); + OS << " if ("; + emitCxxPredicateListExpr(OS); + OS << " &&\n"; Matchers.front()->emitCxxPredicateExpr(OS, "I"); OS << ") {\n"; @@ -406,9 +445,25 @@ M.addAction(P); // First, analyze the whole pattern. - // If the entire pattern has a predicate (e.g., target features), ignore it. - if (!P.getPredicates()->getValues().empty()) - return SkipReason{"Pattern has a predicate"}; + + // If the pattern has predicates (e.g., target features), check them. + for (Init *PredInit : P.getPredicates()->getValues()) { + DefInit *PredDef = dyn_cast(PredInit); + if (!PredDef) + return SkipReason{"Malformed pattern predicate"}; + Record *PredRec = PredDef->getDef(); + if (!PredRec->isSubClassOf("Predicate")) + return SkipReason{"Unrecognized pattern predicate"}; + + std::string CondString = + PredRec->getValueAsString("AssemblerCondString"); + StringRef Cond = CondString; + if (Cond.contains(',') || Cond.contains('!')) + return SkipReason{"Pattern predicate is too complicated"}; + + M.addPredicate( + (Target.getName() + "::" + Cond).str()); + } // Physreg imp-defs require additional logic. Ignore the pattern. if (!P.getDstRegs().empty())