llvm.org GIT mirror llvm / 4783e3c
TableGen: Add address space to matchers Currently AMDGPU uses a CodePatPred to check address spaces from the MachineMemOperand. Introduce a new first class property so that the existing patterns can be easily modified to uses the new generated predicate, which will also be handled for GlobalISel. I would prefer these to match against the pointer type of the instruction, but that would be difficult to get working with SelectionDAG compatbility. This is much easier for now and will avoid a painful tablegen rewrite for all the loads and stores. I'm also not sure if there's a better way to encode multiple address spaces in the table, rather than putting the number to expect. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366128 91177308-0d34-0410-b5e6-96231b3b80d8 Matt Arsenault a month ago
7 changed file(s) with 253 addition(s) and 4 deletion(s). Raw diff Collapse all Expand all
137137 /// - MMOIdx - MMO index
138138 /// - Size - The size in bytes of the memory access
139139 GIM_CheckMemorySizeEqualTo,
140
141 /// Check the address space of the memory access for the given machine memory
142 /// operand.
143 /// - InsnID - Instruction ID
144 /// - MMOIdx - MMO index
145 /// - NumAddrSpace - Number of valid address spaces
146 /// - AddrSpaceN - An allowed space of the memory access
147 /// - AddrSpaceN+1 ...
148 GIM_CheckMemoryAddressSpace,
149
140150 /// Check the size of the memory access for the given machine memory operand
141151 /// against the size of an operand.
142152 /// - InsnID - Instruction ID
369369 return false;
370370 break;
371371 }
372 case GIM_CheckMemoryAddressSpace: {
373 int64_t InsnID = MatchTable[CurrentIdx++];
374 int64_t MMOIdx = MatchTable[CurrentIdx++];
375 // This accepts a list of possible address spaces.
376 const int NumAddrSpace = MatchTable[CurrentIdx++];
377
378 if (State.MIs[InsnID]->getNumMemOperands() <= MMOIdx) {
379 if (handleReject() == RejectAndGiveUp)
380 return false;
381 break;
382 }
383
384 // Need to still jump to the end of the list of address spaces if we find
385 // a match earlier.
386 const uint64_t LastIdx = CurrentIdx + NumAddrSpace;
387
388 const MachineMemOperand *MMO
389 = *(State.MIs[InsnID]->memoperands_begin() + MMOIdx);
390 const unsigned MMOAddrSpace = MMO->getAddrSpace();
391
392 bool Success = false;
393 for (int I = 0; I != NumAddrSpace; ++I) {
394 unsigned AddrSpace = MatchTable[CurrentIdx++];
395 DEBUG_WITH_TYPE(
396 TgtInstructionSelector::getName(),
397 dbgs() << "addrspace(" << MMOAddrSpace << ") vs "
398 << AddrSpace << '\n');
399
400 if (AddrSpace == MMOAddrSpace) {
401 Success = true;
402 break;
403 }
404 }
405
406 CurrentIdx = LastIdx;
407 if (!Success && handleReject() == RejectAndGiveUp)
408 return false;
409 break;
410 }
372411 case GIM_CheckMemorySizeEqualTo: {
373412 int64_t InsnID = MatchTable[CurrentIdx++];
374413 int64_t MMOIdx = MatchTable[CurrentIdx++];
736736 // cast(N)->isTruncatingStore();
737737 bit IsTruncStore = ?;
738738
739 // cast(N)->getAddressSpace() ==
740 // If this empty, accept any address space.
741 list AddressSpaces = ?;
742
739743 // cast(N)->getOrdering() == AtomicOrdering::Monotonic
740744 bit IsAtomicOrderingMonotonic = ?;
741745 // cast(N)->getOrdering() == AtomicOrdering::Acquire
761765 // cast(N)->getMemoryVT().getScalarType() == MVT::;
762766 // cast(N)->getMemoryVT().getScalarType() == MVT::;
763767 ValueType ScalarMemoryVT = ?;
768
769 // TODO: Add alignment
764770 }
765771
766772 // PatFrag - A version of PatFrags matching only a single fragment.
0 // RUN: llvm-tblgen -gen-dag-isel -I %p/../../include %s 2>&1 | FileCheck -check-prefix=SDAG %s
1 // RUN: llvm-tblgen -gen-global-isel -optimize-match-table=false -I %p/../../include %s -o - < %s | FileCheck -check-prefix=GISEL %s
2
3 include "llvm/Target/Target.td"
4
5 def TestTargetInstrInfo : InstrInfo;
6
7
8 def TestTarget : Target {
9 let InstructionSet = TestTargetInstrInfo;
10 }
11
12 def R0 : Register<"r0"> { let Namespace = "MyTarget"; }
13 def GPR32 : RegisterClass<"MyTarget", [i32], 32, (add R0)>;
14
15
16 // With one address space
17 def pat_frag_a : PatFrag <(ops node:$ptr), (load node:$ptr), [{}]> {
18 let AddressSpaces = [ 999 ];
19 let IsLoad = 1; // FIXME: Can this be inferred?
20 let MemoryVT = i32;
21 }
22
23 // With multiple address spaces
24 def pat_frag_b : PatFrag <(ops node:$ptr), (load node:$ptr), [{}]> {
25 let AddressSpaces = [ 123, 455 ];
26 let IsLoad = 1; // FIXME: Can this be inferred?
27 let MemoryVT = i32;
28 }
29
30 def inst_a : Instruction {
31 let OutOperandList = (outs GPR32:$dst);
32 let InOperandList = (ins GPR32:$src);
33 }
34
35 def inst_b : Instruction {
36 let OutOperandList = (outs GPR32:$dst);
37 let InOperandList = (ins GPR32:$src);
38 }
39
40 // SDAG: case 2: {
41 // SDAG: // Predicate_pat_frag_a
42 // SDAG-NEXT: SDNode *N = Node;
43 // SDAG-NEXT: (void)N;
44 // SDAG-NEXT: unsigned AddrSpace = cast(N)->getAddressSpace();
45
46 // SDAG-NEXT: if (AddrSpace != 999)
47 // SDAG-NEXT: return false;
48 // SDAG-NEXT: if (cast(N)->getMemoryVT() != MVT::i32) return false;
49 // SDAG-NEXT: return true;
50
51 // GISEL: GIM_Try, /*On fail goto*//*Label 0*/ 47, // Rule ID 0 //
52 // GISEL-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
53 // GISEL-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_LOAD,
54 // GISEL-NEXT: GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0,
55 // GISEL-NEXT: GIM_CheckMemoryAddressSpace, /*MI*/0, /*MMO*/0, /*NumAddrSpace*/1, /*AddrSpace*/999,
56 // GISEL-NEXT: GIM_CheckMemorySizeEqualTo, /*MI*/0, /*MMO*/0, /*Size*/4,
57 // GISEL-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic,
58 def : Pat <
59 (pat_frag_a GPR32:$src),
60 (inst_a GPR32:$src)
61 >;
62
63 // SDAG: case 3: {
64 // SDAG-NEXT: // Predicate_pat_frag_b
65 // SDAG-NEXT: SDNode *N = Node;
66 // SDAG-NEXT: (void)N;
67 // SDAG-NEXT: unsigned AddrSpace = cast(N)->getAddressSpace();
68 // SDAG-NEXT: if (AddrSpace != 123 && AddrSpace != 455)
69 // SDAG-NEXT: return false;
70 // SDAG-NEXT: if (cast(N)->getMemoryVT() != MVT::i32) return false;
71 // SDAG-NEXT: return true;
72
73
74 // GISEL: GIM_Try, /*On fail goto*//*Label 1*/ 95, // Rule ID 1 //
75 // GISEL-NEXT: GIM_CheckNumOperands, /*MI*/0, /*Expected*/2,
76 // GISEL-NEXT: GIM_CheckOpcode, /*MI*/0, TargetOpcode::G_LOAD,
77 // GISEL-NEXT: GIM_CheckMemorySizeEqualToLLT, /*MI*/0, /*MMO*/0, /*OpIdx*/0,
78 // GISEL-NEXT: GIM_CheckMemoryAddressSpace, /*MI*/0, /*MMO*/0, /*NumAddrSpace*/2, /*AddrSpace*/123, /*AddrSpace*/455,
79 // GISEL-NEXT: GIM_CheckMemorySizeEqualTo, /*MI*/0, /*MMO*/0, /*Size*/4,
80 // GISEL-NEXT: GIM_CheckAtomicOrdering, /*MI*/0, /*Order*/(int64_t)AtomicOrdering::NotAtomic,
81 def : Pat <
82 (pat_frag_b GPR32:$src),
83 (inst_b GPR32:$src)
84 >;
953953 }
954954
955955 if (isLoad() || isStore() || isAtomic()) {
956 StringRef SDNodeName =
957 isLoad() ? "LoadSDNode" : isStore() ? "StoreSDNode" : "AtomicSDNode";
956 if (ListInit *AddressSpaces = getAddressSpaces()) {
957 Code += "unsigned AddrSpace = cast(N)->getAddressSpace();\n"
958 " if (";
959
960 bool First = true;
961 for (Init *Val : AddressSpaces->getValues()) {
962 if (First)
963 First = false;
964 else
965 Code += " && ";
966
967 IntInit *IntVal = dyn_cast(Val);
968 if (!IntVal) {
969 PrintFatalError(getOrigPatFragRecord()->getRecord()->getLoc(),
970 "AddressSpaces element must be integer");
971 }
972
973 Code += "AddrSpace != " + utostr(IntVal->getValue());
974 }
975
976 Code += ")\nreturn false;\n";
977 }
958978
959979 Record *MemoryVT = getMemoryVT();
960980
961981 if (MemoryVT)
962 Code += ("if (cast<" + SDNodeName + ">(N)->getMemoryVT() != MVT::" +
982 Code += ("if (cast<MemSDNode>(N)->getMemoryVT() != MVT::" +
963983 MemoryVT->getName() + ") return false;\n")
964984 .str();
965985 }
11481168 return nullptr;
11491169 return R->getValueAsDef("MemoryVT");
11501170 }
1171
1172 ListInit *TreePredicateFn::getAddressSpaces() const {
1173 Record *R = getOrigPatFragRecord()->getRecord();
1174 if (R->isValueUnset("AddressSpaces"))
1175 return nullptr;
1176 return R->getValueAsListInit("AddressSpaces");
1177 }
1178
11511179 Record *TreePredicateFn::getScalarMemoryVT() const {
11521180 Record *R = getOrigPatFragRecord()->getRecord();
11531181 if (R->isValueUnset("ScalarMemoryVT"))
592592 /// ValueType record for the memory VT.
593593 Record *getScalarMemoryVT() const;
594594
595 ListInit *getAddressSpaces() const;
596
595597 // If true, indicates that GlobalISel-based C++ code was supplied.
596598 bool hasGISelPredicateCode() const;
597599 std::string getGISelPredicateCode() const;
231231 if (Record *VT = P.getScalarMemoryVT())
232232 Explanation += (" ScalarVT(MemVT)=" + VT->getName()).str();
233233
234 if (ListInit *AddrSpaces = P.getAddressSpaces()) {
235 raw_string_ostream OS(Explanation);
236 OS << " AddressSpaces=[";
237
238 StringRef AddrSpaceSeparator;
239 for (Init *Val : AddrSpaces->getValues()) {
240 IntInit *IntVal = dyn_cast(Val);
241 if (!IntVal)
242 continue;
243
244 OS << AddrSpaceSeparator << IntVal->getValue();
245 AddrSpaceSeparator = ", ";
246 }
247
248 OS << ']';
249 }
250
234251 if (P.isAtomicOrderingMonotonic())
235252 Explanation += " monotonic";
236253 if (P.isAtomicOrderingAcquire())
304321
305322 if (Predicate.isLoad() || Predicate.isStore()) {
306323 if (Predicate.isUnindexed())
324 continue;
325 }
326
327 if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
328 const ListInit *AddrSpaces = Predicate.getAddressSpaces();
329 if (AddrSpaces && !AddrSpaces->empty())
307330 continue;
308331 }
309332
10271050 IPM_AtomicOrderingMMO,
10281051 IPM_MemoryLLTSize,
10291052 IPM_MemoryVsLLTSize,
1053 IPM_MemoryAddressSpace,
10301054 IPM_GenericPredicate,
10311055 OPM_SameOperand,
10321056 OPM_ComplexPattern,
17851809 << MatchTable::Comment("MMO") << MatchTable::IntValue(MMOIdx)
17861810 << MatchTable::Comment("Size") << MatchTable::IntValue(Size)
17871811 << MatchTable::LineBreak;
1812 }
1813 };
1814
1815 class MemoryAddressSpacePredicateMatcher : public InstructionPredicateMatcher {
1816 protected:
1817 unsigned MMOIdx;
1818 SmallVector AddrSpaces;
1819
1820 public:
1821 MemoryAddressSpacePredicateMatcher(unsigned InsnVarID, unsigned MMOIdx,
1822 ArrayRef AddrSpaces)
1823 : InstructionPredicateMatcher(IPM_MemoryAddressSpace, InsnVarID),
1824 MMOIdx(MMOIdx), AddrSpaces(AddrSpaces.begin(), AddrSpaces.end()) {}
1825
1826 static bool classof(const PredicateMatcher *P) {
1827 return P->getKind() == IPM_MemoryAddressSpace;
1828 }
1829 bool isIdentical(const PredicateMatcher &B) const override {
1830 if (!InstructionPredicateMatcher::isIdentical(B))
1831 return false;
1832 auto *Other = cast(&B);
1833 return MMOIdx == Other->MMOIdx && AddrSpaces == Other->AddrSpaces;
1834 }
1835
1836 void emitPredicateOpcodes(MatchTable &Table,
1837 RuleMatcher &Rule) const override {
1838 Table << MatchTable::Opcode("GIM_CheckMemoryAddressSpace")
1839 << MatchTable::Comment("MI") << MatchTable::IntValue(InsnVarID)
1840 << MatchTable::Comment("MMO") << MatchTable::IntValue(MMOIdx)
1841 // Encode number of address spaces to expect.
1842 << MatchTable::Comment("NumAddrSpace")
1843 << MatchTable::IntValue(AddrSpaces.size());
1844 for (unsigned AS : AddrSpaces)
1845 Table << MatchTable::Comment("AddrSpace") << MatchTable::IntValue(AS);
1846
1847 Table << MatchTable::LineBreak;
17881848 }
17891849 };
17901850
32093269 continue;
32103270 }
32113271
3212 // G_LOAD is used for both non-extending and any-extending loads.
3272 // An address space check is needed in all contexts if there is one.
3273 if (Predicate.isLoad() || Predicate.isStore() || Predicate.isAtomic()) {
3274 if (const ListInit *AddrSpaces = Predicate.getAddressSpaces()) {
3275 SmallVector ParsedAddrSpaces;
3276
3277 for (Init *Val : AddrSpaces->getValues()) {
3278 IntInit *IntVal = dyn_cast(Val);
3279 if (!IntVal)
3280 return failedImport("Address space is not an integer");
3281 ParsedAddrSpaces.push_back(IntVal->getValue());
3282 }
3283
3284 if (!ParsedAddrSpaces.empty()) {
3285 InsnMatcher.addPredicate(
3286 0, ParsedAddrSpaces);
3287 }
3288 }
3289 }
3290
3291 // G_LOAD is used for both non-extending and any-extending loads.
32133292 if (Predicate.isLoad() && Predicate.isNonExtLoad()) {
32143293 InsnMatcher.addPredicate(
32153294 0, MemoryVsLLTSizePredicateMatcher::EqualTo, 0);