[llvm] r310343 - [globalisel][tablegen] Add support for importing 'imm' operands.
Daniel Sanders via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 8 03:44:31 PDT 2017
Author: dsanders
Date: Tue Aug 8 03:44:31 2017
New Revision: 310343
URL: http://llvm.org/viewvc/llvm-project?rev=310343&view=rev
Log:
[globalisel][tablegen] Add support for importing 'imm' operands.
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
Added:
llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-imm.mir
Modified:
llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
llvm/trunk/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir
llvm/trunk/test/TableGen/GlobalISelEmitter.td
llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h?rev=310343&r1=310342&r2=310343&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelector.h Tue Aug 8 03:44:31 2017
@@ -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
Modified: llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h?rev=310343&r1=310342&r2=310343&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h (original)
+++ llvm/trunk/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h Tue Aug 8 03:44:31 2017
@@ -346,6 +346,23 @@ bool InstructionSelector::executeMatchTa
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++];
Modified: llvm/trunk/include/llvm/Target/GlobalISel/SelectionDAGCompat.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/GlobalISel/SelectionDAGCompat.td?rev=310343&r1=310342&r2=310343&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Target/GlobalISel/SelectionDAGCompat.td (original)
+++ llvm/trunk/include/llvm/Target/GlobalISel/SelectionDAGCompat.td Tue Aug 8 03:44:31 2017
@@ -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>;
Modified: llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp?rev=310343&r1=310342&r2=310343&view=diff
==============================================================================
--- llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp (original)
+++ llvm/trunk/lib/Target/AArch64/AArch64InstructionSelector.cpp Tue Aug 8 03:44:31 2017
@@ -702,7 +702,8 @@ bool AArch64InstructionSelector::select(
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');
Added: llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-imm.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-imm.mir?rev=310343&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-imm.mir (added)
+++ llvm/trunk/test/CodeGen/AArch64/GlobalISel/select-imm.mir Tue Aug 8 03:44:31 2017
@@ -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)
+...
Modified: llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir?rev=310343&r1=310342&r2=310343&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir (original)
+++ llvm/trunk/test/CodeGen/X86/GlobalISel/select-inc.mir Tue Aug 8 03:44:31 2017
@@ -15,7 +15,7 @@ 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 }
@@ -23,8 +23,7 @@ registers:
- { 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
Modified: llvm/trunk/test/TableGen/GlobalISelEmitter.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/TableGen/GlobalISelEmitter.td?rev=310343&r1=310342&r2=310343&view=diff
==============================================================================
--- llvm/trunk/test/TableGen/GlobalISelEmitter.td (original)
+++ llvm/trunk/test/TableGen/GlobalISelEmitter.td Tue Aug 8 03:44:31 2017
@@ -117,7 +117,8 @@ def HasC : Predicate<"Subtarget->hasC()"
// 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]]
@@ -588,7 +589,7 @@ def : Pat<(not GPR32:$Wm), (ORN R0, GPR3
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,
@@ -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
@@ -619,12 +641,13 @@ def MOV1 : I<(outs GPR32:$dst), (ins), [
// 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)]>;
Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=310343&r1=310342&r2=310343&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Tue Aug 8 03:44:31 2017
@@ -477,7 +477,7 @@ public:
RuleMatcher(RuleMatcher &&Other) = default;
RuleMatcher &operator=(RuleMatcher &&Other) = default;
- InstructionMatcher &addInstructionMatcher();
+ InstructionMatcher &addInstructionMatcher(StringRef SymbolicName);
void addRequiredFeature(Record *Feature);
const std::vector<Record *> &getRequiredFeatures() const;
@@ -501,6 +501,8 @@ public:
return make_range(defined_insn_vars_begin(), defined_insn_vars_end());
}
+ const InstructionMatcher &getInstructionMatcher(StringRef SymbolicName) const;
+
void emitCaptureOpcodes(MatchTable &Table);
void emit(MatchTable &Table);
@@ -575,8 +577,8 @@ public:
/// are represented by a virtual register defined by a G_CONSTANT instruction.
enum PredicateKind {
OPM_ComplexPattern,
- OPM_Instruction,
OPM_IntrinsicID,
+ OPM_Instruction,
OPM_Int,
OPM_LiteralInt,
OPM_LLT,
@@ -619,9 +621,7 @@ public:
/// Compare the priority of this object and B.
///
/// Returns true if this object is more important than B.
- virtual bool isHigherPriorityThan(const OperandPredicateMatcher &B) const {
- return Kind < B.Kind;
- };
+ virtual bool isHigherPriorityThan(const OperandPredicateMatcher &B) const;
/// Report the maximum number of temporary operands needed by the predicate
/// matcher.
@@ -987,6 +987,10 @@ public:
return false;
};
+
+ bool isConstantInstruction() const {
+ return I->TheDef->getName() == "G_CONSTANT";
+ }
};
/// Generates code to check that a set of predicates and operands match for a
@@ -1004,7 +1008,11 @@ protected:
/// condition is always true.
OperandVec Operands;
+ std::string SymbolicName;
+
public:
+ InstructionMatcher(StringRef SymbolicName) : SymbolicName(SymbolicName) {}
+
/// Add an operand to the matcher.
OperandMatcher &addOperand(unsigned OpIdx, const std::string &SymbolicName,
unsigned AllocatedTemporariesBaseID) {
@@ -1041,6 +1049,7 @@ public:
llvm_unreachable("Failed to lookup operand");
}
+ StringRef getSymbolicName() const { return SymbolicName; }
unsigned getNumOperands() const { return Operands.size(); }
OperandVec::iterator operands_begin() { return Operands.begin(); }
OperandVec::iterator operands_end() { return Operands.end(); }
@@ -1116,6 +1125,14 @@ public:
return A + Operand->countRendererFns();
});
}
+
+ bool isConstantInstruction() const {
+ for (const auto &P : predicates())
+ if (const InstructionOpcodeMatcher *Opcode =
+ dyn_cast<InstructionOpcodeMatcher>(P.get()))
+ return Opcode->isConstantInstruction();
+ return false;
+ }
};
/// Generates code to check that the operand is a register defined by an
@@ -1132,9 +1149,9 @@ protected:
std::unique_ptr<InstructionMatcher> InsnMatcher;
public:
- InstructionOperandMatcher()
+ InstructionOperandMatcher(StringRef SymbolicName)
: OperandPredicateMatcher(OPM_Instruction),
- InsnMatcher(new InstructionMatcher()) {}
+ InsnMatcher(new InstructionMatcher(SymbolicName)) {}
static bool classof(const OperandPredicateMatcher *P) {
return P->getKind() == OPM_Instruction;
@@ -1168,6 +1185,7 @@ public:
enum RendererKind {
OR_Copy,
OR_CopySubReg,
+ OR_CopyConstantAsImm,
OR_Imm,
OR_Register,
OR_ComplexPattern
@@ -1202,7 +1220,9 @@ public:
CopyRenderer(unsigned NewInsnID, const InstructionMatcher &Matched,
StringRef SymbolicName)
: OperandRenderer(OR_Copy), NewInsnID(NewInsnID), Matched(Matched),
- SymbolicName(SymbolicName) {}
+ SymbolicName(SymbolicName) {
+ assert(!SymbolicName.empty() && "Cannot copy from an unspecified source");
+ }
static bool classof(const OperandRenderer *R) {
return R->getKind() == OR_Copy;
@@ -1221,6 +1241,38 @@ public:
}
};
+/// A CopyConstantAsImmRenderer emits code to render a G_CONSTANT instruction to
+/// an extended immediate operand.
+class CopyConstantAsImmRenderer : public OperandRenderer {
+protected:
+ unsigned NewInsnID;
+ /// The name of the operand.
+ const std::string SymbolicName;
+ bool Signed;
+
+public:
+ CopyConstantAsImmRenderer(unsigned NewInsnID, StringRef SymbolicName)
+ : OperandRenderer(OR_CopyConstantAsImm), NewInsnID(NewInsnID),
+ SymbolicName(SymbolicName), Signed(true) {}
+
+ static bool classof(const OperandRenderer *R) {
+ return R->getKind() == OR_CopyConstantAsImm;
+ }
+
+ const StringRef getSymbolicName() const { return SymbolicName; }
+
+ void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
+ const InstructionMatcher &InsnMatcher = Rule.getInstructionMatcher(SymbolicName);
+ unsigned OldInsnVarID = Rule.getInsnVarID(InsnMatcher);
+ Table << MatchTable::Opcode(Signed ? "GIR_CopyConstantAsSImm"
+ : "GIR_CopyConstantAsUImm")
+ << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID)
+ << MatchTable::Comment("OldInsnID")
+ << MatchTable::IntValue(OldInsnVarID)
+ << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
+ }
+};
+
/// A CopySubRegRenderer emits code to copy a single register operand from an
/// existing instruction to the one being built and indicate that only a
/// subregister should be copied.
@@ -1479,7 +1531,8 @@ public:
std::sort(MergeInsnIDs.begin(), MergeInsnIDs.end());
for (const auto &MergeInsnID : MergeInsnIDs)
Table << MatchTable::IntValue(MergeInsnID);
- Table << MatchTable::NamedValue("GIU_MergeMemOperands_EndOfList");
+ Table << MatchTable::NamedValue("GIU_MergeMemOperands_EndOfList")
+ << MatchTable::LineBreak;
}
Table << MatchTable::Opcode("GIR_EraseFromParent")
@@ -1526,8 +1579,8 @@ public:
}
};
-InstructionMatcher &RuleMatcher::addInstructionMatcher() {
- Matchers.emplace_back(new InstructionMatcher());
+InstructionMatcher &RuleMatcher::addInstructionMatcher(StringRef SymbolicName) {
+ Matchers.emplace_back(new InstructionMatcher(SymbolicName));
return *Matchers.back();
}
@@ -1572,6 +1625,15 @@ unsigned RuleMatcher::getInsnVarID(const
llvm_unreachable("Matched Insn was not captured in a local variable");
}
+const InstructionMatcher &
+RuleMatcher::getInstructionMatcher(StringRef SymbolicName) const {
+ for (const auto &I : InsnVariableIDs)
+ if (I.first->getSymbolicName() == SymbolicName)
+ return *I.first;
+ llvm_unreachable(
+ ("Failed to lookup instruction " + SymbolicName).str().c_str());
+}
+
/// Emit MatchTable opcodes to check the shape of the match and capture
/// instructions into local variables.
void RuleMatcher::emitCaptureOpcodes(MatchTable &Table) {
@@ -1699,6 +1761,32 @@ unsigned RuleMatcher::countRendererFns()
});
}
+bool OperandPredicateMatcher::isHigherPriorityThan(
+ const OperandPredicateMatcher &B) const {
+ // Generally speaking, an instruction is more important than an Int or a
+ // LiteralInt because it can cover more nodes but theres an exception to
+ // this. G_CONSTANT's are less important than either of those two because they
+ // are more permissive.
+ if (const InstructionOperandMatcher *AOM =
+ dyn_cast<InstructionOperandMatcher>(this)) {
+ if (AOM->getInsnMatcher().isConstantInstruction()) {
+ if (B.Kind == OPM_Int) {
+ return false;
+ }
+ }
+ }
+ if (const InstructionOperandMatcher *BOM =
+ dyn_cast<InstructionOperandMatcher>(&B)) {
+ if (BOM->getInsnMatcher().isConstantInstruction()) {
+ if (Kind == OPM_Int) {
+ return true;
+ }
+ }
+ }
+
+ return Kind < B.Kind;
+};
+
//===- GlobalISelEmitter class --------------------------------------------===//
class GlobalISelEmitter {
@@ -1844,6 +1932,14 @@ GlobalISelEmitter::createAndImportSelDAG
} else {
assert(SrcGIOrNull &&
"Expected to have already found an equivalent Instruction");
+ if (SrcGIOrNull->TheDef->getName() == "G_CONSTANT") {
+ // imm still has an operand but we don't need to do anything with it
+ // here since we don't support ImmLeaf predicates yet. However, we still
+ // need to note the hidden operand to get GIM_CheckNumOperands correct.
+ InsnMatcher.addOperand(OpIdx++, "", TempOpIdx);
+ return InsnMatcher;
+ }
+
// Match the used operands (i.e. the children of the operator).
for (unsigned i = 0, e = Src->getNumChildren(); i != e; ++i) {
TreePatternNode *SrcChild = Src->getChild(i);
@@ -1905,7 +2001,7 @@ Error GlobalISelEmitter::importChildMatc
if (!SrcChild->isLeaf()) {
// Map the node to a gMIR instruction.
InstructionOperandMatcher &InsnOperand =
- OM.addPredicate<InstructionOperandMatcher>();
+ OM.addPredicate<InstructionOperandMatcher>(SrcChild->getName());
auto InsnMatcherOrError = createAndImportSelDAGMatcher(
InsnOperand.getInsnMatcher(), SrcChild, TempOpIdx);
if (auto Error = InsnMatcherOrError.takeError())
@@ -1960,9 +2056,9 @@ Error GlobalISelEmitter::importChildMatc
Error GlobalISelEmitter::importExplicitUseRenderer(
BuildMIAction &DstMIBuilder, TreePatternNode *DstChild,
const InstructionMatcher &InsnMatcher) const {
- // The only non-leaf child we accept is 'bb': it's an operator because
- // BasicBlockSDNode isn't inline, but in MI it's just another operand.
if (!DstChild->isLeaf()) {
+ // We accept 'bb' here. It's an operator because BasicBlockSDNode isn't
+ // inline, but in MI it's just another operand.
if (DstChild->getOperator()->isSubClassOf("SDNode")) {
auto &ChildSDNI = CGP.getSDNodeInfo(DstChild->getOperator());
if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") {
@@ -1971,6 +2067,17 @@ Error GlobalISelEmitter::importExplicitU
return Error::success();
}
}
+
+ // Similarly, imm is an operator in TreePatternNode's view but must be
+ // rendered as operands.
+ // FIXME: The target should be able to choose sign-extended when appropriate
+ // (e.g. on Mips).
+ if (DstChild->getOperator()->getName() == "imm") {
+ DstMIBuilder.addRenderer<CopyConstantAsImmRenderer>(0,
+ DstChild->getName());
+ return Error::success();
+ }
+
return failedImport("Dst pattern child isn't a leaf node or an MBB");
}
@@ -2194,7 +2301,7 @@ Expected<RuleMatcher> GlobalISelEmitter:
to_string(Src->getExtTypes().size()) + " def(s) vs " +
to_string(DstI.Operands.NumDefs) + " def(s))");
- InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher();
+ InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(Src->getName());
unsigned TempOpIdx = 0;
auto InsnMatcherOrError =
createAndImportSelDAGMatcher(InsnMatcherTemp, Src, TempOpIdx);
More information about the llvm-commits
mailing list