class GINodeEquiv<Instruction i, SDNode node> {
Instruction I = i;
SDNode Node = node;
+
+ // SelectionDAG has separate nodes for atomic and non-atomic memory operations
+ // (ISD::LOAD, ISD::ATOMIC_LOAD, ISD::STORE, ISD::ATOMIC_STORE) but GlobalISel
+ // stores this information in the MachineMemoryOperand.
+ bit CheckMMOIsNonAtomic = 0;
}
// These are defined in the same order as the G_* instructions.
def : GINodeEquiv<G_BR, br>;
def : GINodeEquiv<G_BSWAP, bswap>;
+// Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some
+// complications that tablegen must take care of. For example, Predicates such
+// as isSignExtLoad require that this is not a perfect 1:1 mapping since a
+// sign-extending load is (G_SEXT (G_LOAD x)) in GlobalISel. Additionally,
+// G_LOAD handles both atomic and non-atomic loads where as SelectionDAG had
+// separate nodes for them. This GINodeEquiv maps the non-atomic loads to
+// G_LOAD with a non-atomic MachineMemOperand.
+def : GINodeEquiv<G_LOAD, ld> { let CheckMMOIsNonAtomic = 1; }
+// Broadly speaking G_STORE is equivalent to ISD::STORE but there are some
+// complications that tablegen must take care of. For example, predicates such
+// as isTruncStore require that this is not a perfect 1:1 mapping since a
+// truncating store is (G_STORE (G_TRUNCATE x)) in GlobalISel. Additionally,
+// G_STORE handles both atomic and non-atomic stores where as SelectionDAG had
+// separate nodes for them. This GINodeEquiv maps the non-atomic stores to
+// G_STORE with a non-atomic MachineMemOperand.
+def : GINodeEquiv<G_STORE, st> { let CheckMMOIsNonAtomic = 1; }
+
// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.
// Should be used on defs that subclass GIComplexOperandMatcher<>.
class GIComplexPatternEquiv<ComplexPattern seldag> {
enum PredicateKind {
IPM_Opcode,
IPM_ImmPredicate,
+ IPM_NonAtomicMMO,
};
PredicateKind Kind;
}
};
+/// Generates code to check that a memory instruction has a non-atomic MachineMemoryOperand.
+class NonAtomicMMOPredicateMatcher : public InstructionPredicateMatcher {
+public:
+ NonAtomicMMOPredicateMatcher()
+ : InstructionPredicateMatcher(IPM_NonAtomicMMO) {}
+
+ static bool classof(const InstructionPredicateMatcher *P) {
+ return P->getKind() == IPM_NonAtomicMMO;
+ }
+
+ void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule,
+ unsigned InsnVarID) const override {
+ Table << MatchTable::Opcode("GIM_CheckNonAtomic")
+ << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
+ << MatchTable::LineBreak;
+ }
+};
+
/// Generates code to check that a set of predicates and operands match for a
/// particular instruction.
///
const CodeGenTarget &Target;
CodeGenRegBank CGRegs;
- /// Keep track of the equivalence between SDNodes and Instruction.
+ /// Keep track of the equivalence between SDNodes and Instruction by mapping
+ /// SDNodes to the GINodeEquiv mapping. We need to map to the GINodeEquiv to
+ /// check for attributes on the relation such as CheckMMOIsNonAtomic.
/// This is defined using 'GINodeEquiv' in the target description.
- DenseMap<Record *, const CodeGenInstruction *> NodeEquivs;
+ DenseMap<Record *, Record *> NodeEquivs;
/// Keep track of the equivalence between ComplexPattern's and
/// GIComplexOperandMatcher. Map entries are specified by subclassing
SubtargetFeatureInfoMap SubtargetFeatures;
void gatherNodeEquivs();
- const CodeGenInstruction *findNodeEquiv(Record *N) const;
+ Record *findNodeEquiv(Record *N) const;
Error importRulePredicates(RuleMatcher &M, ArrayRef<Predicate> Predicates);
Expected<InstructionMatcher &>
void GlobalISelEmitter::gatherNodeEquivs() {
assert(NodeEquivs.empty());
for (Record *Equiv : RK.getAllDerivedDefinitions("GINodeEquiv"))
- NodeEquivs[Equiv->getValueAsDef("Node")] =
- &Target.getInstruction(Equiv->getValueAsDef("I"));
+ NodeEquivs[Equiv->getValueAsDef("Node")] = Equiv;
assert(ComplexPatternEquivs.empty());
for (Record *Equiv : RK.getAllDerivedDefinitions("GIComplexPatternEquiv")) {
}
}
-const CodeGenInstruction *GlobalISelEmitter::findNodeEquiv(Record *N) const {
+Record *GlobalISelEmitter::findNodeEquiv(Record *N) const {
return NodeEquivs.lookup(N);
}
GlobalISelEmitter::createAndImportSelDAGMatcher(InstructionMatcher &InsnMatcher,
const TreePatternNode *Src,
unsigned &TempOpIdx) const {
+ Record *SrcGIEquivOrNull = nullptr;
const CodeGenInstruction *SrcGIOrNull = nullptr;
// Start with the defined operands (i.e., the results of the root operator).
return failedImport(
"Unable to deduce gMIR opcode to handle Src (which is a leaf)");
} else {
- SrcGIOrNull = findNodeEquiv(Src->getOperator());
- if (!SrcGIOrNull)
+ SrcGIEquivOrNull = findNodeEquiv(Src->getOperator());
+ if (!SrcGIEquivOrNull)
return failedImport("Pattern operator lacks an equivalent Instruction" +
explainOperator(Src->getOperator()));
- auto &SrcGI = *SrcGIOrNull;
+ SrcGIOrNull = &Target.getInstruction(SrcGIEquivOrNull->getValueAsDef("I"));
// The operators look good: match the opcode
- InsnMatcher.addPredicate<InstructionOpcodeMatcher>(&SrcGI);
+ InsnMatcher.addPredicate<InstructionOpcodeMatcher>(SrcGIOrNull);
}
unsigned OpIdx = 0;
return failedImport("Src pattern child has predicate (" +
explainPredicates(Src) + ")");
}
+ if (SrcGIEquivOrNull && SrcGIEquivOrNull->getValueAsBit("CheckMMOIsNonAtomic"))
+ InsnMatcher.addPredicate<NonAtomicMMOPredicateMatcher>();
if (Src->isLeaf()) {
Init *SrcInit = Src->getLeafValue();