diff options
6 files changed, 84 insertions, 12 deletions
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h index 60ce22a80b2..59a4073646e 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h @@ -107,6 +107,11 @@ enum { /// - OpIdx - Operand index /// - Expected integer GIM_CheckLiteralInt, + /// Check the operand is a specific intrinsic ID + /// - InsnID - Instruction ID + /// - OpIdx - Operand index + /// - Expected Intrinsic ID + GIM_CheckIntrinsicID, /// Check the specified operand is an MBB /// - InsnID - Instruction ID /// - OpIdx - Operand index diff --git a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h index 3eca289964a..db9d04f6d36 100644 --- a/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h +++ b/llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h @@ -156,6 +156,18 @@ bool InstructionSelector::executeMatchTable( return false; break; } + case GIM_CheckIntrinsicID: { + int64_t InsnID = *Command++; + int64_t OpIdx = *Command++; + int64_t Value = *Command++; + DEBUG(dbgs() << "GIM_CheckIntrinsicID(MIs[" << InsnID << "]->getOperand(" << OpIdx + << "), Value=" << Value << ")\n"); + assert(State.MIs[InsnID] != nullptr && "Used insn before defined"); + MachineOperand &OM = State.MIs[InsnID]->getOperand(OpIdx); + if (!OM.isIntrinsicID() || OM.getIntrinsicID() != Value) + return false; + break; + } case GIM_CheckIsMBB: { int64_t InsnID = *Command++; int64_t OpIdx = *Command++; diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td index 6cb723d187a..3cd7ebd2cb0 100644 --- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td +++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td @@ -714,10 +714,10 @@ def : InstAlias<"negs $dst, $src$shift", defm UDIV : Div<0, "udiv", udiv>; defm SDIV : Div<1, "sdiv", sdiv>; -def : Pat<(int_aarch64_udiv GPR32:$Rn, GPR32:$Rm), (UDIVWr $Rn, $Rm)>; -def : Pat<(int_aarch64_udiv GPR64:$Rn, GPR64:$Rm), (UDIVXr $Rn, $Rm)>; -def : Pat<(int_aarch64_sdiv GPR32:$Rn, GPR32:$Rm), (SDIVWr $Rn, $Rm)>; -def : Pat<(int_aarch64_sdiv GPR64:$Rn, GPR64:$Rm), (SDIVXr $Rn, $Rm)>; +def : Pat<(int_aarch64_udiv GPR32:$Rn, GPR32:$Rm), (UDIVWr GPR32:$Rn, GPR32:$Rm)>; +def : Pat<(int_aarch64_udiv GPR64:$Rn, GPR64:$Rm), (UDIVXr GPR64:$Rn, GPR64:$Rm)>; +def : Pat<(int_aarch64_sdiv GPR32:$Rn, GPR32:$Rm), (SDIVWr GPR32:$Rn, GPR32:$Rm)>; +def : Pat<(int_aarch64_sdiv GPR64:$Rn, GPR64:$Rm), (SDIVXr GPR64:$Rn, GPR64:$Rm)>; // Variable shift defm ASRV : Shift<0b10, "asr", sra>; diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir new file mode 100644 index 00000000000..43e682c6b6c --- /dev/null +++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-intrinsic-aarch64-sdiv.mir @@ -0,0 +1,38 @@ +# RUN: llc -mtriple=aarch64-- -run-pass=instruction-select -verify-machineinstrs -global-isel %s -o - | FileCheck %s + +--- | + target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" + + define void @sdiv_s32_gpr() { ret void } +... + +--- +# Check that we select a 32-bit GPR sdiv intrinsic into SDIVWrr for GPR32. +# Also check that we constrain the register class of the COPY to GPR32. +# CHECK-LABEL: name: sdiv_s32_gpr +name: sdiv_s32_gpr +legalized: true +regBankSelected: true + +# CHECK: registers: +# CHECK-NEXT: - { id: 0, class: gpr32, preferred-register: '' } +# CHECK-NEXT: - { id: 1, class: gpr32, preferred-register: '' } +# CHECK-NEXT: - { id: 2, class: gpr32, preferred-register: '' } +registers: + - { id: 0, class: gpr } + - { id: 1, class: gpr } + - { id: 2, class: gpr } + +# CHECK: body: +# CHECK: %0 = COPY %w0 +# CHECK: %1 = COPY %w1 +# CHECK: %2 = SDIVWr %0, %1 +body: | + bb.0: + liveins: %w0, %w1 + + %0(s32) = COPY %w0 + %1(s32) = COPY %w1 + %2(s32) = G_INTRINSIC intrinsic(@llvm.aarch64.sdiv.i32), %0, %1 + %w0 = COPY %2(s32) +... diff --git a/llvm/test/TableGen/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter.td index 1c96d5acffa..189e2979c9d 100644 --- a/llvm/test/TableGen/GlobalISelEmitter.td +++ b/llvm/test/TableGen/GlobalISelEmitter.td @@ -170,11 +170,11 @@ def ADD : I<(outs GPR32:$dst), (ins GPR32:$src1, GPR32:$src2), // 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: GIM_CheckLiteralInt, /*MI*/0, /*Op*/1, [[ID:[0-9]+]], +// CHECK-NEXT: GIM_CheckIntrinsicID, /*MI*/0, /*Op*/1, Intrinsic::mytarget_nop, // CHECK-NEXT: // MIs[0] src1 // CHECK-NEXT: GIM_CheckType, /*MI*/0, /*Op*/2, /*Type*/GILLT_s32, // CHECK-NEXT: GIM_CheckRegBankForClass, /*MI*/0, /*Op*/2, /*RC*/MyTarget::GPR32RegClassID, -// CHECK-NEXT: // (intrinsic_wo_chain:i32 [[ID]]:iPTR, GPR32:i32:$src1) => (MOV:i32 GPR32:i32:$src1) +// CHECK-NEXT: // (intrinsic_wo_chain:i32 [[ID:[0-9]+]]:iPTR, GPR32:i32:$src1) => (MOV:i32 GPR32:i32:$src1) // CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOV, // CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index ef65317c739..1d21042e95a 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -338,6 +338,7 @@ public: enum PredicateKind { OPM_ComplexPattern, OPM_Instruction, + OPM_IntrinsicID, OPM_Int, OPM_LiteralInt, OPM_LLT, @@ -519,6 +520,26 @@ public: } }; +/// Generates code to check that an operand is an intrinsic ID. +class IntrinsicIDOperandMatcher : public OperandPredicateMatcher { +protected: + const CodeGenIntrinsic *II; + +public: + IntrinsicIDOperandMatcher(const CodeGenIntrinsic *II) + : OperandPredicateMatcher(OPM_IntrinsicID), II(II) {} + + static bool classof(const OperandPredicateMatcher *P) { + return P->getKind() == OPM_IntrinsicID; + } + + void emitPredicateOpcodes(raw_ostream &OS, RuleMatcher &Rule, + unsigned InsnVarID, unsigned OpIdx) const override { + OS << " GIM_CheckIntrinsicID, /*MI*/" << InsnVarID << ", /*Op*/" + << OpIdx << ", Intrinsic::" << II->EnumName << ",\n"; + } +}; + /// Generates code to check that a set of predicates match for a particular /// operand. class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> { @@ -1513,14 +1534,10 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher( // For G_INTRINSIC, the operand immediately following the defs is an // intrinsic ID. if (SrcGIOrNull->TheDef->getName() == "G_INTRINSIC" && i == 0) { - if (!SrcChild->isLeaf()) - return failedImport("Expected IntInit containing intrinsic ID"); - - if (IntInit *SrcChildIntInit = - dyn_cast<IntInit>(SrcChild->getLeafValue())) { + if (const CodeGenIntrinsic *II = Src->getIntrinsicInfo(CGP)) { OperandMatcher &OM = InsnMatcher.addOperand(OpIdx++, SrcChild->getName(), TempOpIdx); - OM.addPredicate<LiteralIntOperandMatcher>(SrcChildIntInit->getValue()); + OM.addPredicate<IntrinsicIDOperandMatcher>(II); continue; } |

