diff --git a/llvm/docs/GlobalISel/MIRPatterns.rst b/llvm/docs/GlobalISel/MIRPatterns.rst index d7dce1b978cd2..7e6d88683d491 100644 --- a/llvm/docs/GlobalISel/MIRPatterns.rst +++ b/llvm/docs/GlobalISel/MIRPatterns.rst @@ -274,8 +274,32 @@ it's less verbose. Combine Rules also allow mixing C++ code with MIR patterns, so that you -may perform additional checks when matching, or run additional code after -rewriting a pattern. +may perform additional checks when matching, or run a C++ action after +matching. + +Note that C++ code in ``apply`` pattern is mutually exclusive with +other patterns. However, you can freely mix C++ code with other +types of patterns in ``match`` patterns. +C++ code in ``match`` patterns is always run last, after all other +patterns matched. + +.. code-block:: text + :caption: Apply Pattern Examples with C++ code + + // Valid + def Foo : GICombineRule< + (defs root:$root), + (match (G_ZEXT $tmp, (i32 0)), + (G_STORE $tmp, $ptr):$root, + "return myFinalCheck()"), + (apply "runMyAction(${root})")>; + + // error: 'apply' patterns cannot mix C++ code with other types of patterns + def Bar : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, $src):$mi), + (apply (G_MUL $dst, $src, $src), + "runMyAction(${root})")>; The following expansions are available for MIR patterns: diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h index 72c63ecba529f..371c5c5a0a1e1 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutor.h @@ -471,16 +471,11 @@ enum { /// - RendererFnID(2) - Custom renderer function to call GIR_CustomRenderer, - /// Calls a C++ function to perform an action when a match is complete. - /// The MatcherState is passed to the function to allow it to modify - /// instructions. - /// This is less constrained than a custom renderer and can update - /// instructions - /// in the state. + /// Calls a C++ function that concludes the current match. + /// The C++ function is free to return false and reject the match, or + /// return true and mutate the instruction(s) (or do nothing, even). /// - FnID(2) - The function to call. - /// TODO: Remove this at some point when combiners aren't reliant on it. It's - /// a bit of a hack. - GIR_CustomAction, + GIR_DoneWithCustomAction, /// Render operands to the specified instruction using a custom function, /// reading from a specific operand. @@ -688,7 +683,7 @@ class GIMatchTableExecutor { llvm_unreachable("Subclass does not implement testSimplePredicate!"); } - virtual void runCustomAction(unsigned, const MatcherState &State, + virtual bool runCustomAction(unsigned, const MatcherState &State, NewMIVector &OutMIs) const { llvm_unreachable("Subclass does not implement runCustomAction!"); } diff --git a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h index 4d147bf20c26a..2ea9d11779f0a 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/GIMatchTableExecutorImpl.h @@ -1335,13 +1335,19 @@ bool GIMatchTableExecutor::executeMatchTable( -1); // Not a source operand of the old instruction. break; } - case GIR_CustomAction: { + case GIR_DoneWithCustomAction: { uint16_t FnID = readU16(); DEBUG_WITH_TYPE(TgtExecutor::getName(), - dbgs() << CurrentIdx << ": GIR_CustomAction(FnID=" << FnID - << ")\n"); + dbgs() << CurrentIdx << ": GIR_DoneWithCustomAction(FnID=" + << FnID << ")\n"); assert(FnID > GICXXCustomAction_Invalid && "Expected a valid FnID"); - runCustomAction(FnID, State, OutMIs); + if (runCustomAction(FnID, State, OutMIs)) { + propagateFlags(); + return true; + } + + if (handleReject() == RejectAndGiveUp) + return false; break; } case GIR_CustomOperandRenderer: { diff --git a/llvm/include/llvm/Target/GlobalISel/Combine.td b/llvm/include/llvm/Target/GlobalISel/Combine.td index 98d266c8c0b4f..d61a5759d5a96 100644 --- a/llvm/include/llvm/Target/GlobalISel/Combine.td +++ b/llvm/include/llvm/Target/GlobalISel/Combine.td @@ -338,7 +338,7 @@ def bitreverse_shl : GICombineRule< // Combine bitreverse(lshr (bitreverse x), y)) -> (shl x, y) def bitreverse_lshr : GICombineRule< - (defs root:$d, build_fn_matchinfo:$matchinfo), + (defs root:$d), (match (G_BITREVERSE $rev, $val), (G_LSHR $src, $rev, $amt):$mi, (G_BITREVERSE $d, $src), @@ -1352,7 +1352,7 @@ def match_extract_of_element : GICombineRule< (apply [{ Helper.applyBuildFn(*${root}, ${matchinfo}); }])>; def extract_vector_element_not_const : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), + (defs root:$root), (match (G_INSERT_VECTOR_ELT $src, $x, $value, $idx), (G_EXTRACT_VECTOR_ELT $root, $src, $idx)), (apply (GIReplaceReg $root, $value))>; @@ -1567,20 +1567,20 @@ def combine_shuffle_concat : GICombineRule< (apply [{ Helper.applyCombineShuffleConcat(*${root}, ${matchinfo}); }])>; def insert_vector_element_idx_undef : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), + (defs root:$root), (match (G_IMPLICIT_DEF $idx), (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx)), (apply (G_IMPLICIT_DEF $root))>; def insert_vector_element_elt_undef : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), + (defs root:$root), (match (G_IMPLICIT_DEF $elt), (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx), [{ return isGuaranteedNotToBePoison(${src}.getReg(), MRI); }]), (apply (GIReplaceReg $root, $src))>; def insert_vector_element_extract_vector_element : GICombineRule< - (defs root:$root, build_fn_matchinfo:$matchinfo), + (defs root:$root), (match (G_EXTRACT_VECTOR_ELT $elt, $src, $idx), (G_INSERT_VECTOR_ELT $root, $src, $elt, $idx)), (apply (GIReplaceReg $root, $src))>; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td new file mode 100644 index 0000000000000..bb1acde296429 --- /dev/null +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-cxx.td @@ -0,0 +1,143 @@ +// RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \ +// RUN: -combiners=MyCombiner %s | \ +// RUN: FileCheck %s + +include "llvm/Target/Target.td" +include "llvm/Target/GlobalISel/Combine.td" + +def MyTargetISA : InstrInfo; +def MyTarget : Target { let InstructionSet = MyTargetISA; } + +def OneMatchOneApply : GICombineRule< + (defs root:$a), + (match (G_FABS $a, $b), "return MATCH0;"), + (apply "APPLY0")>; + +def TwoMatchTwoApply : GICombineRule< + (defs root:$a), + (match (G_FNEG $a, $b), "return MATCH0;", "return MATCH1;"), + (apply "APPLY0", "APPLY1")>; + +def TwoMatchNoApply : GICombineRule< + (defs root:$a), + (match (G_STORE $x, $y):$a, "return MATCH0;", "return MATCH1;"), + (apply (GIEraseRoot))>; + +def NoMatchTwoApply : GICombineRule< + (defs root:$a), + (match (G_SEXT $a, $y)), + (apply "APPLY0", "APPLY1")>; + +def MyCombiner: GICombiner<"GenMyCombiner", [ + OneMatchOneApply, + TwoMatchTwoApply, + TwoMatchNoApply, + NoMatchTwoApply +]>; + +// CHECK: bool GenMyCombiner::testMIPredicate_MI(unsigned PredicateID, const MachineInstr & MI, const MatcherState &State) const { +// CHECK-NEXT: switch (PredicateID) { +// CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner0: { +// CHECK-NEXT: return MATCH0; +// CHECK-NEXT: } +// CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner1: { +// CHECK-NEXT: return MATCH1; +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: llvm_unreachable("Unknown predicate"); +// CHECK-NEXT: return false; +// CHECK-NEXT: } + +// CHECK: bool GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const { +// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); +// CHECK-NEXT: switch(ApplyID) { +// CHECK-NEXT: case GICXXCustomAction_GICombiner0:{ +// CHECK-NEXT: // Match Patterns +// CHECK-NEXT: if(![&](){return MATCH0;}()) { +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY0 +// CHECK-NEXT: return true; +// CHECK-NEXT: } +// CHECK-NEXT: case GICXXCustomAction_GICombiner1:{ +// CHECK-NEXT: // Match Patterns +// CHECK-NEXT: if(![&](){return MATCH0;}()) { +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: if(![&](){return MATCH1;}()) { +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY0 +// CHECK-NEXT: APPLY1 +// CHECK-NEXT: return true; +// CHECK-NEXT: } +// CHECK-NEXT: case GICXXCustomAction_GICombiner2:{ +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY0 +// CHECK-NEXT: APPLY1 +// CHECK-NEXT: return true; +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: llvm_unreachable("Unknown Apply Action"); +// CHECK-NEXT: } + +// CHECK: const uint8_t *GenMyCombiner::getMatchTable() const { +// CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { +// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(94), GIMT_Encode2(194), /*)*//*default:*//*Label 4*/ GIMT_Encode4(464), +// CHECK-NEXT: /*TargetOpcode::G_STORE*//*Label 0*/ GIMT_Encode4(410), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_SEXT*//*Label 1*/ GIMT_Encode4(428), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_FNEG*//*Label 2*/ GIMT_Encode4(440), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_FABS*//*Label 3*/ GIMT_Encode4(452), +// CHECK-NEXT: // Label 0: @410 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(427), // Rule ID 2 // +// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled), +// CHECK-NEXT: // MIs[0] x +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // MIs[0] y +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0), +// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner1), +// CHECK-NEXT: // Combiner Rule #2: TwoMatchNoApply +// CHECK-NEXT: GIR_EraseRootFromParent_Done, +// CHECK-NEXT: // Label 5: @427 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: // Label 1: @428 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(439), // Rule ID 3 // +// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled), +// CHECK-NEXT: // MIs[0] a +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // MIs[0] y +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // Combiner Rule #3: NoMatchTwoApply +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2), +// CHECK-NEXT: // Label 6: @439 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: // Label 2: @440 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(451), // Rule ID 1 // +// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled), +// CHECK-NEXT: // MIs[0] a +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // MIs[0] b +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // Combiner Rule #1: TwoMatchTwoApply +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1), +// CHECK-NEXT: // Label 7: @451 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: // Label 3: @452 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(463), // Rule ID 0 // +// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), +// CHECK-NEXT: // MIs[0] a +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // MIs[0] b +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // Combiner Rule #0: OneMatchOneApply +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 8: @463 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: // Label 4: @464 +// CHECK-NEXT: GIM_Reject, +// CHECK-NEXT: }; // Size: 465 bytes +// CHECK-NEXT: return MatchTable0; +// CHECK-NEXT: } diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td index fda57d5b64e02..4a908e7823484 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-permutations.td @@ -24,7 +24,7 @@ def Test0 : GICombineRule< (MatchFooPerms $cst1, (i32 20)):$b, (MatchFooPerms $cst2, (i32 30)):$c ), - (apply (COPY $dst, (i32 0)), "APPLY ${cst0}")>; + (apply "APPLY ${cst0}")>; def MyCombiner: GICombiner<"GenMyCombiner", [ Test0 @@ -159,9 +159,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK: const uint8_t *GenMyCombiner::getMatchTable() const { // CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(738), +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 0*/ GIMT_Encode4(562), // CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, GIMT_Encode2(TargetOpcode::G_AND), -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(88), // Rule ID 7 // +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 1*/ GIMT_Encode4(66), // Rule ID 7 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -187,16 +187,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner22), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner23), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/4, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[1], c[1]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 1: @88 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(175), // Rule ID 6 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 1: @66 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 2*/ GIMT_Encode4(131), // Rule ID 6 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -225,16 +219,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner19), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner20), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/5, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[1], c[0]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 2: @175 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(262), // Rule ID 5 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 2: @131 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(196), // Rule ID 5 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -263,16 +251,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner16), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner17), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/5, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[0], c[1]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 3: @262 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(357), // Rule ID 4 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 3: @196 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(269), // Rule ID 4 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -304,16 +286,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner13), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner14), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/6, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[1], b[0], c[0]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 4: @357 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(444), // Rule ID 3 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 4: @269 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(334), // Rule ID 3 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -342,16 +318,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner10), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner11), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/5, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[1], c[1]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 5: @444 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(539), // Rule ID 2 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 5: @334 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(407), // Rule ID 2 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -383,16 +353,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner7), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner8), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/6, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[1], c[0]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 6: @539 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(634), // Rule ID 1 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 6: @407 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(480), // Rule ID 1 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -424,16 +388,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner4), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner5), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/6, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[0], c[1]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 7: @634 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(737), // Rule ID 0 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 7: @480 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(561), // Rule ID 0 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates @@ -468,18 +426,12 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner1), // CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner2), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/7, -// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, -// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #0: Test0 @ [a[0], b[0], c[0]] -// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY), -// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst -// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 8: @737 +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 8: @561 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 0: @738 +// CHECK-NEXT: // Label 0: @562 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: }; // Size: 739 bytes +// CHECK-NEXT: }; // Size: 563 bytes // CHECK-NEXT: return MatchTable0; // CHECK-NEXT: } diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td index 83b77519bc73a..35bddf912a541 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table-variadics.td @@ -37,11 +37,11 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK: const uint8_t *GenMyCombiner::getMatchTable() const { // CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { -// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(69), GIMT_Encode2(73), /*)*//*default:*//*Label 2*/ GIMT_Encode4(88), +// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(69), GIMT_Encode2(73), /*)*//*default:*//*Label 2*/ GIMT_Encode4(84), // CHECK-NEXT: /*TargetOpcode::G_UNMERGE_VALUES*//*Label 0*/ GIMT_Encode4(26), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_BUILD_VECTOR*//*Label 1*/ GIMT_Encode4(57), +// CHECK-NEXT: /*TargetOpcode::G_BUILD_VECTOR*//*Label 1*/ GIMT_Encode4(55), // CHECK-NEXT: // Label 0: @26 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(41), // Rule ID 2 // +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 3*/ GIMT_Encode4(40), // Rule ID 2 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled), // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2, // CHECK-NEXT: // MIs[0] a @@ -49,10 +49,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] b // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #2: InstTest2 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 3: @41 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(56), // Rule ID 3 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 3: @40 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 4*/ GIMT_Encode4(54), // Rule ID 3 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled), // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4, // CHECK-NEXT: // MIs[0] a @@ -64,12 +63,11 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] d // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #3: InstTest3 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 4: @56 +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 4: @54 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 1: @57 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(72), // Rule ID 1 // +// CHECK-NEXT: // Label 1: @55 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 5*/ GIMT_Encode4(69), // Rule ID 1 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled), // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2, // CHECK-NEXT: // MIs[0] a @@ -77,10 +75,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] b // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #1: InstTest1 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 5: @72 -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(87), // Rule ID 0 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 5: @69 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 6*/ GIMT_Encode4(83), // Rule ID 0 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/4, // CHECK-NEXT: // MIs[0] a @@ -92,12 +89,11 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: // MIs[0] d // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #0: InstTest0 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 6: @87 +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 6: @83 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 2: @88 +// CHECK-NEXT: // Label 2: @84 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: }; // Size: 89 bytes +// CHECK-NEXT: }; // Size: 85 bytes // CHECK-NEXT: return MatchTable0; // CHECK-NEXT: } diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td index 1052e31b2d051..513a86754d6d9 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/match-table.td @@ -41,7 +41,7 @@ def InOutInstTest0 : GICombineRule< (defs root:$root), (match (G_ZEXT $tmp, $ext), (G_STORE $tmp, $ptr):$root), - (apply (G_STORE $ext, $ptr):$root, "APPLY ${ext} ${ptr} ${root}")>; + (apply (G_STORE $ext, $ptr):$root)>; // Imm operand of G_CONSTANT should match a literal int, while the second // should match a constant. @@ -76,16 +76,9 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // We have at most 2 registers used by one rule at a time, so we should only have 2 registers MDInfos. -// CHECK: struct MatchInfosTy { -// CHECK-NEXT: Register MDInfo0, MDInfo1; -// CHECK-NEXT: }; - // Check predicates // CHECK: switch (PredicateID) { // CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner0: { -// CHECK-NEXT: return CHECK State.MIs[0]->getOperand(0), State.MIs[0]->getOperand(1), State.MIs[1]->getOperand(1), State.MIs[0] -// CHECK-NEXT: } -// CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner1: { // CHECK-NEXT: return matchIConstant(State.MIs[0]->getOperand(1), 0); // CHECK-NEXT: } @@ -96,8 +89,6 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: B.setInstrAndDebugLoc(I); // CHECK-NEXT: State.MIs.clear(); // CHECK-NEXT: State.MIs.push_back(&I); -// CHECK-NEXT: MatchInfos = MatchInfosTy(); -// CHECK-EMPTY: // CHECK-NEXT: if (executeMatchTable(*this, State, ExecInfo, B, getMatchTable(), *ST.getInstrInfo(), MRI, *MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures, /*CoverageInfo*/ nullptr)) // CHECK-NEXT: return true; // CHECK-NEXT: } @@ -107,43 +98,52 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // Check apply // CHECK: enum { -// CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner0 = GICXXCustomAction_Invalid + 1, -// CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner1, -// CHECK-NEXT: GICXXCustomAction_CombineApplyGICombiner2, +// CHECK-NEXT: GICXXCustomAction_GICombiner0 = GICXXCustomAction_Invalid + 1, +// CHECK-NEXT: GICXXCustomAction_GICombiner1, +// CHECK-NEXT: GICXXCustomAction_GICombiner2, // CHECK-NEXT: }; -// CHECK-NEXT: void GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const { + +// CHECK: bool GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const { +// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); // CHECK-NEXT: switch(ApplyID) { -// CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner0:{ -// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); +// CHECK-NEXT: case GICXXCustomAction_GICombiner0:{ +// CHECK-NEXT: // Apply Patterns // CHECK-NEXT: APPLY -// CHECK-NEXT: return; +// CHECK-NEXT: return true; // CHECK-NEXT: } -// CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner1:{ -// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); -// CHECK-NEXT: APPLY MatchInfos.MDInfo0, MatchInfos.MDInfo1 -// CHECK-NEXT: return; +// CHECK-NEXT: case GICXXCustomAction_GICombiner1:{ +// CHECK-NEXT: Register GIMatchData_r0; +// CHECK-NEXT: Register GIMatchData_r1; +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY GIMatchData_r0, GIMatchData_r1 +// CHECK-NEXT: return true; +// CHECK-NEXT: } +// CHECK-NEXT: case GICXXCustomAction_GICombiner2:{ +// CHECK-NEXT: Register GIMatchData_r0; +// CHECK-NEXT: // Match Patterns +// CHECK-NEXT: if(![&](){return CHECK State.MIs[0]->getOperand(0), State.MIs[0]->getOperand(1), State.MIs[1]->getOperand(1), State.MIs[0]}()) { +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: // Apply Patterns +// CHECK-NEXT: APPLY +// CHECK-NEXT: return true; // CHECK-NEXT: } -// CHECK-NEXT: case GICXXCustomAction_CombineApplyGICombiner2:{ -// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]); -// CHECK-NEXT: APPLY State.MIs[1]->getOperand(1) State.MIs[0]->getOperand(1) OutMIs[0] -// CHECK-NEXT: return; // CHECK-NEXT: } -// CHECK-NEXT: } // CHECK-NEXT: llvm_unreachable("Unknown Apply Action"); // CHECK-NEXT: } // Verify match table. // CHECK: const uint8_t *GenMyCombiner::getMatchTable() const { // CHECK-NEXT: constexpr static uint8_t MatchTable0[] = { -// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(19), GIMT_Encode2({{[0-9]+}}), /*)*//*default:*//*Label 6*/ GIMT_Encode4([[L677:[0-9]+]]), -// CHECK-NEXT: /*TargetOpcode::COPY*//*Label 0*/ GIMT_Encode4([[L462:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_AND*//*Label 1*/ GIMT_Encode4([[L504:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_STORE*//*Label 2*/ GIMT_Encode4([[L557:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_TRUNC*//*Label 3*/ GIMT_Encode4([[L599:[0-9]+]]), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_SEXT*//*Label 4*/ GIMT_Encode4([[L624:[0-9]+]]), GIMT_Encode4(0), -// CHECK-NEXT: /*TargetOpcode::G_ZEXT*//*Label 5*/ GIMT_Encode4([[L637:[0-9]+]]), -// CHECK-NEXT: // Label 0: @[[L462]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4([[L491:[0-9]+]]), // Rule ID 4 // +// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2(19), GIMT_Encode2(133), /*)*//*default:*//*Label 6*/ GIMT_Encode4(653), +// CHECK-NEXT: /*TargetOpcode::COPY*//*Label 0*/ GIMT_Encode4(466), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_AND*//*Label 1*/ GIMT_Encode4(502), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_STORE*//*Label 2*/ GIMT_Encode4(549), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_TRUNC*//*Label 3*/ GIMT_Encode4(583), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_SEXT*//*Label 4*/ GIMT_Encode4(606), GIMT_Encode4(0), +// CHECK-NEXT: /*TargetOpcode::G_ZEXT*//*Label 5*/ GIMT_Encode4(618), +// CHECK-NEXT: // Label 0: @466 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4(490), // Rule ID 4 // // CHECK-NEXT: GIM_CheckFeatures, GIMT_Encode2(GIFBS_HasAnswerToEverything), // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled), // CHECK-NEXT: // MIs[0] a @@ -153,25 +153,22 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ZEXT), // CHECK-NEXT: // MIs[1] c // CHECK-NEXT: // No operand predicates -// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0), // CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/1, // CHECK-NEXT: // Combiner Rule #3: InstTest1 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 7: @[[L491]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4([[L503:[0-9]+]]), // Rule ID 3 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2), +// CHECK-NEXT: // Label 7: @490 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4(501), // Rule ID 3 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled), // CHECK-NEXT: // MIs[0] a // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // MIs[0] b // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // Combiner Rule #2: InstTest0 -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner1), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 8: @[[L503]] +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1), +// CHECK-NEXT: // Label 8: @501 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 1: @[[L504]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4([[L556:[0-9]+]]), // Rule ID 6 // +// CHECK-NEXT: // Label 1: @502 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4(548), // Rule ID 6 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule5Enabled), // CHECK-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32, // CHECK-NEXT: // MIs[0] dst @@ -188,10 +185,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // z // CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 9: @[[L556]] +// CHECK-NEXT: // Label 9: @548 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 2: @[[L557]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4([[L598:[0-9]+]]), // Rule ID 5 // +// CHECK-NEXT: // Label 2: @549 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4(582), // Rule ID 5 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule4Enabled), // CHECK-NEXT: // MIs[0] tmp // CHECK-NEXT: GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/0, // MIs[1] @@ -206,40 +203,36 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // ext // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // ptr // CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*NumInsns*/2, /*MergeInsnID's*/0, 1, -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner2), // CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 10: @[[L598]] +// CHECK-NEXT: // Label 10: @582 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 3: @[[L599]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 11*/ GIMT_Encode4([[L611:[0-9]+]]), // Rule ID 0 // +// CHECK-NEXT: // Label 3: @583 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 11*/ GIMT_Encode4(594), // Rule ID 0 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled), // CHECK-NEXT: // Combiner Rule #0: WipOpcodeTest0; wip_match_opcode 'G_TRUNC' -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 11: @[[L611]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 12*/ GIMT_Encode4([[L623:[0-9]+]]), // Rule ID 1 // +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 11: @594 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 12*/ GIMT_Encode4(605), // Rule ID 1 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled), // CHECK-NEXT: // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_TRUNC' -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 12: @[[L623]] +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 12: @605 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 4: @[[L624]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4([[L636:[0-9]+]]), // Rule ID 2 // +// CHECK-NEXT: // Label 4: @606 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4(617), // Rule ID 2 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled), // CHECK-NEXT: // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_SEXT' -// CHECK-NEXT: GIR_CustomAction, GIMT_Encode2(GICXXCustomAction_CombineApplyGICombiner0), -// CHECK-NEXT: GIR_Done, -// CHECK-NEXT: // Label 13: @[[L636]] +// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0), +// CHECK-NEXT: // Label 13: @617 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 5: @[[L637]] -// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 14*/ GIMT_Encode4([[L676:[0-9]+]]), // Rule ID 7 // +// CHECK-NEXT: // Label 5: @618 +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 14*/ GIMT_Encode4(652), // Rule ID 7 // // CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule6Enabled), // CHECK-NEXT: // MIs[0] dst // CHECK-NEXT: // No operand predicates // CHECK-NEXT: // MIs[0] cst // CHECK-NEXT: // No operand predicates -// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner1), +// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0), // CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32, // CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0), // CHECK-NEXT: // Combiner Rule #6: PatFragTest0 @ [__PatFragTest0_match_1[0]] @@ -247,10 +240,10 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ // CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst // CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0, // CHECK-NEXT: GIR_EraseRootFromParent_Done, -// CHECK-NEXT: // Label 14: @[[L676]] +// CHECK-NEXT: // Label 14: @652 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: // Label 6: @[[L677]] +// CHECK-NEXT: // Label 6: @653 // CHECK-NEXT: GIM_Reject, -// CHECK-NEXT: }; // Size: {{[0-9]+}} bytes +// CHECK-NEXT: }; // Size: 654 bytes // CHECK-NEXT: return MatchTable0; // CHECK-NEXT: } diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/patfrag-errors.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/patfrag-errors.td index 6f5c2b93609f4..8a3c501a1b4e6 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/patfrag-errors.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/patfrag-errors.td @@ -28,7 +28,7 @@ def too_many_perms : GICombineRule< (MatchFooPerms $cst, (i32 0)):$b, (MatchFooPerms $cst, (i32 0)):$c ), - (apply (COPY $dst, (i32 0)), "APPLY ${src}")>; + (apply (COPY $dst, (i32 0)))>; def DummyCXXPF: GICombinePatFrag< (outs), diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-errors.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-errors.td index 4b214d2ca89ed..5017672f5cbd7 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-errors.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-errors.td @@ -270,6 +270,19 @@ def badflagref_in_apply : GICombineRule< (match (G_ZEXT $dst, $src):$mi), (apply (G_MUL $dst, $src, $src, (MIFlags $impostor)))>; +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: 'apply' patterns cannot mix C++ code with other types of patterns +def mixed_cxx_apply : GICombineRule< + (defs root:$dst), + (match (G_ZEXT $dst, $src):$mi), + (apply (G_MUL $dst, $src, $src), "APPLY")>; + +// CHECK: :[[@LINE+2]]:{{[0-9]+}}: error: GIDefMatchData can only be used if 'apply' in entirely written in C++ +def dummy_md : GIDefMatchData<"unsigned">; +def matchdata_without_cxx_apply : GICombineRule< + (defs root:$dst, dummy_md:$md), + (match (G_ZEXT $dst, $src):$mi), + (apply (G_MUL $dst, $src, $src))>; + // CHECK: error: Failed to parse one or more rules def MyCombiner: GICombiner<"GenMyCombiner", [ @@ -311,5 +324,7 @@ def MyCombiner: GICombiner<"GenMyCombiner", [ miflags_in_builtin, miflags_in_intrin, using_flagref_in_match, - badflagref_in_apply + badflagref_in_apply, + mixed_cxx_apply, + matchdata_without_cxx_apply ]>; diff --git a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td index c261ec4575453..85075359df737 100644 --- a/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td +++ b/llvm/test/TableGen/GlobalISelCombinerEmitter/pattern-parsing.td @@ -65,7 +65,7 @@ def InstTest0 : GICombineRule< // CHECK: (CombineRule name:InstTest1 id:3 root:d // CHECK-NEXT: (MatchDatas -// CHECK-NEXT: (MatchDataInfo pattern_symbol:r0 type:'Register' var_name:MDInfo0) +// CHECK-NEXT: (MatchDataDef symbol:r0 type:Register) // CHECK-NEXT: ) // CHECK-NEXT: (MatchPats // CHECK-NEXT: d:(CodeGenInstructionPattern COPY operands:[$a, i32:$b]) @@ -90,7 +90,7 @@ def InstTest1 : GICombineRule< // CHECK: (CombineRule name:InstTest2 id:4 root:d // CHECK-NEXT: (MatchDatas -// CHECK-NEXT: (MatchDataInfo pattern_symbol:r0 type:'Register' var_name:MDInfo0) +// CHECK-NEXT: (MatchDataDef symbol:r0 type:Register) // CHECK-NEXT: ) // CHECK-NEXT: (MatchPats // CHECK-NEXT: __InstTest2_match_0:(CodeGenInstructionPattern COPY operands:[$d, (i32 0):$x]) @@ -116,7 +116,6 @@ def InstTest2 : GICombineRule< // CHECK-NEXT: ) // CHECK-NEXT: (ApplyPats // CHECK-NEXT: __InOutInstTest0_apply_0:(CodeGenInstructionPattern G_TRUNC operands:[$dst, $src]) -// CHECK-NEXT: __InOutInstTest0_apply_1:(CXXPattern apply code:"APPLY ${src}") // CHECK-NEXT: ) // CHECK-NEXT: (OperandTable MatchPats // CHECK-NEXT: dst -> __InOutInstTest0_match_0 @@ -132,7 +131,7 @@ def InOutInstTest0 : GICombineRule< (defs root:$dst), (match (COPY $dst, $tmp), (G_ZEXT $tmp, $src)), - (apply (G_TRUNC $dst, $src), "APPLY ${src}")>; + (apply (G_TRUNC $dst, $src))>; def MatchICst: GICombinePatFrag< (outs), @@ -156,7 +155,6 @@ def MatchICst: GICombinePatFrag< // CHECK-NEXT: ) // CHECK-NEXT: (ApplyPats // CHECK-NEXT: __PatFragTest0_apply_0:(CodeGenInstructionPattern COPY operands:[$dst, (i32 0)]) -// CHECK-NEXT: __PatFragTest0_apply_1:(CXXPattern apply code:"APPLY ${src}") // CHECK-NEXT: ) // CHECK-NEXT: (OperandTable MatchPats // CHECK-NEXT: cst -> @@ -169,7 +167,7 @@ def MatchICst: GICombinePatFrag< def PatFragTest0 : GICombineRule< (defs root:$dst), (match (G_ZEXT $dst, $cst), (MatchICst $cst, (i32 0))), - (apply (COPY $dst, (i32 0)), "APPLY ${src}")>; + (apply (COPY $dst, (i32 0)))>; def MatchFooPerms: GICombinePatFrag< (outs), @@ -205,7 +203,6 @@ def MatchFooPerms: GICombinePatFrag< // CHECK-NEXT: ) // CHECK-NEXT: (ApplyPats // CHECK-NEXT: __PatFragTest1_apply_0:(CodeGenInstructionPattern COPY operands:[$dst, (i32 0)]) -// CHECK-NEXT: __PatFragTest1_apply_1:(CXXPattern apply code:"APPLY ${src}") // CHECK-NEXT: ) // CHECK-NEXT: (OperandTable MatchPats // CHECK-NEXT: cst -> @@ -252,7 +249,7 @@ def PatFragTest1 : GICombineRule< (MatchFooPerms $cst, (i32 0)):$b, (MatchFooPerms $cst, (i32 0)):$c ), - (apply (COPY $dst, (i32 0)), "APPLY ${src}")>; + (apply (COPY $dst, (i32 0)))>; // CHECK: (CombineRule name:VariadicsInTest id:8 root:dst // CHECK-NEXT: (MatchPats diff --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td index 23b3d6f59b381..5d5bf92664a79 100644 --- a/llvm/test/TableGen/GlobalISelEmitter.td +++ b/llvm/test/TableGen/GlobalISelEmitter.td @@ -83,7 +83,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } // CHECK-NEXT: const uint8_t *getMatchTable() const override; // CHECK-NEXT: bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override; // CHECK-NEXT: bool testSimplePredicate(unsigned PredicateID) const override; -// CHECK-NEXT: void runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override; +// CHECK-NEXT: bool runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override; // CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL // CHECK-LABEL: #ifdef GET_GLOBALISEL_TEMPORARIES_INIT diff --git a/llvm/test/TableGen/GlobalISelEmitterHwModes.td b/llvm/test/TableGen/GlobalISelEmitterHwModes.td index 7c8340a154e8b..9d235f5f07a74 100644 --- a/llvm/test/TableGen/GlobalISelEmitterHwModes.td +++ b/llvm/test/TableGen/GlobalISelEmitterHwModes.td @@ -55,7 +55,7 @@ class I Pat> // CHECK-NEXT: const uint8_t *getMatchTable() const override; // CHECK-NEXT: bool testMIPredicate_MI(unsigned PredicateID, const MachineInstr &MI, const MatcherState &State) const override; // CHECK-NEXT: bool testSimplePredicate(unsigned PredicateID) const override; -// CHECK-NEXT: void runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override; +// CHECK-NEXT: bool runCustomAction(unsigned FnID, const MatcherState &State, NewMIVector &OutMIs) const override; // CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL // CHECK-LABEL: #ifdef GET_GLOBALISEL_TEMPORARIES_INIT diff --git a/llvm/utils/TableGen/Common/CMakeLists.txt b/llvm/utils/TableGen/Common/CMakeLists.txt index c31ed5a1de690..30f188ae48a2a 100644 --- a/llvm/utils/TableGen/Common/CMakeLists.txt +++ b/llvm/utils/TableGen/Common/CMakeLists.txt @@ -16,7 +16,6 @@ add_llvm_library(LLVMTableGenCommon STATIC OBJECT EXCLUDE_FROM_ALL GlobalISel/CXXPredicates.cpp GlobalISel/GlobalISelMatchTable.cpp GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp - GlobalISel/MatchDataInfo.cpp GlobalISel/PatternParser.cpp GlobalISel/Patterns.cpp diff --git a/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp index e39293ebfe7ae..cbf70278a2813 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.cpp @@ -45,7 +45,7 @@ CXXPredicateCode::CXXPredicateCode(std::string Code, unsigned ID) : Code(Code), ID(ID), BaseEnumName("GICombiner" + std::to_string(ID)) {} CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXMatchCode; -CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXApplyCode; +CXXPredicateCode::CXXPredicateCodePool CXXPredicateCode::AllCXXCustomActionCode; } // namespace gi } // namespace llvm diff --git a/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h index 01610a13110dd..01a4cb46a22a9 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h +++ b/llvm/utils/TableGen/Common/GlobalISel/CXXPredicates.h @@ -37,7 +37,7 @@ class CXXPredicateCode { using CXXPredicateCodePool = DenseMap>; static CXXPredicateCodePool AllCXXMatchCode; - static CXXPredicateCodePool AllCXXApplyCode; + static CXXPredicateCodePool AllCXXCustomActionCode; /// Sorts a `CXXPredicateCodePool` by their IDs and returns it. static std::vector @@ -55,16 +55,16 @@ class CXXPredicateCode { return get(AllCXXMatchCode, std::move(Code)); } - static const CXXPredicateCode &getApplyCode(std::string Code) { - return get(AllCXXApplyCode, std::move(Code)); + static const CXXPredicateCode &getCustomActionCode(std::string Code) { + return get(AllCXXCustomActionCode, std::move(Code)); } static std::vector getAllMatchCode() { return getSorted(AllCXXMatchCode); } - static std::vector getAllApplyCode() { - return getSorted(AllCXXApplyCode); + static std::vector getAllCustomActionsCode() { + return getSorted(AllCXXCustomActionCode); } const std::string Code; diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp index 6d03eecae672a..e011e78c67b15 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.cpp @@ -1034,32 +1034,47 @@ void RuleMatcher::emit(MatchTable &Table) { for (const auto &PM : EpilogueMatchers) PM->emitPredicateOpcodes(Table, *this); - // Emit all actions except the last one, then emit coverage and emit the - // final action. - // - // This is because some actions, such as GIR_EraseRootFromParent_Done, also - // double as a GIR_Done and terminate execution of the rule. - if (!Actions.empty()) { - for (const auto &MA : drop_end(Actions)) + if (!CustomCXXAction.empty()) { + /// Handle combiners relying on custom C++ code instead of actions. + assert(Table.isCombiner() && "CustomCXXAction is only for combiners!"); + // We cannot have actions other than debug comments. + assert(none_of(Actions, [](auto &A) { + return A->getKind() != MatchAction::AK_DebugComment; + })); + for (const auto &MA : Actions) MA->emitActionOpcodes(Table, *this); - } - - assert((Table.isWithCoverage() ? !Table.isCombiner() : true) && - "Combiner tables don't support coverage!"); - if (Table.isWithCoverage()) - Table << MatchTable::Opcode("GIR_Coverage") - << MatchTable::IntValue(4, RuleID) << MatchTable::LineBreak; - else if (!Table.isCombiner()) - Table << MatchTable::Comment(("GIR_Coverage, " + Twine(RuleID) + ",").str()) + Table << MatchTable::Opcode("GIR_DoneWithCustomAction", -1) + << MatchTable::Comment("Fn") + << MatchTable::NamedValue(2, CustomCXXAction) << MatchTable::LineBreak; + } else { + // Emit all actions except the last one, then emit coverage and emit the + // final action. + // + // This is because some actions, such as GIR_EraseRootFromParent_Done, also + // double as a GIR_Done and terminate execution of the rule. + if (!Actions.empty()) { + for (const auto &MA : drop_end(Actions)) + MA->emitActionOpcodes(Table, *this); + } + + assert((Table.isWithCoverage() ? !Table.isCombiner() : true) && + "Combiner tables don't support coverage!"); + if (Table.isWithCoverage()) + Table << MatchTable::Opcode("GIR_Coverage") + << MatchTable::IntValue(4, RuleID) << MatchTable::LineBreak; + else if (!Table.isCombiner()) + Table << MatchTable::Comment( + ("GIR_Coverage, " + Twine(RuleID) + ",").str()) + << MatchTable::LineBreak; - if (Actions.empty() || - !Actions.back()->emitActionOpcodesAndDone(Table, *this)) { - Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak; + if (Actions.empty() || + !Actions.back()->emitActionOpcodesAndDone(Table, *this)) { + Table << MatchTable::Opcode("GIR_Done", -1) << MatchTable::LineBreak; + } } Table << MatchTable::Label(LabelID); - ++NumPatternEmitted; } @@ -2108,14 +2123,6 @@ void CustomOperandRenderer::emitRenderOpcodes(MatchTable &Table, << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak; } -//===- CustomCXXAction ----------------------------------------------------===// - -void CustomCXXAction::emitActionOpcodes(MatchTable &Table, - RuleMatcher &Rule) const { - Table << MatchTable::Opcode("GIR_CustomAction") - << MatchTable::NamedValue(2, FnEnumName) << MatchTable::LineBreak; -} - //===- BuildMIAction ------------------------------------------------------===// bool BuildMIAction::canMutate(RuleMatcher &Rule, diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h index 30301c28ce6c4..5fe3f9a32c016 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTable.h @@ -473,6 +473,10 @@ class RuleMatcher : public Matcher { /// have succeeded. ActionList Actions; + /// Combiners can sometimes just run C++ code to finish matching a rule & + /// mutate instructions instead of relying on MatchActions. Empty if unused. + std::string CustomCXXAction; + using DefinedInsnVariablesMap = std::map; /// A map of instruction matchers to the local variables @@ -563,6 +567,10 @@ class RuleMatcher : public Matcher { /// should NOT be emitted. bool tryEraseInsnID(unsigned ID) { return ErasedInsnIDs.insert(ID).second; } + void setCustomCXXAction(StringRef FnEnumName) { + CustomCXXAction = FnEnumName.str(); + } + // Emplaces an action of the specified Kind at the end of the action list. // // Returns a reference to the newly created action. @@ -2206,7 +2214,6 @@ class MatchAction { public: enum ActionKind { AK_DebugComment, - AK_CustomCXX, AK_BuildMI, AK_BuildConstantMI, AK_EraseInst, @@ -2261,20 +2268,6 @@ class DebugCommentAction : public MatchAction { } }; -class CustomCXXAction : public MatchAction { - std::string FnEnumName; - -public: - CustomCXXAction(StringRef FnEnumName) - : MatchAction(AK_CustomCXX), FnEnumName(FnEnumName.str()) {} - - static bool classof(const MatchAction *A) { - return A->getKind() == AK_CustomCXX; - } - - void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override; -}; - /// Generates code to build an instruction or mutate an existing instruction /// into the desired instruction when this is possible. class BuildMIAction : public MatchAction { diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp index 5697899a915a0..331da97a6f7c6 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.cpp @@ -236,11 +236,10 @@ void GlobalISelMatchTableExecutorEmitter::emitTemporariesDecl( ", const MatcherState &State) " "const override;\n" << " bool testSimplePredicate(unsigned PredicateID) const override;\n" - << " void runCustomAction(unsigned FnID, const MatcherState &State, " + << " bool runCustomAction(unsigned FnID, const MatcherState &State, " "NewMIVector &OutMIs) " - "const override;\n"; - emitAdditionalTemporariesDecl(OS, " "); - OS << "#endif // ifdef " << IfDefName << "\n\n"; + "const override;\n" + << "#endif // ifdef " << IfDefName << "\n\n"; } void GlobalISelMatchTableExecutorEmitter::emitTemporariesInit( diff --git a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h index d2b6a74c75771..13dcfc0e55e1e 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h +++ b/llvm/utils/TableGen/Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h @@ -182,10 +182,6 @@ class GlobalISelMatchTableExecutorEmitter { /// Emit additional content in emitExecutorImpl virtual void emitAdditionalImpl(raw_ostream &OS) {} - /// Emit additional content in emitTemporariesDecl. - virtual void emitAdditionalTemporariesDecl(raw_ostream &OS, - StringRef Indent) {} - /// Emit additional content in emitTemporariesInit. virtual void emitAdditionalTemporariesInit(raw_ostream &OS) {} diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.cpp b/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.cpp deleted file mode 100644 index b5c9e4f8c2485..0000000000000 --- a/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.cpp +++ /dev/null @@ -1,49 +0,0 @@ -//===- MatchDataInfo.cpp ----------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// -//===----------------------------------------------------------------------===// - -#include "MatchDataInfo.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" - -namespace llvm { -namespace gi { - -StringMap> AllMatchDataVars; - -StringRef MatchDataInfo::getVariableName() const { - assert(hasVariableName()); - return VarName; -} - -void MatchDataInfo::print(raw_ostream &OS) const { - OS << "(MatchDataInfo pattern_symbol:" << PatternSymbol << " type:'" << Type - << "' var_name:" << (VarName.empty() ? "" : VarName) << ")"; -} - -void MatchDataInfo::dump() const { print(dbgs()); } - -void AssignMatchDataVariables(MutableArrayRef Infos) { - static unsigned NextVarID = 0; - - StringMap SeenTypes; - for (auto &Info : Infos) { - unsigned &NumSeen = SeenTypes[Info.getType()]; - auto &ExistingVars = AllMatchDataVars[Info.getType()]; - - if (NumSeen == ExistingVars.size()) - ExistingVars.push_back("MDInfo" + std::to_string(NextVarID++)); - - Info.setVariableName(ExistingVars[NumSeen++]); - } -} - -} // namespace gi -} // namespace llvm diff --git a/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.h b/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.h deleted file mode 100644 index abe1245bc67d0..0000000000000 --- a/llvm/utils/TableGen/Common/GlobalISel/MatchDataInfo.h +++ /dev/null @@ -1,90 +0,0 @@ -//===- MatchDataInfo.h ------------------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -/// \file Contains utilities related to handling "match data" for GlobalISel -/// Combiners. Match data allows for setting some arbitrary data in the "match" -/// phase and pass it down to the "apply" phase. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_UTILS_MIRPATTERNS_MATCHDATAINFO_H -#define LLVM_UTILS_MIRPATTERNS_MATCHDATAINFO_H - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringMap.h" -#include "llvm/ADT/StringRef.h" -#include -#include - -namespace llvm { - -class raw_ostream; - -namespace gi { - -/// Represents MatchData defined by the match stage and required by the apply -/// stage. -/// -/// This allows the plumbing of arbitrary data from C++ predicates between the -/// stages. -/// -/// When this class is initially created, it only has a pattern symbol and a -/// type. When all of the MatchDatas declarations of a given pattern have been -/// parsed, `AssignVariables` must be called to assign storage variable names to -/// each MatchDataInfo. -class MatchDataInfo { - StringRef PatternSymbol; - StringRef Type; - std::string VarName; - -public: - static constexpr StringLiteral StructTypeName = "MatchInfosTy"; - static constexpr StringLiteral StructName = "MatchInfos"; - - MatchDataInfo(StringRef PatternSymbol, StringRef Type) - : PatternSymbol(PatternSymbol), Type(Type.trim()) {} - - StringRef getPatternSymbol() const { return PatternSymbol; }; - StringRef getType() const { return Type; }; - - bool hasVariableName() const { return !VarName.empty(); } - void setVariableName(StringRef Name) { VarName = Name; } - StringRef getVariableName() const; - - std::string getQualifiedVariableName() const { - return StructName.str() + "." + getVariableName().str(); - } - - void print(raw_ostream &OS) const; - void dump() const; -}; - -/// Pool of type -> variables used to emit MatchData variables declarations. -/// -/// e.g. if the map contains "int64_t" -> ["MD0", "MD1"], then two variable -/// declarations must be emitted: `int64_t MD0` and `int64_t MD1`. -/// -/// This has a static lifetime and will outlive all the `MatchDataInfo` objects -/// by design. It needs a static lifetime so the backends can emit variable -/// declarations after processing all the inputs. -extern StringMap> AllMatchDataVars; - -/// Assign variable names to all MatchDatas used by a pattern. This must be -/// called after all MatchData decls have been parsed for a given processing -/// unit (e.g. a combine rule) -/// -/// Requires an array of MatchDataInfo so we can handle cases where a pattern -/// uses multiple instances of the same MatchData type. -/// -/// Writes to \ref AllMatchDataVars. -void AssignMatchDataVariables(MutableArrayRef Infos); - -} // namespace gi -} // end namespace llvm - -#endif // ifndef LLVM_UTILS_MIRPATTERNS_MATCHDATAINFO_H diff --git a/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp b/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp index 388bf7e9e8334..28a9bcc2568c3 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp +++ b/llvm/utils/TableGen/Common/GlobalISel/Patterns.cpp @@ -145,6 +145,8 @@ CXXPattern::CXXPattern(const StringInit &Code, StringRef Name) const CXXPredicateCode & CXXPattern::expandCode(const CodeExpansions &CE, ArrayRef Locs, function_ref AddComment) const { + assert(!IsApply && "'apply' CXX patterns should be handled differently!"); + std::string Result; raw_string_ostream OS(Result); @@ -153,8 +155,6 @@ CXXPattern::expandCode(const CodeExpansions &CE, ArrayRef Locs, CodeExpander Expander(RawCode, CE, Locs, /*ShowExpansions*/ false); Expander.emit(OS); - if (IsApply) - return CXXPredicateCode::getApplyCode(std::move(Result)); return CXXPredicateCode::getMatchCode(std::move(Result)); } diff --git a/llvm/utils/TableGen/Common/GlobalISel/Patterns.h b/llvm/utils/TableGen/Common/GlobalISel/Patterns.h index dac092556548d..76d018bdbd71c 100644 --- a/llvm/utils/TableGen/Common/GlobalISel/Patterns.h +++ b/llvm/utils/TableGen/Common/GlobalISel/Patterns.h @@ -205,6 +205,10 @@ class CXXPattern : public Pattern { /// Expands raw code, replacing things such as `${foo}` with their /// substitution in \p CE. /// + /// Can only be used on 'match' CXX Patterns. 'apply' CXX pattern emission + /// is handled differently as we emit both the 'match' and 'apply' part + /// together in a single Custom CXX Action. + /// /// \param CE Map of Code Expansions /// \param Locs SMLocs for the Code Expander, in case it needs to emit /// diagnostics. diff --git a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp index ef9e9ff04f85f..085841ed963e4 100644 --- a/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelCombinerEmitter.cpp @@ -35,7 +35,6 @@ #include "Common/GlobalISel/CombinerUtils.h" #include "Common/GlobalISel/GlobalISelMatchTable.h" #include "Common/GlobalISel/GlobalISelMatchTableExecutorEmitter.h" -#include "Common/GlobalISel/MatchDataInfo.h" #include "Common/GlobalISel/PatternParser.h" #include "Common/GlobalISel/Patterns.h" #include "Common/SubtargetFeatureInfo.h" @@ -45,6 +44,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SetVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -79,8 +79,9 @@ cl::opt DebugTypeInfer("gicombiner-debug-typeinfer", cl::desc("Print type inference debug logs"), cl::cat(GICombinerEmitterCat)); -constexpr StringLiteral CXXApplyPrefix = "GICXXCustomAction_CombineApply"; +constexpr StringLiteral CXXCustomActionPrefix = "GICXXCustomAction_"; constexpr StringLiteral CXXPredPrefix = "GICXXPred_MI_Predicate_"; +constexpr StringLiteral MatchDataClassName = "GIDefMatchData"; //===- CodeExpansions Helpers --------------------------------------------===// @@ -605,6 +606,21 @@ CombineRuleOperandTypeChecker::getRuleEqClasses() const { return TECs; } +//===- MatchData Handling -------------------------------------------------===// +struct MatchDataDef { + MatchDataDef(StringRef Symbol, StringRef Type) : Symbol(Symbol), Type(Type) {} + + StringRef Symbol; + StringRef Type; + + /// \returns the desired variable name for this MatchData. + std::string getVarName() const { + // Add a prefix in case the symbol name is very generic and conflicts with + // something else. + return "GIMatchData_" + Symbol.str(); + } +}; + //===- CombineRuleBuilder -------------------------------------------------===// /// Parses combine rule and builds a small intermediate representation to tie @@ -671,10 +687,6 @@ class CombineRuleBuilder { void addCXXPredicate(RuleMatcher &M, const CodeExpansions &CE, const CXXPattern &P, const PatternAlternatives &Alts); - /// Adds an apply \p P to \p IM, expanding its code using \p CE. - void addCXXAction(RuleMatcher &M, const CodeExpansions &CE, - const CXXPattern &P); - bool hasOnlyCXXApplyPatterns() const; bool hasEraseRoot() const; @@ -721,6 +733,8 @@ class CombineRuleBuilder { DenseSet &SeenPats); bool emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M); + bool emitCXXMatchApply(CodeExpansions &CE, RuleMatcher &M, + ArrayRef Matchers); // Recursively visits InstructionPatterns from P to build up the // RuleMatcher actions. @@ -777,7 +791,7 @@ class CombineRuleBuilder { Pattern *MatchRoot = nullptr; SmallDenseSet ApplyRoots; - SmallVector MatchDatas; + SmallVector MatchDatas; SmallVector PermutationsToEmit; }; @@ -811,7 +825,6 @@ bool CombineRuleBuilder::emitRuleMatchers() { assert(MatchRoot); CodeExpansions CE; - declareAllMatchDatasExpansions(CE); assert(!PermutationsToEmit.empty()); for (const auto &Alts : PermutationsToEmit) { @@ -845,9 +858,8 @@ void CombineRuleBuilder::print(raw_ostream &OS) const { if (!MatchDatas.empty()) { OS << " (MatchDatas\n"; for (const auto &MD : MatchDatas) { - OS << " "; - MD.print(OS); - OS << '\n'; + OS << " (MatchDataDef symbol:" << MD.Symbol << " type:" << MD.Type + << ")\n"; } OS << " )\n"; } @@ -1008,7 +1020,7 @@ bool CombineRuleBuilder::addMatchPattern(std::unique_ptr Pat) { void CombineRuleBuilder::declareAllMatchDatasExpansions( CodeExpansions &CE) const { for (const auto &MD : MatchDatas) - CE.declare(MD.getPatternSymbol(), MD.getQualifiedVariableName()); + CE.declare(MD.Symbol, MD.getVarName()); } void CombineRuleBuilder::addCXXPredicate(RuleMatcher &M, @@ -1030,13 +1042,6 @@ void CombineRuleBuilder::addCXXPredicate(RuleMatcher &M, ExpandedCode.getEnumNameWithPrefix(CXXPredPrefix)); } -void CombineRuleBuilder::addCXXAction(RuleMatcher &M, const CodeExpansions &CE, - const CXXPattern &P) { - const auto &ExpandedCode = P.expandCode(CE, RuleDef.getLoc()); - M.addAction( - ExpandedCode.getEnumNameWithPrefix(CXXApplyPrefix)); -} - bool CombineRuleBuilder::hasOnlyCXXApplyPatterns() const { return all_of(ApplyPats, [&](auto &Entry) { return isa(Entry.second.get()); @@ -1175,9 +1180,20 @@ bool CombineRuleBuilder::checkSemantics() { UsesWipMatchOpcode = true; } + std::optional IsUsingCXXPatterns; for (const auto &Apply : ApplyPats) { - assert(Apply.second.get()); - const auto *IP = dyn_cast(Apply.second.get()); + Pattern *Pat = Apply.second.get(); + if (IsUsingCXXPatterns) { + if (*IsUsingCXXPatterns != isa(Pat)) { + PrintError("'apply' patterns cannot mix C++ code with other types of " + "patterns"); + return false; + } + } else + IsUsingCXXPatterns = isa(Pat); + + assert(Pat); + const auto *IP = dyn_cast(Pat); if (!IP) continue; @@ -1260,6 +1276,12 @@ bool CombineRuleBuilder::checkSemantics() { } } + if (!hasOnlyCXXApplyPatterns() && !MatchDatas.empty()) { + PrintError(MatchDataClassName + + " can only be used if 'apply' in entirely written in C++"); + return false; + } + return true; } @@ -1440,7 +1462,7 @@ bool CombineRuleBuilder::parseDefs(const DagInit &Def) { // data from the match stage to the apply stage, and ensure that the // generated matcher has a suitable variable for it to do so. if (Record *MatchDataRec = - getDefOfSubClass(*Def.getArg(I), "GIDefMatchData")) { + getDefOfSubClass(*Def.getArg(I), MatchDataClassName)) { MatchDatas.emplace_back(Def.getArgNameStr(I), MatchDataRec->getValueAsString("Type")); continue; @@ -1463,9 +1485,6 @@ bool CombineRuleBuilder::parseDefs(const DagInit &Def) { } RootName = Roots.front(); - - // Assign variables to all MatchDatas. - AssignMatchDataVariables(MatchDatas); return true; } @@ -1502,6 +1521,8 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, llvm_unreachable("Unknown kind of InstructionPattern!"); // Emit remaining patterns + const bool IsUsingCustomCXXAction = hasOnlyCXXApplyPatterns(); + SmallVector CXXMatchers; for (auto &Pat : values(MatchPats)) { if (SeenPats.contains(Pat.get())) continue; @@ -1523,7 +1544,11 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, cast(Pat.get())->reportUnreachable(RuleDef.getLoc()); return false; case Pattern::K_CXX: { - addCXXPredicate(M, CE, *cast(Pat.get()), Alts); + // Delay emission for top-level C++ matchers (which can use MatchDatas). + if (IsUsingCustomCXXAction) + CXXMatchers.push_back(cast(Pat.get())); + else + addCXXPredicate(M, CE, *cast(Pat.get()), Alts); continue; } default: @@ -1531,7 +1556,8 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, } } - return emitApplyPatterns(CE, M); + return IsUsingCustomCXXAction ? emitCXXMatchApply(CE, M, CXXMatchers) + : emitApplyPatterns(CE, M); } bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, @@ -1539,6 +1565,7 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, const AnyOpcodePattern &AOP) { auto StackTrace = PrettyStackTraceEmit(RuleDef, &AOP); + const bool IsUsingCustomCXXAction = hasOnlyCXXApplyPatterns(); for (const CodeGenInstruction *CGI : AOP.insts()) { auto &M = addRuleMatcher(Alts, "wip_match_opcode '" + CGI->TheDef->getName() + "'"); @@ -1552,6 +1579,7 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, IM.addPredicate(CGI); // Emit remaining patterns. + SmallVector CXXMatchers; for (auto &Pat : values(MatchPats)) { if (Pat.get() == &AOP) continue; @@ -1576,7 +1604,11 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, RuleDef.getLoc()); return false; case Pattern::K_CXX: { - addCXXPredicate(M, CE, *cast(Pat.get()), Alts); + // Delay emission for top-level C++ matchers (which can use MatchDatas). + if (IsUsingCustomCXXAction) + CXXMatchers.push_back(cast(Pat.get())); + else + addCXXPredicate(M, CE, *cast(Pat.get()), Alts); break; } default: @@ -1584,7 +1616,10 @@ bool CombineRuleBuilder::emitMatchPattern(CodeExpansions &CE, } } - if (!emitApplyPatterns(CE, M)) + const bool Res = IsUsingCustomCXXAction + ? emitCXXMatchApply(CE, M, CXXMatchers) + : emitApplyPatterns(CE, M); + if (!Res) return false; } @@ -1727,11 +1762,7 @@ bool CombineRuleBuilder::emitPatFragMatchPattern( } bool CombineRuleBuilder::emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M) { - if (hasOnlyCXXApplyPatterns()) { - for (auto &Pat : values(ApplyPats)) - addCXXAction(M, CE, *cast(Pat.get())); - return true; - } + assert(MatchDatas.empty()); DenseSet SeenPats; StringMap OperandToTempRegID; @@ -1764,8 +1795,8 @@ bool CombineRuleBuilder::emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M) { cast(*Pat).reportUnreachable(RuleDef.getLoc()); return false; case Pattern::K_CXX: { - addCXXAction(M, CE, *cast(Pat.get())); - continue; + llvm_unreachable( + "CXX Pattern Emission should have been handled earlier!"); } default: llvm_unreachable("unknown pattern kind!"); @@ -1780,6 +1811,44 @@ bool CombineRuleBuilder::emitApplyPatterns(CodeExpansions &CE, RuleMatcher &M) { return true; } +bool CombineRuleBuilder::emitCXXMatchApply(CodeExpansions &CE, RuleMatcher &M, + ArrayRef Matchers) { + assert(hasOnlyCXXApplyPatterns()); + declareAllMatchDatasExpansions(CE); + + std::string CodeStr; + raw_string_ostream OS(CodeStr); + + for (auto &MD : MatchDatas) + OS << MD.Type << " " << MD.getVarName() << ";\n"; + + if (!Matchers.empty()) { + OS << "// Match Patterns\n"; + for (auto *M : Matchers) { + OS << "if(![&](){"; + CodeExpander Expander(M->getRawCode(), CE, RuleDef.getLoc(), + /*ShowExpansions=*/false); + Expander.emit(OS); + OS << "}()) {\n" + << " return false;\n}\n"; + } + } + + OS << "// Apply Patterns\n"; + ListSeparator LS("\n"); + for (auto &Pat : ApplyPats) { + auto *CXXPat = cast(Pat.second.get()); + CodeExpander Expander(CXXPat->getRawCode(), CE, RuleDef.getLoc(), + /*ShowExpansions=*/ false); + OS << LS; + Expander.emit(OS); + } + + const auto &Code = CXXPredicateCode::getCustomActionCode(CodeStr); + M.setCustomCXXAction(Code.getEnumNameWithPrefix(CXXCustomActionPrefix)); + return true; +} + bool CombineRuleBuilder::emitInstructionApplyPattern( CodeExpansions &CE, RuleMatcher &M, const InstructionPattern &P, DenseSet &SeenPats, @@ -2226,9 +2295,6 @@ class GICombinerEmitter final : public GlobalISelMatchTableExecutorEmitter { void emitTestSimplePredicate(raw_ostream &OS) override; void emitRunCustomAction(raw_ostream &OS) override; - void emitAdditionalTemporariesDecl(raw_ostream &OS, - StringRef Indent) override; - const CodeGenTarget &getTarget() const override { return Target; } StringRef getClassName() const override { return Combiner->getValueAsString("Classname"); @@ -2371,8 +2437,6 @@ void GICombinerEmitter::emitAdditionalImpl(raw_ostream &OS) { << " B.setInstrAndDebugLoc(I);\n" << " State.MIs.clear();\n" << " State.MIs.push_back(&I);\n" - << " " << MatchDataInfo::StructName << " = " - << MatchDataInfo::StructTypeName << "();\n\n" << " if (executeMatchTable(*this, State, ExecInfo, B" << ", getMatchTable(), *ST.getInstrInfo(), MRI, " "*MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures" @@ -2438,50 +2502,38 @@ void GICombinerEmitter::emitTestSimplePredicate(raw_ostream &OS) { } void GICombinerEmitter::emitRunCustomAction(raw_ostream &OS) { - const auto ApplyCode = CXXPredicateCode::getAllApplyCode(); + const auto CustomActionsCode = CXXPredicateCode::getAllCustomActionsCode(); - if (!ApplyCode.empty()) { + if (!CustomActionsCode.empty()) { OS << "enum {\n"; std::string EnumeratorSeparator = " = GICXXCustomAction_Invalid + 1,\n"; - for (const auto &Apply : ApplyCode) { - OS << " " << Apply->getEnumNameWithPrefix(CXXApplyPrefix) + for (const auto &CA : CustomActionsCode) { + OS << " " << CA->getEnumNameWithPrefix(CXXCustomActionPrefix) << EnumeratorSeparator; EnumeratorSeparator = ",\n"; } OS << "};\n"; } - OS << "void " << getClassName() + OS << "bool " << getClassName() << "::runCustomAction(unsigned ApplyID, const MatcherState &State, " "NewMIVector &OutMIs) const " - "{\n"; - if (!ApplyCode.empty()) { + "{\n Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]);\n"; + if (!CustomActionsCode.empty()) { OS << " switch(ApplyID) {\n"; - for (const auto &Apply : ApplyCode) { - OS << " case " << Apply->getEnumNameWithPrefix(CXXApplyPrefix) << ":{\n" - << " Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]);\n" - << " " << join(split(Apply->Code, '\n'), "\n ") << '\n' - << " return;\n"; + for (const auto &CA : CustomActionsCode) { + OS << " case " << CA->getEnumNameWithPrefix(CXXCustomActionPrefix) + << ":{\n" + << " " << join(split(CA->Code, '\n'), "\n ") << '\n' + << " return true;\n"; OS << " }\n"; } - OS << "}\n"; + OS << " }\n"; } OS << " llvm_unreachable(\"Unknown Apply Action\");\n" << "}\n"; } -void GICombinerEmitter::emitAdditionalTemporariesDecl(raw_ostream &OS, - StringRef Indent) { - OS << Indent << "struct " << MatchDataInfo::StructTypeName << " {\n"; - for (const auto &[Type, VarNames] : AllMatchDataVars) { - assert(!VarNames.empty() && "Cannot have no vars for this type!"); - OS << Indent << " " << Type << " " << join(VarNames, ", ") << ";\n"; - } - OS << Indent << "};\n" - << Indent << "mutable " << MatchDataInfo::StructTypeName << " " - << MatchDataInfo::StructName << ";\n\n"; -} - GICombinerEmitter::GICombinerEmitter(RecordKeeper &RK, const CodeGenTarget &Target, StringRef Name, Record *Combiner) diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index cf7e4398741ca..9b356148cc171 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -2353,7 +2353,7 @@ void GlobalISelEmitter::emitTestSimplePredicate(raw_ostream &OS) { } void GlobalISelEmitter::emitRunCustomAction(raw_ostream &OS) { - OS << "void " << getClassName() + OS << "bool " << getClassName() << "::runCustomAction(unsigned, const MatcherState&, NewMIVector &) const " "{\n" << " llvm_unreachable(\"" + getClassName() +