mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-15 07:59:57 +00:00
[globalisel][tablegen] Correct matching of intrinsic ID's.
TreePatternNode considers them to be plain integers but MachineInstr considers them to be a distinct kind of operand. The tweak to AArch64InstrInfo.td to produce a simple test case is a NFC for everything except GlobalISelEmitter (confirmed by diffing the tablegenerated files). GlobalISelEmitter is currently unable to infer the type of operands in the Dst pattern from the operands in the Src pattern. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307634 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6845427d1b
commit
ec48fd1277
@ -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
|
||||
|
@ -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++;
|
||||
|
@ -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>;
|
||||
|
@ -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)
|
||||
...
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user