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.
- gisel_ab/__init__.py +120 -0
- gisel_ab/__main__.py +8 -0
- gisel_ab/baseline.py +145 -0
- gisel_ab/bugreport.py +113 -0
- gisel_ab/cli.py +150 -0
- gisel_ab/cohort.py +704 -0
- gisel_ab/cpp/aarch64_generated_ctor.cpp +23 -0
- gisel_ab/cpp/aarch64_query_runner.cpp +380 -0
- gisel_ab/cpp/arm_generated_ctor.cpp +18 -0
- gisel_ab/cpp/arm_query_runner.cpp +58 -0
- gisel_ab/cpp/m68k_generated_ctor.cpp +21 -0
- gisel_ab/cpp/m68k_query_runner.cpp +43 -0
- gisel_ab/cpp/mips_generated_ctor.cpp +16 -0
- gisel_ab/cpp/mips_query_runner.cpp +52 -0
- gisel_ab/cpp/ppc_generated_ctor.cpp +16 -0
- gisel_ab/cpp/ppc_query_runner.cpp +46 -0
- gisel_ab/cpp/query-recovery.h +229 -0
- gisel_ab/cpp/query_runner.cpp +419 -0
- gisel_ab/cpp/query_runner_common.h +417 -0
- gisel_ab/cpp/riscv_generated_ctor.cpp +25 -0
- gisel_ab/cpp/riscv_query_runner.cpp +379 -0
- gisel_ab/cpp/spirv_generated_ctor.cpp +24 -0
- gisel_ab/cpp/spirv_query_runner.cpp +98 -0
- gisel_ab/cpp/wasm_generated_ctor.cpp +17 -0
- gisel_ab/cpp/wasm_query_runner.cpp +52 -0
- gisel_ab/cpp/x86_generated_ctor.cpp +24 -0
- gisel_ab/data/aarch64-contract.json +102 -0
- gisel_ab/data/baseline-2026-11-12.json +1684 -0
- gisel_ab/data/closure/aarch64-D.json +156 -0
- gisel_ab/data/closure/aarch64-G.json +75 -0
- gisel_ab/data/closure/arm-D.json +50 -0
- gisel_ab/data/closure/arm-G.json +57 -0
- gisel_ab/data/closure/m68k-D.json +46 -0
- gisel_ab/data/closure/m68k-G.json +54 -0
- gisel_ab/data/closure/mips-D.json +50 -0
- gisel_ab/data/closure/mips-G.json +87 -0
- gisel_ab/data/closure/ppc-D.json +49 -0
- gisel_ab/data/closure/ppc-G.json +56 -0
- gisel_ab/data/closure/riscv-D.json +59 -0
- gisel_ab/data/closure/riscv-G.json +66 -0
- gisel_ab/data/closure/spirv-D.json +58 -0
- gisel_ab/data/closure/spirv-G.json +58 -0
- gisel_ab/data/closure/wasm-D.json +56 -0
- gisel_ab/data/closure/wasm-G.json +62 -0
- gisel_ab/data/closure/x86-D.json +60 -0
- gisel_ab/data/closure/x86-G.json +66 -0
- gisel_ab/data/domain.json +139 -0
- gisel_ab/data/mir-configs.json +444 -0
- gisel_ab/data/mir-shapes.jsonc +1168 -0
- gisel_ab/data/riscv-contract.json +102 -0
- gisel_ab/data/suite/README.md +81 -0
- gisel_ab/data/suite/aarch64/official.answers.jsonl +12559 -0
- gisel_ab/data/suite/aarch64/queries.jsonl +12559 -0
- gisel_ab/data/suite/aarch64/suite.json +43 -0
- gisel_ab/data/suite/m68k/official.answers.jsonl +35 -0
- gisel_ab/data/suite/m68k/queries.jsonl +35 -0
- gisel_ab/data/suite/m68k/suite.json +24 -0
- gisel_ab/data/suite/riscv/official.answers.jsonl +6086 -0
- gisel_ab/data/suite/riscv/queries.jsonl +6086 -0
- gisel_ab/data/suite/riscv/suite.json +41 -0
- gisel_ab/data/suite/x86/official.answers.jsonl +3014 -0
- gisel_ab/data/suite/x86/queries.jsonl +3014 -0
- gisel_ab/data/suite/x86/suite.json +33 -0
- gisel_ab/data/targets/aarch64.json +39 -0
- gisel_ab/data/targets/arm.json +39 -0
- gisel_ab/data/targets/m68k.json +39 -0
- gisel_ab/data/targets/mips.json +39 -0
- gisel_ab/data/targets/ppc.json +39 -0
- gisel_ab/data/targets/riscv.json +39 -0
- gisel_ab/data/targets/schema.json +266 -0
- gisel_ab/data/targets/spirv.json +39 -0
- gisel_ab/data/targets/wasm.json +39 -0
- gisel_ab/data/targets/x86-ctor.json +39 -0
- gisel_ab/data/targets/x86.json +39 -0
- gisel_ab/data/x86-contract.json +93 -0
- gisel_ab/doctor.py +320 -0
- gisel_ab/domain_plan.py +130 -0
- gisel_ab/evidence.py +892 -0
- gisel_ab/l0/__init__.py +0 -0
- gisel_ab/l0/attribute.py +286 -0
- gisel_ab/l0/closure.py +255 -0
- gisel_ab/l0/diff.py +388 -0
- gisel_ab/l0/g_attribution.py +93 -0
- gisel_ab/l0/inject_opcode.py +123 -0
- gisel_ab/l0/inject_predicate.py +150 -0
- gisel_ab/l0/queries.py +215 -0
- gisel_ab/l0/run.py +688 -0
- gisel_ab/l0/swap.py +257 -0
- gisel_ab/l0/u_attribution.py +192 -0
- gisel_ab/l3.py +271 -0
- gisel_ab/mir/__init__.py +0 -0
- gisel_ab/mir/config_check.py +144 -0
- gisel_ab/mir/from_query.py +717 -0
- gisel_ab/mir/libs.py +252 -0
- gisel_ab/mir/replay.py +548 -0
- gisel_ab/paths.py +151 -0
- gisel_ab/refresh_counts.py +80 -0
- gisel_ab/replay_frozen.py +154 -0
- gisel_ab/setup.py +92 -0
- gisel_ab/suite.py +390 -0
- gisel_ab/targets.py +287 -0
- gisel_ab/vertical.py +654 -0
- gisel_ab-0.9.0.dist-info/METADATA +349 -0
- gisel_ab-0.9.0.dist-info/RECORD +107 -0
- gisel_ab-0.9.0.dist-info/WHEEL +5 -0
- gisel_ab-0.9.0.dist-info/entry_points.txt +2 -0
- 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
|