summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/Target.td6
-rw-r--r--test/TableGen/FastISelEmitter.td37
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp1
-rw-r--r--utils/TableGen/CodeGenInstruction.h1
-rw-r--r--utils/TableGen/FastISelEmitter.cpp7
5 files changed, 52 insertions, 0 deletions
diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td
index 83ead7a566b..bd9b726c18a 100644
--- a/include/llvm/Target/Target.td
+++ b/include/llvm/Target/Target.td
@@ -568,6 +568,12 @@ class Instruction {
/// can be queried via the getNamedOperandIdx() function which is generated
/// by TableGen.
bit UseNamedOperandTable = 0;
+
+ /// Should FastISel ignore this instruction. For certain ISAs, they have
+ /// instructions which map to the same ISD Opcode, value type operands and
+ /// instruction selection predicates. FastISel cannot handle such cases, but
+ /// SelectionDAG can.
+ bit FastISelShouldIgnore = 0;
}
/// PseudoInstExpansion - Expansion information for a pseudo-instruction.
diff --git a/test/TableGen/FastISelEmitter.td b/test/TableGen/FastISelEmitter.td
new file mode 100644
index 00000000000..d5fea8dd1e0
--- /dev/null
+++ b/test/TableGen/FastISelEmitter.td
@@ -0,0 +1,37 @@
+// RUN: llvm-tblgen --gen-fast-isel -I %p/../../include %s 2>&1 | FileCheck %s
+
+include "llvm/Target/Target.td"
+
+//===- Define the necessary boilerplate for our test target. --------------===//
+
+def MyTargetISA : InstrInfo;
+def MyTarget : Target { let InstructionSet = MyTargetISA; }
+
+def R0 : Register<"r0"> { let Namespace = "MyTarget"; }
+def R1 : Register<"r0"> { let Namespace = "MyTarget"; }
+def GPR32M : RegisterClass<"MyTarget", [i32], 32, (add R0)>;
+def GPR32MOp : RegisterOperand<GPR32M>;
+
+def GPR32 : RegisterClass<"MyTarget", [i32], 32, (add R0, R1)>;
+def GPR32Op : RegisterOperand<GPR32>;
+
+class I<dag OOps, dag IOps, list<dag> Pat> : Instruction {
+ let Namespace = "MyTarget";
+ let OutOperandList = OOps;
+ let InOperandList = IOps;
+ let Pattern = Pat;
+}
+
+def HasA : Predicate<"Subtarget->hasA()">;
+
+let Predicates = [HasA] in {
+
+ def ADD : I<(outs GPR32Op:$rd), (ins GPR32Op:$rs, GPR32Op:$rt),
+ [(set GPR32Op:$rd, (add GPR32Op:$rs, GPR32Op:$rt))]>;
+
+ let FastISelShouldIgnore = 1 in
+ def ADD_M : I<(outs GPR32MOp:$rd), (ins GPR32MOp:$rs, GPR32MOp:$rt),
+ [(set GPR32MOp:$rd, (add GPR32MOp:$rs, GPR32MOp:$rt))]>;
+}
+
+// CHECK-NOT: error: Duplicate predicate in FastISel table!
diff --git a/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 44ee16f6fd7..bb6d9f0c707 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/utils/TableGen/CodeGenInstruction.cpp
@@ -327,6 +327,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
isInsertSubreg = R->getValueAsBit("isInsertSubreg");
isConvergent = R->getValueAsBit("isConvergent");
hasNoSchedulingInfo = R->getValueAsBit("hasNoSchedulingInfo");
+ FastISelShouldIgnore = R->getValueAsBit("FastISelShouldIgnore");
bool Unset;
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
diff --git a/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index 9e76a5baf45..d0e7fea40b3 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/utils/TableGen/CodeGenInstruction.h
@@ -258,6 +258,7 @@ template <typename T> class ArrayRef;
bool isInsertSubreg : 1;
bool isConvergent : 1;
bool hasNoSchedulingInfo : 1;
+ bool FastISelShouldIgnore : 1;
std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;
diff --git a/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index f132e09415f..539efb4a78e 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/utils/TableGen/FastISelEmitter.cpp
@@ -453,6 +453,13 @@ void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
if (II.Operands.empty())
continue;
+ // Allow instructions to be marked as unavailable for FastISel for
+ // certain cases, i.e. an ISA has two 'and' instruction which differ
+ // by what registers they can use but are otherwise identical for
+ // codegen purposes.
+ if (II.FastISelShouldIgnore)
+ continue;
+
// For now, ignore multi-instruction patterns.
bool MultiInsts = false;
for (unsigned i = 0, e = Dst->getNumChildren(); i != e; ++i) {