summaryrefslogtreecommitdiff
path: root/utils/TableGen/GlobalISelEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r--utils/TableGen/GlobalISelEmitter.cpp157
1 files changed, 138 insertions, 19 deletions
diff --git a/utils/TableGen/GlobalISelEmitter.cpp b/utils/TableGen/GlobalISelEmitter.cpp
index 997ceb12becd..f1c02134198b 100644
--- a/utils/TableGen/GlobalISelEmitter.cpp
+++ b/utils/TableGen/GlobalISelEmitter.cpp
@@ -1,9 +1,8 @@
//===- GlobalISelEmitter.cpp - Generate an instruction selector -----------===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
@@ -233,6 +232,23 @@ static std::string explainPredicates(const TreePatternNode *N) {
if (Record *VT = P.getScalarMemoryVT())
Explanation += (" ScalarVT(MemVT)=" + VT->getName()).str();
+ if (ListInit *AddrSpaces = P.getAddressSpaces()) {
+ raw_string_ostream OS(Explanation);
+ OS << " AddressSpaces=[";
+
+ StringRef AddrSpaceSeparator;
+ for (Init *Val : AddrSpaces->getValues()) {
+ IntInit *IntVal = dyn_cast<IntInit>(Val);
+ if (!IntVal)
+ continue;
+
+ OS << AddrSpaceSeparator << IntVal->getValue();
+ AddrSpaceSeparator = ", ";
+ }
+
+ OS << ']';
+ }
+
if (P.isAtomicOrderingMonotonic())
Explanation += " monotonic";
if (P.isAtomicOrderingAcquire())
@@ -298,7 +314,7 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {
Predicate.isSignExtLoad() || Predicate.isZeroExtLoad())
continue;
- if (Predicate.isNonTruncStore())
+ if (Predicate.isNonTruncStore() || Predicate.isTruncStore())
continue;
if (Predicate.isLoad() && Predicate.getMemoryVT())
@@ -309,6 +325,12 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {
continue;
}
+ if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
+ const ListInit *AddrSpaces = Predicate.getAddressSpaces();
+ if (AddrSpaces && !AddrSpaces->empty())
+ continue;
+ }
+
if (Predicate.isAtomic() && Predicate.getMemoryVT())
continue;
@@ -882,12 +904,19 @@ public:
void defineOperand(StringRef SymbolicName, OperandMatcher &OM);
- void defineComplexSubOperand(StringRef SymbolicName, Record *ComplexPattern,
- unsigned RendererID, unsigned SubOperandID) {
- assert(ComplexSubOperands.count(SymbolicName) == 0 && "Already defined");
+ Error defineComplexSubOperand(StringRef SymbolicName, Record *ComplexPattern,
+ unsigned RendererID, unsigned SubOperandID) {
+ if (ComplexSubOperands.count(SymbolicName))
+ return failedImport(
+ "Complex suboperand referenced more than once (Operand: " +
+ SymbolicName + ")");
+
ComplexSubOperands[SymbolicName] =
std::make_tuple(ComplexPattern, RendererID, SubOperandID);
+
+ return Error::success();
}
+
Optional<DefinedComplexPatternSubOperand>
getComplexSubOperand(StringRef SymbolicName) const {
const auto &I = ComplexSubOperands.find(SymbolicName);
@@ -1022,6 +1051,7 @@ public:
IPM_AtomicOrderingMMO,
IPM_MemoryLLTSize,
IPM_MemoryVsLLTSize,
+ IPM_MemoryAddressSpace,
IPM_GenericPredicate,
OPM_SameOperand,
OPM_ComplexPattern,
@@ -1507,6 +1537,9 @@ Error OperandMatcher::addTypeCheckPredicate(const TypeSetByHwMode &VTy,
if (OperandIsAPointer)
addPredicate<PointerToAnyOperandMatcher>(OpTyOrNone->get().getSizeInBits());
+ else if (VTy.isPointer())
+ addPredicate<LLTOperandMatcher>(LLT::pointer(VTy.getPtrAddrSpace(),
+ OpTyOrNone->get().getSizeInBits()));
else
addPredicate<LLTOperandMatcher>(*OpTyOrNone);
return Error::success();
@@ -1780,6 +1813,42 @@ public:
}
};
+class MemoryAddressSpacePredicateMatcher : public InstructionPredicateMatcher {
+protected:
+ unsigned MMOIdx;
+ SmallVector<unsigned, 4> AddrSpaces;
+
+public:
+ MemoryAddressSpacePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx,
+ ArrayRef<unsigned> AddrSpaces)
+ : InstructionPredicateMatcher(IPM_MemoryAddressSpace, InsnVarID),
+ MMOIdx(MMOIdx), AddrSpaces(AddrSpaces.begin(), AddrSpaces.end()) {}
+
+ static bool classof(const PredicateMatcher *P) {
+ return P->getKind() == IPM_MemoryAddressSpace;
+ }
+ bool isIdentical(const PredicateMatcher &B) const override {
+ if (!InstructionPredicateMatcher::isIdentical(B))
+ return false;
+ auto *Other = cast<MemoryAddressSpacePredicateMatcher>(&B);
+ return MMOIdx == Other->MMOIdx && AddrSpaces == Other->AddrSpaces;
+ }
+
+ void emitPredicateOpcodes(MatchTable &Table,
+ RuleMatcher &Rule) const override {
+ Table << MatchTable::Opcode("GIM_CheckMemoryAddressSpace")
+ << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
+ << MatchTable::Comment("MMO") << MatchTable::IntValue(MMOIdx)
+ // Encode number of address spaces to expect.
+ << MatchTable::Comment("NumAddrSpace")
+ << MatchTable::IntValue(AddrSpaces.size());
+ for (unsigned AS : AddrSpaces)
+ Table << MatchTable::Comment("AddrSpace") << MatchTable::IntValue(AS);
+
+ Table << MatchTable::LineBreak;
+ }
+};
+
/// Generates code to check that the size of an MMO is less-than, equal-to, or
/// greater than a given LLT.
class MemoryVsLLTSizePredicateMatcher : public InstructionPredicateMatcher {
@@ -3028,7 +3097,8 @@ private:
importExplicitUseRenderer(action_iterator InsertPt, RuleMatcher &Rule,
BuildMIAction &DstMIBuilder,
TreePatternNode *DstChild);
- Error importDefaultOperandRenderers(BuildMIAction &DstMIBuilder,
+ Error importDefaultOperandRenderers(action_iterator InsertPt, RuleMatcher &M,
+ BuildMIAction &DstMIBuilder,
DagInit *DefaultOps) const;
Error
importImplicitDefRenderers(BuildMIAction &DstMIBuilder,
@@ -3200,7 +3270,26 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
continue;
}
- // G_LOAD is used for both non-extending and any-extending loads.
+ // An address space check is needed in all contexts if there is one.
+ if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
+ if (const ListInit *AddrSpaces = Predicate.getAddressSpaces()) {
+ SmallVector<unsigned, 4> ParsedAddrSpaces;
+
+ for (Init *Val : AddrSpaces->getValues()) {
+ IntInit *IntVal = dyn_cast<IntInit>(Val);
+ if (!IntVal)
+ return failedImport("Address space is not an integer");
+ ParsedAddrSpaces.push_back(IntVal->getValue());
+ }
+
+ if (!ParsedAddrSpaces.empty()) {
+ InsnMatcher.addPredicate<MemoryAddressSpacePredicateMatcher>(
+ 0, ParsedAddrSpaces);
+ }
+ }
+ }
+
+ // G_LOAD is used for both non-extending and any-extending loads.
if (Predicate.isLoad() && Predicate.isNonExtLoad()) {
InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0);
@@ -3212,6 +3301,13 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
continue;
}
+ if (Predicate.isStore() && Predicate.isTruncStore()) {
+ // FIXME: If MemoryVT is set, we end up with 2 checks for the MMO size.
+ InsnMatcher.addPredicate<MemoryVsLLTSizePredicateMatcher>(
+ 0, MemoryVsLLTSizePredicateMatcher::LessThan, 0);
+ continue;
+ }
+
// No check required. We already did it by swapping the opcode.
if (!SrcGIEquivOrNull->isValueUnset("IfSignExtend") &&
Predicate.isSignExtLoad())
@@ -3422,9 +3518,12 @@ Error GlobalISelEmitter::importChildMatcher(RuleMatcher &Rule,
for (unsigned i = 0, e = SrcChild->getNumChildren(); i != e; ++i) {
auto *SubOperand = SrcChild->getChild(i);
- if (!SubOperand->getName().empty())
- Rule.defineComplexSubOperand(SubOperand->getName(),
- SrcChild->getOperator(), RendererID, i);
+ if (!SubOperand->getName().empty()) {
+ if (auto Error = Rule.defineComplexSubOperand(SubOperand->getName(),
+ SrcChild->getOperator(),
+ RendererID, i))
+ return Error;
+ }
}
return Error::success();
@@ -3765,7 +3864,8 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
// end up with too many rendered operands.
if (DstIOperand.Rec->isSubClassOf("OperandWithDefaultOps")) {
DagInit *DefaultOps = DstIOperand.Rec->getValueAsDag("DefaultOps");
- if (auto Error = importDefaultOperandRenderers(DstMIBuilder, DefaultOps))
+ if (auto Error = importDefaultOperandRenderers(
+ InsertPt, M, DstMIBuilder, DefaultOps))
return std::move(Error);
++NumDefaultOps;
continue;
@@ -3790,19 +3890,39 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
}
Error GlobalISelEmitter::importDefaultOperandRenderers(
- BuildMIAction &DstMIBuilder, DagInit *DefaultOps) const {
+ action_iterator InsertPt, RuleMatcher &M, BuildMIAction &DstMIBuilder,
+ DagInit *DefaultOps) const {
for (const auto *DefaultOp : DefaultOps->getArgs()) {
+ Optional<LLTCodeGen> OpTyOrNone = None;
+
// Look through ValueType operators.
if (const DagInit *DefaultDagOp = dyn_cast<DagInit>(DefaultOp)) {
if (const DefInit *DefaultDagOperator =
dyn_cast<DefInit>(DefaultDagOp->getOperator())) {
- if (DefaultDagOperator->getDef()->isSubClassOf("ValueType"))
+ if (DefaultDagOperator->getDef()->isSubClassOf("ValueType")) {
+ OpTyOrNone = MVTToLLT(getValueType(
+ DefaultDagOperator->getDef()));
DefaultOp = DefaultDagOp->getArg(0);
+ }
}
}
if (const DefInit *DefaultDefOp = dyn_cast<DefInit>(DefaultOp)) {
- DstMIBuilder.addRenderer<AddRegisterRenderer>(DefaultDefOp->getDef());
+ auto Def = DefaultDefOp->getDef();
+ if (Def->getName() == "undef_tied_input") {
+ unsigned TempRegID = M.allocateTempRegID();
+ M.insertAction<MakeTempRegisterAction>(
+ InsertPt, OpTyOrNone.getValue(), TempRegID);
+ InsertPt = M.insertAction<BuildMIAction>(
+ InsertPt, M.allocateOutputInsnID(),
+ &Target.getInstruction(RK.getDef("IMPLICIT_DEF")));
+ BuildMIAction &IDMIBuilder = *static_cast<BuildMIAction *>(
+ InsertPt->get());
+ IDMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
+ DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
+ } else {
+ DstMIBuilder.addRenderer<AddRegisterRenderer>(Def);
+ }
continue;
}
@@ -4489,8 +4609,7 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
<< ", // " << Record->getName() << "\n";
OS << "};\n\n";
- std::stable_sort(Rules.begin(), Rules.end(), [&](const RuleMatcher &A,
- const RuleMatcher &B) {
+ llvm::stable_sort(Rules, [&](const RuleMatcher &A, const RuleMatcher &B) {
int ScoreA = RuleMatcherScores[A.getRuleID()];
int ScoreB = RuleMatcherScores[B.getRuleID()];
if (ScoreA > ScoreB)