Skip to content

Commit

Permalink
[globalisel][tablegen] Add support for importing 'imm' operands.
Browse files Browse the repository at this point in the history
Summary:
This patch enables the import of rules containing 'imm' operands that do not
constrain the acceptable values using predicates. Support for ImmLeaf will
arrive in a later patch.

Depends on D35681

Reviewers: ab, t.p.northover, qcolombet, rovka, aditya_nandakumar

Reviewed By: rovka

Subscribers: kristof.beyls, javed.absar, igorb, llvm-commits

Differential Revision: https://reviews.llvm.org/D35833

llvm-svn: 310343
  • Loading branch information
dsandersllvm committed Aug 8, 2017
1 parent 6e35c31 commit 0554004
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 27 deletions.
6 changes: 6 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
Expand Up @@ -184,6 +184,12 @@ enum {
/// - RendererID - The renderer to call
GIR_ComplexRenderer,

/// Render a G_CONSTANT operator as a sign-extended immediate.
/// - NewInsnID - Instruction ID to modify
/// - OldInsnID - Instruction ID to copy from
/// The operand index is implicitly 1.
GIR_CopyConstantAsSImm,

/// Constrain an instruction operand to a register class.
/// - InsnID - Instruction ID to modify
/// - OpIdx - Operand index
Expand Down
17 changes: 17 additions & 0 deletions llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
Expand Up @@ -346,6 +346,23 @@ bool InstructionSelector::executeMatchTable(
break;
}

case GIR_CopyConstantAsSImm: {
int64_t NewInsnID = MatchTable[CurrentIdx++];
int64_t OldInsnID = MatchTable[CurrentIdx++];
assert(OutMIs[NewInsnID] && "Attempted to add to undefined instruction");
assert(State.MIs[OldInsnID]->getOpcode() == TargetOpcode::G_CONSTANT && "Expected G_CONSTANT");
if (State.MIs[OldInsnID]->getOperand(1).isCImm()) {
OutMIs[NewInsnID].addImm(
State.MIs[OldInsnID]->getOperand(1).getCImm()->getSExtValue());
} else if (State.MIs[OldInsnID]->getOperand(1).isImm())
OutMIs[NewInsnID].add(State.MIs[OldInsnID]->getOperand(1));
else
llvm_unreachable("Expected Imm or CImm operand");
DEBUG(dbgs() << CurrentIdx << ": GIR_CopyConstantAsSImm(OutMIs[" << NewInsnID
<< "], MIs[" << OldInsnID << "])\n");
break;
}

case GIR_ConstrainOperandRC: {
int64_t InsnID = MatchTable[CurrentIdx++];
int64_t OpIdx = MatchTable[CurrentIdx++];
Expand Down
2 changes: 1 addition & 1 deletion llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
Expand Up @@ -33,7 +33,7 @@ def : GINodeEquiv<G_TRUNC, trunc>;
def : GINodeEquiv<G_BITCAST, bitconvert>;
// G_INTTOPTR - SelectionDAG has no equivalent.
// G_PTRTOINT - SelectionDAG has no equivalent.
// G_CONSTANT - Not needed since constants aren't operators.
def : GINodeEquiv<G_CONSTANT, imm>;
// G_FCONSTANT - Not needed since constants aren't operators.
def : GINodeEquiv<G_ADD, add>;
def : GINodeEquiv<G_SUB, sub>;
Expand Down
3 changes: 2 additions & 1 deletion llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
Expand Up @@ -702,7 +702,8 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
return false;
}
} else {
if (Ty != s32 && Ty != s64 && Ty != p0) {
// s32 and s64 are covered by tablegen.
if (Ty != p0) {
DEBUG(dbgs() << "Unable to materialize integer " << Ty
<< " constant, expected: " << s32 << ", " << s64 << ", or "
<< p0 << '\n');
Expand Down
53 changes: 53 additions & 0 deletions llvm/test/CodeGen/AArch64/GlobalISel/select-imm.mir
@@ -0,0 +1,53 @@
# RUN: llc -O0 -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 @imm_s32_gpr() { ret void }
define void @imm_s64_gpr() { ret void }

...

---
# Check that we select a 32-bit immediate into a MOVi32imm.
# CHECK-LABEL: name: imm_s32_gpr
name: imm_s32_gpr
legalized: true
regBankSelected: true

# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gpr32, preferred-register: '' }
registers:
- { id: 0, class: gpr }

# CHECK: body:
# CHECK: %0 = MOVi32imm -1234
body: |
bb.0:
liveins: %w0, %w1
%0(s32) = G_CONSTANT i32 -1234
%w0 = COPY %0(s32)
...

---
# Check that we select a 64-bit immediate into a MOVi64imm.
# CHECK-LABEL: name: imm_s64_gpr
name: imm_s64_gpr
legalized: true
regBankSelected: true

# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: gpr64, preferred-register: '' }
registers:
- { id: 0, class: gpr }

# CHECK: body:
# CHECK: %0 = MOVi64imm 1234
body: |
bb.0:
liveins: %w0, %w1
%0(s64) = G_CONSTANT i64 1234
%w0 = COPY %0(s64)
...
5 changes: 2 additions & 3 deletions llvm/test/CodeGen/X86/GlobalISel/select-inc.mir
Expand Up @@ -15,16 +15,15 @@ regBankSelected: true
# ALL: registers:
# ALL-NEXT: - { id: 0, class: gr8, preferred-register: '' }
# INC-NEXT: - { id: 1, class: gpr, preferred-register: '' }
# ADD-NEXT: - { id: 1, class: gr8, preferred-register: '' }
# ADD-NEXT: - { id: 1, class: gpr, preferred-register: '' }
# ALL-NEXT: - { id: 2, class: gr8, preferred-register: '' }
registers:
- { id: 0, class: gpr }
- { id: 1, class: gpr }
- { id: 2, class: gpr }
# ALL: %0 = COPY %al
# INC-NEXT: %2 = INC8r %0
# ADD-NEXT: %1 = MOV8ri 1
# ADD-NEXT: %2 = ADD8rr %0, %1
# ADD-NEXT: %2 = ADD8ri %0, 1
body: |
bb.1 (%ir-block.0):
liveins: %al
Expand Down
37 changes: 30 additions & 7 deletions llvm/test/TableGen/GlobalISelEmitter.td
Expand Up @@ -117,7 +117,8 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/1, // src1
// CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/1,
// CHECK-NEXT: GIR_ComplexRenderer, /*InsnID*/0, /*RendererID*/0,
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*MergeInsnID's*/0, GIU_MergeMemOperands_EndOfList, GIR_EraseFromParent, /*InsnID*/0,
// CHECK-NEXT: GIR_MergeMemOperands, /*InsnID*/0, /*MergeInsnID's*/0, GIU_MergeMemOperands_EndOfList,
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
// CHECK-NEXT: GIR_Done,
// CHECK-NEXT: // Label 0: @[[LABEL]]
Expand Down Expand Up @@ -588,7 +589,7 @@ def : Pat<(not GPR32:$Wm), (ORN R0, GPR32:$Wm)>;
def : Pat<(i32 (bitconvert FPR32:$src1)),
(COPY_TO_REGCLASS FPR32:$src1, GPR32)>;

//===- Test a simple pattern with just a leaf immediate. ------------------===//
//===- Test a simple pattern with just a specific leaf immediate. ---------===//

// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 15*/ [[LABEL:[0-9]+]],
// CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
Expand All @@ -608,9 +609,30 @@ def : Pat<(i32 (bitconvert FPR32:$src1)),

def MOV1 : I<(outs GPR32:$dst), (ins), [(set GPR32:$dst, 1)]>;

//===- Test a pattern with an MBB operand. --------------------------------===//
//===- Test a simple pattern with just a leaf immediate. ------------------===//

// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 16*/ [[LABEL:[0-9]+]],
// CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
// CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_CONSTANT,
// 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 predicates
// CHECK-NEXT: // (imm:i32):$imm => (MOVimm:i32 (imm:i32):$imm)
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm,
// CHECK-NEXT: GIR_Copy, /*NewInsnID*/0, /*OldInsnID*/0, /*OpIdx*/0, // dst
// CHECK-NEXT: GIR_CopyConstantAsSImm, /*NewInsnID*/0, /*OldInsnID*/0, // imm
// CHECK-NEXT: GIR_EraseFromParent, /*InsnID*/0,
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
// CHECK-NEXT: GIR_Done,
// CHECK-NEXT: // Label 16: @[[LABEL]]

def MOVimm : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, imm:$imm)]>;

//===- Test a pattern with an MBB operand. --------------------------------===//

// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 17*/ [[LABEL:[0-9]+]],
// CHECK-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/1,
// CHECK-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_BR,
// CHECK-NEXT: // MIs[0] target
Expand All @@ -619,12 +641,13 @@ def MOV1 : I<(outs GPR32:$dst), (ins), [(set GPR32:$dst, 1)]>;
// CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::BR,
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
// CHECK-NEXT: GIR_Done,
// CHECK-NEXT: // Label 16: @[[LABEL]]
// CHECK-NEXT: // Label 17: @[[LABEL]]

def BR : I<(outs), (ins unknown:$target),
[(br bb:$target)]>;

// CHECK-NEXT: GIM_Reject,
// CHECK-NEXT: };
// CHECK-NEXT: if (executeMatchTable(*this, OutMIs, State, MatcherInfo, MatchTable0, TII, MRI, TRI, RBI, AvailableFeatures)) {
// CHECK-NEXT: return true;
// CHECK-NEXT: }

def BR : I<(outs), (ins unknown:$target),
[(br bb:$target)]>;

0 comments on commit 0554004

Please sign in to comment.