summaryrefslogtreecommitdiff
path: root/llvm/utils/TableGen/GlobalISelEmitter.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /llvm/utils/TableGen/GlobalISelEmitter.cpp
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'llvm/utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp250
1 files changed, 192 insertions, 58 deletions
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index c14294951cc11..4e8dcc52fc202 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -448,7 +448,6 @@ public:
: LabelID(LabelID_.hasValue() ? LabelID_.getValue() : ~0u),
EmitStr(EmitStr), NumElements(NumElements), Flags(Flags),
RawValue(RawValue) {
-
assert((!LabelID_.hasValue() || LabelID != ~0u) &&
"This value is reserved for non-labels");
}
@@ -1044,6 +1043,28 @@ public:
for (const auto &Predicate : predicates())
Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...);
}
+
+ /// Provide a function to avoid emitting certain predicates. This is used to
+ /// defer some predicate checks until after others
+ using PredicateFilterFunc = std::function<bool(const PredicateTy&)>;
+
+ /// Emit MatchTable opcodes for predicates which satisfy \p
+ /// ShouldEmitPredicate. This should be called multiple times to ensure all
+ /// predicates are eventually added to the match table.
+ template <class... Args>
+ void emitFilteredPredicateListOpcodes(PredicateFilterFunc ShouldEmitPredicate,
+ MatchTable &Table, Args &&... args) {
+ if (Predicates.empty() && !Optimized) {
+ Table << MatchTable::Comment(getNoPredicateComment())
+ << MatchTable::LineBreak;
+ return;
+ }
+
+ for (const auto &Predicate : predicates()) {
+ if (ShouldEmitPredicate(*Predicate))
+ Predicate->emitPredicateOpcodes(Table, std::forward<Args>(args)...);
+ }
+ }
};
class PredicateMatcher {
@@ -1101,6 +1122,13 @@ public:
PredicateKind getKind() const { return Kind; }
+ bool dependsOnOperands() const {
+ // Custom predicates really depend on the context pattern of the
+ // instruction, not just the individual instruction. This therefore
+ // implicitly depends on all other pattern constraints.
+ return Kind == IPM_GenericPredicate;
+ }
+
virtual bool isIdentical(const PredicateMatcher &B) const {
return B.getKind() == getKind() && InsnVarID == B.InsnVarID &&
OpIdx == B.OpIdx;
@@ -1498,7 +1526,7 @@ public:
const StringRef getSymbolicName() const { return SymbolicName; }
void setSymbolicName(StringRef Name) {
assert(SymbolicName.empty() && "Operand already has a symbolic name");
- SymbolicName = Name;
+ SymbolicName = std::string(Name);
}
/// Construct a new operand predicate and add it to the matcher.
@@ -2128,10 +2156,23 @@ public:
InstructionNumOperandsMatcher(InsnVarID, getNumOperands())
.emitPredicateOpcodes(Table, Rule);
- emitPredicateListOpcodes(Table, Rule);
+ // First emit all instruction level predicates need to be verified before we
+ // can verify operands.
+ emitFilteredPredicateListOpcodes(
+ [](const PredicateMatcher &P) {
+ return !P.dependsOnOperands();
+ }, Table, Rule);
+ // Emit all operand constraints.
for (const auto &Operand : Operands)
Operand->emitPredicateOpcodes(Table, Rule);
+
+ // All of the tablegen defined predicates should now be matched. Now emit
+ // any custom predicates that rely on all generated checks.
+ emitFilteredPredicateListOpcodes(
+ [](const PredicateMatcher &P) {
+ return P.dependsOnOperands();
+ }, Table, Rule);
}
/// Compare the priority of this object and B.
@@ -2585,26 +2626,37 @@ class TempRegRenderer : public OperandRenderer {
protected:
unsigned InsnID;
unsigned TempRegID;
+ const CodeGenSubRegIndex *SubRegIdx;
bool IsDef;
public:
- TempRegRenderer(unsigned InsnID, unsigned TempRegID, bool IsDef = false)
+ TempRegRenderer(unsigned InsnID, unsigned TempRegID, bool IsDef = false,
+ const CodeGenSubRegIndex *SubReg = nullptr)
: OperandRenderer(OR_Register), InsnID(InsnID), TempRegID(TempRegID),
- IsDef(IsDef) {}
+ SubRegIdx(SubReg), IsDef(IsDef) {}
static bool classof(const OperandRenderer *R) {
return R->getKind() == OR_TempRegister;
}
void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
- Table << MatchTable::Opcode("GIR_AddTempRegister")
- << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
+ if (SubRegIdx) {
+ assert(!IsDef);
+ Table << MatchTable::Opcode("GIR_AddTempSubRegister");
+ } else
+ Table << MatchTable::Opcode("GIR_AddTempRegister");
+
+ Table << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
<< MatchTable::Comment("TempRegID") << MatchTable::IntValue(TempRegID)
<< MatchTable::Comment("TempRegFlags");
+
if (IsDef)
Table << MatchTable::NamedValue("RegState::Define");
else
Table << MatchTable::IntValue(0);
+
+ if (SubRegIdx)
+ Table << MatchTable::NamedValue(SubRegIdx->getQualifiedName());
Table << MatchTable::LineBreak;
}
};
@@ -2779,7 +2831,7 @@ private:
std::string S;
public:
- DebugCommentAction(StringRef S) : S(S) {}
+ DebugCommentAction(StringRef S) : S(std::string(S)) {}
void emitActionOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
Table << MatchTable::Comment(S) << MatchTable::LineBreak;
@@ -2950,8 +3002,8 @@ public:
Table << MatchTable::Opcode("GIR_ConstrainOperandRC")
<< MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
<< MatchTable::Comment("Op") << MatchTable::IntValue(OpIdx)
- << MatchTable::Comment("RC " + RC.getName())
- << MatchTable::IntValue(RC.EnumValue) << MatchTable::LineBreak;
+ << MatchTable::NamedValue(RC.getQualifiedName() + "RegClassID")
+ << MatchTable::LineBreak;
}
};
@@ -3260,6 +3312,22 @@ void SameOperandMatcher::emitPredicateOpcodes(MatchTable &Table,
//===- GlobalISelEmitter class --------------------------------------------===//
+static Expected<LLTCodeGen> getInstResultType(const TreePatternNode *Dst) {
+ ArrayRef<TypeSetByHwMode> ChildTypes = Dst->getExtTypes();
+ if (ChildTypes.size() != 1)
+ return failedImport("Dst pattern child has multiple results");
+
+ Optional<LLTCodeGen> MaybeOpTy;
+ if (ChildTypes.front().isMachineValueType()) {
+ MaybeOpTy =
+ MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy);
+ }
+
+ if (!MaybeOpTy)
+ return failedImport("Dst operand has an unsupported type");
+ return *MaybeOpTy;
+}
+
class GlobalISelEmitter {
public:
explicit GlobalISelEmitter(RecordKeeper &RK);
@@ -3269,7 +3337,7 @@ private:
const RecordKeeper &RK;
const CodeGenDAGPatterns CGP;
const CodeGenTarget &Target;
- CodeGenRegBank CGRegs;
+ CodeGenRegBank &CGRegs;
/// Keep track of the equivalence between SDNodes and Instruction by mapping
/// SDNodes to the GINodeEquiv mapping. We need to map to the GINodeEquiv to
@@ -3477,7 +3545,7 @@ GlobalISelEmitter::getEquivNode(Record &Equiv, const TreePatternNode *N) const {
GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
: RK(RK), CGP(RK), Target(CGP.getTargetInfo()),
- CGRegs(RK, Target.getHwModes()) {}
+ CGRegs(Target.getRegBank()) {}
//===- Emitter ------------------------------------------------------------===//
@@ -3737,7 +3805,7 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
CCDef->getValueAsString("ICmpPredicate");
if (!PredType.empty()) {
- OM.addPredicate<CmpPredicateOperandMatcher>(PredType);
+ OM.addPredicate<CmpPredicateOperandMatcher>(std::string(PredType));
// Process the other 2 operands normally.
--NumChildren;
}
@@ -3836,9 +3904,10 @@ Error GlobalISelEmitter::importChildMatcher(
Record *PhysReg = nullptr;
StringRef SrcChildName = getSrcChildName(SrcChild, PhysReg);
- OperandMatcher &OM = PhysReg ?
- InsnMatcher.addPhysRegInput(PhysReg, OpIdx, TempOpIdx) :
- InsnMatcher.addOperand(OpIdx, SrcChildName, TempOpIdx);
+ OperandMatcher &OM =
+ PhysReg
+ ? InsnMatcher.addPhysRegInput(PhysReg, OpIdx, TempOpIdx)
+ : InsnMatcher.addOperand(OpIdx, std::string(SrcChildName), TempOpIdx);
if (OM.isSameAsAnotherOperand())
return Error::success();
@@ -3971,6 +4040,10 @@ Error GlobalISelEmitter::importChildMatcher(
"Src pattern child def is an unsupported tablegen class (ImmLeaf)");
}
+ // Place holder for SRCVALUE nodes. Nothing to do here.
+ if (ChildRec->getName() == "srcvalue")
+ return Error::success();
+
return failedImport(
"Src pattern child def is an unsupported tablegen class");
}
@@ -4040,20 +4113,13 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
}
if (DstChild->getOperator()->isSubClassOf("Instruction")) {
- ArrayRef<TypeSetByHwMode> ChildTypes = DstChild->getExtTypes();
- if (ChildTypes.size() != 1)
- return failedImport("Dst pattern child has multiple results");
-
- Optional<LLTCodeGen> OpTyOrNone = None;
- if (ChildTypes.front().isMachineValueType())
- OpTyOrNone =
- MVTToLLT(ChildTypes.front().getMachineValueType().SimpleTy);
- if (!OpTyOrNone)
- return failedImport("Dst operand has an unsupported type");
+ auto OpTy = getInstResultType(DstChild);
+ if (!OpTy)
+ return OpTy.takeError();
unsigned TempRegID = Rule.allocateTempRegID();
InsertPt = Rule.insertAction<MakeTempRegisterAction>(
- InsertPt, OpTyOrNone.getValue(), TempRegID);
+ InsertPt, *OpTy, TempRegID);
DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID);
auto InsertPtOrError = createAndImportSubInstructionRenderer(
@@ -4225,7 +4291,7 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
if (!SubIdx)
return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
- const auto &SrcRCDstRCPair =
+ const auto SrcRCDstRCPair =
(*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
M.insertAction<ConstrainOperandToRegClassAction>(
@@ -4257,6 +4323,29 @@ GlobalISelEmitter::createAndImportSubInstructionRenderer(
return InsertPtOrError.get();
}
+ if (OpName == "REG_SEQUENCE") {
+ auto SuperClass = inferRegClassFromPattern(Dst->getChild(0));
+ M.insertAction<ConstrainOperandToRegClassAction>(
+ InsertPt, DstMIBuilder.getInsnID(), 0, **SuperClass);
+
+ unsigned Num = Dst->getNumChildren();
+ for (unsigned I = 1; I != Num; I += 2) {
+ TreePatternNode *SubRegChild = Dst->getChild(I + 1);
+
+ auto SubIdx = inferSubRegIndexForNode(SubRegChild);
+ if (!SubIdx)
+ return failedImport("REG_SEQUENCE child is not a subreg index");
+
+ const auto SrcRCDstRCPair =
+ (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
+ assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
+ M.insertAction<ConstrainOperandToRegClassAction>(
+ InsertPt, DstMIBuilder.getInsnID(), I, *SrcRCDstRCPair->second);
+ }
+
+ return InsertPtOrError.get();
+ }
+
M.insertAction<ConstrainOperandsToDefinitionAction>(InsertPt,
DstMIBuilder.getInsnID());
return InsertPtOrError.get();
@@ -4303,33 +4392,51 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderers(
// EXTRACT_SUBREG needs to use a subregister COPY.
if (Name == "EXTRACT_SUBREG") {
- if (!Dst->getChild(0)->isLeaf())
- return failedImport("EXTRACT_SUBREG child #1 is not a leaf");
-
- if (DefInit *SubRegInit =
- dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue())) {
- Record *RCDef = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());
- if (!RCDef)
- return failedImport("EXTRACT_SUBREG child #0 could not "
- "be coerced to a register class");
-
- CodeGenRegisterClass *RC = CGRegs.getRegClass(RCDef);
- CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
-
- const auto &SrcRCDstRCPair =
- RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
- if (SrcRCDstRCPair.hasValue()) {
- assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
- if (SrcRCDstRCPair->first != RC)
- return failedImport("EXTRACT_SUBREG requires an additional COPY");
- }
+ DefInit *SubRegInit = dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue());
+ if (!SubRegInit)
+ return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
+
+ CodeGenSubRegIndex *SubIdx = CGRegs.getSubRegIdx(SubRegInit->getDef());
+ TreePatternNode *ValChild = Dst->getChild(0);
+ if (!ValChild->isLeaf()) {
+ // We really have to handle the source instruction, and then insert a
+ // copy from the subregister.
+ auto ExtractSrcTy = getInstResultType(ValChild);
+ if (!ExtractSrcTy)
+ return ExtractSrcTy.takeError();
+
+ unsigned TempRegID = M.allocateTempRegID();
+ InsertPt = M.insertAction<MakeTempRegisterAction>(
+ InsertPt, *ExtractSrcTy, TempRegID);
- DstMIBuilder.addRenderer<CopySubRegRenderer>(Dst->getChild(0)->getName(),
- SubIdx);
+ auto InsertPtOrError = createAndImportSubInstructionRenderer(
+ ++InsertPt, M, ValChild, TempRegID);
+ if (auto Error = InsertPtOrError.takeError())
+ return std::move(Error);
+
+ DstMIBuilder.addRenderer<TempRegRenderer>(TempRegID, false, SubIdx);
return InsertPt;
}
- return failedImport("EXTRACT_SUBREG child #1 is not a subreg index");
+ // If this is a source operand, this is just a subregister copy.
+ Record *RCDef = getInitValueAsRegClass(ValChild->getLeafValue());
+ if (!RCDef)
+ return failedImport("EXTRACT_SUBREG child #0 could not "
+ "be coerced to a register class");
+
+ CodeGenRegisterClass *RC = CGRegs.getRegClass(RCDef);
+
+ const auto SrcRCDstRCPair =
+ RC->getMatchingSubClassWithSubRegs(CGRegs, SubIdx);
+ if (SrcRCDstRCPair.hasValue()) {
+ assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
+ if (SrcRCDstRCPair->first != RC)
+ return failedImport("EXTRACT_SUBREG requires an additional COPY");
+ }
+
+ DstMIBuilder.addRenderer<CopySubRegRenderer>(Dst->getChild(0)->getName(),
+ SubIdx);
+ return InsertPt;
}
if (Name == "REG_SEQUENCE") {
@@ -4731,15 +4838,13 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
if (DstIOpRec == nullptr)
return failedImport("REG_SEQUENCE operand #0 isn't a register class");
} else if (DstIName == "EXTRACT_SUBREG") {
- if (!Dst->getChild(0)->isLeaf())
- return failedImport("EXTRACT_SUBREG operand #0 isn't a leaf");
+ auto InferredClass = inferRegClassFromPattern(Dst->getChild(0));
+ if (!InferredClass)
+ return failedImport("Could not infer class for EXTRACT_SUBREG operand #0");
// We can assume that a subregister is in the same bank as it's super
// register.
- DstIOpRec = getInitValueAsRegClass(Dst->getChild(0)->getLeafValue());
-
- if (DstIOpRec == nullptr)
- return failedImport("EXTRACT_SUBREG operand #0 isn't a register class");
+ DstIOpRec = (*InferredClass)->getDef();
} else if (DstIName == "INSERT_SUBREG") {
auto MaybeSuperClass = inferSuperRegisterClassForNode(
VTy, Dst->getChild(0), Dst->getChild(2));
@@ -4832,8 +4937,13 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
assert(Src->getExtTypes().size() == 1 &&
"Expected Src of EXTRACT_SUBREG to have one result type");
- const auto &SrcRCDstRCPair =
+ const auto SrcRCDstRCPair =
(*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
+ if (!SrcRCDstRCPair) {
+ return failedImport("subreg index is incompatible "
+ "with inferred reg class");
+ }
+
assert(SrcRCDstRCPair->second && "Couldn't find a matching subclass");
M.addAction<ConstrainOperandToRegClassAction>(0, 0, *SrcRCDstRCPair->second);
M.addAction<ConstrainOperandToRegClassAction>(0, 1, *SrcRCDstRCPair->first);
@@ -4889,6 +4999,30 @@ Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
return std::move(M);
}
+ if (DstIName == "REG_SEQUENCE") {
+ auto SuperClass = inferRegClassFromPattern(Dst->getChild(0));
+
+ M.addAction<ConstrainOperandToRegClassAction>(0, 0, **SuperClass);
+
+ unsigned Num = Dst->getNumChildren();
+ for (unsigned I = 1; I != Num; I += 2) {
+ TreePatternNode *SubRegChild = Dst->getChild(I + 1);
+
+ auto SubIdx = inferSubRegIndexForNode(SubRegChild);
+ if (!SubIdx)
+ return failedImport("REG_SEQUENCE child is not a subreg index");
+
+ const auto SrcRCDstRCPair =
+ (*SuperClass)->getMatchingSubClassWithSubRegs(CGRegs, *SubIdx);
+
+ M.addAction<ConstrainOperandToRegClassAction>(0, I,
+ *SrcRCDstRCPair->second);
+ }
+
+ ++NumPatternImported;
+ return std::move(M);
+ }
+
M.addAction<ConstrainOperandsToDefinitionAction>(0);
// We're done with this pattern! It's eligible for GISel emission; return it.