summaryrefslogtreecommitdiffstats
path: root/llvm
diff options
context:
space:
mode:
authorDaniel Sanders <daniel_l_sanders@apple.com>2017-08-11 15:40:32 +0000
committerDaniel Sanders <daniel_l_sanders@apple.com>2017-08-11 15:40:32 +0000
commit1fb1ce0c87b1b2c78068488be3f624d3c0cbb19a (patch)
treeafd9ad2c0f4f26ba2281f5c32265a5cf952f233a /llvm
parent16bddf21cf20a747dffb4e9d922a139f08cbcc59 (diff)
downloadbcm5719-llvm-1fb1ce0c87b1b2c78068488be3f624d3c0cbb19a.tar.gz
bcm5719-llvm-1fb1ce0c87b1b2c78068488be3f624d3c0cbb19a.zip
[globalisel][tablegen] Support zero-instruction emission.
Summary: Support the case where an operand of a pattern is also the whole of the result pattern. In this case the original result and all its uses must be replaced by the operand. However, register class restrictions can require a COPY. This patch handles both cases by always emitting the copy and leaving it for the register allocator to optimize. Depends on D35833 Reviewers: ab, t.p.northover, qcolombet, rovka, aditya_nandakumar Subscribers: javed.absar, kristof.beyls, igorb, llvm-commits Differential Revision: https://reviews.llvm.org/D36084 llvm-svn: 310716
Diffstat (limited to 'llvm')
-rw-r--r--llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp12
-rw-r--r--llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir52
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp69
3 files changed, 107 insertions, 26 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
index 1b45f87bc72..22586a1708e 100644
--- a/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
+++ b/llvm/lib/Target/AArch64/AArch64InstructionSelector.cpp
@@ -1163,9 +1163,19 @@ bool AArch64InstructionSelector::select(MachineInstr &I) const {
case TargetOpcode::G_INTTOPTR:
- case TargetOpcode::G_BITCAST:
+ // The importer is currently unable to import pointer types since they
+ // didn't exist in SelectionDAG.
return selectCopy(I, TII, MRI, TRI, RBI);
+ case TargetOpcode::G_BITCAST:
+ // Imported SelectionDAG rules can handle every bitcast except those that
+ // bitcast from a type to the same type. Ideally, these shouldn't occur
+ // but we might not run an optimizer that deletes them.
+ if (MRI.getType(I.getOperand(0).getReg()) ==
+ MRI.getType(I.getOperand(1).getReg()))
+ return selectCopy(I, TII, MRI, TRI, RBI);
+ return false;
+
case TargetOpcode::G_FPEXT: {
if (MRI.getType(I.getOperand(0).getReg()) != LLT::scalar(64)) {
DEBUG(dbgs() << "G_FPEXT to type " << Ty
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir b/llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir
index 5e4034d1624..fe077a25f7c 100644
--- a/llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/select-bitcast.mir
@@ -11,6 +11,8 @@
define void @bitcast_s64_fpr() { ret void }
define void @bitcast_s64_gpr_fpr() { ret void }
define void @bitcast_s64_fpr_gpr() { ret void }
+ define void @bitcast_s64_v2f32_fpr() { ret void }
+ define void @bitcast_s64_v8i8_fpr() { ret void }
...
---
@@ -210,3 +212,53 @@ body: |
%1(s64) = G_BITCAST %0
%x0 = COPY %1(s64)
...
+
+---
+# CHECK-LABEL: name: bitcast_s64_v2f32_fpr
+name: bitcast_s64_v2f32_fpr
+legalized: true
+regBankSelected: true
+
+# CHECK: registers:
+# CHECK-NEXT: - { id: 0, class: fpr64, preferred-register: '' }
+# CHECK-NEXT: - { id: 1, class: fpr64, preferred-register: '' }
+registers:
+ - { id: 0, class: fpr }
+ - { id: 1, class: fpr }
+
+# CHECK: body:
+# CHECK: %0 = COPY %d0
+# CHECK: %1 = COPY %0
+body: |
+ bb.0:
+ liveins: %d0
+
+ %0(s64) = COPY %d0
+ %1(<2 x s32>) = G_BITCAST %0
+ %x0 = COPY %1(<2 x s32>)
+...
+
+---
+# CHECK-LABEL: name: bitcast_s64_v8i8_fpr
+name: bitcast_s64_v8i8_fpr
+legalized: true
+regBankSelected: true
+
+# CHECK: registers:
+# CHECK-NEXT: - { id: 0, class: fpr64, preferred-register: '' }
+# CHECK-NEXT: - { id: 1, class: fpr64, preferred-register: '' }
+registers:
+ - { id: 0, class: fpr }
+ - { id: 1, class: fpr }
+
+# CHECK: body:
+# CHECK: %0 = COPY %d0
+# CHECK: %1 = COPY %0
+body: |
+ bb.0:
+ liveins: %d0
+
+ %0(s64) = COPY %d0
+ %1(<8 x s8>) = G_BITCAST %0
+ %x0 = COPY %1(<8 x s8>)
+...
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index d1821b64dd8..246af4c3a38 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -182,14 +182,6 @@ static Error failedImport(const Twine &Reason) {
static Error isTrivialOperatorNode(const TreePatternNode *N) {
std::string Explanation = "";
std::string Separator = "";
- if (N->isLeaf()) {
- if (isa<IntInit>(N->getLeafValue()))
- return Error::success();
-
- Explanation = "Is a leaf";
- Separator = ", ";
- }
-
if (N->hasAnyPredicate()) {
Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")";
Separator = ", ";
@@ -200,7 +192,7 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {
Separator = ", ";
}
- if (!N->isLeaf() && !N->hasAnyPredicate() && !N->getTransformFn())
+ if (!N->hasAnyPredicate() && !N->getTransformFn())
return Error::success();
return failedImport(Explanation);
@@ -2287,8 +2279,42 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
return failedImport("Src pattern root isn't a trivial operator (" +
toString(std::move(Err)) + ")");
- if (Dst->isLeaf())
+ InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(Src->getName());
+ unsigned TempOpIdx = 0;
+ auto InsnMatcherOrError =
+ createAndImportSelDAGMatcher(InsnMatcherTemp, Src, TempOpIdx);
+ if (auto Error = InsnMatcherOrError.takeError())
+ return std::move(Error);
+ InstructionMatcher &InsnMatcher = InsnMatcherOrError.get();
+
+ if (Dst->isLeaf()) {
+ Record *RCDef = getInitValueAsRegClass(Dst->getLeafValue());
+
+ const CodeGenRegisterClass &RC = Target.getRegisterClass(RCDef);
+ if (RCDef) {
+ // We need to replace the def and all its uses with the specified
+ // operand. However, we must also insert COPY's wherever needed.
+ // For now, emit a copy and let the register allocator clean up.
+ auto &DstI = Target.getInstruction(RK.getDef("COPY"));
+ const auto &DstIOperand = DstI.Operands[0];
+
+ OperandMatcher &OM0 = InsnMatcher.getOperand(0);
+ OM0.setSymbolicName(DstIOperand.Name);
+ OM0.addPredicate<RegisterBankOperandMatcher>(RC);
+
+ auto &DstMIBuilder = M.addAction<BuildMIAction>(0, &DstI, InsnMatcher);
+ DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher, DstIOperand.Name);
+ DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher, Dst->getName());
+ M.addAction<ConstrainOperandToRegClassAction>(0, 0, RC);
+
+ // We're done with this pattern! It's eligible for GISel emission; return
+ // it.
+ ++NumPatternImported;
+ return std::move(M);
+ }
+
return failedImport("Dst pattern root isn't a known leaf");
+ }
// Start with the defined operands (i.e., the results of the root operator).
Record *DstOp = Dst->getOperator();
@@ -2301,14 +2327,6 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
to_string(Src->getExtTypes().size()) + " def(s) vs " +
to_string(DstI.Operands.NumDefs) + " def(s))");
- InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher(Src->getName());
- unsigned TempOpIdx = 0;
- auto InsnMatcherOrError =
- createAndImportSelDAGMatcher(InsnMatcherTemp, Src, TempOpIdx);
- if (auto Error = InsnMatcherOrError.takeError())
- return std::move(Error);
- InstructionMatcher &InsnMatcher = InsnMatcherOrError.get();
-
// The root of the match also has constraints on the register bank so that it
// matches the result instruction.
unsigned OpIdx = 0;
@@ -2537,13 +2555,14 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
// for the matcher to reference them with.
std::vector<LLTCodeGen> TypeObjects = {
LLT::scalar(8), LLT::scalar(16), LLT::scalar(32),
- LLT::scalar(64), LLT::scalar(80), LLT::vector(8, 1),
- LLT::vector(16, 1), LLT::vector(32, 1), LLT::vector(64, 1),
- LLT::vector(8, 8), LLT::vector(16, 8), LLT::vector(32, 8),
- LLT::vector(64, 8), LLT::vector(4, 16), LLT::vector(8, 16),
- LLT::vector(16, 16), LLT::vector(32, 16), LLT::vector(2, 32),
- LLT::vector(4, 32), LLT::vector(8, 32), LLT::vector(16, 32),
- LLT::vector(2, 64), LLT::vector(4, 64), LLT::vector(8, 64),
+ LLT::scalar(64), LLT::scalar(80), LLT::scalar(128),
+ LLT::vector(8, 1), LLT::vector(16, 1), LLT::vector(32, 1),
+ LLT::vector(64, 1), LLT::vector(8, 8), LLT::vector(16, 8),
+ LLT::vector(32, 8), LLT::vector(64, 8), LLT::vector(4, 16),
+ LLT::vector(8, 16), LLT::vector(16, 16), LLT::vector(32, 16),
+ LLT::vector(2, 32), LLT::vector(4, 32), LLT::vector(8, 32),
+ LLT::vector(16, 32), LLT::vector(2, 64), LLT::vector(4, 64),
+ LLT::vector(8, 64),
};
std::sort(TypeObjects.begin(), TypeObjects.end());
OS << "enum {\n";
OpenPOWER on IntegriCloud