summaryrefslogtreecommitdiffstats
path: root/llvm/test
diff options
context:
space:
mode:
authorVolkan Keles <vkeles@apple.com>2018-01-16 18:44:05 +0000
committerVolkan Keles <vkeles@apple.com>2018-01-16 18:44:05 +0000
commitf7f2568613025e120c406da4f9f95a323f477024 (patch)
treea79099f2323f99327a85c48f258c020e5cd2e262 /llvm/test
parenta0db63a195de29e6e9e43293fe6c3d977c82b3b9 (diff)
downloadbcm5719-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.mir34
-rw-r--r--llvm/test/TableGen/GlobalISelEmitter.td84
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: }
OpenPOWER on IntegriCloud