xref: /llvm-project/llvm/test/CodeGen/AArch64/Atomics/generate-tests.py (revision b71edfaa4ec3c998aadb35255ce2f60bba2940b0)
1f3fb9739STomas Matheson#!/usr/bin/env python3
2f3fb9739STomas Mathesonimport textwrap
3f3fb9739STomas Mathesonimport enum
4f3fb9739STomas Mathesonimport os
5*b71edfaaSTobias Hieta
6f3fb9739STomas Matheson"""
7f3fb9739STomas MathesonGenerate the tests in llvm/test/CodeGen/AArch64/Atomics. Run from top level llvm-project.
8f3fb9739STomas Matheson"""
9f3fb9739STomas Matheson
10f3fb9739STomas MathesonTRIPLES = [
11*b71edfaaSTobias Hieta    "aarch64",
12*b71edfaaSTobias Hieta    "aarch64_be",
13f3fb9739STomas Matheson]
14f3fb9739STomas Matheson
15f3fb9739STomas Matheson
16f3fb9739STomas Matheson# Type name size
17f3fb9739STomas Mathesonclass Type(enum.Enum):
18f3fb9739STomas Matheson    # Value is the size in bytes
19f3fb9739STomas Matheson    i8 = 1
20f3fb9739STomas Matheson    i16 = 2
21f3fb9739STomas Matheson    i32 = 4
22f3fb9739STomas Matheson    i64 = 8
23f3fb9739STomas Matheson    i128 = 16
24f3fb9739STomas Matheson
25f3fb9739STomas Matheson    def align(self, aligned: bool) -> int:
26f3fb9739STomas Matheson        return self.value if aligned else 1
27f3fb9739STomas Matheson
28f3fb9739STomas Matheson    def __str__(self) -> str:
29f3fb9739STomas Matheson        return self.name
30f3fb9739STomas Matheson
31f3fb9739STomas Matheson
32f3fb9739STomas Matheson# Is this an aligned or unaligned access?
33f3fb9739STomas Mathesonclass Aligned(enum.Enum):
34f3fb9739STomas Matheson    aligned = True
35f3fb9739STomas Matheson    unaligned = False
36f3fb9739STomas Matheson
37f3fb9739STomas Matheson    def __str__(self) -> str:
38f3fb9739STomas Matheson        return self.name
39f3fb9739STomas Matheson
40f3fb9739STomas Matheson    def __bool__(self) -> bool:
41f3fb9739STomas Matheson        return self.value
42f3fb9739STomas Matheson
43f3fb9739STomas Matheson
44f3fb9739STomas Mathesonclass AtomicOrder(enum.Enum):
45f3fb9739STomas Matheson    notatomic = 0
46f3fb9739STomas Matheson    unordered = 1
47f3fb9739STomas Matheson    monotonic = 2
48f3fb9739STomas Matheson    acquire = 3
49f3fb9739STomas Matheson    release = 4
50f3fb9739STomas Matheson    acq_rel = 5
51f3fb9739STomas Matheson    seq_cst = 6
52f3fb9739STomas Matheson
53f3fb9739STomas Matheson    def __str__(self) -> str:
54f3fb9739STomas Matheson        return self.name
55f3fb9739STomas Matheson
56f3fb9739STomas Matheson
57f3fb9739STomas MathesonATOMICRMW_ORDERS = [
58f3fb9739STomas Matheson    AtomicOrder.monotonic,
59f3fb9739STomas Matheson    AtomicOrder.acquire,
60f3fb9739STomas Matheson    AtomicOrder.release,
61f3fb9739STomas Matheson    AtomicOrder.acq_rel,
62f3fb9739STomas Matheson    AtomicOrder.seq_cst,
63f3fb9739STomas Matheson]
64f3fb9739STomas Matheson
65f3fb9739STomas MathesonATOMIC_LOAD_ORDERS = [
66f3fb9739STomas Matheson    AtomicOrder.unordered,
67f3fb9739STomas Matheson    AtomicOrder.monotonic,
68f3fb9739STomas Matheson    AtomicOrder.acquire,
69f3fb9739STomas Matheson    AtomicOrder.seq_cst,
70f3fb9739STomas Matheson]
71f3fb9739STomas Matheson
72f3fb9739STomas MathesonATOMIC_STORE_ORDERS = [
73f3fb9739STomas Matheson    AtomicOrder.unordered,
74f3fb9739STomas Matheson    AtomicOrder.monotonic,
75f3fb9739STomas Matheson    AtomicOrder.release,
76f3fb9739STomas Matheson    AtomicOrder.seq_cst,
77f3fb9739STomas Matheson]
78f3fb9739STomas Matheson
79f3fb9739STomas MathesonATOMIC_FENCE_ORDERS = [
80f3fb9739STomas Matheson    AtomicOrder.acquire,
81f3fb9739STomas Matheson    AtomicOrder.release,
82f3fb9739STomas Matheson    AtomicOrder.acq_rel,
83f3fb9739STomas Matheson    AtomicOrder.seq_cst,
84f3fb9739STomas Matheson]
85f3fb9739STomas Matheson
86f3fb9739STomas MathesonCMPXCHG_SUCCESS_ORDERS = [
87f3fb9739STomas Matheson    AtomicOrder.monotonic,
88f3fb9739STomas Matheson    AtomicOrder.acquire,
89f3fb9739STomas Matheson    AtomicOrder.release,
90f3fb9739STomas Matheson    AtomicOrder.acq_rel,
91f3fb9739STomas Matheson    AtomicOrder.seq_cst,
92f3fb9739STomas Matheson]
93f3fb9739STomas Matheson
94f3fb9739STomas MathesonCMPXCHG_FAILURE_ORDERS = [
95f3fb9739STomas Matheson    AtomicOrder.monotonic,
96f3fb9739STomas Matheson    AtomicOrder.acquire,
97f3fb9739STomas Matheson    AtomicOrder.seq_cst,
98f3fb9739STomas Matheson]
99f3fb9739STomas Matheson
100f3fb9739STomas MathesonFENCE_ORDERS = [
101f3fb9739STomas Matheson    AtomicOrder.acquire,
102f3fb9739STomas Matheson    AtomicOrder.release,
103f3fb9739STomas Matheson    AtomicOrder.acq_rel,
104f3fb9739STomas Matheson    AtomicOrder.seq_cst,
105f3fb9739STomas Matheson]
106f3fb9739STomas Matheson
107f3fb9739STomas Matheson
108f3fb9739STomas Mathesonclass Feature(enum.Flag):
1097c84f94eSTomas Matheson    # Feature names in filenames are determined by the spelling here:
110f3fb9739STomas Matheson    v8a = enum.auto()
111f3fb9739STomas Matheson    v8_1a = enum.auto()  # -mattr=+v8.1a, mandatory FEAT_LOR, FEAT_LSE
112f3fb9739STomas Matheson    rcpc = enum.auto()  # FEAT_LRCPC
113f3fb9739STomas Matheson    lse2 = enum.auto()  # FEAT_LSE2
114f3fb9739STomas Matheson    outline_atomics = enum.auto()  # -moutline-atomics
1157c84f94eSTomas Matheson    rcpc3 = enum.auto()  # FEAT_LSE2 + FEAT_LRCPC3
1165a9cb377STomas Matheson    lse2_lse128 = enum.auto()  # FEAT_LSE2 + FEAT_LSE128
117f3fb9739STomas Matheson
118f3fb9739STomas Matheson    @property
119f3fb9739STomas Matheson    def mattr(self):
120f3fb9739STomas Matheson        if self == Feature.outline_atomics:
121*b71edfaaSTobias Hieta            return "+outline-atomics"
122f3fb9739STomas Matheson        if self == Feature.v8_1a:
123*b71edfaaSTobias Hieta            return "+v8.1a"
1247c84f94eSTomas Matheson        if self == Feature.rcpc3:
125*b71edfaaSTobias Hieta            return "+lse2,+rcpc3"
1265a9cb377STomas Matheson        if self == Feature.lse2_lse128:
127*b71edfaaSTobias Hieta            return "+lse2,+lse128"
128*b71edfaaSTobias Hieta        return "+" + self.name
129f3fb9739STomas Matheson
130f3fb9739STomas Matheson
131f3fb9739STomas MathesonATOMICRMW_OPS = [
132*b71edfaaSTobias Hieta    "xchg",
133*b71edfaaSTobias Hieta    "add",
134*b71edfaaSTobias Hieta    "sub",
135*b71edfaaSTobias Hieta    "and",
136*b71edfaaSTobias Hieta    "nand",
137*b71edfaaSTobias Hieta    "or",
138*b71edfaaSTobias Hieta    "xor",
139*b71edfaaSTobias Hieta    "max",
140*b71edfaaSTobias Hieta    "min",
141*b71edfaaSTobias Hieta    "umax",
142*b71edfaaSTobias Hieta    "umin",
143f3fb9739STomas Matheson]
144f3fb9739STomas Matheson
145f3fb9739STomas Matheson
146f3fb9739STomas Mathesondef all_atomicrmw(f):
147f3fb9739STomas Matheson    for op in ATOMICRMW_OPS:
148f3fb9739STomas Matheson        for aligned in Aligned:
149f3fb9739STomas Matheson            for ty in Type:
150f3fb9739STomas Matheson                for ordering in ATOMICRMW_ORDERS:
151*b71edfaaSTobias Hieta                    name = f"atomicrmw_{op}_{ty}_{aligned}_{ordering}"
152*b71edfaaSTobias Hieta                    instr = "atomicrmw"
153f3fb9739STomas Matheson                    f.write(
154*b71edfaaSTobias Hieta                        textwrap.dedent(
155*b71edfaaSTobias Hieta                            f"""
156f3fb9739STomas Matheson                        define dso_local {ty} @{name}(ptr %ptr, {ty} %value) {{
157f3fb9739STomas Matheson                            %r = {instr} {op} ptr %ptr, {ty} %value {ordering}, align {ty.align(aligned)}
158f3fb9739STomas Matheson                            ret {ty} %r
159f3fb9739STomas Matheson                        }}
160*b71edfaaSTobias Hieta                    """
161*b71edfaaSTobias Hieta                        )
162*b71edfaaSTobias Hieta                    )
163f3fb9739STomas Matheson
164f3fb9739STomas Matheson
165f3fb9739STomas Mathesondef all_load(f):
166f3fb9739STomas Matheson    for aligned in Aligned:
167f3fb9739STomas Matheson        for ty in Type:
168f3fb9739STomas Matheson            for ordering in ATOMIC_LOAD_ORDERS:
169f3fb9739STomas Matheson                for const in [False, True]:
170*b71edfaaSTobias Hieta                    name = f"load_atomic_{ty}_{aligned}_{ordering}"
171*b71edfaaSTobias Hieta                    instr = "load atomic"
172f3fb9739STomas Matheson                    if const:
173*b71edfaaSTobias Hieta                        name += "_const"
174*b71edfaaSTobias Hieta                    arg = "ptr readonly %ptr" if const else "ptr %ptr"
175f3fb9739STomas Matheson                    f.write(
176*b71edfaaSTobias Hieta                        textwrap.dedent(
177*b71edfaaSTobias Hieta                            f"""
178f3fb9739STomas Matheson                        define dso_local {ty} @{name}({arg}) {{
179f3fb9739STomas Matheson                            %r = {instr} {ty}, ptr %ptr {ordering}, align {ty.align(aligned)}
180f3fb9739STomas Matheson                            ret {ty} %r
181f3fb9739STomas Matheson                        }}
182*b71edfaaSTobias Hieta                    """
183*b71edfaaSTobias Hieta                        )
184*b71edfaaSTobias Hieta                    )
185f3fb9739STomas Matheson
186f3fb9739STomas Matheson
187f3fb9739STomas Mathesondef all_store(f):
188f3fb9739STomas Matheson    for aligned in Aligned:
189f3fb9739STomas Matheson        for ty in Type:
190f3fb9739STomas Matheson            for ordering in ATOMIC_STORE_ORDERS:  # FIXME stores
191*b71edfaaSTobias Hieta                name = f"store_atomic_{ty}_{aligned}_{ordering}"
192*b71edfaaSTobias Hieta                instr = "store atomic"
193f3fb9739STomas Matheson                f.write(
194*b71edfaaSTobias Hieta                    textwrap.dedent(
195*b71edfaaSTobias Hieta                        f"""
196f3fb9739STomas Matheson                    define dso_local void @{name}({ty} %value, ptr %ptr) {{
197f3fb9739STomas Matheson                        {instr} {ty} %value, ptr %ptr {ordering}, align {ty.align(aligned)}
198f3fb9739STomas Matheson                        ret void
199f3fb9739STomas Matheson                    }}
200*b71edfaaSTobias Hieta                """
201*b71edfaaSTobias Hieta                    )
202*b71edfaaSTobias Hieta                )
203f3fb9739STomas Matheson
204f3fb9739STomas Matheson
205f3fb9739STomas Mathesondef all_cmpxchg(f):
206f3fb9739STomas Matheson    for aligned in Aligned:
207f3fb9739STomas Matheson        for ty in Type:
208f3fb9739STomas Matheson            for success_ordering in CMPXCHG_SUCCESS_ORDERS:
209f3fb9739STomas Matheson                for failure_ordering in CMPXCHG_FAILURE_ORDERS:
210f3fb9739STomas Matheson                    for weak in [False, True]:
211*b71edfaaSTobias Hieta                        name = f"cmpxchg_{ty}_{aligned}_{success_ordering}_{failure_ordering}"
212*b71edfaaSTobias Hieta                        instr = "cmpxchg"
213f3fb9739STomas Matheson                        if weak:
214*b71edfaaSTobias Hieta                            name += "_weak"
215*b71edfaaSTobias Hieta                            instr += " weak"
216f3fb9739STomas Matheson                        f.write(
217*b71edfaaSTobias Hieta                            textwrap.dedent(
218*b71edfaaSTobias Hieta                                f"""
219f3fb9739STomas Matheson                            define dso_local {ty} @{name}({ty} %expected, {ty} %new, ptr %ptr) {{
220f3fb9739STomas Matheson                                %pair = {instr} ptr %ptr, {ty} %expected, {ty} %new {success_ordering} {failure_ordering}, align {ty.align(aligned)}
221f3fb9739STomas Matheson                                %r = extractvalue {{ {ty}, i1 }} %pair, 0
222f3fb9739STomas Matheson                                ret {ty} %r
223f3fb9739STomas Matheson                            }}
224*b71edfaaSTobias Hieta                        """
225*b71edfaaSTobias Hieta                            )
226*b71edfaaSTobias Hieta                        )
227f3fb9739STomas Matheson
228f3fb9739STomas Matheson
229f3fb9739STomas Mathesondef all_fence(f):
230f3fb9739STomas Matheson    for ordering in FENCE_ORDERS:
231*b71edfaaSTobias Hieta        name = f"fence_{ordering}"
232f3fb9739STomas Matheson        f.write(
233*b71edfaaSTobias Hieta            textwrap.dedent(
234*b71edfaaSTobias Hieta                f"""
235f3fb9739STomas Matheson            define dso_local void @{name}() {{
236f3fb9739STomas Matheson                fence {ordering}
237f3fb9739STomas Matheson                ret void
238f3fb9739STomas Matheson            }}
239*b71edfaaSTobias Hieta        """
240*b71edfaaSTobias Hieta            )
241*b71edfaaSTobias Hieta        )
242f3fb9739STomas Matheson
243f3fb9739STomas Matheson
244f3fb9739STomas Mathesondef header(f, triple, features, filter_args: str):
245*b71edfaaSTobias Hieta    f.write(
246*b71edfaaSTobias Hieta        "; NOTE: Assertions have been autogenerated by "
247*b71edfaaSTobias Hieta        "utils/update_llc_test_checks.py UTC_ARGS: "
248*b71edfaaSTobias Hieta    )
249f3fb9739STomas Matheson    f.write(filter_args)
250*b71edfaaSTobias Hieta    f.write("\n")
251*b71edfaaSTobias Hieta    f.write(f"; The base test file was generated by {__file__}\n")
252f3fb9739STomas Matheson    for feat in features:
253*b71edfaaSTobias Hieta        for OptFlag in ["-O0", "-O1"]:
254*b71edfaaSTobias Hieta            f.write(
255*b71edfaaSTobias Hieta                " ".join(
256*b71edfaaSTobias Hieta                    [
257*b71edfaaSTobias Hieta                        ";",
258*b71edfaaSTobias Hieta                        "RUN:",
259*b71edfaaSTobias Hieta                        "llc",
260*b71edfaaSTobias Hieta                        "%s",
261*b71edfaaSTobias Hieta                        "-o",
262*b71edfaaSTobias Hieta                        "-",
263*b71edfaaSTobias Hieta                        "-verify-machineinstrs",
264*b71edfaaSTobias Hieta                        f"-mtriple={triple}",
265*b71edfaaSTobias Hieta                        f"-mattr={feat.mattr}",
266*b71edfaaSTobias Hieta                        OptFlag,
267*b71edfaaSTobias Hieta                        "|",
268*b71edfaaSTobias Hieta                        "FileCheck",
269*b71edfaaSTobias Hieta                        "%s",
270*b71edfaaSTobias Hieta                        f"--check-prefixes=CHECK,{OptFlag}\n",
271*b71edfaaSTobias Hieta                    ]
272*b71edfaaSTobias Hieta                )
273*b71edfaaSTobias Hieta            )
274f3fb9739STomas Matheson
275f3fb9739STomas Matheson
276f3fb9739STomas Mathesondef write_lit_tests():
277*b71edfaaSTobias Hieta    os.chdir("llvm/test/CodeGen/AArch64/Atomics/")
278f3fb9739STomas Matheson    for triple in TRIPLES:
279f3fb9739STomas Matheson        # Feature has no effect on fence, so keep it to one file.
280*b71edfaaSTobias Hieta        with open(f"{triple}-fence.ll", "w") as f:
281f3fb9739STomas Matheson            filter_args = r'--filter "^\s*(dmb)"'
282f3fb9739STomas Matheson            header(f, triple, Feature, filter_args)
283f3fb9739STomas Matheson            all_fence(f)
284f3fb9739STomas Matheson
285f3fb9739STomas Matheson        for feat in Feature:
286*b71edfaaSTobias Hieta            with open(f"{triple}-atomicrmw-{feat.name}.ll", "w") as f:
287f3fb9739STomas Matheson                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)"'
288f3fb9739STomas Matheson                header(f, triple, [feat], filter_args)
289f3fb9739STomas Matheson                all_atomicrmw(f)
290f3fb9739STomas Matheson
291*b71edfaaSTobias Hieta            with open(f"{triple}-cmpxchg-{feat.name}.ll", "w") as f:
292f3fb9739STomas Matheson                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)"'
293f3fb9739STomas Matheson                header(f, triple, [feat], filter_args)
294f3fb9739STomas Matheson                all_cmpxchg(f)
295f3fb9739STomas Matheson
296*b71edfaaSTobias Hieta            with open(f"{triple}-atomic-load-{feat.name}.ll", "w") as f:
297f3fb9739STomas Matheson                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)"'
298f3fb9739STomas Matheson                header(f, triple, [feat], filter_args)
299f3fb9739STomas Matheson                all_load(f)
300f3fb9739STomas Matheson
301*b71edfaaSTobias Hieta            with open(f"{triple}-atomic-store-{feat.name}.ll", "w") as f:
302f3fb9739STomas Matheson                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)"'
303f3fb9739STomas Matheson                header(f, triple, [feat], filter_args)
304f3fb9739STomas Matheson                all_store(f)
305f3fb9739STomas Matheson
306*b71edfaaSTobias Hieta
307*b71edfaaSTobias Hietaif __name__ == "__main__":
308f3fb9739STomas Matheson    write_lit_tests()
309f3fb9739STomas Matheson
310*b71edfaaSTobias Hieta    print(
311*b71edfaaSTobias Hieta        textwrap.dedent(
312*b71edfaaSTobias Hieta            """
313f3fb9739STomas Matheson        Testcases written. To update checks run:
314f3fb9739STomas Matheson            $ ./llvm/utils/update_llc_test_checks.py -u llvm/test/CodeGen/AArch64/Atomics/*.ll
315f3fb9739STomas Matheson
316f3fb9739STomas Matheson        Or in parallel:
317f3fb9739STomas Matheson            $ parallel ./llvm/utils/update_llc_test_checks.py -u ::: llvm/test/CodeGen/AArch64/Atomics/*.ll
318*b71edfaaSTobias Hieta    """
319*b71edfaaSTobias Hieta        )
320*b71edfaaSTobias Hieta    )
321