diff options
| author | Volkan Keles <vkeles@apple.com> | 2018-01-16 18:44:05 +0000 |
|---|---|---|
| committer | Volkan Keles <vkeles@apple.com> | 2018-01-16 18:44:05 +0000 |
| commit | f7f2568613025e120c406da4f9f95a323f477024 (patch) | |
| tree | a79099f2323f99327a85c48f258c020e5cd2e262 /llvm/test | |
| parent | a0db63a195de29e6e9e43293fe6c3d977c82b3b9 (diff) | |
| download | bcm5719-llvm-f7f2568613025e120c406da4f9f95a323f477024.tar.gz bcm5719-llvm-f7f2568613025e120c406da4f9f95a323f477024.zip | |
[GlobalISel][TableGen] Add support for SDNodeXForm
Summary:
This patch adds CustomRenderer which renders the matched
operands to the specified instruction.
Targets can enable the matching of SDNodeXForm by adding
a definition that inherits from GICustomOperandRenderer and
GISDNodeXFormEquiv as follows.
def gi_imm8 : GICustomOperandRenderer<"renderImm8”>,
GISDNodeXFormEquiv<imm8_xform>;
Custom renderer functions should be of the form:
void render(MachineInstrBuilder &MIB, const MachineInstr &I);
Reviewers: dsanders, ab, rovka
Reviewed By: dsanders
Subscribers: kristof.beyls, javed.absar, llvm-commits, mgrang, qcolombet
Differential Revision: https://reviews.llvm.org/D42012
llvm-svn: 322582
Diffstat (limited to 'llvm/test')
| -rw-r--r-- | llvm/test/CodeGen/AArch64/GlobalISel/select-mul.mir | 34 | ||||
| -rw-r--r-- | llvm/test/TableGen/GlobalISelEmitter.td | 84 |
2 files changed, 102 insertions, 16 deletions
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-mul.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-mul.mir new file mode 100644 index 00000000000..5b4971d41d8 --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-mul.mir @@ -0,0 +1,34 @@ +# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py +# RUN: llc -O0 -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s +--- +name: mul_i64_sext_imm32 +legalized: true +regBankSelected: true + +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + - { id: 3, class: gpr } + +body: | + bb.0: + liveins: %w0 + + ; Make sure InstructionSelector is able to match a pattern + ; with an SDNodeXForm, trunc_imm. + ; def : Pat<(i64 (mul (sext GPR32:$Rn), (s64imm_32bit:$C))), + ; (SMADDLrrr GPR32:$Rn, (MOVi32imm (trunc_imm imm:$C)), XZR)>; + ; CHECK-LABEL: name: mul_i64_sext_imm32 + ; CHECK: [[COPY:%[0-9]+]]:gpr32 = COPY %w0 + ; CHECK: [[MOVi32imm:%[0-9]+]]:gpr32 = MOVi32imm 3 + ; CHECK: [[SMADDLrrr:%[0-9]+]]:gpr64 = SMADDLrrr [[COPY]], [[MOVi32imm]], %xzr + ; CHECK: %x0 = COPY [[SMADDLrrr]] + %0:gpr(s32) = COPY %w0 + %1:gpr(s64) = G_SEXT %0(s32) + %2:gpr(s64) = G_CONSTANT i64 3 + %3:gpr(s64) = G_MUL %1, %2 + %x0 = COPY %3(s64) +... + + diff --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td index bc0b509622c..fe2f355f871 100644 --- a/llvm/test/TableGen/GlobalISelEmitter.td +++ b/llvm/test/TableGen/GlobalISelEmitter.td @@ -45,6 +45,16 @@ def gi_complex_rr : GIComplexOperandMatcher<s32, "selectComplexPatternRR">, GIComplexPatternEquiv<complex_rr>; +def cimm8_xform : SDNodeXForm<imm, [{ + uint64_t Val = N->getZExtValue() << 1; + return CurDAG->getTargetConstant(Val, SDLoc(N), MVT::i64); + }]>; + +def cimm8 : Operand<i32>, ImmLeaf<i32, [{return isInt<8>(Imm);}], cimm8_xform>; + +def gi_cimm8 : GICustomOperandRenderer<"renderImm8">, + GISDNodeXFormEquiv<cimm8_xform>; + def m1 : OperandWithDefaultOps <i32, (ops (i32 -1))>; def Z : OperandWithDefaultOps <i32, (ops R0)>; def m1Z : OperandWithDefaultOps <i32, (ops (i32 -1), R0)>; @@ -61,8 +71,10 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } // CHECK-LABEL: #ifdef GET_GLOBALISEL_TEMPORARIES_DECL // CHECK-NEXT: mutable MatcherState State; // CHECK-NEXT: typedef ComplexRendererFns(MyTargetInstructionSelector::*ComplexMatcherMemFn)(MachineOperand &) const; -// CHECK-NEXT: const MatcherInfoTy<PredicateBitset, ComplexMatcherMemFn> MatcherInfo; +// CHECK-NEXT: typedef void(MyTargetInstructionSelector::*CustomRendererFn)(MachineInstrBuilder &, const MachineInstr&) const; +// CHECK-NEXT: const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, CustomRendererFn> ISelInfo; // CHECK-NEXT: static MyTargetInstructionSelector::ComplexMatcherMemFn ComplexPredicateFns[]; +// CHECK-NEXT: static MyTargetInstructionSelector::CustomRendererFn CustomRenderers[]; // CHECK-NEXT: bool testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const override; // CHECK-NEXT: bool testImmPredicate_APInt(unsigned PredicateID, const APInt &Imm) const override; // CHECK-NEXT: bool testImmPredicate_APFloat(unsigned PredicateID, const APFloat &Imm) const override; @@ -70,7 +82,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } // CHECK-LABEL: #ifdef GET_GLOBALISEL_TEMPORARIES_INIT // CHECK-NEXT: , State(2), -// CHECK-NEXT: MatcherInfo({TypeObjects, FeatureBitsets, ComplexPredicateFns}) +// CHECK-NEXT: ISelInfo({TypeObjects, FeatureBitsets, ComplexPredicateFns, CustomRenderers}) // CHECK-NEXT: #endif // ifdef GET_GLOBALISEL_TEMPORARIES_INIT // CHECK-LABEL: enum SubtargetFeatureBits : uint8_t { @@ -128,19 +140,27 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } // CHECK-LABEL: // PatFrag predicates. // CHECK-NEXT: enum { -// CHECK-NEXT: GIPFP_I64_Predicate_simm8 = GIPFP_I64_Invalid + 1, +// CHECK-NEXT: GIPFP_I64_Predicate_cimm8 = GIPFP_I64_Invalid + 1, +// CHECK-NEXT: GIPFP_I64_Predicate_simm8, // CHECK-NEXT: }; -// CHECK-NEXT: bool MyTargetInstructionSelector::testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const { -// CHECK-NEXT: switch (PredicateID) { -// CHECK-NEXT: case GIPFP_I64_Predicate_simm8: { + + +// CHECK-NEXT: bool MyTargetInstructionSelector::testImmPredicate_I64(unsigned PredicateID, int64_t Imm) const { +// CHECK-NEXT: switch (PredicateID) { +// CHECK-NEXT: case GIPFP_I64_Predicate_cimm8: { +// CHECK-NEXT: return isInt<8>(Imm); +// CHECK-NEXT: llvm_unreachable("ImmediateCode should have returned"); +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: case GIPFP_I64_Predicate_simm8: { // CHECK-NEXT: return isInt<8>(Imm); -// CHECK-NEXT: llvm_unreachable("ImmediateCode should have returned"); -// CHECK-NEXT: return false; -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: llvm_unreachable("Unknown predicate"); -// CHECK-NEXT: return false; -// CHECK-NEXT: } +// CHECK-NEXT: llvm_unreachable("ImmediateCode should have returned"); +// CHECK-NEXT: return false; +// CHECK-NEXT: } +// CHECK-NEXT: } +// CHECK-NEXT: llvm_unreachable("Unknown predicate"); +// CHECK-NEXT: return false; +// CHECK-NEXT: } // CHECK-LABEL: // PatFrag predicates. // CHECK-NEXT: enum { @@ -181,6 +201,17 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; } // CHECK-NEXT: &MyTargetInstructionSelector::selectComplexPatternRR, // gi_complex_rr // CHECK-NEXT: } +// CHECK-LABEL: // Custom renderers. +// CHECK-NEXT: enum { +// CHECK-NEXT: GICR_Invalid, +// CHECK-NEXT: GICR_renderImm8, +// CHECK-NEXT: }; +// CHECK-NEXT: MyTargetInstructionSelector::CustomRendererFn +// CHECK-NEXT: MyTargetInstructionSelector::CustomRenderers[] = { +// CHECK-NEXT: nullptr, // GICP_Invalid +// CHECK-NEXT: &MyTargetInstructionSelector::renderImm8, // gi_cimm8 +// CHECK-NEXT: }; + // CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const { // CHECK-NEXT: MachineFunction &MF = *I.getParent()->getParent(); // CHECK-NEXT: MachineRegisterInfo &MRI = MF.getRegInfo(); @@ -892,12 +923,33 @@ def MOVimm9 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, simm9:$i // CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0, // CHECK-NEXT: GIR_Done, // CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]] + +def MOVimm : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, imm:$imm)]>; + + +//===- Test a pattern with a custom renderer. -----------------------------===// +// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label [[LABEL_NUM:[0-9]+]]*/ [[LABEL:[0-9]+]], +// CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2, +// NOOPT-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT, +// CHECK-NEXT: GIM_CheckI64ImmPredicate, /*MI*/0, /*Predicate*/GIPFP_I64_Predicate_cimm8, +// CHECK-NEXT: // MIs[0] dst +// CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/0, /*Type*/GILLT_s32, +// CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/0, /*RC*/MyTarget::GPR32RegClassID, +// CHECK-NEXT: // MIs[0] Operand 1 +// CHECK-NEXT: // No operand predicates +// CHECK-NEXT: // (imm:{ *:[i32] })<<P:Predicate_cimm8>><<X:cimm8_xform>>:$imm => (MOVcimm8:{ *:[i32] } (cimm8_xform:{ *:[i32] } (imm:{ *:[i32] }):$imm)) +// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVcimm8, +// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst +// CHECK-NEXT: GIR_CustomRenderer, /*InsnID*/0, /*OldInsnID*/0, /*Renderer*/GICR_renderImm8, // imm +// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0, +// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0, +// CHECK-NEXT: GIR_Done, +// CHECK-NEXT: // Label [[LABEL_NUM]]: @[[LABEL]] // Closing the G_CONSTANT group. // OPT-NEXT: GIM_Reject, // OPT-NEXT: GIR_Done, // OPT-NEXT: // Label [[GRP_LABEL_NUM]]: @[[GRP_LABEL]] - -def MOVimm : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, imm:$imm)]>; +def MOVcimm8 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, cimm8:$imm)]>; //===- Test a simple pattern with a FP immediate and a predicate. ---------===// @@ -1020,6 +1072,6 @@ def BR : I<(outs), (ins unknown:$target), // CHECK-NEXT: GIM_Reject, // CHECK-NEXT: }; -// CHECK-NEXT: if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable0, TII, MRI, TRI, RBI, AvailableFeatures, CoverageInfo)) { +// CHECK-NEXT: if (executeMatchTable(*this, OutMIs, State, ISelInfo, MatchTable0, TII, MRI, TRI, RBI, AvailableFeatures, CoverageInfo)) { // CHECK-NEXT: return true; // CHECK-NEXT: } |

