Skip to content

Commit 39690bd

Browse files
committedOct 15, 2017
[globalisel][tablegen] Map ld and st to G_LOAD and G_STORE. NFC
Summary: There is an important mismatch between ISD::LOAD and G_LOAD (and likewise for ISD::STORE and G_STORE). In SelectionDAG, ISD::LOAD is a non-atomic load and atomic loads are handled by a separate node. However, this is not true of GlobalISel's G_LOAD. For G_LOAD, the MachineMemOperand indicates the atomicity of the operation. As a result, this mapping must also add a predicate that checks for non-atomic MachineMemOperands. This is NFC since these nodes always have predicates in practice and are therefore always rejected at the moment. Depends on D37443 Reviewers: ab, qcolombet, t.p.northover, rovka, aditya_nandakumar Reviewed By: qcolombet Subscribers: kristof.beyls, llvm-commits, igorb Differential Revision: https://reviews.llvm.org/D37445 llvm-svn: 315843
1 parent b7c0b08 commit 39690bd

File tree

4 files changed

+77
-10
lines changed

4 files changed

+77
-10
lines changed
 

‎llvm/include/llvm/CodeGen/GlobalISel/InstructionSelector.h

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,9 @@ enum {
107107
/// - InsnID - Instruction ID
108108
/// - The predicate to test
109109
GIM_CheckAPFloatImmPredicate,
110+
/// Check a memory operation is non-atomic.
111+
/// - InsnID - Instruction ID
112+
GIM_CheckNonAtomic,
110113

111114
/// Check the type for the specified operand
112115
/// - InsnID - Instruction ID

‎llvm/include/llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h

+19
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,25 @@ bool InstructionSelector::executeMatchTable(
209209
return false;
210210
break;
211211
}
212+
case GIM_CheckNonAtomic: {
213+
int64_t InsnID = MatchTable[CurrentIdx++];
214+
DEBUG(dbgs() << CurrentIdx << ": GIM_CheckNonAtomic(MIs[" << InsnID
215+
<< "])\n");
216+
assert(State.MIs[InsnID] != nullptr && "Used insn before defined");
217+
assert((State.MIs[InsnID]->getOpcode() == TargetOpcode::G_LOAD ||
218+
State.MIs[InsnID]->getOpcode() == TargetOpcode::G_STORE) &&
219+
"Expected G_LOAD/G_STORE");
220+
221+
if (!State.MIs[InsnID]->hasOneMemOperand())
222+
if (handleReject() == RejectAndGiveUp)
223+
return false;
224+
225+
for (const auto &MMO : State.MIs[InsnID]->memoperands())
226+
if (MMO->getOrdering() != AtomicOrdering::NotAtomic)
227+
if (handleReject() == RejectAndGiveUp)
228+
return false;
229+
break;
230+
}
212231

213232
case GIM_CheckType: {
214233
int64_t InsnID = MatchTable[CurrentIdx++];

‎llvm/include/llvm/Target/GlobalISel/SelectionDAGCompat.td

+22
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@
2323
class GINodeEquiv<Instruction i, SDNode node> {
2424
Instruction I = i;
2525
SDNode Node = node;
26+
27+
// SelectionDAG has separate nodes for atomic and non-atomic memory operations
28+
// (ISD::LOAD, ISD::ATOMIC_LOAD, ISD::STORE, ISD::ATOMIC_STORE) but GlobalISel
29+
// stores this information in the MachineMemoryOperand.
30+
bit CheckMMOIsNonAtomic = 0;
2631
}
2732

2833
// These are defined in the same order as the G_* instructions.
@@ -72,6 +77,23 @@ def : GINodeEquiv<G_INTRINSIC_W_SIDE_EFFECTS, intrinsic_w_chain>;
7277
def : GINodeEquiv<G_BR, br>;
7378
def : GINodeEquiv<G_BSWAP, bswap>;
7479

80+
// Broadly speaking G_LOAD is equivalent to ISD::LOAD but there are some
81+
// complications that tablegen must take care of. For example, Predicates such
82+
// as isSignExtLoad require that this is not a perfect 1:1 mapping since a
83+
// sign-extending load is (G_SEXT (G_LOAD x)) in GlobalISel. Additionally,
84+
// G_LOAD handles both atomic and non-atomic loads where as SelectionDAG had
85+
// separate nodes for them. This GINodeEquiv maps the non-atomic loads to
86+
// G_LOAD with a non-atomic MachineMemOperand.
87+
def : GINodeEquiv<G_LOAD, ld> { let CheckMMOIsNonAtomic = 1; }
88+
// Broadly speaking G_STORE is equivalent to ISD::STORE but there are some
89+
// complications that tablegen must take care of. For example, predicates such
90+
// as isTruncStore require that this is not a perfect 1:1 mapping since a
91+
// truncating store is (G_STORE (G_TRUNCATE x)) in GlobalISel. Additionally,
92+
// G_STORE handles both atomic and non-atomic stores where as SelectionDAG had
93+
// separate nodes for them. This GINodeEquiv maps the non-atomic stores to
94+
// G_STORE with a non-atomic MachineMemOperand.
95+
def : GINodeEquiv<G_STORE, st> { let CheckMMOIsNonAtomic = 1; }
96+
7597
// Specifies the GlobalISel equivalents for SelectionDAG's ComplexPattern.
7698
// Should be used on defs that subclass GIComplexOperandMatcher<>.
7799
class GIComplexPatternEquiv<ComplexPattern seldag> {

‎llvm/utils/TableGen/GlobalISelEmitter.cpp

+33-10
Original file line numberDiff line numberDiff line change
@@ -997,6 +997,7 @@ class InstructionPredicateMatcher {
997997
enum PredicateKind {
998998
IPM_Opcode,
999999
IPM_ImmPredicate,
1000+
IPM_NonAtomicMMO,
10001001
};
10011002

10021003
PredicateKind Kind;
@@ -1125,6 +1126,24 @@ class InstructionImmPredicateMatcher : public InstructionPredicateMatcher {
11251126
}
11261127
};
11271128

1129+
/// Generates code to check that a memory instruction has a non-atomic MachineMemoryOperand.
1130+
class NonAtomicMMOPredicateMatcher : public InstructionPredicateMatcher {
1131+
public:
1132+
NonAtomicMMOPredicateMatcher()
1133+
: InstructionPredicateMatcher(IPM_NonAtomicMMO) {}
1134+
1135+
static bool classof(const InstructionPredicateMatcher *P) {
1136+
return P->getKind() == IPM_NonAtomicMMO;
1137+
}
1138+
1139+
void emitPredicateOpcodes(MatchTable &Table, RuleMatcher &Rule,
1140+
unsigned InsnVarID) const override {
1141+
Table << MatchTable::Opcode("GIM_CheckNonAtomic")
1142+
<< MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
1143+
<< MatchTable::LineBreak;
1144+
}
1145+
};
1146+
11281147
/// Generates code to check that a set of predicates and operands match for a
11291148
/// particular instruction.
11301149
///
@@ -1991,9 +2010,11 @@ class GlobalISelEmitter {
19912010
const CodeGenTarget &Target;
19922011
CodeGenRegBank CGRegs;
19932012

1994-
/// Keep track of the equivalence between SDNodes and Instruction.
2013+
/// Keep track of the equivalence between SDNodes and Instruction by mapping
2014+
/// SDNodes to the GINodeEquiv mapping. We need to map to the GINodeEquiv to
2015+
/// check for attributes on the relation such as CheckMMOIsNonAtomic.
19952016
/// This is defined using 'GINodeEquiv' in the target description.
1996-
DenseMap<Record *, const CodeGenInstruction *> NodeEquivs;
2017+
DenseMap<Record *, Record *> NodeEquivs;
19972018

19982019
/// Keep track of the equivalence between ComplexPattern's and
19992020
/// GIComplexOperandMatcher. Map entries are specified by subclassing
@@ -2004,7 +2025,7 @@ class GlobalISelEmitter {
20042025
SubtargetFeatureInfoMap SubtargetFeatures;
20052026

20062027
void gatherNodeEquivs();
2007-
const CodeGenInstruction *findNodeEquiv(Record *N) const;
2028+
Record *findNodeEquiv(Record *N) const;
20082029

20092030
Error importRulePredicates(RuleMatcher &M, ArrayRef<Predicate> Predicates);
20102031
Expected<InstructionMatcher &>
@@ -2041,8 +2062,7 @@ class GlobalISelEmitter {
20412062
void GlobalISelEmitter::gatherNodeEquivs() {
20422063
assert(NodeEquivs.empty());
20432064
for (Record *Equiv : RK.getAllDerivedDefinitions("GINodeEquiv"))
2044-
NodeEquivs[Equiv->getValueAsDef("Node")] =
2045-
&Target.getInstruction(Equiv->getValueAsDef("I"));
2065+
NodeEquivs[Equiv->getValueAsDef("Node")] = Equiv;
20462066

20472067
assert(ComplexPatternEquivs.empty());
20482068
for (Record *Equiv : RK.getAllDerivedDefinitions("GIComplexPatternEquiv")) {
@@ -2053,7 +2073,7 @@ void GlobalISelEmitter::gatherNodeEquivs() {
20532073
}
20542074
}
20552075

2056-
const CodeGenInstruction *GlobalISelEmitter::findNodeEquiv(Record *N) const {
2076+
Record *GlobalISelEmitter::findNodeEquiv(Record *N) const {
20572077
return NodeEquivs.lookup(N);
20582078
}
20592079

@@ -2080,6 +2100,7 @@ Expected<InstructionMatcher &>
20802100
GlobalISelEmitter::createAndImportSelDAGMatcher(InstructionMatcher &InsnMatcher,
20812101
const TreePatternNode *Src,
20822102
unsigned &TempOpIdx) const {
2103+
Record *SrcGIEquivOrNull = nullptr;
20832104
const CodeGenInstruction *SrcGIOrNull = nullptr;
20842105

20852106
// Start with the defined operands (i.e., the results of the root operator).
@@ -2095,14 +2116,14 @@ GlobalISelEmitter::createAndImportSelDAGMatcher(InstructionMatcher &InsnMatcher,
20952116
return failedImport(
20962117
"Unable to deduce gMIR opcode to handle Src (which is a leaf)");
20972118
} else {
2098-
SrcGIOrNull = findNodeEquiv(Src->getOperator());
2099-
if (!SrcGIOrNull)
2119+
SrcGIEquivOrNull = findNodeEquiv(Src->getOperator());
2120+
if (!SrcGIEquivOrNull)
21002121
return failedImport("Pattern operator lacks an equivalent Instruction" +
21012122
explainOperator(Src->getOperator()));
2102-
auto &SrcGI = *SrcGIOrNull;
2123+
SrcGIOrNull = &Target.getInstruction(SrcGIEquivOrNull->getValueAsDef("I"));
21032124

21042125
// The operators look good: match the opcode
2105-
InsnMatcher.addPredicate<InstructionOpcodeMatcher>(&SrcGI);
2126+
InsnMatcher.addPredicate<InstructionOpcodeMatcher>(SrcGIOrNull);
21062127
}
21072128

21082129
unsigned OpIdx = 0;
@@ -2132,6 +2153,8 @@ GlobalISelEmitter::createAndImportSelDAGMatcher(InstructionMatcher &InsnMatcher,
21322153
return failedImport("Src pattern child has predicate (" +
21332154
explainPredicates(Src) + ")");
21342155
}
2156+
if (SrcGIEquivOrNull && SrcGIEquivOrNull->getValueAsBit("CheckMMOIsNonAtomic"))
2157+
InsnMatcher.addPredicate<NonAtomicMMOPredicateMatcher>();
21352158

21362159
if (Src->isLeaf()) {
21372160
Init *SrcInit = Src->getLeafValue();

0 commit comments

Comments
 (0)
Please sign in to comment.