Skip to content

Commit

Permalink
[globalisel][tablegen] Add support for ImmLeaf without SDNodeXForm
Browse files Browse the repository at this point in the history
Summary:
This patch adds support for predicates on imm nodes but only for ImmLeaf and not for PatLeaf or PatFrag and only where the value does not need to be transformed before being rendered into the instruction.

The limitation on PatLeaf/PatFrag/SDNodeXForm is due to differences in the necessary target-supplied C++ for GlobalISel.

Depends on D36085

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/D36086

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@311546 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
dsandersllvm committed Aug 23, 2017
1 parent 6c41152 commit 6310201
Show file tree
Hide file tree
Showing 5 changed files with 234 additions and 19 deletions.
7 changes: 7 additions & 0 deletions include/llvm/CodeGen/GlobalISel/InstructionSelector.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ enum {
/// - InsnID - Instruction ID
/// - Expected number of operands
GIM_CheckNumOperands,
/// Check an immediate predicate on the specified instruction
/// - InsnID - Instruction ID
/// - The predicate to test
GIM_CheckImmPredicate,

/// Check the type for the specified operand
/// - InsnID - Instruction ID
Expand Down Expand Up @@ -222,6 +226,8 @@ enum {
/// Provides the logic to select generic machine instructions.
class InstructionSelector {
public:
typedef bool(*ImmediatePredicateFn)(int64_t);

virtual ~InstructionSelector() = default;

/// Select the (possibly generic) instruction \p I to only use target-specific
Expand Down Expand Up @@ -254,6 +260,7 @@ class InstructionSelector {
struct MatcherInfoTy {
const LLT *TypeObjects;
const PredicateBitset *FeatureBitsets;
const ImmediatePredicateFn *ImmPredicateFns;
const std::vector<ComplexMatcherMemFn> ComplexPredicates;
};

Expand Down
28 changes: 28 additions & 0 deletions include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
#define LLVM_CODEGEN_GLOBALISEL_INSTRUCTIONSELECTORIMPL_H

namespace llvm {

/// GlobalISel PatFrag Predicates
enum {
GIPFP_Invalid,
};

template <class TgtInstructionSelector, class PredicateBitset,
class ComplexMatcherMemFn>
bool InstructionSelector::executeMatchTable(
Expand Down Expand Up @@ -126,6 +132,28 @@ bool InstructionSelector::executeMatchTable(
}
break;
}
case GIM_CheckImmPredicate: {
int64_t InsnID = MatchTable[CurrentIdx++];
int64_t Predicate = MatchTable[CurrentIdx++];
DEBUG(dbgs() << CurrentIdx << ": GIM_CheckImmPredicate(MIs[" << InsnID
<< "], Predicate=" << Predicate << ")\n");
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
assert(State.MIs[InsnID]->getOpcode() == TargetOpcode::G_CONSTANT &&
"Expected G_CONSTANT");
assert(Predicate > GIPFP_Invalid && "Expected a valid predicate");
int64_t Value = 0;
if (State.MIs[InsnID]->getOperand(1).isCImm())
Value = State.MIs[InsnID]->getOperand(1).getCImm()->getSExtValue();
else if (State.MIs[InsnID]->getOperand(1).isImm())
Value = State.MIs[InsnID]->getOperand(1).getImm();
else
llvm_unreachable("Expected Imm or CImm operand");

if (!MatcherInfo.ImmPredicateFns[Predicate](Value))
if (handleReject() == RejectAndGiveUp)
return false;
break;
}

case GIM_CheckType: {
int64_t InsnID = MatchTable[CurrentIdx++];
Expand Down
37 changes: 37 additions & 0 deletions test/CodeGen/AArch64/GlobalISel/select-neon-vcvtfxu2fp.mir
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# RUN: llc -mtriple=aarch64-- -mattr=+neon,+fullfp16 -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 @vcvtfxu2fp_s64_fpr() { ret void }
...

---
# Check that we select a 64-bit FPR vcvtfxu2fp intrinsic into UCVTFd for FPR64.
# CHECK-LABEL: name: vcvtfxu2fp_s64_fpr
name: vcvtfxu2fp_s64_fpr
legalized: true
regBankSelected: true

# CHECK: registers:
# CHECK-NEXT: - { id: 0, class: fpr64, preferred-register: '' }
# CHECK-NEXT: - { id: 1, class: gpr, preferred-register: '' }
# CHECK-NEXT: - { id: 2, class: fpr64, preferred-register: '' }
registers:
- { id: 0, class: fpr }
- { id: 1, class: gpr }
- { id: 2, class: fpr }

# CHECK: body:
# CHECK: %0 = COPY %d0
# CHECK: %2 = UCVTFd %0, 12
# CHECK: %d1 = COPY %2
body: |
bb.0:
liveins: %d0
%0(s64) = COPY %d0
%1(s32) = G_CONSTANT i32 12
%2(s64) = G_INTRINSIC intrinsic(@llvm.aarch64.neon.vcvtfxu2fp.f64), %0, %1
%d1 = COPY %2(s64)
...
44 changes: 38 additions & 6 deletions test/TableGen/GlobalISelEmitter.td
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,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, {
// CHECK-NEXT: MatcherInfo({TypeObjects, FeatureBitsets, ImmPredicateFns, {
// CHECK-NEXT: nullptr, // GICP_Invalid
// CHECK-NEXT: &MyTargetInstructionSelector::selectComplexPattern, // gi_complex
// CHECK-NEXT: }})
Expand Down Expand Up @@ -109,6 +109,15 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
// CHECK-NEXT: GICP_gi_complex,
// CHECK-NEXT: };

// CHECK-LABEL: // PatFrag predicates.
// CHECK-NEXT: enum {
// CHECK-NEXT: GIPFP_Predicate_simm8 = GIPFP_Invalid,
// CHECK-NEXT: };
// CHECK-NEXT: static bool Predicate_simm8(int64_t Imm) { return isInt<8>(Imm); }
// CHECK-NEXT: static InstructionSelector::ImmediatePredicateFn ImmPredicateFns[] = {
// CHECK-NEXT: Predicate_simm8,
// CHECK-NEXT: };

// CHECK: bool MyTargetInstructionSelector::selectImpl(MachineInstr &I) const {
// CHECK-NEXT: MachineFunction &MF = *I.getParent()->getParent();
// CHECK-NEXT: MachineRegisterInfo &MRI = MF.getRegInfo();
Expand Down Expand Up @@ -635,30 +644,53 @@ def : Pat<(i32 (bitconvert FPR32:$src1)),

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

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

// 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: GIM_CheckImmPredicate, /*MI*/0, /*Predicate*/GIPFP_Predicate_simm8,
// 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_simm8>>:$imm => (MOVimm8:i32 (imm:i32):$imm)
// CHECK-NEXT: GIR_BuildMI, /*InsnID*/0, /*Opcode*/MyTarget::MOVimm8,
// 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 simm8 : ImmLeaf<i32, [{ return isInt<8>(Imm); }]>;
def MOVimm8 : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, simm8:$imm)]>;

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

// CHECK-NEXT: GIM_Try, /*On fail goto*//*Label 17*/ [[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: // No operand 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]]
// CHECK-NEXT: // Label 17: @[[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_Try, /*On fail goto*//*Label 18*/ [[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 @@ -667,7 +699,7 @@ def MOVimm : I<(outs GPR32:$dst), (ins i32imm:$imm), [(set GPR32:$dst, imm:$imm)
// CHECK-NEXT: GIR_MutateOpcode, /*InsnID*/0, /*RecycleInsnID*/0, /*Opcode*/MyTarget::BR,
// CHECK-NEXT: GIR_ConstrainSelectedInstOperands, /*InsnID*/0,
// CHECK-NEXT: GIR_Done,
// CHECK-NEXT: // Label 17: @[[LABEL]]
// CHECK-NEXT: // Label 18: @[[LABEL]]

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

0 comments on commit 6310201

Please sign in to comment.