@@ -48,6 +48,16 @@ for (op, rmwop) in OP_RMW_TABLE
48
48
first (UnsafeAtomics. modify! (ptr, $ op, x, ord))
49
49
end
50
50
51
+ const ATOMIC_INTRINSICS = isdefined (Core. Intrinsics, :atomic_pointerref )
52
+
53
+ if VERSION >= v " 1.12.0-DEV.161" && Int == Int64
54
+ const MAX_ATOMIC_SIZE = 16
55
+ const MAX_POINTERATOMIC_SIZE = 16
56
+ else
57
+ const MAX_ATOMIC_SIZE = 8
58
+ const MAX_POINTERATOMIC_SIZE = 8
59
+ end
60
+
51
61
# Based on: https://github.com/JuliaLang/julia/blob/v1.6.3/base/atomics.jl
52
62
for typ in (inttypes... , floattypes... )
53
63
lt = llvmtypes[typ]
@@ -56,35 +66,48 @@ for typ in (inttypes..., floattypes...)
56
66
for ord in orderings
57
67
ord in (release, acq_rel) && continue
58
68
59
- @eval function UnsafeAtomics. load (x:: Ptr{$typ} , :: $ (typeof (ord)))
60
- return llvmcall (
61
- $ ("""
62
- %ptr = inttoptr i$WORD_SIZE %0 to $lt *
63
- %rv = load atomic $rt %ptr $ord , align $(sizeof (typ))
64
- ret $lt %rv
65
- """ ),
66
- $ typ,
67
- Tuple{Ptr{$ typ}},
68
- x,
69
- )
69
+ if ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE
70
+ @eval function UnsafeAtomics. load (x:: Ptr{$typ} , :: $ (typeof (ord)))
71
+ return Core. Intrinsics. atomic_pointerref (x, base_ordering ($ ord))
72
+ end
73
+ else
74
+ @eval function UnsafeAtomics. load (x:: Ptr{$typ} , :: $ (typeof (ord)))
75
+ return llvmcall (
76
+ $ ("""
77
+ %ptr = inttoptr i$WORD_SIZE %0 to $lt *
78
+ %rv = load atomic $rt %ptr $ord , align $(sizeof (typ))
79
+ ret $lt %rv
80
+ """ ),
81
+ $ typ,
82
+ Tuple{Ptr{$ typ}},
83
+ x,
84
+ )
85
+ end
70
86
end
71
87
end
72
88
73
89
for ord in orderings
74
90
ord in (acquire, acq_rel) && continue
75
91
76
- @eval function UnsafeAtomics. store! (x:: Ptr{$typ} , v:: $typ , :: $ (typeof (ord)))
77
- return llvmcall (
78
- $ ("""
79
- %ptr = inttoptr i$WORD_SIZE %0 to $lt *
80
- store atomic $lt %1, $lt * %ptr $ord , align $(sizeof (typ))
81
- ret void
82
- """ ),
83
- Cvoid,
84
- Tuple{Ptr{$ typ},$ typ},
85
- x,
86
- v,
87
- )
92
+ if ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE
93
+ @eval function UnsafeAtomics. store! (x:: Ptr{$typ} , v:: $typ , :: $ (typeof (ord)))
94
+ Core. Intrinsics. atomic_pointerset (x, v, base_ordering ($ ord))
95
+ return nothing
96
+ end
97
+ else
98
+ @eval function UnsafeAtomics. store! (x:: Ptr{$typ} , v:: $typ , :: $ (typeof (ord)))
99
+ return llvmcall (
100
+ $ ("""
101
+ %ptr = inttoptr i$WORD_SIZE %0 to $lt *
102
+ store atomic $lt %1, $lt * %ptr $ord , align $(sizeof (typ))
103
+ ret void
104
+ """ ),
105
+ Cvoid,
106
+ Tuple{Ptr{$ typ},$ typ},
107
+ x,
108
+ v,
109
+ )
110
+ end
88
111
end
89
112
end
90
113
@@ -93,37 +116,55 @@ for typ in (inttypes..., floattypes...)
93
116
94
117
typ <: AbstractFloat && break
95
118
96
- @eval function UnsafeAtomics. cas! (
97
- x:: Ptr{$typ} ,
98
- cmp:: $typ ,
99
- new:: $typ ,
100
- :: $ (typeof (success_ordering)),
101
- :: $ (typeof (failure_ordering)),
102
- )
103
- success = Ref {Int8} ()
104
- GC. @preserve success begin
105
- old = llvmcall (
106
- $ (
107
- """
108
- %ptr = inttoptr i$WORD_SIZE %0 to $lt *
109
- %rs = cmpxchg $lt * %ptr, $lt %1, $lt %2 $success_ordering $failure_ordering
110
- %rv = extractvalue { $lt , i1 } %rs, 0
111
- %s1 = extractvalue { $lt , i1 } %rs, 1
112
- %s8 = zext i1 %s1 to i8
113
- %sptr = inttoptr i$WORD_SIZE %3 to i8*
114
- store i8 %s8, i8* %sptr
115
- ret $lt %rv
116
- """
117
- ),
118
- $ typ,
119
- Tuple{Ptr{$ typ},$ typ,$ typ,Ptr{Int8}},
119
+ if ATOMIC_INTRINSICS && sizeof (typ) <= MAX_POINTERATOMIC_SIZE
120
+ @eval function UnsafeAtomics. cas! (
121
+ x:: Ptr{$typ} ,
122
+ cmp:: $typ ,
123
+ new:: $typ ,
124
+ :: $ (typeof (success_ordering)),
125
+ :: $ (typeof (failure_ordering)),
126
+ )
127
+ return Core. Intrinsics. atomic_pointerreplace (
120
128
x,
121
129
cmp,
122
130
new,
123
- Ptr {Int8} (pointer_from_objref (success)),
131
+ base_ordering ($ success_ordering),
132
+ base_ordering ($ failure_ordering)
124
133
)
125
134
end
126
- return (old = old, success = ! iszero (success[]))
135
+ else
136
+ @eval function UnsafeAtomics. cas! (
137
+ x:: Ptr{$typ} ,
138
+ cmp:: $typ ,
139
+ new:: $typ ,
140
+ :: $ (typeof (success_ordering)),
141
+ :: $ (typeof (failure_ordering)),
142
+ )
143
+ success = Ref {Int8} ()
144
+ GC. @preserve success begin
145
+ old = llvmcall (
146
+ $ (
147
+ """
148
+ %ptr = inttoptr i$WORD_SIZE %0 to $lt *
149
+ %rs = cmpxchg $lt * %ptr, $lt %1, $lt %2 $success_ordering $failure_ordering
150
+ %rv = extractvalue { $lt , i1 } %rs, 0
151
+ %s1 = extractvalue { $lt , i1 } %rs, 1
152
+ %s8 = zext i1 %s1 to i8
153
+ %sptr = inttoptr i$WORD_SIZE %3 to i8*
154
+ store i8 %s8, i8* %sptr
155
+ ret $lt %rv
156
+ """
157
+ ),
158
+ $ typ,
159
+ Tuple{Ptr{$ typ},$ typ,$ typ,Ptr{Int8}},
160
+ x,
161
+ cmp,
162
+ new,
163
+ Ptr {Int8} (pointer_from_objref (success)),
164
+ )
165
+ end
166
+ return (old = old, success = ! iszero (success[]))
167
+ end
127
168
end
128
169
end
129
170
@@ -144,24 +185,36 @@ for typ in (inttypes..., floattypes...)
144
185
end
145
186
end
146
187
for ord in orderings
147
- @eval function UnsafeAtomics . modify! (
148
- x :: Ptr{$ typ} ,
149
- :: typeof ( $ op),
150
- v :: $typ ,
151
- :: $ ( typeof (ord) ),
152
- )
153
- old = llvmcall (
154
- $ ( """
155
- %ptr = inttoptr i $WORD_SIZE %0 to $lt *
156
- %rv = atomicrmw $rmw $lt * %ptr, $lt %1 $ord
157
- ret $lt %rv
158
- """ ),
159
- $ typ,
160
- Tuple{Ptr{ $ typ}, $ typ} ,
161
- x ,
162
- v ,
188
+ # Enable this code iff https://github.com/JuliaLang/julia/pull/45122 get's merged
189
+ if false && ATOMIC_INTRINSICS && sizeof ( typ) <= MAX_POINTERATOMIC_SIZE
190
+ @eval function UnsafeAtomics . modify! (
191
+ x :: Ptr{ $typ} ,
192
+ op :: typeof ($ op ),
193
+ v :: $typ ,
194
+ :: $ ( typeof (ord)),
195
+ )
196
+ return Core . Intrinsics . atomic_pointermodify (x, op, v, base_ordering ( $ ord))
197
+ end
198
+ else
199
+ @eval function UnsafeAtomics . modify! (
200
+ x :: Ptr{ $typ} ,
201
+ :: typeof ( $ op) ,
202
+ v :: $typ ,
203
+ :: $ ( typeof (ord)) ,
163
204
)
164
- return old => $ op (old, v)
205
+ old = llvmcall (
206
+ $ ("""
207
+ %ptr = inttoptr i$WORD_SIZE %0 to $lt *
208
+ %rv = atomicrmw $rmw $lt * %ptr, $lt %1 $ord
209
+ ret $lt %rv
210
+ """ ),
211
+ $ typ,
212
+ Tuple{Ptr{$ typ},$ typ},
213
+ x,
214
+ v,
215
+ )
216
+ return old => $ op (old, v)
217
+ end
165
218
end
166
219
end
167
220
end
0 commit comments