@@ -196,7 +196,145 @@ def : LoadPatExternSymOffOnly<i64, anyext_aload_16_64, ATOMIC_LOAD16_U_I64>;
196
196
// Atomic stores
197
197
//===----------------------------------------------------------------------===//
198
198
199
- // TODO: add atomic stores here...
199
+ let Defs = [ARGUMENTS] in {
200
+ defm ATOMIC_STORE_I32 : WebAssemblyStore<I32, "i32.atomic.store", 0xfe17>;
201
+ defm ATOMIC_STORE_I64 : WebAssemblyStore<I64, "i64.atomic.store", 0xfe18>;
202
+ } // Defs = [ARGUMENTS]
203
+
204
+ // We need an 'atomic' version of store patterns because store and atomic_store
205
+ // nodes have different operand orders:
206
+ // store: (store $val, $ptr)
207
+ // atomic_store: (store $ptr, $val)
208
+
209
+ let Predicates = [HasAtomics] in {
210
+
211
+ // Select stores with no constant offset.
212
+ class AStorePatNoOffset<ValueType ty, PatFrag node, NI inst> :
213
+ Pat<(node I32:$addr, ty:$val), (inst 0, 0, $addr, $val)>;
214
+ def : AStorePatNoOffset<i32, atomic_store_32, ATOMIC_STORE_I32>;
215
+ def : AStorePatNoOffset<i64, atomic_store_64, ATOMIC_STORE_I64>;
216
+
217
+ // Select stores with a constant offset.
218
+
219
+ // Pattern with address + immediate offset
220
+ class AStorePatImmOff<ValueType ty, PatFrag storekind, PatFrag operand,
221
+ NI inst> :
222
+ Pat<(storekind (operand I32:$addr, imm:$off), ty:$val),
223
+ (inst 0, imm:$off, $addr, ty:$val)>;
224
+ def : AStorePatImmOff<i32, atomic_store_32, regPlusImm, ATOMIC_STORE_I32>;
225
+ def : AStorePatImmOff<i64, atomic_store_64, regPlusImm, ATOMIC_STORE_I64>;
226
+ def : AStorePatImmOff<i32, atomic_store_32, or_is_add, ATOMIC_STORE_I32>;
227
+ def : AStorePatImmOff<i64, atomic_store_64, or_is_add, ATOMIC_STORE_I64>;
228
+
229
+ class AStorePatGlobalAddr<ValueType ty, PatFrag storekind, NI inst> :
230
+ Pat<(storekind (regPlusGA I32:$addr, (WebAssemblywrapper tglobaladdr:$off)),
231
+ ty:$val),
232
+ (inst 0, tglobaladdr:$off, I32:$addr, ty:$val)>;
233
+ def : AStorePatGlobalAddr<i32, atomic_store_32, ATOMIC_STORE_I32>;
234
+ def : AStorePatGlobalAddr<i64, atomic_store_64, ATOMIC_STORE_I64>;
235
+
236
+ class AStorePatExternalSym<ValueType ty, PatFrag storekind, NI inst> :
237
+ Pat<(storekind (add I32:$addr, (WebAssemblywrapper texternalsym:$off)),
238
+ ty:$val),
239
+ (inst 0, texternalsym:$off, I32:$addr, ty:$val)>;
240
+ def : AStorePatExternalSym<i32, atomic_store_32, ATOMIC_STORE_I32>;
241
+ def : AStorePatExternalSym<i64, atomic_store_64, ATOMIC_STORE_I64>;
242
+
243
+ // Select stores with just a constant offset.
244
+ class AStorePatOffsetOnly<ValueType ty, PatFrag storekind, NI inst> :
245
+ Pat<(storekind imm:$off, ty:$val),
246
+ (inst 0, imm:$off, (CONST_I32 0), ty:$val)>;
247
+ def : AStorePatOffsetOnly<i32, atomic_store_32, ATOMIC_STORE_I32>;
248
+ def : AStorePatOffsetOnly<i64, atomic_store_64, ATOMIC_STORE_I64>;
249
+
250
+ class AStorePatGlobalAddrOffOnly<ValueType ty, PatFrag storekind, NI inst> :
251
+ Pat<(storekind (WebAssemblywrapper tglobaladdr:$off), ty:$val),
252
+ (inst 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>;
253
+ def : AStorePatGlobalAddrOffOnly<i32, atomic_store_32, ATOMIC_STORE_I32>;
254
+ def : AStorePatGlobalAddrOffOnly<i64, atomic_store_64, ATOMIC_STORE_I64>;
255
+
256
+ class AStorePatExternSymOffOnly<ValueType ty, PatFrag storekind, NI inst> :
257
+ Pat<(storekind (WebAssemblywrapper texternalsym:$off), ty:$val),
258
+ (inst 0, texternalsym:$off, (CONST_I32 0), ty:$val)>;
259
+ def : AStorePatExternSymOffOnly<i32, atomic_store_32, ATOMIC_STORE_I32>;
260
+ def : AStorePatExternSymOffOnly<i64, atomic_store_64, ATOMIC_STORE_I64>;
261
+
262
+ } // Predicates = [HasAtomics]
263
+
264
+ // Truncating stores.
265
+ let Defs = [ARGUMENTS] in {
266
+ defm ATOMIC_STORE8_I32 : WebAssemblyStore<I32, "i32.atomic.store8", 0xfe19>;
267
+ defm ATOMIC_STORE16_I32 : WebAssemblyStore<I32, "i32.atomic.store16", 0xfe1a>;
268
+ defm ATOMIC_STORE8_I64 : WebAssemblyStore<I64, "i64.atomic.store8", 0xfe1b>;
269
+ defm ATOMIC_STORE16_I64 : WebAssemblyStore<I64, "i64.atomic.store16", 0xfe1c>;
270
+ defm ATOMIC_STORE32_I64 : WebAssemblyStore<I64, "i64.atomic.store32", 0xfe1d>;
271
+ } // Defs = [ARGUMENTS]
272
+
273
+ // Fragments for truncating stores.
274
+
275
+ // We don't have single truncating atomic store instructions. For 32-bit
276
+ // instructions, we just need to match bare atomic stores. On the other hand,
277
+ // truncating stores from i64 values are once truncated to i32 first.
278
+ class trunc_astore_64<PatFrag storekind> :
279
+ PatFrag<(ops node:$addr, node:$val),
280
+ (storekind node:$addr, (i32 (trunc (i64 node:$val))))>;
281
+ def trunc_astore_8_64 : trunc_astore_64<atomic_store_8>;
282
+ def trunc_astore_16_64 : trunc_astore_64<atomic_store_16>;
283
+ def trunc_astore_32_64 : trunc_astore_64<atomic_store_32>;
284
+
285
+ let Predicates = [HasAtomics] in {
286
+
287
+ // Truncating stores with no constant offset
288
+ def : AStorePatNoOffset<i32, atomic_store_8, ATOMIC_STORE8_I32>;
289
+ def : AStorePatNoOffset<i32, atomic_store_16, ATOMIC_STORE16_I32>;
290
+ def : AStorePatNoOffset<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>;
291
+ def : AStorePatNoOffset<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>;
292
+ def : AStorePatNoOffset<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>;
293
+
294
+ // Truncating stores with a constant offset
295
+ def : AStorePatImmOff<i32, atomic_store_8, regPlusImm, ATOMIC_STORE8_I32>;
296
+ def : AStorePatImmOff<i32, atomic_store_16, regPlusImm, ATOMIC_STORE16_I32>;
297
+ def : AStorePatImmOff<i64, trunc_astore_8_64, regPlusImm, ATOMIC_STORE8_I64>;
298
+ def : AStorePatImmOff<i64, trunc_astore_16_64, regPlusImm, ATOMIC_STORE16_I64>;
299
+ def : AStorePatImmOff<i64, trunc_astore_32_64, regPlusImm, ATOMIC_STORE32_I64>;
300
+ def : AStorePatImmOff<i32, atomic_store_8, or_is_add, ATOMIC_STORE8_I32>;
301
+ def : AStorePatImmOff<i32, atomic_store_16, or_is_add, ATOMIC_STORE16_I32>;
302
+ def : AStorePatImmOff<i64, trunc_astore_8_64, or_is_add, ATOMIC_STORE8_I64>;
303
+ def : AStorePatImmOff<i64, trunc_astore_16_64, or_is_add, ATOMIC_STORE16_I64>;
304
+ def : AStorePatImmOff<i64, trunc_astore_32_64, or_is_add, ATOMIC_STORE32_I64>;
305
+
306
+ def : AStorePatGlobalAddr<i32, atomic_store_8, ATOMIC_STORE8_I32>;
307
+ def : AStorePatGlobalAddr<i32, atomic_store_16, ATOMIC_STORE16_I32>;
308
+ def : AStorePatGlobalAddr<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>;
309
+ def : AStorePatGlobalAddr<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>;
310
+ def : AStorePatGlobalAddr<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>;
311
+
312
+ def : AStorePatExternalSym<i32, atomic_store_8, ATOMIC_STORE8_I32>;
313
+ def : AStorePatExternalSym<i32, atomic_store_16, ATOMIC_STORE16_I32>;
314
+ def : AStorePatExternalSym<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>;
315
+ def : AStorePatExternalSym<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>;
316
+ def : AStorePatExternalSym<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>;
317
+
318
+ // Truncating stores with just a constant offset
319
+ def : AStorePatOffsetOnly<i32, atomic_store_8, ATOMIC_STORE8_I32>;
320
+ def : AStorePatOffsetOnly<i32, atomic_store_16, ATOMIC_STORE16_I32>;
321
+ def : AStorePatOffsetOnly<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>;
322
+ def : AStorePatOffsetOnly<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>;
323
+ def : AStorePatOffsetOnly<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>;
324
+
325
+ def : AStorePatGlobalAddrOffOnly<i32, atomic_store_8, ATOMIC_STORE8_I32>;
326
+ def : AStorePatGlobalAddrOffOnly<i32, atomic_store_16, ATOMIC_STORE16_I32>;
327
+ def : AStorePatGlobalAddrOffOnly<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>;
328
+ def : AStorePatGlobalAddrOffOnly<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>;
329
+ def : AStorePatGlobalAddrOffOnly<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>;
330
+
331
+ def : AStorePatExternSymOffOnly<i32, atomic_store_8, ATOMIC_STORE8_I32>;
332
+ def : AStorePatExternSymOffOnly<i32, atomic_store_16, ATOMIC_STORE16_I32>;
333
+ def : AStorePatExternSymOffOnly<i64, trunc_astore_8_64, ATOMIC_STORE8_I64>;
334
+ def : AStorePatExternSymOffOnly<i64, trunc_astore_16_64, ATOMIC_STORE16_I64>;
335
+ def : AStorePatExternSymOffOnly<i64, trunc_astore_32_64, ATOMIC_STORE32_I64>;
336
+
337
+ } // Predicates = [HasAtomics]
200
338
201
339
//===----------------------------------------------------------------------===//
202
340
// Low-level exclusive operations
0 commit comments