forked from terralang/terra
-
Notifications
You must be signed in to change notification settings - Fork 2
/
atomicrmw.t
145 lines (104 loc) · 2.91 KB
/
atomicrmw.t
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
134
135
136
137
138
139
140
141
142
143
144
145
local has_fmin = terralib.llvm_version >= 150
print("atomicrmw test settings: fmin " .. tostring(has_fmin))
-- Basic cases: integers with ordering/syncscope/alignment
terra atomic_add(x : &int, y : int, z : int, w : int, u : int)
terralib.atomicrmw("add", x, y, {ordering = "seq_cst"})
terralib.atomicrmw("add", x, z, {ordering = "acq_rel"})
terralib.fence({ordering = "release"})
terralib.atomicrmw("add", x, w, {ordering = "monotonic", syncscope = "singlethread", align = 16})
terralib.fence({ordering = "acquire"})
terralib.atomicrmw("add", x, u, {ordering = "monotonic", isvolatile = true})
end
atomic_add:printpretty(false)
atomic_add:disas()
local c = terralib.includecstring [[
#ifndef _WIN32
#include "stdlib.h"
#else
#include "malloc.h"
#include "errno.h"
int posix_memalign(void **p, size_t a, size_t s) {
*p = _aligned_malloc(s, a);
return *p ? 0 : errno;
}
#endif
]]
terra add()
var i : &int
if c.posix_memalign([&&opaque](&i), 16, terralib.sizeof(int)) ~= 0 then
return 0
end
@i = 1
atomic_add(i, 20, 300, 4000, 50000)
return @i
end
print(add())
assert(add() == 54321)
-- Returns previous value
terra atomic_add_and_return(x : &int, y : int)
return terralib.atomicrmw("add", x, y, {ordering = "acq_rel"})
end
atomic_add_and_return:printpretty(false)
atomic_add_and_return:disas()
terra add_and_return()
var i : int = 1
var r = atomic_add_and_return(&i, 20)
return r + i
end
print(add_and_return())
assert(add_and_return() == 22)
-- Floating point
terra atomic_fadd(x : &double, y : double)
terralib.atomicrmw("fadd", x, y, {ordering = "monotonic"})
end
atomic_fadd:printpretty(false)
atomic_fadd:disas()
terra fadd()
var f : double = 1.0
atomic_fadd(&f, 20.0)
return f
end
print(fadd())
assert(fadd() == 21.0)
if has_fmin then
terra atomic_fmin(x : &double, y : double)
terralib.atomicrmw("fmin", x, y, {ordering = "monotonic"})
end
atomic_fmin:printpretty(false)
atomic_fmin:disas()
terra fmin(x : double, y : double)
var f : double = x
atomic_fmin(&f, y)
return f
end
print(fmin(1.0, 20.0))
assert(fmin(1.0, 20.0) == 1.0)
print(fmin(5.0, 3.0))
assert(fmin(5.0, 3.0) == 3.0)
end
-- Pointers
-- Note: when using pointers, you must cast to an integer type (e.g.,
-- int64). LLVM (contrary to its documentation) does not support xchg
-- on pointers.
local intptr
if terralib.sizeof(&int) == 8 then
intptr = int64
elseif terralib.sizeof(&int) == 4 then
intptr = int32
else
assert(false, "not sure what size a pointer is on this machine")
end
terra atomic_xchg_pointer(x : &&int, y : &int)
return [&int](terralib.atomicrmw("xchg", [&intptr](x), [intptr](y), {ordering = "acq_rel"}))
end
atomic_xchg_pointer:printpretty(false)
atomic_xchg_pointer:disas()
terra xchg_pointer()
var i : int = 1
var j : int = 20
var k = &i
var r = atomic_xchg_pointer(&k, &j)
return r == &i and k == &j
end
print(xchg_pointer())
assert(xchg_pointer())