summaryrefslogtreecommitdiff
path: root/utils
diff options
context:
space:
mode:
authorDaniel Sanders <daniel_l_sanders@apple.com>2017-10-16 00:56:30 +0000
committerDaniel Sanders <daniel_l_sanders@apple.com>2017-10-16 00:56:30 +0000
commit508747d41851c6a0dcd44b7e14b6e5de08634d73 (patch)
tree9a9e1b42a1ea01c59f332294261134bf17d35d08 /utils
parenta057c40dc32b0970a2d0e3ddc5299aa43484025b (diff)
[globalisel][tablegen] Implement unindexed load, non-extending load, and MemVT checks
Summary: This includes some context-sensitivity in the MVT to LLT conversion so that pointer types are tested correctly. FIXME: I'm not happy with the way this is done since everything is a special-case. I've yet to find a reasonable way to implement it. select-load.mir fails because <1 x s64> loads in tablegen get priority over s64 loads. This is fixed in the next patch and as such they should be committed together, I've posted them separately to help with the review. Depends on D37456 Reviewers: ab, qcolombet, t.p.northover, rovka, aditya_nandakumar Subscribers: kristof.beyls, javed.absar, llvm-commits, igorb Differential Revision: https://reviews.llvm.org/D37457 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@315884 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils')
-rw-r--r--utils/TableGen/GlobalISelEmitter.cpp122
1 files changed, 105 insertions, 17 deletions
diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp
index e19b4392689..3bfaa887301 100644
--- a/utils/TableGen/GlobalISelEmitter.cpp
+++ b/utils/TableGen/GlobalISelEmitter.cpp
@@ -103,6 +103,12 @@ public:
OS << "GILLT_v" << Ty.getNumElements() << "s" << Ty.getScalarSizeInBits();
return;
}
+ if (Ty.isPointer()) {
+ OS << "GILLT_p" << Ty.getAddressSpace();
+ if (Ty.getSizeInBits() > 0)
+ OS << "s" << Ty.getSizeInBits();
+ return;
+ }
llvm_unreachable("Unhandled LLT");
}
@@ -116,6 +122,11 @@ public:
<< Ty.getScalarSizeInBits() << ")";
return;
}
+ if (Ty.isPointer() && Ty.getSizeInBits() > 0) {
+ OS << "LLT::pointer(" << Ty.getAddressSpace() << ", "
+ << Ty.getSizeInBits() << ")";
+ return;
+ }
llvm_unreachable("Unhandled LLT");
}
@@ -152,9 +163,11 @@ class InstructionMatcher;
/// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...).
static Optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) {
MVT VT(SVT);
+
if (VT.isVector() && VT.getVectorNumElements() != 1)
return LLTCodeGen(
LLT::vector(VT.getVectorNumElements(), VT.getScalarSizeInBits()));
+
if (VT.isInteger() || VT.isFloatingPoint())
return LLTCodeGen(LLT::scalar(VT.getSizeInBits()));
return None;
@@ -228,6 +241,11 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {
if (Predicate.isImmediatePattern())
continue;
+ if (Predicate.isLoad() && Predicate.isUnindexed())
+ continue;
+
+ if (Predicate.isNonExtLoad())
+ continue;
HasUnsupportedPredicate = true;
Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")";
Separator = ", ";
@@ -661,6 +679,7 @@ public:
OPM_Int,
OPM_LiteralInt,
OPM_LLT,
+ OPM_PointerToAny,
OPM_RegBank,
OPM_MBB,
};
@@ -748,6 +767,37 @@ public:
std::set<LLTCodeGen> LLTOperandMatcher::KnownTypes;
+/// Generates code to check that an operand is a pointer to any address space.
+///
+/// In SelectionDAG, the types did not describe pointers or address spaces. As a
+/// result, iN is used to describe a pointer of N bits to any address space and
+/// PatFrag predicates are typically used to constrain the address space. There's
+/// no reliable means to derive the missing type information from the pattern so
+/// imported rules must test the components of a pointer separately.
+///
+/// SizeInBits must be non-zero and the matched pointer must be that size.
+/// TODO: Add support for iPTR via SizeInBits==0 and a subtarget query.
+class PointerToAnyOperandMatcher : public OperandPredicateMatcher {
+protected:
+ unsigned SizeInBits;
+
+public:
+ PointerToAnyOperandMatcher(unsigned SizeInBits)
+ : OperandPredicateMatcher(OPM_PointerToAny), SizeInBits(SizeInBits) {}
+
+ static bool classof(const OperandPredicateMatcher *P) {
+ return P->getKind() == OPM_PointerToAny;
+ }
+
+ void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule,
+ unsigned InsnVarID, unsigned OpIdx) const override {
+ Table << MatchTable::Opcode("GIM_CheckPointerToAny") << MatchTable::Comment("MI")
+ << MatchTable::IntValue(InsnVarID) << MatchTable::Comment("Op")
+ << MatchTable::IntValue(OpIdx) << MatchTable::Comment("SizeInBits")
+ << MatchTable::IntValue(SizeInBits) << MatchTable::LineBreak;
+ }
+};
+
/// Generates code to check that an operand is a particular target constant.
class ComplexPatternOperandMatcher : public OperandPredicateMatcher {
protected:
@@ -927,6 +977,22 @@ public:
InstructionMatcher &getInstructionMatcher() const { return Insn; }
+ Error addTypeCheckPredicate(const TypeSetByHwMode &VTy,
+ bool OperandIsAPointer) {
+ auto OpTyOrNone = VTy.isMachineValueType()
+ ? MVTToLLT(VTy.getMachineValueType().SimpleTy)
+ : None;
+ if (!OpTyOrNone)
+ return failedImport("unsupported type");
+
+ if (OperandIsAPointer)
+ addPredicate<PointerToAnyOperandMatcher>(
+ OpTyOrNone->get().getSizeInBits());
+ else
+ addPredicate<LLTOperandMatcher>(*OpTyOrNone);
+ return Error::success();
+ }
+
/// Emit MatchTable opcodes to capture instructions into the MIs table.
void emitCaptureOpcodes(MatchTable &Table, RuleMatcher &Rule,
unsigned InsnVarID) const {
@@ -2070,7 +2136,8 @@ private:
Error importComplexPatternOperandMatcher(OperandMatcher &OM, Record *R,
unsigned &TempOpIdx) const;
Error importChildMatcher(RuleMatcher &Rule, InstructionMatcher &InsnMatcher,
- const TreePatternNode *SrcChild, unsigned OpIdx,
+ const TreePatternNode *SrcChild,
+ bool OperandIsAPointer, unsigned OpIdx,
unsigned &TempOpIdx) const;
Expected<BuildMIAction &>
createAndImportInstructionRenderer(RuleMatcher &M, const TreePatternNode *Dst,
@@ -2164,17 +2231,12 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
unsigned OpIdx = 0;
for (const TypeSetByHwMode &VTy : Src->getExtTypes()) {
- auto OpTyOrNone = VTy.isMachineValueType()
- ? MVTToLLT(VTy.getMachineValueType().SimpleTy)
- : None;
- if (!OpTyOrNone)
- return failedImport(
- "Result of Src pattern operator has an unsupported type");
-
// Results don't have a name unless they are the root node. The caller will
// set the name if appropriate.
OperandMatcher &OM = InsnMatcher.addOperand(OpIdx++, "", TempOpIdx);
- OM.addPredicate<LLTOperandMatcher>(*OpTyOrNone);
+ if (auto Error = OM.addTypeCheckPredicate(VTy, false /* OperandIsAPointer */))
+ return failedImport(toString(std::move(Error)) +
+ " for result of Src pattern operator");
}
for (const auto &Predicate : Src->getPredicateFns()) {
@@ -2186,6 +2248,25 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
continue;
}
+ // No check required. A G_LOAD is an unindexed load.
+ if (Predicate.isLoad() && Predicate.isUnindexed())
+ continue;
+
+ // No check required. G_LOAD by itself is a non-extending load.
+ if (Predicate.isNonExtLoad())
+ continue;
+
+ if (Predicate.isLoad() && Predicate.getMemoryVT() != nullptr) {
+ Optional<LLTCodeGen> MemTyOrNone =
+ MVTToLLT(getValueType(Predicate.getMemoryVT()));
+
+ if (!MemTyOrNone)
+ return failedImport("MemVT could not be converted to LLT");
+
+ InsnMatcher.getOperand(0).addPredicate<LLTOperandMatcher>(MemTyOrNone.getValue());
+ continue;
+ }
+
return failedImport("Src pattern child has predicate (" +
explainPredicates(Src) + ")");
}
@@ -2217,6 +2298,13 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
for (unsigned i = 0, e = Src->getNumChildren(); i != e; ++i) {
TreePatternNode *SrcChild = Src->getChild(i);
+ // SelectionDAG allows pointers to be represented with iN since it doesn't
+ // distinguish between pointers and integers but they are different types in GlobalISel.
+ // Coerce integers to pointers to address space 0 if the context indicates a pointer.
+ // TODO: Find a better way to do this, SDTCisPtrTy?
+ bool OperandIsAPointer =
+ SrcGIOrNull->TheDef->getName() == "G_LOAD" && i == 0;
+
// For G_INTRINSIC/G_INTRINSIC_W_SIDE_EFFECTS, the operand immediately
// following the defs is an intrinsic ID.
if ((SrcGIOrNull->TheDef->getName() == "G_INTRINSIC" ||
@@ -2232,8 +2320,9 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
return failedImport("Expected IntInit containing instrinsic ID)");
}
- if (auto Error = importChildMatcher(Rule, InsnMatcher, SrcChild, OpIdx++,
- TempOpIdx))
+ if (auto Error =
+ importChildMatcher(Rule, InsnMatcher, SrcChild, OperandIsAPointer,
+ OpIdx++, TempOpIdx))
return std::move(Error);
}
}
@@ -2256,6 +2345,7 @@ Error GlobalISelEmitter::importComplexPatternOperandMatcher(
Error GlobalISelEmitter::importChildMatcher(RuleMatcher &Rule,
InstructionMatcher &InsnMatcher,
const TreePatternNode *SrcChild,
+ bool OperandIsAPointer,
unsigned OpIdx,
unsigned &TempOpIdx) const {
OperandMatcher &OM =
@@ -2278,12 +2368,10 @@ Error GlobalISelEmitter::importChildMatcher(RuleMatcher &Rule,
}
}
- Optional<LLTCodeGen> OpTyOrNone = None;
- if (ChildTypes.front().isMachineValueType())
- OpTyOrNone = MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy);
- if (!OpTyOrNone)
- return failedImport("Src operand has an unsupported type (" + to_string(*SrcChild) + ")");
- OM.addPredicate<LLTOperandMatcher>(*OpTyOrNone);
+ if (auto Error =
+ OM.addTypeCheckPredicate(ChildTypes.front(), OperandIsAPointer))
+ return failedImport(toString(std::move(Error)) + " for Src operand (" +
+ to_string(*SrcChild) + ")");
// Check for nested instructions.
if (!SrcChild->isLeaf()) {