gisel-ab 0.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. gisel_ab/__init__.py +120 -0
  2. gisel_ab/__main__.py +8 -0
  3. gisel_ab/baseline.py +145 -0
  4. gisel_ab/bugreport.py +113 -0
  5. gisel_ab/cli.py +150 -0
  6. gisel_ab/cohort.py +704 -0
  7. gisel_ab/cpp/aarch64_generated_ctor.cpp +23 -0
  8. gisel_ab/cpp/aarch64_query_runner.cpp +380 -0
  9. gisel_ab/cpp/arm_generated_ctor.cpp +18 -0
  10. gisel_ab/cpp/arm_query_runner.cpp +58 -0
  11. gisel_ab/cpp/m68k_generated_ctor.cpp +21 -0
  12. gisel_ab/cpp/m68k_query_runner.cpp +43 -0
  13. gisel_ab/cpp/mips_generated_ctor.cpp +16 -0
  14. gisel_ab/cpp/mips_query_runner.cpp +52 -0
  15. gisel_ab/cpp/ppc_generated_ctor.cpp +16 -0
  16. gisel_ab/cpp/ppc_query_runner.cpp +46 -0
  17. gisel_ab/cpp/query-recovery.h +229 -0
  18. gisel_ab/cpp/query_runner.cpp +419 -0
  19. gisel_ab/cpp/query_runner_common.h +417 -0
  20. gisel_ab/cpp/riscv_generated_ctor.cpp +25 -0
  21. gisel_ab/cpp/riscv_query_runner.cpp +379 -0
  22. gisel_ab/cpp/spirv_generated_ctor.cpp +24 -0
  23. gisel_ab/cpp/spirv_query_runner.cpp +98 -0
  24. gisel_ab/cpp/wasm_generated_ctor.cpp +17 -0
  25. gisel_ab/cpp/wasm_query_runner.cpp +52 -0
  26. gisel_ab/cpp/x86_generated_ctor.cpp +24 -0
  27. gisel_ab/data/aarch64-contract.json +102 -0
  28. gisel_ab/data/baseline-2026-11-12.json +1684 -0
  29. gisel_ab/data/closure/aarch64-D.json +156 -0
  30. gisel_ab/data/closure/aarch64-G.json +75 -0
  31. gisel_ab/data/closure/arm-D.json +50 -0
  32. gisel_ab/data/closure/arm-G.json +57 -0
  33. gisel_ab/data/closure/m68k-D.json +46 -0
  34. gisel_ab/data/closure/m68k-G.json +54 -0
  35. gisel_ab/data/closure/mips-D.json +50 -0
  36. gisel_ab/data/closure/mips-G.json +87 -0
  37. gisel_ab/data/closure/ppc-D.json +49 -0
  38. gisel_ab/data/closure/ppc-G.json +56 -0
  39. gisel_ab/data/closure/riscv-D.json +59 -0
  40. gisel_ab/data/closure/riscv-G.json +66 -0
  41. gisel_ab/data/closure/spirv-D.json +58 -0
  42. gisel_ab/data/closure/spirv-G.json +58 -0
  43. gisel_ab/data/closure/wasm-D.json +56 -0
  44. gisel_ab/data/closure/wasm-G.json +62 -0
  45. gisel_ab/data/closure/x86-D.json +60 -0
  46. gisel_ab/data/closure/x86-G.json +66 -0
  47. gisel_ab/data/domain.json +139 -0
  48. gisel_ab/data/mir-configs.json +444 -0
  49. gisel_ab/data/mir-shapes.jsonc +1168 -0
  50. gisel_ab/data/riscv-contract.json +102 -0
  51. gisel_ab/data/suite/README.md +81 -0
  52. gisel_ab/data/suite/aarch64/official.answers.jsonl +12559 -0
  53. gisel_ab/data/suite/aarch64/queries.jsonl +12559 -0
  54. gisel_ab/data/suite/aarch64/suite.json +43 -0
  55. gisel_ab/data/suite/m68k/official.answers.jsonl +35 -0
  56. gisel_ab/data/suite/m68k/queries.jsonl +35 -0
  57. gisel_ab/data/suite/m68k/suite.json +24 -0
  58. gisel_ab/data/suite/riscv/official.answers.jsonl +6086 -0
  59. gisel_ab/data/suite/riscv/queries.jsonl +6086 -0
  60. gisel_ab/data/suite/riscv/suite.json +41 -0
  61. gisel_ab/data/suite/x86/official.answers.jsonl +3014 -0
  62. gisel_ab/data/suite/x86/queries.jsonl +3014 -0
  63. gisel_ab/data/suite/x86/suite.json +33 -0
  64. gisel_ab/data/targets/aarch64.json +39 -0
  65. gisel_ab/data/targets/arm.json +39 -0
  66. gisel_ab/data/targets/m68k.json +39 -0
  67. gisel_ab/data/targets/mips.json +39 -0
  68. gisel_ab/data/targets/ppc.json +39 -0
  69. gisel_ab/data/targets/riscv.json +39 -0
  70. gisel_ab/data/targets/schema.json +266 -0
  71. gisel_ab/data/targets/spirv.json +39 -0
  72. gisel_ab/data/targets/wasm.json +39 -0
  73. gisel_ab/data/targets/x86-ctor.json +39 -0
  74. gisel_ab/data/targets/x86.json +39 -0
  75. gisel_ab/data/x86-contract.json +93 -0
  76. gisel_ab/doctor.py +320 -0
  77. gisel_ab/domain_plan.py +130 -0
  78. gisel_ab/evidence.py +892 -0
  79. gisel_ab/l0/__init__.py +0 -0
  80. gisel_ab/l0/attribute.py +286 -0
  81. gisel_ab/l0/closure.py +255 -0
  82. gisel_ab/l0/diff.py +388 -0
  83. gisel_ab/l0/g_attribution.py +93 -0
  84. gisel_ab/l0/inject_opcode.py +123 -0
  85. gisel_ab/l0/inject_predicate.py +150 -0
  86. gisel_ab/l0/queries.py +215 -0
  87. gisel_ab/l0/run.py +688 -0
  88. gisel_ab/l0/swap.py +257 -0
  89. gisel_ab/l0/u_attribution.py +192 -0
  90. gisel_ab/l3.py +271 -0
  91. gisel_ab/mir/__init__.py +0 -0
  92. gisel_ab/mir/config_check.py +144 -0
  93. gisel_ab/mir/from_query.py +717 -0
  94. gisel_ab/mir/libs.py +252 -0
  95. gisel_ab/mir/replay.py +548 -0
  96. gisel_ab/paths.py +151 -0
  97. gisel_ab/refresh_counts.py +80 -0
  98. gisel_ab/replay_frozen.py +154 -0
  99. gisel_ab/setup.py +92 -0
  100. gisel_ab/suite.py +390 -0
  101. gisel_ab/targets.py +287 -0
  102. gisel_ab/vertical.py +654 -0
  103. gisel_ab-0.9.0.dist-info/METADATA +349 -0
  104. gisel_ab-0.9.0.dist-info/RECORD +107 -0
  105. gisel_ab-0.9.0.dist-info/WHEEL +5 -0
  106. gisel_ab-0.9.0.dist-info/entry_points.txt +2 -0
  107. gisel_ab-0.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,23 @@
1
+ // The AArch64 A/B ours build replaces only the legalizer constructor. The
2
+ // remaining target library, including custom legalization, stays official.
3
+
4
+ #include "AArch64Subtarget.h"
5
+ #include "GISel/AArch64LegalizerInfo.h"
6
+ #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
7
+ #include "llvm/CodeGen/TargetLowering.h"
8
+ #include "llvm/CodeGen/TargetOpcodes.h"
9
+ #include "llvm/Target/TargetMachine.h"
10
+
11
+ using namespace llvm;
12
+ using namespace LegalizeActions;
13
+ using namespace LegalizeMutations;
14
+ using namespace LegalityPredicates;
15
+ using namespace MIPatternMatch;
16
+
17
+ AArch64LegalizerInfo::AArch64LegalizerInfo(const AArch64Subtarget &ST)
18
+ : ST(&ST) {
19
+ using namespace TargetOpcode;
20
+ const AArch64Subtarget &Subtarget = ST;
21
+ const TargetMachine &TM = ST.getTargetLowering()->getTargetMachine();
22
+ #include "AArch64LegalizerInfo.inc"
23
+ }
@@ -0,0 +1,380 @@
1
+ //===- aarch64_query_runner.cpp - answer fixed AArch64 queries ------------===//
2
+
3
+ #include "AArch64Subtarget.h"
4
+ #include "AArch64TargetMachine.h"
5
+ #include "llvm/ADT/SmallVector.h"
6
+ #include "llvm/ADT/StringMap.h"
7
+ #include "llvm/ADT/StringSwitch.h"
8
+ #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
9
+ #include "llvm/CodeGen/TargetOpcodes.h"
10
+ #include "llvm/IR/Function.h"
11
+ #include "llvm/IR/LLVMContext.h"
12
+ #include "llvm/IR/Module.h"
13
+ #include "llvm/MC/TargetRegistry.h"
14
+ #include "llvm/Support/AtomicOrdering.h"
15
+ #include "llvm/Support/JSON.h"
16
+ #include "llvm/Support/TargetSelect.h"
17
+ #include "llvm/Support/raw_ostream.h"
18
+ #include "llvm/Target/TargetMachine.h"
19
+ #include "llvm/Target/TargetOptions.h"
20
+ #include "llvm/TargetParser/Triple.h"
21
+ #include <fstream>
22
+ #include <memory>
23
+ #include <optional>
24
+ #include <string>
25
+ #include <vector>
26
+
27
+ #include "query-recovery.h"
28
+ using namespace llvm;
29
+ using namespace TargetOpcode;
30
+ using namespace LegalizeActions;
31
+ using namespace LegalizeMutations;
32
+ using namespace LegalityPredicates;
33
+
34
+ #include "GISel/AArch64LegalizerInfo.h"
35
+ using Legalizer = AArch64LegalizerInfo;
36
+
37
+ namespace {
38
+
39
+ static std::optional<AtomicOrdering> parseOrdering(StringRef Text) {
40
+ return StringSwitch<std::optional<AtomicOrdering>>(Text)
41
+ .Case("NotAtomic", AtomicOrdering::NotAtomic)
42
+ .Case("Unordered", AtomicOrdering::Unordered)
43
+ .Case("Monotonic", AtomicOrdering::Monotonic)
44
+ .Case("Acquire", AtomicOrdering::Acquire)
45
+ .Case("Release", AtomicOrdering::Release)
46
+ .Case("AcquireRelease", AtomicOrdering::AcquireRelease)
47
+ .Case("SequentiallyConsistent", AtomicOrdering::SequentiallyConsistent)
48
+ .Default(std::nullopt);
49
+ }
50
+
51
+ struct Config {
52
+ const char *ID;
53
+ const char *Features;
54
+ CodeModel::Model CM;
55
+ };
56
+
57
+ static const Config Configs[] = {
58
+ {"baseline", "", CodeModel::Large},
59
+ {"small-cm", "", CodeModel::Small},
60
+ {"fullfp16", "+fullfp16", CodeModel::Large},
61
+ {"sve", "+sve", CodeModel::Large},
62
+ {"bf16", "+bf16", CodeModel::Large},
63
+ {"cssc", "+cssc", CodeModel::Large},
64
+ {"rcpc3", "+rcpc3", CodeModel::Large},
65
+ {"lse", "+lse", CodeModel::Large},
66
+ {"outline-atomics", "+outline-atomics", CodeModel::Large},
67
+ };
68
+
69
+ struct Sigma {
70
+ std::unique_ptr<TargetMachine> TM;
71
+ const AArch64Subtarget *STI = nullptr;
72
+ std::unique_ptr<Legalizer> L;
73
+ };
74
+
75
+ static std::string jsonString(StringRef S) {
76
+ std::string Out = "\"";
77
+ for (char C : S) {
78
+ if (C == '\"' || C == '\\') {
79
+ Out += '\\';
80
+ Out += C;
81
+ } else if (C == '\n') {
82
+ Out += "\\n";
83
+ } else {
84
+ Out += C;
85
+ }
86
+ }
87
+ Out += '"';
88
+ return Out;
89
+ }
90
+
91
+ static std::string lltStr(LLT Ty) {
92
+ if (!Ty.isValid())
93
+ return "LLT_invalid";
94
+ if (Ty.isPointer())
95
+ return "p" + std::to_string(Ty.getAddressSpace()) + ":" +
96
+ std::to_string(Ty.getSizeInBits());
97
+ if (Ty.isVector()) {
98
+ std::string Elem = lltStr(Ty.getElementType());
99
+ return (Ty.isScalable() ? "nxv" : "v") +
100
+ std::to_string(Ty.getElementCount().getKnownMinValue()) + Elem;
101
+ }
102
+ if (Ty.isBFloat16())
103
+ return "bf16";
104
+ if (Ty.isFloat())
105
+ return "f" + std::to_string(Ty.getScalarSizeInBits());
106
+ if (Ty.isInteger())
107
+ return "i" + std::to_string(Ty.getScalarSizeInBits());
108
+ return "s" + std::to_string(Ty.getScalarSizeInBits());
109
+ }
110
+
111
+ static const char *actionName(LegalizeAction A) {
112
+ switch (A) {
113
+ case Legal: return "Legal";
114
+ case NarrowScalar: return "NarrowScalar";
115
+ case WidenScalar: return "WidenScalar";
116
+ case FewerElements: return "FewerElements";
117
+ case MoreElements: return "MoreElements";
118
+ case Bitcast: return "Bitcast";
119
+ case Lower: return "Lower";
120
+ case Libcall: return "Libcall";
121
+ case Unsupported: return "Unsupported";
122
+ case Custom: return "Custom";
123
+ default: return "?";
124
+ }
125
+ }
126
+
127
+ static unsigned opcodeFor(StringRef Name) {
128
+ #undef HANDLE_TARGET_OPCODE
129
+ #undef HANDLE_TARGET_OPCODE_MARKER
130
+ return StringSwitch<unsigned>(Name)
131
+ #define HANDLE_TARGET_OPCODE(OPC) .Case(#OPC, TargetOpcode::OPC)
132
+ #define HANDLE_TARGET_OPCODE_MARKER(IDENT, OP)
133
+ #include "llvm/Support/TargetOpcodes.def"
134
+ #undef HANDLE_TARGET_OPCODE
135
+ #undef HANDLE_TARGET_OPCODE_MARKER
136
+ .Default(0);
137
+ }
138
+
139
+ // `p0:*` is the configuration-dependent pointer width; the subtarget decides
140
+ // it (LP64 -> 64, ILP32 -> 32), exactly as it does for RISC-V's XLen.
141
+ static std::optional<LLT> parseLLT(StringRef S, unsigned PointerBits = 0) {
142
+ if (S == "bf16")
143
+ return LLT::bfloat16();
144
+ if (S.starts_with("nxv") || S.starts_with("v")) {
145
+ bool Scalable = S.starts_with("nxv");
146
+ S = S.drop_front(Scalable ? 3 : 1);
147
+ size_t I = 0;
148
+ while (I < S.size() && S[I] >= '0' && S[I] <= '9')
149
+ ++I;
150
+ unsigned N = 0;
151
+ if (I == 0 || S.substr(0, I).getAsInteger(10, N))
152
+ return std::nullopt;
153
+ auto Elem = parseLLT(S.drop_front(I), PointerBits);
154
+ if (!Elem)
155
+ return std::nullopt;
156
+ return LLT::vector(Scalable ? ElementCount::getScalable(N)
157
+ : ElementCount::getFixed(N), *Elem);
158
+ }
159
+ if (S.starts_with("p")) {
160
+ size_t Colon = S.find(':');
161
+ unsigned AS = 0;
162
+ if (Colon == StringRef::npos ||
163
+ S.substr(1, Colon - 1).getAsInteger(10, AS))
164
+ return std::nullopt;
165
+ if (S.drop_front(Colon + 1) == "*") {
166
+ if (!PointerBits)
167
+ return std::nullopt;
168
+ return LLT::pointer(AS, PointerBits);
169
+ }
170
+ unsigned Bits = 0;
171
+ if (S.drop_front(Colon + 1).getAsInteger(10, Bits))
172
+ return std::nullopt;
173
+ return LLT::pointer(AS, Bits);
174
+ }
175
+ char Kind = S.empty() ? '?' : S[0];
176
+ unsigned Bits = 0;
177
+ if (S.drop_front().getAsInteger(10, Bits))
178
+ return std::nullopt;
179
+ switch (Kind) {
180
+ case 's': return LLT::scalar(Bits);
181
+ case 'i': return LLT::integer(Bits);
182
+ case 'f': return LLT::floatIEEE(Bits);
183
+ default: return std::nullopt;
184
+ }
185
+ }
186
+
187
+ static bool makeSigma(const Config &C, Sigma &S) {
188
+ Triple TT("aarch64");
189
+ std::string Err;
190
+ const Target *T = TargetRegistry::lookupTarget("", TT, Err);
191
+ if (!T) {
192
+ errs() << "no target: " << Err << "\n";
193
+ return false;
194
+ }
195
+ TargetOptions Opts;
196
+ S.TM.reset(T->createTargetMachine(TT, "generic", C.Features, Opts,
197
+ std::nullopt, C.CM));
198
+ if (!S.TM)
199
+ return false;
200
+ static LLVMContext Ctx;
201
+ static Module M("t", Ctx);
202
+ if (!M.getFunction("f"))
203
+ Function::Create(FunctionType::get(Type::getVoidTy(Ctx), false),
204
+ Function::ExternalLinkage, "f", &M);
205
+ S.STI = static_cast<const AArch64Subtarget *>(
206
+ S.TM->getSubtargetImpl(*M.getFunction("f")));
207
+ if (!S.STI)
208
+ return false;
209
+ S.L = std::make_unique<Legalizer>(*S.STI);
210
+ return true;
211
+ }
212
+
213
+ static int answerLine(StringRef Line, const StringMap<Sigma *> &Sigmas,
214
+ raw_ostream &Out) {
215
+ Expected<json::Value> Parsed = json::parse(Line);
216
+ if (!Parsed)
217
+ return 2;
218
+ json::Object *Obj = Parsed->getAsObject();
219
+ if (!Obj)
220
+ return 2;
221
+ auto ConfigName = Obj->getString("config");
222
+ auto Name = Obj->getString("name");
223
+ json::Array *TypeArr = Obj->getArray("types");
224
+ if (!ConfigName || !Name || !TypeArr)
225
+ return 2;
226
+ auto It = Sigmas.find(*ConfigName);
227
+ if (It == Sigmas.end())
228
+ return 2;
229
+ Sigma &S = *It->second;
230
+ unsigned PtrBits = S.TM->createDataLayout().getPointerSizeInBits(0);
231
+ SmallVector<LLT, 4> Types;
232
+ // Keep the caller's spelling. A target without LLT::setUseExtended (RISC-V)
233
+ // maps `f16` and `s16` to the same scalar(16), so re-spelling the parsed type
234
+ // would collapse two distinct query keys in the answer file. The key must
235
+ // survive the round trip; only the answer is up to the legalizer.
236
+ SmallVector<std::string, 4> TypeText;
237
+ for (const json::Value &V : *TypeArr) {
238
+ auto Text = V.getAsString();
239
+ if (!Text)
240
+ return 2;
241
+ auto Ty = parseLLT(*Text, PtrBits);
242
+ if (!Ty)
243
+ return 2;
244
+ Types.push_back(*Ty);
245
+ TypeText.push_back(Text->str());
246
+ }
247
+
248
+ // Immediate operands are part of the query: a rule may read Q.Immediates
249
+ // (e.g. LegalizePredicates::immIs). Dropping them makes the rule index the
250
+ // empty array and abort, which would look like an answer difference.
251
+ SmallVector<int64_t, 2> Imms;
252
+ if (json::Array *ImmArr = Obj->getArray("imms"))
253
+ for (const json::Value &V : *ImmArr) {
254
+ auto I = V.getAsInteger();
255
+ if (!I)
256
+ return 2;
257
+ Imms.push_back(*I);
258
+ }
259
+ std::string ImmsText = "[";
260
+ for (size_t I = 0; I != Imms.size(); ++I) {
261
+ if (I)
262
+ ImmsText += ",";
263
+ ImmsText += std::to_string(Imms[I]);
264
+ }
265
+ ImmsText += "]";
266
+
267
+ SmallVector<LegalityQuery::MemDesc, 1> MMOs;
268
+ std::string MemText = "null";
269
+ if (json::Array *Mem = Obj->getArray("mem")) {
270
+ if (Mem->size() != 2 && Mem->size() != 4)
271
+ return 2;
272
+ auto TyText = (*Mem)[0].getAsString();
273
+ auto Align = (*Mem)[1].getAsInteger();
274
+ if (!TyText || !Align)
275
+ return 2;
276
+ auto Ty = parseLLT(*TyText, PtrBits);
277
+ if (!Ty)
278
+ return 2;
279
+ AtomicOrdering Ordering = AtomicOrdering::NotAtomic;
280
+ AtomicOrdering Failure = AtomicOrdering::NotAtomic;
281
+ std::optional<StringRef> OrderingText;
282
+ std::optional<StringRef> FailureText;
283
+ if (Mem->size() == 4) {
284
+ OrderingText = (*Mem)[2].getAsString();
285
+ FailureText = (*Mem)[3].getAsString();
286
+ auto ParsedOrdering = OrderingText ? parseOrdering(*OrderingText)
287
+ : std::nullopt;
288
+ auto ParsedFailure = FailureText ? parseOrdering(*FailureText)
289
+ : std::nullopt;
290
+ if (!ParsedOrdering || !ParsedFailure)
291
+ return 2;
292
+ Ordering = *ParsedOrdering;
293
+ Failure = *ParsedFailure;
294
+ }
295
+ MMOs.push_back(LegalityQuery::MemDesc(*Ty, *Align, Ordering, Failure));
296
+ MemText = "[" + jsonString(*TyText) + "," +
297
+ std::to_string(*Align);
298
+ if (Mem->size() == 4)
299
+ MemText += "," + jsonString(*OrderingText) + "," +
300
+ jsonString(*FailureText);
301
+ MemText += "]";
302
+ }
303
+
304
+ unsigned Opcode = opcodeFor(*Name);
305
+ if (!Opcode)
306
+ return 2;
307
+ LegalityQuery Q(Opcode, Types, MMOs, Imms);
308
+ LegalizeActionStep Step = S.L->getAction(Q);
309
+ Out << "{\"config\":" << jsonString(*ConfigName)
310
+ << ",\"name\":" << jsonString(*Name) << ",\"types\":[";
311
+ for (size_t I = 0; I != Types.size(); ++I) {
312
+ if (I)
313
+ Out << ',';
314
+ Out << jsonString(TypeText[I]);
315
+ }
316
+ Out << "],\"mem\":" << MemText << ",\"imms\":" << ImmsText
317
+ << ",\"action\":" << jsonString(actionName(Step.Action))
318
+ << ",\"type_idx\":" << (unsigned)Step.TypeIdx
319
+ << ",\"new_type\":" << jsonString(lltStr(Step.NewType)) << "}\n";
320
+ return 0;
321
+ }
322
+
323
+ } // namespace
324
+
325
+ int main(int Argc, char **Argv) {
326
+ ab::disableCoreDumps();
327
+ StringRef Queries;
328
+ for (int I = 1; I < Argc; ++I) {
329
+ StringRef A(Argv[I]);
330
+ if (A == "--queries" && I + 1 < Argc)
331
+ Queries = Argv[++I];
332
+ else if (A == "-h" || A == "--help")
333
+ return 0;
334
+ else
335
+ return 2;
336
+ }
337
+ if (Queries.empty())
338
+ return 2;
339
+
340
+ LLVMInitializeAArch64TargetInfo();
341
+ LLVMInitializeAArch64Target();
342
+ LLVMInitializeAArch64TargetMC();
343
+
344
+ StringMap<Sigma *> Sigmas;
345
+ std::vector<std::unique_ptr<Sigma>> Storage;
346
+ for (const Config &C : Configs) {
347
+ auto S = std::make_unique<Sigma>();
348
+ if (!makeSigma(C, *S))
349
+ return 2;
350
+ Sigmas[C.ID] = S.get();
351
+ Storage.push_back(std::move(S));
352
+ }
353
+
354
+ std::ifstream In(Queries.str());
355
+ if (!In)
356
+ return 2;
357
+ std::string Line;
358
+ unsigned N = 0;
359
+ while (std::getline(In, Line)) {
360
+ if (Line.empty())
361
+ continue;
362
+ int Rc = 0;
363
+ if (!ab::runQuery([&] { Rc = answerLine(Line, Sigmas, outs()); })) {
364
+ // The query aborted inside LLVM. The legalizer is built and const, so
365
+ // the only loss is memory allocated by the abandoned call.
366
+ ab::writeUnanswerable(Line, outs());
367
+ outs().flush();
368
+ ++N;
369
+ continue;
370
+ }
371
+ if (Rc)
372
+ return Rc;
373
+ // Flush per answer: a real crash would still lose a buffered tail, and
374
+ // run-queries.py restarts after it.
375
+ outs().flush();
376
+ ++N;
377
+ }
378
+ errs() << "answered " << N << " queries\n";
379
+ return 0;
380
+ }
@@ -0,0 +1,18 @@
1
+ // The ARM A/B ours build replaces only the legalizer constructor. The rest of
2
+ // the target library stays official.
3
+
4
+ #include "ARMLegalizerInfo.h"
5
+ #include "ARMSubtarget.h"
6
+ #include "llvm/CodeGen/TargetOpcodes.h"
7
+
8
+ using namespace llvm;
9
+ using namespace LegalizeActions;
10
+ using namespace LegalizeMutations;
11
+ using namespace LegalityPredicates;
12
+
13
+ // The class keeps a reference to the subtarget; the official constructor
14
+ // initialises it in its member-init list, and so must this one.
15
+ ARMLegalizerInfo::ARMLegalizerInfo(const ARMSubtarget &ST) : ST(ST) {
16
+ using namespace TargetOpcode;
17
+ #include "ARMLegalizerInfo.inc"
18
+ }
@@ -0,0 +1,58 @@
1
+ //===- arm_query_runner.cpp - answer JSONL queries with ARM's rules ------===//
2
+ //
3
+ // Built twice: `official` links the target library's constructor, `ours` also
4
+ // links a replacement constructor object that includes the generated `.inc`.
5
+ // The two binaries differ only in which definition of the constructor the
6
+ // linker picks, so an answer difference is a rule difference.
7
+ //
8
+ // The configuration axes are the ones the constructor itself reads:
9
+ // `ST.useSoftFloat()`, `ST.hasVFP2Base()`, `ST.hasVFP4Base()`, `ST.hasNEON()`,
10
+ // `ST.hasV5TOps()`, the hardware-divide gate, and the AEABI gate. Thumb1 is
11
+ // deliberately absent: the constructor returns before registering a rule, so
12
+ // the generated table -- which has no way to spell "this subtarget has no
13
+ // rules" -- would disagree on every query by construction. That gap is
14
+ // recorded in docs/REPORT-cxx-corpus.md rather than papered over.
15
+ //===----------------------------------------------------------------------===//
16
+
17
+ #include "ARMLegalizerInfo.h"
18
+ #include "ARMSubtarget.h"
19
+ #include "llvm/Support/TargetSelect.h"
20
+
21
+ using namespace llvm;
22
+
23
+ using TargetSubtarget = ARMSubtarget;
24
+ using TargetLegalizer = ARMLegalizerInfo;
25
+
26
+ #include "query_runner_common.h"
27
+
28
+ namespace {
29
+
30
+ static void initializeTarget() {
31
+ LLVMInitializeARMTargetInfo();
32
+ LLVMInitializeARMTarget();
33
+ LLVMInitializeARMTargetMC();
34
+ }
35
+
36
+ static ArrayRef<Config> configs() {
37
+ // `armv7a-neon` is a Cortex-A7 (VFP4 + NEON + hardware divide); `a5` has no
38
+ // VFP4; `nodiv` drops the divide instructions; `arm1176` is NEON-less;
39
+ // `armv4t` has neither V5T nor VFP2; `thumbv7m` is M-profile (no FPU);
40
+ // `armv7-soft` forces the soft-float ABI on a Cortex-A7.
41
+ static const Config Table[] = {
42
+ {"armv7a-neon", "armv7-unknown-linux-gnueabihf", "cortex-a7", "", std::nullopt},
43
+ {"armv7a-nodiv", "armv7-unknown-linux-gnueabihf", "cortex-a7", "-hwdiv,-hwdiv-arm", std::nullopt},
44
+ {"armv7a-a5", "armv7-unknown-linux-gnueabihf", "cortex-a5", "", std::nullopt},
45
+ {"armv6-arm1176", "armv6-unknown-linux-gnueabihf", "arm1176jzf-s", "", std::nullopt},
46
+ {"armv4t", "armv4t-unknown-linux-gnueabi", "arm7tdmi", "+soft-float", std::nullopt},
47
+ {"thumbv7m", "thumbv7m-unknown-none-eabi", "cortex-m3", "", std::nullopt},
48
+ {"armv7-soft", "armv7-unknown-linux-gnueabi", "generic", "+soft-float", std::nullopt},
49
+ };
50
+ return Table;
51
+ }
52
+
53
+ static std::unique_ptr<TargetLegalizer>
54
+ makeLegalizer(const TargetSubtarget &ST, TargetMachine &) {
55
+ return std::make_unique<TargetLegalizer>(ST);
56
+ }
57
+
58
+ } // namespace
@@ -0,0 +1,21 @@
1
+ // The M68k A/B ours build replaces only the legalizer constructor. The rest
2
+ // of the target library, including custom legalization, stays official.
3
+
4
+ #include "GISel/M68kLegalizerInfo.h"
5
+ #include "M68kSubtarget.h"
6
+ #include "llvm/CodeGen/GlobalISel/MIPatternMatch.h"
7
+ #include "llvm/CodeGen/TargetLowering.h"
8
+ #include "llvm/CodeGen/TargetOpcodes.h"
9
+ #include "llvm/Target/TargetMachine.h"
10
+
11
+ using namespace llvm;
12
+ using namespace LegalizeActions;
13
+ using namespace LegalizeMutations;
14
+ using namespace LegalityPredicates;
15
+ using namespace MIPatternMatch;
16
+
17
+ M68kLegalizerInfo::M68kLegalizerInfo(const M68kSubtarget &ST) {
18
+ using namespace TargetOpcode;
19
+ const M68kSubtarget &Subtarget = ST;
20
+ #include "M68kLegalizerInfo.inc"
21
+ }
@@ -0,0 +1,43 @@
1
+ //===- m68k_query_runner.cpp - answer JSONL queries with M68k's legalizer -===//
2
+ //
3
+ // Built twice: `official` links the target library's constructor, `ours` also
4
+ // links a replacement constructor object that includes the generated `.inc`.
5
+ // The two binaries differ only in which definition of the constructor the
6
+ // linker picks, so an answer difference is a rule difference.
7
+ //===----------------------------------------------------------------------===//
8
+
9
+ #include "GISel/M68kLegalizerInfo.h"
10
+ #include "M68kSubtarget.h"
11
+ #include "M68kTargetMachine.h"
12
+ #include "llvm/Support/TargetSelect.h"
13
+
14
+ using namespace llvm;
15
+
16
+ using TargetSubtarget = M68kSubtarget;
17
+ using TargetLegalizer = M68kLegalizerInfo;
18
+
19
+ #include "query_runner_common.h"
20
+
21
+ namespace {
22
+
23
+ static void initializeTarget() {
24
+ LLVMInitializeM68kTargetInfo();
25
+ LLVMInitializeM68kTarget();
26
+ LLVMInitializeM68kTargetMC();
27
+ }
28
+
29
+ static ArrayRef<Config> configs() {
30
+ // M68k's constructor reads no subtarget feature, so the configuration axis
31
+ // is one point. `M68040` is the CPU the GlobalISel MIR tests run on.
32
+ static const Config Table[] = {
33
+ {"default", "m68k", "M68040", "", std::nullopt},
34
+ };
35
+ return Table;
36
+ }
37
+
38
+ static std::unique_ptr<TargetLegalizer>
39
+ makeLegalizer(const TargetSubtarget &ST, TargetMachine &) {
40
+ return std::make_unique<TargetLegalizer>(ST);
41
+ }
42
+
43
+ } // namespace
@@ -0,0 +1,16 @@
1
+ // The Mips A/B ours build replaces only the legalizer constructor. The rest
2
+ // of the target library stays official.
3
+
4
+ #include "MipsLegalizerInfo.h"
5
+ #include "MipsSubtarget.h"
6
+ #include "llvm/CodeGen/TargetOpcodes.h"
7
+
8
+ using namespace llvm;
9
+ using namespace LegalizeActions;
10
+ using namespace LegalizeMutations;
11
+ using namespace LegalityPredicates;
12
+
13
+ MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) {
14
+ using namespace TargetOpcode;
15
+ #include "MipsLegalizerInfo.inc"
16
+ }
@@ -0,0 +1,52 @@
1
+ //===- mips_query_runner.cpp - answer JSONL queries with Mips' rules -----===//
2
+ //
3
+ // Built twice: `official` links the target library's constructor, `ours` also
4
+ // links a replacement constructor object that includes the generated `.inc`.
5
+ // The two binaries differ only in which definition of the constructor the
6
+ // linker picks, so an answer difference is a rule difference.
7
+ //
8
+ // The constructor reads three subtarget predicates: `ST.hasMSA()` (the vector
9
+ // rules), `ST.hasMips32r2()` (G_BSWAP legal vs. lower), and
10
+ // `ST.systemSupportsUnalignedAccess()` (which memory sizes need an aligned
11
+ // access). The five configurations below are those three axes on the
12
+ // 32-bit flavours the legalizer assumes (`p0` is `pointer(0, 32)`).
13
+ //===----------------------------------------------------------------------===//
14
+
15
+ #include "MipsLegalizerInfo.h"
16
+ #include "MipsSubtarget.h"
17
+ #include "llvm/Support/TargetSelect.h"
18
+
19
+ using namespace llvm;
20
+
21
+ using TargetSubtarget = MipsSubtarget;
22
+ using TargetLegalizer = MipsLegalizerInfo;
23
+
24
+ #include "query_runner_common.h"
25
+
26
+ namespace {
27
+
28
+ static void initializeTarget() {
29
+ LLVMInitializeMipsTargetInfo();
30
+ LLVMInitializeMipsTarget();
31
+ LLVMInitializeMipsTargetMC();
32
+ }
33
+
34
+ static ArrayRef<Config> configs() {
35
+ // MSA needs the 64-bit FP register file (`+fp64`) or the subtarget reports
36
+ // it unavailable.
37
+ static const Config Table[] = {
38
+ {"mips32", "mips-unknown-linux-gnu", "mips32", "", std::nullopt},
39
+ {"mips32r2", "mips-unknown-linux-gnu", "mips32r2", "", std::nullopt},
40
+ {"mips32r6", "mips-unknown-linux-gnu", "mips32r6", "", std::nullopt},
41
+ {"mips32r5-msa", "mips-unknown-linux-gnu", "mips32r5", "+msa,+fp64", std::nullopt},
42
+ {"mips32r6-msa", "mips-unknown-linux-gnu", "mips32r6", "+msa,+fp64", std::nullopt},
43
+ };
44
+ return Table;
45
+ }
46
+
47
+ static std::unique_ptr<TargetLegalizer>
48
+ makeLegalizer(const TargetSubtarget &ST, TargetMachine &) {
49
+ return std::make_unique<TargetLegalizer>(ST);
50
+ }
51
+
52
+ } // namespace
@@ -0,0 +1,16 @@
1
+ // The PowerPC A/B ours build replaces only the legalizer constructor. The
2
+ // rest of the target library stays official.
3
+
4
+ #include "GISel/PPCLegalizerInfo.h"
5
+ #include "PPCSubtarget.h"
6
+ #include "llvm/CodeGen/TargetOpcodes.h"
7
+
8
+ using namespace llvm;
9
+ using namespace LegalizeActions;
10
+ using namespace LegalizeMutations;
11
+ using namespace LegalityPredicates;
12
+
13
+ PPCLegalizerInfo::PPCLegalizerInfo(const PPCSubtarget &ST) {
14
+ using namespace TargetOpcode;
15
+ #include "PowerPCLegalizerInfo.inc"
16
+ }
@@ -0,0 +1,46 @@
1
+ //===- ppc_query_runner.cpp - answer JSONL queries with PowerPC's rules ---===//
2
+ //
3
+ // Built twice: `official` links the target library's constructor, `ours` also
4
+ // links a replacement constructor object that includes the generated `.inc`.
5
+ // The two binaries differ only in which definition of the constructor the
6
+ // linker picks, so an answer difference is a rule difference.
7
+ //
8
+ // The constructor reads no subtarget feature: every rule is about types, so
9
+ // the configuration axis is one point, like M68k.
10
+ //===----------------------------------------------------------------------===//
11
+
12
+ #include "GISel/PPCLegalizerInfo.h"
13
+ #include "PPCSubtarget.h"
14
+ #include "PPCTargetMachine.h"
15
+ #include "llvm/Support/TargetSelect.h"
16
+
17
+ using namespace llvm;
18
+
19
+ using TargetSubtarget = PPCSubtarget;
20
+ using TargetLegalizer = PPCLegalizerInfo;
21
+
22
+ #include "query_runner_common.h"
23
+
24
+ namespace {
25
+
26
+ static void initializeTarget() {
27
+ LLVMInitializePowerPCTargetInfo();
28
+ LLVMInitializePowerPCTarget();
29
+ LLVMInitializePowerPCTargetMC();
30
+ }
31
+
32
+ static ArrayRef<Config> configs() {
33
+ // The legalizer assumes the 64-bit register file (P0 is `pointer(0, 64)`),
34
+ // so the triple is ppc64le; the CPU does not change a rule.
35
+ static const Config Table[] = {
36
+ {"default", "powerpc64le-unknown-linux-gnu", "", "", std::nullopt},
37
+ };
38
+ return Table;
39
+ }
40
+
41
+ static std::unique_ptr<TargetLegalizer>
42
+ makeLegalizer(const TargetSubtarget &ST, TargetMachine &) {
43
+ return std::make_unique<TargetLegalizer>(ST);
44
+ }
45
+
46
+ } // namespace