[NFC][RemoveDIs] Prefer iterators over inst-pointers in InstCombine
[llvm-project.git] / llvm / test / CodeGen / AArch64 / Atomics / generate-tests.py
blobecda5fd69ca5d931e7ca207757744f82ead9eeaa
1 #!/usr/bin/env python3
2 import textwrap
3 import enum
4 import os
6 """
7 Generate the tests in llvm/test/CodeGen/AArch64/Atomics. Run from top level llvm-project.
8 """
10 TRIPLES = [
11 "aarch64",
12 "aarch64_be",
16 # Type name size
17 class Type(enum.Enum):
18 # Value is the size in bytes
19 i8 = 1
20 i16 = 2
21 i32 = 4
22 i64 = 8
23 i128 = 16
25 def align(self, aligned: bool) -> int:
26 return self.value if aligned else 1
28 def __str__(self) -> str:
29 return self.name
32 # Is this an aligned or unaligned access?
33 class Aligned(enum.Enum):
34 aligned = True
35 unaligned = False
37 def __str__(self) -> str:
38 return self.name
40 def __bool__(self) -> bool:
41 return self.value
44 class AtomicOrder(enum.Enum):
45 notatomic = 0
46 unordered = 1
47 monotonic = 2
48 acquire = 3
49 release = 4
50 acq_rel = 5
51 seq_cst = 6
53 def __str__(self) -> str:
54 return self.name
57 ATOMICRMW_ORDERS = [
58 AtomicOrder.monotonic,
59 AtomicOrder.acquire,
60 AtomicOrder.release,
61 AtomicOrder.acq_rel,
62 AtomicOrder.seq_cst,
65 ATOMIC_LOAD_ORDERS = [
66 AtomicOrder.unordered,
67 AtomicOrder.monotonic,
68 AtomicOrder.acquire,
69 AtomicOrder.seq_cst,
72 ATOMIC_STORE_ORDERS = [
73 AtomicOrder.unordered,
74 AtomicOrder.monotonic,
75 AtomicOrder.release,
76 AtomicOrder.seq_cst,
79 ATOMIC_FENCE_ORDERS = [
80 AtomicOrder.acquire,
81 AtomicOrder.release,
82 AtomicOrder.acq_rel,
83 AtomicOrder.seq_cst,
86 CMPXCHG_SUCCESS_ORDERS = [
87 AtomicOrder.monotonic,
88 AtomicOrder.acquire,
89 AtomicOrder.release,
90 AtomicOrder.acq_rel,
91 AtomicOrder.seq_cst,
94 CMPXCHG_FAILURE_ORDERS = [
95 AtomicOrder.monotonic,
96 AtomicOrder.acquire,
97 AtomicOrder.seq_cst,
100 FENCE_ORDERS = [
101 AtomicOrder.acquire,
102 AtomicOrder.release,
103 AtomicOrder.acq_rel,
104 AtomicOrder.seq_cst,
108 class Feature(enum.Flag):
109 # Feature names in filenames are determined by the spelling here:
110 v8a = enum.auto()
111 v8_1a = enum.auto() # -mattr=+v8.1a, mandatory FEAT_LOR, FEAT_LSE
112 rcpc = enum.auto() # FEAT_LRCPC
113 lse2 = enum.auto() # FEAT_LSE2
114 outline_atomics = enum.auto() # -moutline-atomics
115 rcpc3 = enum.auto() # FEAT_LSE2 + FEAT_LRCPC3
116 lse2_lse128 = enum.auto() # FEAT_LSE2 + FEAT_LSE128
118 @property
119 def mattr(self):
120 if self == Feature.outline_atomics:
121 return "+outline-atomics"
122 if self == Feature.v8_1a:
123 return "+v8.1a"
124 if self == Feature.rcpc3:
125 return "+lse2,+rcpc3"
126 if self == Feature.lse2_lse128:
127 return "+lse2,+lse128"
128 return "+" + self.name
131 ATOMICRMW_OPS = [
132 "xchg",
133 "add",
134 "sub",
135 "and",
136 "nand",
137 "or",
138 "xor",
139 "max",
140 "min",
141 "umax",
142 "umin",
146 def all_atomicrmw(f):
147 for op in ATOMICRMW_OPS:
148 for aligned in Aligned:
149 for ty in Type:
150 for ordering in ATOMICRMW_ORDERS:
151 name = f"atomicrmw_{op}_{ty}_{aligned}_{ordering}"
152 instr = "atomicrmw"
153 f.write(
154 textwrap.dedent(
155 f"""
156 define dso_local {ty} @{name}(ptr %ptr, {ty} %value) {{
157 %r = {instr} {op} ptr %ptr, {ty} %value {ordering}, align {ty.align(aligned)}
158 ret {ty} %r
165 def all_load(f):
166 for aligned in Aligned:
167 for ty in Type:
168 for ordering in ATOMIC_LOAD_ORDERS:
169 for const in [False, True]:
170 name = f"load_atomic_{ty}_{aligned}_{ordering}"
171 instr = "load atomic"
172 if const:
173 name += "_const"
174 arg = "ptr readonly %ptr" if const else "ptr %ptr"
175 f.write(
176 textwrap.dedent(
177 f"""
178 define dso_local {ty} @{name}({arg}) {{
179 %r = {instr} {ty}, ptr %ptr {ordering}, align {ty.align(aligned)}
180 ret {ty} %r
187 def all_store(f):
188 for aligned in Aligned:
189 for ty in Type:
190 for ordering in ATOMIC_STORE_ORDERS: # FIXME stores
191 name = f"store_atomic_{ty}_{aligned}_{ordering}"
192 instr = "store atomic"
193 f.write(
194 textwrap.dedent(
195 f"""
196 define dso_local void @{name}({ty} %value, ptr %ptr) {{
197 {instr} {ty} %value, ptr %ptr {ordering}, align {ty.align(aligned)}
198 ret void
205 def all_cmpxchg(f):
206 for aligned in Aligned:
207 for ty in Type:
208 for success_ordering in CMPXCHG_SUCCESS_ORDERS:
209 for failure_ordering in CMPXCHG_FAILURE_ORDERS:
210 for weak in [False, True]:
211 name = f"cmpxchg_{ty}_{aligned}_{success_ordering}_{failure_ordering}"
212 instr = "cmpxchg"
213 if weak:
214 name += "_weak"
215 instr += " weak"
216 f.write(
217 textwrap.dedent(
218 f"""
219 define dso_local {ty} @{name}({ty} %expected, {ty} %new, ptr %ptr) {{
220 %pair = {instr} ptr %ptr, {ty} %expected, {ty} %new {success_ordering} {failure_ordering}, align {ty.align(aligned)}
221 %r = extractvalue {{ {ty}, i1 }} %pair, 0
222 ret {ty} %r
229 def all_fence(f):
230 for ordering in FENCE_ORDERS:
231 name = f"fence_{ordering}"
232 f.write(
233 textwrap.dedent(
234 f"""
235 define dso_local void @{name}() {{
236 fence {ordering}
237 ret void
244 def header(f, triple, features, filter_args: str):
245 f.write(
246 "; NOTE: Assertions have been autogenerated by "
247 "utils/update_llc_test_checks.py UTC_ARGS: "
249 f.write(filter_args)
250 f.write("\n")
251 f.write(f"; The base test file was generated by {__file__}\n")
252 for feat in features:
253 for OptFlag in ["-O0", "-O1"]:
254 f.write(
255 " ".join(
257 ";",
258 "RUN:",
259 "llc",
260 "%s",
261 "-o",
262 "-",
263 "-verify-machineinstrs",
264 f"-mtriple={triple}",
265 f"-mattr={feat.mattr}",
266 OptFlag,
267 "|",
268 "FileCheck",
269 "%s",
270 f"--check-prefixes=CHECK,{OptFlag}\n",
276 def write_lit_tests():
277 os.chdir("llvm/test/CodeGen/AArch64/Atomics/")
278 for triple in TRIPLES:
279 # Feature has no effect on fence, so keep it to one file.
280 with open(f"{triple}-fence.ll", "w") as f:
281 filter_args = r'--filter "^\s*(dmb)"'
282 header(f, triple, Feature, filter_args)
283 all_fence(f)
285 for feat in Feature:
286 with open(f"{triple}-atomicrmw-{feat.name}.ll", "w") as f:
287 filter_args = r'--filter-out "\b(sp)\b" --filter "^\s*(ld[^r]|st[^r]|swp|cas|bl|add|and|eor|orn|orr|sub|mvn|sxt|cmp|ccmp|csel|dmb)"'
288 header(f, triple, [feat], filter_args)
289 all_atomicrmw(f)
291 with open(f"{triple}-cmpxchg-{feat.name}.ll", "w") as f:
292 filter_args = r'--filter-out "\b(sp)\b" --filter "^\s*(ld[^r]|st[^r]|swp|cas|bl|add|and|eor|orn|orr|sub|mvn|sxt|cmp|ccmp|csel|dmb)"'
293 header(f, triple, [feat], filter_args)
294 all_cmpxchg(f)
296 with open(f"{triple}-atomic-load-{feat.name}.ll", "w") as f:
297 filter_args = r'--filter-out "\b(sp)\b" --filter "^\s*(ld|st[^r]|swp|cas|bl|add|and|eor|orn|orr|sub|mvn|sxt|cmp|ccmp|csel|dmb)"'
298 header(f, triple, [feat], filter_args)
299 all_load(f)
301 with open(f"{triple}-atomic-store-{feat.name}.ll", "w") as f:
302 filter_args = r'--filter-out "\b(sp)\b" --filter "^\s*(ld[^r]|st|swp|cas|bl|add|and|eor|orn|orr|sub|mvn|sxt|cmp|ccmp|csel|dmb)"'
303 header(f, triple, [feat], filter_args)
304 all_store(f)
307 if __name__ == "__main__":
308 write_lit_tests()
310 print(
311 textwrap.dedent(
313 Testcases written. To update checks run:
314 $ ./llvm/utils/update_llc_test_checks.py -u llvm/test/CodeGen/AArch64/Atomics/*.ll
316 Or in parallel:
317 $ parallel ./llvm/utils/update_llc_test_checks.py -u ::: llvm/test/CodeGen/AArch64/Atomics/*.ll