summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen/GlobalISelEmitter.cpp
diff options
context:
space:
mode:
authorMatt Arsenault <Matthew.Arsenault@amd.com>2020-01-08 12:53:15 -0500
committerMatt Arsenault <arsenm2@gmail.com>2020-01-09 17:37:52 -0500
commitb4a647449fa01bd4e29bce5afef51770cddec664 (patch)
tree2b73e8bf2fb3b3e6a18121a77c11378fc11c3fb5 /llvm/utils/TableGen/GlobalISelEmitter.cpp
parent0ea3c7291fb8d463d9c7ae6aaec7a432ef366a51 (diff)
downloadbcm5719-llvm-b4a647449fa01bd4e29bce5afef51770cddec664.tar.gz
bcm5719-llvm-b4a647449fa01bd4e29bce5afef51770cddec664.zip
TableGen/GlobalISel: Add way for SDNodeXForm to work on timm
The current implementation assumes there is an instruction associated with the transform, but this is not the case for timm/TargetConstant/immarg values. These transforms should directly operate on a specific MachineOperand in the source instruction. TableGen would assert if you attempted to define an equivalent GISDNodeXFormEquiv using timm when it failed to find the instruction matcher. Specially recognize SDNodeXForms on timm, and pass the operand index to the render function. Ideally this would be a separate render function type that looks like void renderFoo(MachineInstrBuilder, const MachineOperand&), but this proved to be somewhat mechanically painful. Add an optional operand index which will only be passed if the transform should only look at the one source operand. Theoretically it would also be possible to only ever pass the MachineOperand, and the existing renderers would check the parent. I think that would be somewhat ugly for the standard usage which may want to inspect other operands, and I also think MachineOperand should eventually not carry a pointer to the parent instruction. Use it in one sample pattern. This isn't a great example, since the transform exists to satisfy DAG type constraints. This could also be avoided by just changing the MachineInstr's arbitrary choice of operand type from i16 to i32. Other patterns have nontrivial uses, but this serves as the simplest example. One flaw this still has is if you try to use an SDNodeXForm defined for imm, but the source pattern uses timm, you still see the "Failed to lookup instruction" assert. However, there is now a way to avoid it.
Diffstat (limited to 'llvm/utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp51
1 files changed, 47 insertions, 4 deletions
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index ba45d8d170c..ab6836b3681 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -2318,7 +2318,8 @@ public:
OR_Register,
OR_TempRegister,
OR_ComplexPattern,
- OR_Custom
+ OR_Custom,
+ OR_CustomOperand
};
protected:
@@ -2726,6 +2727,38 @@ public:
}
};
+class CustomOperandRenderer : public OperandRenderer {
+protected:
+ unsigned InsnID;
+ const Record &Renderer;
+ /// The name of the operand.
+ const std::string SymbolicName;
+
+public:
+ CustomOperandRenderer(unsigned InsnID, const Record &Renderer,
+ StringRef SymbolicName)
+ : OperandRenderer(OR_CustomOperand), InsnID(InsnID), Renderer(Renderer),
+ SymbolicName(SymbolicName) {}
+
+ static bool classof(const OperandRenderer *R) {
+ return R->getKind() == OR_CustomOperand;
+ }
+
+ void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
+ const OperandMatcher &OpdMatcher = Rule.getOperandMatcher(SymbolicName);
+ Table << MatchTable::Opcode("GIR_CustomOperandRenderer")
+ << MatchTable::Comment("InsnID") << MatchTable::IntValue(InsnID)
+ << MatchTable::Comment("OldInsnID")
+ << MatchTable::IntValue(OpdMatcher.getInsnVarID())
+ << MatchTable::Comment("OpIdx")
+ << MatchTable::IntValue(OpdMatcher.getOpIdx())
+ << MatchTable::Comment("OperandRenderer")
+ << MatchTable::NamedValue(
+ "GICR_" + Renderer.getValueAsString("RendererFn").str())
+ << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
+ }
+};
+
/// An action taken when all Matcher predicates succeeded for a parent rule.
///
/// Typical actions include:
@@ -3939,12 +3972,22 @@ Expected<action_iterator> GlobalISelEmitter::importExplicitUseRenderer(
}
if (!DstChild->isLeaf()) {
-
if (DstChild->getOperator()->isSubClassOf("SDNodeXForm")) {
auto Child = DstChild->getChild(0);
auto I = SDNodeXFormEquivs.find(DstChild->getOperator());
if (I != SDNodeXFormEquivs.end()) {
- DstMIBuilder.addRenderer<CustomRenderer>(*I->second, Child->getName());
+ Record *XFormOpc = DstChild->getOperator()->getValueAsDef("Opcode");
+ if (XFormOpc->getName() == "timm") {
+ // If this is a TargetConstant, there won't be a corresponding
+ // instruction to transform. Instead, this will refer directly to an
+ // operand in an instruction's operand list.
+ DstMIBuilder.addRenderer<CustomOperandRenderer>(*I->second,
+ Child->getName());
+ } else {
+ DstMIBuilder.addRenderer<CustomRenderer>(*I->second,
+ Child->getName());
+ }
+
return InsertPt;
}
return failedImport("SDNodeXForm " + Child->getName() +
@@ -5112,7 +5155,7 @@ void GlobalISelEmitter::run(raw_ostream &OS) {
<< " typedef void(" << Target.getName()
<< "InstructionSelector::*CustomRendererFn)(MachineInstrBuilder &, const "
- "MachineInstr&) "
+ "MachineInstr&, int) "
"const;\n"
<< " const ISelInfoTy<PredicateBitset, ComplexMatcherMemFn, "
"CustomRendererFn> "
OpenPOWER on IntegriCloud