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 }
...
---
%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>)
+...
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 = ", ";
Separator = ", ";
}
- if (!N->isLeaf() && !N->hasAnyPredicate() && !N->getTransformFn())
+ if (!N->hasAnyPredicate() && !N->getTransformFn())
return Error::success();
return failedImport(Explanation);
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();
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;
// 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";