From 89e9308623ff0f03fa2fc5416d6f4c9c8645707d Mon Sep 17 00:00:00 2001 From: Daniel Sanders Date: Thu, 18 May 2017 10:33:36 +0000 Subject: [PATCH] Re-commit: [globalisel][tablegen] Import rules containing intrinsic_wo_chain. Summary: As of this patch, 1018 out of 3938 rules are currently imported. Depends on D32275 Reviewers: qcolombet, kristof.beyls, rovka, t.p.northover, ab, aditya_nandakumar Reviewed By: qcolombet Subscribers: dberris, igorb, llvm-commits Differential Revision: https://reviews.llvm.org/D32278 The previous commit failed on test-suite/Bitcode/simd_ops/AArch64_halide_runtime.bc because isImmOperandEqual() assumed MO was a register operand and that's not always true. llvm-svn: 303341 --- .../llvm/Target/GlobalISel/SelectionDAGCompat.td | 1 + .../lib/CodeGen/GlobalISel/InstructionSelector.cpp | 2 +- llvm/test/TableGen/GlobalISelEmitter.td | 35 ++++++++++++++++++++++ llvm/utils/TableGen/GlobalISelEmitter.cpp | 25 ++++++++++++++-- 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td index a06c67f..071ec2e 100644 --- a/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td +++ b/llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td @@ -62,6 +62,7 @@ def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; def : GINodeEquiv; +def : GINodeEquiv; def : GINodeEquiv; // Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern. diff --git a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp index c67da86..4c0b06d 100644 --- a/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp +++ b/llvm/lib/CodeGen/GlobalISel/InstructionSelector.cpp @@ -73,7 +73,7 @@ bool InstructionSelector::isOperandImmEqual( const MachineOperand &MO, int64_t Value, const MachineRegisterInfo &MRI) const { - if (MO.getReg()) + if (MO.isReg() && MO.getReg()) if (auto VRegVal = getConstantVRegVal(MO.getReg(), MRI)) return *VRegVal == Value; return false; diff --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td index aeac859..2784e93 100644 --- a/llvm/test/TableGen/GlobalISelEmitter.td +++ b/llvm/test/TableGen/GlobalISelEmitter.td @@ -7,6 +7,10 @@ include "llvm/Target/Target.td" def MyTargetISA : InstrInfo; def MyTarget : Target { let InstructionSet = MyTargetISA; } +let TargetPrefix = "mytarget" in { +def int_mytarget_nop : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem]>; +} + def R0 : Register<"r0"> { let Namespace = "MyTarget"; } def GPR32 : RegisterClass<"MyTarget", [i32], 32, (add R0)>; def GPR32Op : RegisterOperand; @@ -127,6 +131,37 @@ def : Pat<(select GPR32:$src1, complex:$src2, complex:$src3), def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2), [(set GPR32:$dst, (add GPR32:$src1, GPR32:$src2))]>; +//===- Test a simple pattern with an intrinsic. ---------------------------===// +// + +// CHECK-LABEL: if ([&]() { +// CHECK-NEXT: MachineInstr &MI0 = I; +// CHECK-NEXT: if (MI0.getNumOperands() < 3) +// CHECK-NEXT: return false; +// CHECK-NEXT: if ((MI0.getOpcode() == TargetOpcode::G_INTRINSIC) && +// CHECK-NEXT: ((/* dst */ (MRI.getType(MI0.getOperand(0).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(MI0.getOperand(0).getReg(), MRI, TRI))))) && +// CHECK-NEXT: ((/* Operand 1 */ (isOperandImmEqual(MI0.getOperand(1), [[ID:[0-9]+]], MRI)))) && +// CHECK-NEXT: ((/* src1 */ (MRI.getType(MI0.getOperand(2).getReg()) == (LLT::scalar(32))) && +// CHECK-NEXT: ((&RBI.getRegBankFromRegClass(MyTarget::GPR32RegClass) == RBI.getRegBank(MI0.getOperand(2).getReg(), MRI, TRI)))))) { +// CHECK-NEXT: // (intrinsic_wo_chain:i32 [[ID]]:iPTR, GPR32:i32:$src1) => (MOV:i32 GPR32:i32:$src1) +// CHECK-NEXT: MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(), TII.get(MyTarget::MOV)); +// CHECK-NEXT: MIB.add(MI0.getOperand(0)/*dst*/); +// CHECK-NEXT: MIB.add(MI0.getOperand(2)/*src1*/); +// CHECK-NEXT: for (const auto *FromMI : {&MI0, }) +// CHECK-NEXT: for (const auto &MMO : FromMI->memoperands()) +// CHECK-NEXT: MIB.addMemOperand(MMO); +// CHECK-NEXT: I.eraseFromParent(); +// CHECK-NEXT: MachineInstr &NewI = *MIB; +// CHECK-NEXT: constrainSelectedInstRegOperands(NewI, TII, TRI, RBI); +// CHECK-NEXT: return true; +// CHECK-NEXT: } +// CHECK-NEXT: return false; +// CHECK-NEXT: }()) { return true; } + +def MOV : I<(outs GPR32:$dst), (ins GPR32:$src1), + [(set GPR32:$dst, (int_mytarget_nop GPR32:$src1))]>; + //===- Test a nested instruction match. -----------------------------------===// // CHECK-LABEL: if ([&]() { diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 7a500ea..dc022fe 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -1325,8 +1325,27 @@ Expected GlobalISelEmitter::createAndImportSelDAGMatcher( // Match the used operands (i.e. the children of the operator). for (unsigned i = 0, e = Src->getNumChildren(); i != e; ++i) { - if (auto Error = importChildMatcher(InsnMatcher, Src->getChild(i), OpIdx++, - TempOpIdx)) + TreePatternNode *SrcChild = Src->getChild(i); + + // For G_INTRINSIC, the operand immediately following the defs is an + // intrinsic ID. + if (SrcGI.TheDef->getName() == "G_INTRINSIC" && i == 0) { + if (!SrcChild->isLeaf()) + return failedImport("Expected IntInit containing intrinsic ID"); + + if (IntInit *SrcChildIntInit = + dyn_cast(SrcChild->getLeafValue())) { + OperandMatcher &OM = + InsnMatcher.addOperand(OpIdx++, SrcChild->getName(), TempOpIdx); + OM.addPredicate(SrcChildIntInit->getValue()); + continue; + } + + return failedImport("Expected IntInit containing instrinsic ID)"); + } + + if (auto Error = + importChildMatcher(InsnMatcher, SrcChild, OpIdx++, TempOpIdx)) return std::move(Error); } @@ -1361,7 +1380,7 @@ Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher, auto OpTyOrNone = MVTToLLT(ChildTypes.front().getConcrete()); if (!OpTyOrNone) - return failedImport("Src operand has an unsupported type"); + return failedImport("Src operand has an unsupported type (" + to_string(*SrcChild) + ")"); OM.addPredicate(*OpTyOrNone); // Check for nested instructions. -- 2.7.4