summaryrefslogtreecommitdiff
path: root/llvm/test/CodeGen/NVPTX/cmpxchg.py
blob: 75623a59ad4818b1b4faf231015b8811f8abc722 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
# For manual usage, not as a part of lit tests. Used for generating the following tests:
# cmpxchg-sm30.ll, cmpxchg-sm70.ll, cmpxchg-sm90.ll

from string import Template
from itertools import product

cmpxchg_func = Template(
    """define i$size @${success}_${failure}_i${size}_${addrspace}_${ptx_scope}(ptr${addrspace_cast} %addr, i$size %cmp, i$size %new) {
    %pairold = cmpxchg ptr${addrspace_cast} %addr, i$size %cmp, i$size %new syncscope(\"${llvm_scope}\") $success $failure
    ret i$size %new
}
"""
)

cmpxchg_func_no_scope = Template(
    """define i$size @${success}_${failure}_i${size}_${addrspace}(ptr${addrspace_cast} %addr, i$size %cmp, i$size %new) {
    %pairold = cmpxchg ptr${addrspace_cast} %addr, i$size %cmp, i$size %new $success $failure
    ret i$size %new
}
"""
)

run_statement = Template(
    """; RUN: llc < %s -march=nvptx64 -mcpu=sm_${sm} -mattr=+ptx${ptx} | FileCheck %s --check-prefix=SM${sm}
; RUN: %if ptxas %{ llc < %s -march=nvptx64 -mcpu=sm_${sm} -mattr=+ptx${ptx} | %ptxas-verify -arch=sm_${sm} %}
"""
)


def get_addrspace_cast(addrspace):
    if addrspace == 0:
        return ""
    else:
        return " addrspace({})".format(str(addrspace))


TESTS = [(60, 50), (70, 63), (90, 87)]

LLVM_SCOPES = ["", "block", "cluster", "device"]

SCOPE_LLVM_TO_PTX = {"": "sys", "block": "cta", "cluster": "cluster", "device": "gpu"}

SUCCESS_ORDERINGS = ["monotonic", "acquire", "release", "acq_rel", "seq_cst"]

FAILURE_ORDERINGS = ["monotonic", "acquire", "seq_cst"]

SIZES = [8, 16, 32, 64]

ADDRSPACES = [0, 1, 3]

ADDRSPACE_NUM_TO_ADDRSPACE = {0: "generic", 1: "global", 3: "shared"}


if __name__ == "__main__":
    for sm, ptx in TESTS:
        with open("cmpxchg-sm{}.ll".format(str(sm)), "w") as fp:
            print(run_statement.substitute(sm=sm, ptx=ptx), file=fp)

            # Our test space is: SIZES X SUCCESS_ORDERINGS X FAILURE_ORDERINGS X ADDRSPACES X LLVM_SCOPES
            # This is very large, so we instead test 3 slices.

            # First slice:  are all orderings correctly supported, with and without emulation loops?
            # set addrspace to global, scope to cta, generate all possible orderings, for all operation sizes
            addrspace, llvm_scope = 1, "block"
            for size, success, failure in product(
                SIZES, SUCCESS_ORDERINGS, FAILURE_ORDERINGS
            ):
                print(
                    cmpxchg_func.substitute(
                        success=success,
                        failure=failure,
                        size=size,
                        addrspace=ADDRSPACE_NUM_TO_ADDRSPACE[addrspace],
                        addrspace_cast=get_addrspace_cast(addrspace),
                        llvm_scope=llvm_scope,
                        ptx_scope=SCOPE_LLVM_TO_PTX[llvm_scope],
                    ),
                    file=fp,
                )

            # Second slice: Are all scopes correctlly supported, with and without emulation loops?
            # fix addrspace, ordering, generate all possible scopes, for operation sizes i8, i32
            addrspace, success, failure = 1, "acq_rel", "acquire"
            for size in [8, 32]:
                print(
                    cmpxchg_func_no_scope.substitute(
                        success=success,
                        failure=failure,
                        size=size,
                        addrspace=ADDRSPACE_NUM_TO_ADDRSPACE[addrspace],
                        addrspace_cast=get_addrspace_cast(addrspace),
                    ),
                    file=fp,
                )

            for llvm_scope in LLVM_SCOPES:
                if sm < 90 and llvm_scope == "cluster":
                    continue
                if llvm_scope == "block":
                    # skip (acq_rel, acquire, global, cta)
                    continue
                print(
                    cmpxchg_func.substitute(
                        success=success,
                        failure=failure,
                        size=size,
                        addrspace=ADDRSPACE_NUM_TO_ADDRSPACE[addrspace],
                        addrspace_cast=get_addrspace_cast(addrspace),
                        llvm_scope=llvm_scope,
                        ptx_scope=SCOPE_LLVM_TO_PTX[llvm_scope],
                    ),
                    file=fp,
                )

            # Third slice: Are all address spaces correctly supported?
            # fix ordering, scope, generate all possible address spaces, for operation sizes i8, i32
            success, failure, llvm_scope = "acq_rel", "acquire", "block"
            for size, addrspace in product([8, 32], ADDRSPACES):
                if addrspace == 1:
                    # skip (acq_rel, acquire, global, cta)
                    continue
                print(
                    cmpxchg_func.substitute(
                        success=success,
                        failure=failure,
                        size=size,
                        addrspace=ADDRSPACE_NUM_TO_ADDRSPACE[addrspace],
                        addrspace_cast=get_addrspace_cast(addrspace),
                        llvm_scope=llvm_scope,
                        ptx_scope=SCOPE_LLVM_TO_PTX[llvm_scope],
                    ),
                    file=fp,
                )