254 lines · plain
1// RUN: llvm-tblgen -I %p/../../../include -gen-global-isel-combiner \2// RUN: -combiners=MyCombiner %s | \3// RUN: FileCheck %s4 5include "llvm/Target/Target.td"6include "llvm/Target/GlobalISel/Combine.td"7 8def MyTargetISA : InstrInfo;9def MyTarget : Target { let InstructionSet = MyTargetISA; }10 11def dummy;12 13def HasAnswerToEverything : Predicate<"Subtarget->getAnswerToUniverse() == 42 && Subtarget->getAnswerToLife() == 42">;14 15def WipOpcodeTest0 : GICombineRule<16 (defs root:$d),17 (match (wip_match_opcode G_TRUNC):$d),18 (apply [{ APPLY }])>;19 20def WipOpcodeTest1 : GICombineRule<21 (defs root:$d),22 (match (wip_match_opcode G_TRUNC, G_SEXT):$d),23 (apply [{ APPLY }])>;24 25// Note: also checks that spaces in the type name are removed.26def reg_matchinfo : GIDefMatchData<"Register ">;27def InstTest0 : GICombineRule<28 (defs root:$d, reg_matchinfo:$r0, reg_matchinfo:$r1),29 (match (COPY $a, $b):$d),30 (apply [{ APPLY ${r0}, ${r1} }])>;31 32let Predicates = [HasAnswerToEverything] in33def InstTest1 : GICombineRule<34 (defs root:$d, reg_matchinfo:$r0),35 (match (COPY $a, $b):$d,36 (G_ZEXT $b, $c),37 [{ return CHECK ${a}, ${b}, ${c}, ${d} }]),38 (apply [{ APPLY }])>;39 40def InOutInstTest0 : GICombineRule<41 (defs root:$root),42 (match (G_ZEXT $tmp, $ext),43 (G_STORE $tmp, $ptr):$root),44 (apply (G_STORE $ext, $ptr):$root)>;45 46// Imm operand of G_CONSTANT should match a literal int, while the second47// should match a constant.48def InOutInstTest1 : GICombineRule<49 (defs root:$dst),50 (match51 (G_CONSTANT $x, -42:$z),52 (G_AND $dst, $x, (i32 43))),53 (apply (G_TRUNC $dst, $z))>;54 55def MatchICst: GICombinePatFrag<56 (outs),57 (ins gi_mo:$foo, gi_imm:$cst),58 [(pattern "return matchIConstant(${foo}, ${cst});")]>;59 60def PatFragTest0 : GICombineRule<61 (defs root:$dst),62 (match (G_ZEXT $dst, $cst), (MatchICst $cst, (i32 0))),63 (apply (COPY $dst, (i32 0)))>;64 65// TODO: add test with temp reg use66 67def MyCombiner: GICombiner<"GenMyCombiner", [68 WipOpcodeTest0,69 WipOpcodeTest1,70 InstTest0,71 InstTest1,72 InOutInstTest0,73 InOutInstTest1,74 PatFragTest075]>;76 77// We have at most 2 registers used by one rule at a time, so we should only have 2 registers MDInfos.78 79// Check predicates80// CHECK: switch (PredicateID) {81// CHECK-NEXT: case GICXXPred_MI_Predicate_GICombiner0: {82// CHECK-NEXT: return matchIConstant(State.MIs[0]->getOperand(1), 0);83// CHECK-NEXT: }84 85// Verify we reset MatchData on each tryCombineAll86// CHECK: bool GenMyCombiner::tryCombineAll(MachineInstr &I) const {87// CHECK-NEXT: const TargetSubtargetInfo &ST = MF.getSubtarget();88// CHECK-NEXT: const PredicateBitset AvailableFeatures = getAvailableFeatures();89// CHECK-NEXT: B.setInstrAndDebugLoc(I);90// CHECK-NEXT: State.MIs.clear();91// CHECK-NEXT: State.MIs.push_back(&I);92// CHECK-NEXT: if (executeMatchTable(*this, State, ExecInfo, B, getMatchTable(), *ST.getInstrInfo(), MRI, *MRI.getTargetRegisterInfo(), *ST.getRegBankInfo(), AvailableFeatures, /*CoverageInfo*/ nullptr))93// CHECK-NEXT: return true;94// CHECK-NEXT: }95// CHECK-EMPTY:96// CHECK-NEXT: return false;97// CHECK-NEXT: }98 99// Check apply100// CHECK: enum {101// CHECK-NEXT: GICXXCustomAction_GICombiner0 = GICXXCustomAction_Invalid + 1,102// CHECK-NEXT: GICXXCustomAction_GICombiner1,103// CHECK-NEXT: GICXXCustomAction_GICombiner2,104// CHECK-NEXT: };105 106// CHECK: bool GenMyCombiner::runCustomAction(unsigned ApplyID, const MatcherState &State, NewMIVector &OutMIs) const {107// CHECK-NEXT: Helper.getBuilder().setInstrAndDebugLoc(*State.MIs[0]);108// CHECK-NEXT: switch(ApplyID) {109// CHECK-NEXT: case GICXXCustomAction_GICombiner0:{110// CHECK-NEXT: // Apply Patterns111// CHECK-NEXT: APPLY112// CHECK-NEXT: return true;113// CHECK-NEXT: }114// CHECK-NEXT: case GICXXCustomAction_GICombiner1:{115// CHECK-NEXT: Register GIMatchData_r0;116// CHECK-NEXT: Register GIMatchData_r1;117// CHECK-NEXT: // Apply Patterns118// CHECK-NEXT: APPLY GIMatchData_r0, GIMatchData_r1119// CHECK-NEXT: return true;120// CHECK-NEXT: }121// CHECK-NEXT: case GICXXCustomAction_GICombiner2:{122// CHECK-NEXT: Register GIMatchData_r0;123// CHECK-NEXT: // Match Patterns124// CHECK-NEXT: if(![&](){return CHECK State.MIs[0]->getOperand(0), State.MIs[0]->getOperand(1), State.MIs[1]->getOperand(1), State.MIs[0]}()) {125// CHECK-NEXT: return false;126// CHECK-NEXT: }127// CHECK-NEXT: // Apply Patterns128// CHECK-NEXT: APPLY129// CHECK-NEXT: return true;130// CHECK-NEXT: }131// CHECK-NEXT: }132// CHECK-NEXT: llvm_unreachable("Unknown Apply Action");133// CHECK-NEXT: }134 135// Verify match table.136// CHECK: const uint8_t *GenMyCombiner::getMatchTable() const {137// CHECK-NEXT: constexpr static uint8_t MatchTable0[] = {138// CHECK-NEXT: GIM_SwitchOpcode, /*MI*/0, /*[*/GIMT_Encode2([[#LOWER:]]), GIMT_Encode2([[#UPPER:]]), /*)*//*default:*//*Label 6*/ GIMT_Encode4([[#DEFAULT:]]),139// CHECK-NEXT: /*TargetOpcode::COPY*//*Label 0*/ GIMT_Encode4([[#%u, mul(UPPER-LOWER, 4) + 10]]),140// CHECK-COUNT-40: GIMT_Encode4(0),141// CHECK-NEXT: /*TargetOpcode::G_AND*//*Label 1*/ GIMT_Encode4([[L1:[0-9]+]]),142// CHECK-COUNT-34: GIMT_Encode4(0),143// CHECK-NEXT: /*TargetOpcode::G_STORE*//*Label 2*/ GIMT_Encode4([[L2:[0-9]+]]),144// CHECK-COUNT-30: GIMT_Encode4(0),145// CHECK-NEXT: /*TargetOpcode::G_TRUNC*//*Label 3*/ GIMT_Encode4([[L3:[0-9]+]]),146// CHECK-COUNT-4: GIMT_Encode4(0),147// CHECK-NEXT: /*TargetOpcode::G_SEXT*//*Label 4*/ GIMT_Encode4([[L4:[0-9]+]]), GIMT_Encode4(0),148// CHECK-NEXT: /*TargetOpcode::G_ZEXT*//*Label 5*/ GIMT_Encode4([[L5:[0-9]+]]),149// CHECK-NEXT: // Label 0: @[[#%u, mul(UPPER-LOWER, 4) + 10]]150// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 7*/ GIMT_Encode4([[L7:[0-9]+]]), // Rule ID 4 //151// CHECK-NEXT: GIM_CheckFeatures, GIMT_Encode2(GIFBS_HasAnswerToEverything),152// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule3Enabled),153// CHECK-NEXT: // MIs[0] a154// CHECK-NEXT: // No operand predicates155// CHECK-NEXT: // MIs[0] b156// CHECK-NEXT: GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]157// CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ZEXT),158// CHECK-NEXT: // MIs[1] c159// CHECK-NEXT: // No operand predicates160// CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/1,161// CHECK-NEXT: // Combiner Rule #3: InstTest1162// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner2),163// CHECK-NEXT: // Label 7: @[[L7]]164// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 8*/ GIMT_Encode4([[L8:[0-9]+]]), // Rule ID 3 //165// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule2Enabled),166// CHECK-NEXT: // MIs[0] a167// CHECK-NEXT: // No operand predicates168// CHECK-NEXT: // MIs[0] b169// CHECK-NEXT: // No operand predicates170// CHECK-NEXT: // Combiner Rule #2: InstTest0171// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner1),172// CHECK-NEXT: // Label 8: @[[L8]]173// CHECK-NEXT: GIM_Reject,174// CHECK-NEXT: // Label 1: @[[L1]]175// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 9*/ GIMT_Encode4([[L9:[0-9]+]]), // Rule ID 6 //176// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule5Enabled),177// CHECK-NEXT: GIM_RootCheckType, /*Op*/2, /*Type*/GILLT_s32,178// CHECK-NEXT: // MIs[0] dst179// CHECK-NEXT: // No operand predicates180// CHECK-NEXT: // MIs[0] x181// CHECK-NEXT: GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/1, // MIs[1]182// CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_CONSTANT),183// CHECK-NEXT: // MIs[1] z184// CHECK-NEXT: GIM_CheckLiteralInt, /*MI*/1, /*Op*/1, GIMT_Encode8(18446744073709551574u),185// CHECK-NEXT: GIM_CheckConstantInt8, /*MI*/0, /*Op*/2, 43,186// CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/1,187// CHECK-NEXT: // Combiner Rule #5: InOutInstTest1188// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_TRUNC),189// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst190// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // z191// CHECK-NEXT: GIR_EraseRootFromParent_Done,192// CHECK-NEXT: // Label 9: @[[L9]]193// CHECK-NEXT: GIM_Reject,194// CHECK-NEXT: // Label 2: @[[L2]]195// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 10*/ GIMT_Encode4([[L10:[0-9]+]]), // Rule ID 5 //196// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule4Enabled),197// CHECK-NEXT: // MIs[0] tmp198// CHECK-NEXT: GIM_RecordInsnIgnoreCopies, /*DefineMI*/1, /*MI*/0, /*OpIdx*/0, // MIs[1]199// CHECK-NEXT: GIM_CheckOpcode, /*MI*/1, GIMT_Encode2(TargetOpcode::G_ZEXT),200// CHECK-NEXT: // MIs[1] ext201// CHECK-NEXT: // No operand predicates202// CHECK-NEXT: // MIs[0] ptr203// CHECK-NEXT: // No operand predicates204// CHECK-NEXT: GIM_CheckIsSafeToFold, /*NumInsns*/1,205// CHECK-NEXT: // Combiner Rule #4: InOutInstTest0206// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::G_STORE),207// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/1, /*OpIdx*/1, // ext208// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/1, // ptr209// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*NumInsns*/2, /*MergeInsnID's*/0, 1,210// CHECK-NEXT: GIR_EraseRootFromParent_Done,211// CHECK-NEXT: // Label 10: @[[L10]]212// CHECK-NEXT: GIM_Reject,213// CHECK-NEXT: // Label 3: @[[L3]]214// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 11*/ GIMT_Encode4([[L11:[0-9]+]]), // Rule ID 0 //215// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule0Enabled),216// CHECK-NEXT: // Combiner Rule #0: WipOpcodeTest0; wip_match_opcode 'G_TRUNC'217// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),218// CHECK-NEXT: // Label 11: @[[L11]]219// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 12*/ GIMT_Encode4([[L12:[0-9]+]]), // Rule ID 1 //220// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled),221// CHECK-NEXT: // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_TRUNC'222// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),223// CHECK-NEXT: // Label 12: @[[L12]]224// CHECK-NEXT: GIM_Reject,225// CHECK-NEXT: // Label 4: @[[L4]]226// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 13*/ GIMT_Encode4([[L13:[0-9]+]]), // Rule ID 2 //227// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule1Enabled),228// CHECK-NEXT: // Combiner Rule #1: WipOpcodeTest1; wip_match_opcode 'G_SEXT'229// CHECK-NEXT: GIR_DoneWithCustomAction, /*Fn*/GIMT_Encode2(GICXXCustomAction_GICombiner0),230// CHECK-NEXT: // Label 13: @[[L13]]231// CHECK-NEXT: GIM_Reject,232// CHECK-NEXT: // Label 5: @[[L5]]233// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 14*/ GIMT_Encode4([[L14:[0-9]+]]), // Rule ID 7 //234// CHECK-NEXT: GIM_CheckSimplePredicate, GIMT_Encode2(GICXXPred_Simple_IsRule6Enabled),235// CHECK-NEXT: // MIs[0] dst236// CHECK-NEXT: // No operand predicates237// CHECK-NEXT: // MIs[0] cst238// CHECK-NEXT: // No operand predicates239// CHECK-NEXT: GIM_CheckCxxInsnPredicate, /*MI*/0, /*FnId*/GIMT_Encode2(GICXXPred_MI_Predicate_GICombiner0),240// CHECK-NEXT: GIR_MakeTempReg, /*TempRegID*/0, /*TypeID*/GILLT_s32,241// CHECK-NEXT: GIR_BuildConstant, /*TempRegID*/0, /*Val*/GIMT_Encode8(0),242// CHECK-NEXT: // Combiner Rule #6: PatFragTest0 @ [__PatFragTest0_match_1[0]]243// CHECK-NEXT: GIR_BuildRootMI, /*Opcode*/GIMT_Encode2(TargetOpcode::COPY),244// CHECK-NEXT: GIR_RootToRootCopy, /*OpIdx*/0, // dst245// CHECK-NEXT: GIR_AddSimpleTempRegister, /*InsnID*/0, /*TempRegID*/0,246// CHECK-NEXT: GIR_EraseRootFromParent_Done,247// CHECK-NEXT: // Label 14: @[[L14]]248// CHECK-NEXT: GIM_Reject,249// CHECK-NEXT: // Label 6: @[[#%u, DEFAULT]]250// CHECK-NEXT: GIM_Reject,251// CHECK-NEXT: }; // Size: [[#%u, DEFAULT + 1]] bytes252// CHECK-NEXT: return MatchTable0;253// CHECK-NEXT: }254