summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Dardis <simon.dardis@mips.com>2018-05-22 14:36:58 +0000
committerSimon Dardis <simon.dardis@mips.com>2018-05-22 14:36:58 +0000
commit13de555737e07b29d126ed72d8450f88bd38f66c (patch)
tree515d1f11102597b3fc6e503635998d14c847c490
parent8a60e5db701ed04926e120142dbb7bdb0528010a (diff)
downloadbcm5719-llvm-13de555737e07b29d126ed72d8450f88bd38f66c.tar.gz
bcm5719-llvm-13de555737e07b29d126ed72d8450f88bd38f66c.zip
[FastISel] Permit instructions to be skipped for FastISel generation.
Some ISA's such as microMIPS32(R6) have instructions which are near identical for code generation purposes, e.g. xor and xor16. These instructions take the same value types for operands and return values, have the same instruction predicates and map to the same ISD opcode. (These instructions do differ by register classes.) In such cases, the FastISel generator rejects the instruction definition. This patch borrows the 'FastIselShouldIgnore' bit from rL129692 and enables applying it to an instruction definition. Reviewers: mcrosier Differential Revision: https://reviews.llvm.org/D46953 llvm-svn: 332983
-rw-r--r--llvm/include/llvm/Target/Target.td6
-rw-r--r--llvm/test/TableGen/FastISelEmitter.td37
-rw-r--r--llvm/utils/TableGen/CodeGenInstruction.cpp1
-rw-r--r--llvm/utils/TableGen/CodeGenInstruction.h1
-rw-r--r--llvm/utils/TableGen/FastISelEmitter.cpp7
5 files changed, 52 insertions, 0 deletions
diff --git a/llvm/include/llvm/Target/Target.td b/llvm/include/llvm/Target/Target.td
index 83ead7a566b..bd9b726c18a 100644
--- a/llvm/include/llvm/Target/Target.td
+++ b/llvm/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/llvm/test/TableGen/FastISelEmitter.td b/llvm/test/TableGen/FastISelEmitter.td
new file mode 100644
index 00000000000..d5fea8dd1e0
--- /dev/null
+++ b/llvm/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/llvm/utils/TableGen/CodeGenInstruction.cpp b/llvm/utils/TableGen/CodeGenInstruction.cpp
index 44ee16f6fd7..bb6d9f0c707 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/llvm/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/llvm/utils/TableGen/CodeGenInstruction.h b/llvm/utils/TableGen/CodeGenInstruction.h
index 9e76a5baf45..d0e7fea40b3 100644
--- a/llvm/utils/TableGen/CodeGenInstruction.h
+++ b/llvm/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/llvm/utils/TableGen/FastISelEmitter.cpp b/llvm/utils/TableGen/FastISelEmitter.cpp
index f132e09415f..539efb4a78e 100644
--- a/llvm/utils/TableGen/FastISelEmitter.cpp
+++ b/llvm/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) {
OpenPOWER on IntegriCloud