summaryrefslogtreecommitdiffstats
path: root/llvm/utils/TableGen/GlobalISelEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/utils/TableGen/GlobalISelEmitter.cpp')
-rw-r--r--llvm/utils/TableGen/GlobalISelEmitter.cpp80
1 files changed, 79 insertions, 1 deletions
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp
index c14c675aff4..d04d232744a 100644
--- a/llvm/utils/TableGen/GlobalISelEmitter.cpp
+++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -246,6 +246,13 @@ static Error isTrivialOperatorNode(const TreePatternNode *N) {
if (Predicate.isNonExtLoad())
continue;
+
+ if (Predicate.isStore() && Predicate.isUnindexed())
+ continue;
+
+ if (Predicate.isNonTruncStore())
+ continue;
+
HasUnsupportedPredicate = true;
Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")";
Separator = ", ";
@@ -1419,6 +1426,7 @@ class OperandRenderer {
public:
enum RendererKind {
OR_Copy,
+ OR_CopyOrAddZeroReg,
OR_CopySubReg,
OR_CopyConstantAsImm,
OR_CopyFConstantAsFPImm,
@@ -1477,6 +1485,48 @@ public:
}
};
+/// A CopyOrAddZeroRegRenderer emits code to copy a single operand from an
+/// existing instruction to the one being built. If the operand turns out to be
+/// a 'G_CONSTANT 0' then it replaces the operand with a zero register.
+class CopyOrAddZeroRegRenderer : public OperandRenderer {
+protected:
+ unsigned NewInsnID;
+ /// The name of the operand.
+ const StringRef SymbolicName;
+ const Record *ZeroRegisterDef;
+
+public:
+ CopyOrAddZeroRegRenderer(unsigned NewInsnID,
+ const InstructionMatcher &Matched,
+ StringRef SymbolicName, Record *ZeroRegisterDef)
+ : OperandRenderer(OR_CopyOrAddZeroReg), NewInsnID(NewInsnID),
+ SymbolicName(SymbolicName), ZeroRegisterDef(ZeroRegisterDef) {
+ assert(!SymbolicName.empty() && "Cannot copy from an unspecified source");
+ }
+
+ static bool classof(const OperandRenderer *R) {
+ return R->getKind() == OR_CopyOrAddZeroReg;
+ }
+
+ const StringRef getSymbolicName() const { return SymbolicName; }
+
+ void emitRenderOpcodes(MatchTable &Table, RuleMatcher &Rule) const override {
+ const OperandMatcher &Operand = Rule.getOperandMatcher(SymbolicName);
+ unsigned OldInsnVarID = Rule.getInsnVarID(Operand.getInstructionMatcher());
+ Table << MatchTable::Opcode("GIR_CopyOrAddZeroReg")
+ << MatchTable::Comment("NewInsnID") << MatchTable::IntValue(NewInsnID)
+ << MatchTable::Comment("OldInsnID")
+ << MatchTable::IntValue(OldInsnVarID) << MatchTable::Comment("OpIdx")
+ << MatchTable::IntValue(Operand.getOperandIndex())
+ << MatchTable::NamedValue(
+ (ZeroRegisterDef->getValue("Namespace")
+ ? ZeroRegisterDef->getValueAsString("Namespace")
+ : ""),
+ ZeroRegisterDef->getName())
+ << MatchTable::Comment(SymbolicName) << MatchTable::LineBreak;
+ }
+};
+
/// A CopyConstantAsImmRenderer emits code to render a G_CONSTANT instruction to
/// an extended immediate operand.
class CopyConstantAsImmRenderer : public OperandRenderer {
@@ -2275,6 +2325,25 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
continue;
}
+ // No check required. A G_STORE is an unindexed store.
+ if (Predicate.isStore() && Predicate.isUnindexed())
+ continue;
+
+ // No check required. G_STORE by itself is a non-extending store.
+ if (Predicate.isNonTruncStore())
+ continue;
+
+ if (Predicate.isStore() && 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) + ")");
}
@@ -2311,7 +2380,8 @@ Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
// 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;
+ (SrcGIOrNull->TheDef->getName() == "G_LOAD" && i == 0) ||
+ (SrcGIOrNull->TheDef->getName() == "G_STORE" && i == 1);
// For G_INTRINSIC/G_INTRINSIC_W_SIDE_EFFECTS, the operand immediately
// following the defs is an intrinsic ID.
@@ -2530,6 +2600,14 @@ Error GlobalISelEmitter::importExplicitUseRenderer(
if (ChildRec->isSubClassOf("RegisterClass") ||
ChildRec->isSubClassOf("RegisterOperand") ||
ChildRec->isSubClassOf("ValueType")) {
+ if (ChildRec->isSubClassOf("RegisterOperand") &&
+ !ChildRec->isValueUnset("GIZeroRegister")) {
+ DstMIBuilder.addRenderer<CopyOrAddZeroRegRenderer>(
+ 0, InsnMatcher, DstChild->getName(),
+ ChildRec->getValueAsDef("GIZeroRegister"));
+ return Error::success();
+ }
+
DstMIBuilder.addRenderer<CopyRenderer>(0, InsnMatcher,
DstChild->getName());
return Error::success();
OpenPOWER on IntegriCloud