} // mayLoad = 1
} // hasSideEffects = 1
-// Select notifys with no constant offset.
-def NotifyPatNoOffset_A32 :
- Pat<(i32 (int_wasm_memory_atomic_notify I32:$addr, I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A32 0, 0, I32:$addr, I32:$count)>,
+def NotifyPat_A32 :
+ Pat<(i32 (int_wasm_memory_atomic_notify (AddrOps32 offset32_op:$offset, I32:$addr), I32:$count)),
+ (MEMORY_ATOMIC_NOTIFY_A32 0, $offset, $addr, $count)>,
Requires<[HasAddr32, HasAtomics]>;
-def NotifyPatNoOffset_A64 :
- Pat<(i32 (int_wasm_memory_atomic_notify I64:$addr, I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A64 0, 0, I64:$addr, I32:$count)>,
+def NotifyPat_A64 :
+ Pat<(i32 (int_wasm_memory_atomic_notify (AddrOps64 offset64_op:$offset, I64:$addr), I32:$count)),
+ (MEMORY_ATOMIC_NOTIFY_A64 0, $offset, $addr, $count)>,
Requires<[HasAddr64, HasAtomics]>;
-// Select notifys with a constant offset.
-// Pattern with address + immediate offset
-multiclass NotifyPatImmOff<PatFrag operand, string inst> {
- def : Pat<(i32 (int_wasm_memory_atomic_notify (operand I32:$addr, imm:$off),
- I32:$count)),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, I32:$count)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(i32 (int_wasm_memory_atomic_notify (operand I64:$addr, imm:$off),
- I32:$count)),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, I32:$count)>,
- Requires<[HasAddr64, HasAtomics]>;
+multiclass WaitPat<ValueType ty, Intrinsic kind, string inst> {
+ def WaitPat_A32 :
+ Pat<(i32 (kind (AddrOps32 offset32_op:$offset, I32:$addr), ty:$exp, I64:$timeout)),
+ (!cast<NI>(inst#_A32) 0, $offset, $addr, $exp, $timeout)>,
+ Requires<[HasAddr32, HasAtomics]>;
+ def WaitPat_A64 :
+ Pat<(i32 (kind (AddrOps64 offset64_op:$offset, I64:$addr), ty:$exp, I64:$timeout)),
+ (!cast<NI>(inst#_A64) 0, $offset, $addr, $exp, $timeout)>,
+ Requires<[HasAddr64, HasAtomics]>;
}
-defm : NotifyPatImmOff<regPlusImm, "MEMORY_ATOMIC_NOTIFY">;
-defm : NotifyPatImmOff<or_is_add, "MEMORY_ATOMIC_NOTIFY">;
-
-// Select notifys with just a constant offset.
-def NotifyPatOffsetOnly_A32 :
- Pat<(i32 (int_wasm_memory_atomic_notify imm:$off, I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A32 0, imm:$off, (CONST_I32 0), I32:$count)>,
- Requires<[HasAddr32, HasAtomics]>;
-def NotifyPatOffsetOnly_A64 :
- Pat<(i32 (int_wasm_memory_atomic_notify imm:$off, I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A64 0, imm:$off, (CONST_I64 0), I32:$count)>,
- Requires<[HasAddr64, HasAtomics]>;
-def NotifyPatGlobalAddrOffOnly_A32 :
- Pat<(i32 (int_wasm_memory_atomic_notify (WebAssemblyWrapper tglobaladdr:$off),
- I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A32 0, tglobaladdr:$off, (CONST_I32 0), I32:$count)
- >,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
-def NotifyPatGlobalAddrOffOnly_A64 :
- Pat<(i32 (int_wasm_memory_atomic_notify (WebAssemblyWrapper tglobaladdr:$off),
- I32:$count)),
- (MEMORY_ATOMIC_NOTIFY_A64 0, tglobaladdr:$off, (CONST_I64 0), I32:$count)
- >,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-
-// Select waits with no constant offset.
-multiclass WaitPatNoOffset<ValueType ty, Intrinsic kind,
- string inst> {
- def : Pat<(i32 (kind I32:$addr, ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A32) 0, 0, I32:$addr, ty:$exp, I64:$timeout)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(i32 (kind I64:$addr, ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A64) 0, 0, I64:$addr, ty:$exp, I64:$timeout)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : WaitPatNoOffset<i32, int_wasm_memory_atomic_wait32,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatNoOffset<i64, int_wasm_memory_atomic_wait64,
- "MEMORY_ATOMIC_WAIT64">;
-defm : WaitPatNoOffset<i32, int_wasm_memory_atomic_wait32,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatNoOffset<i64, int_wasm_memory_atomic_wait64,
- "MEMORY_ATOMIC_WAIT64">;
-
-// Select waits with a constant offset.
-
-// Pattern with address + immediate offset
-multiclass WaitPatImmOff<ValueType ty, Intrinsic kind, PatFrag operand,
- string inst> {
- def : Pat<(i32 (kind (operand I32:$addr, imm:$off), ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(i32 (kind (operand I64:$addr, imm:$off), ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : WaitPatImmOff<i32, int_wasm_memory_atomic_wait32, regPlusImm,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatImmOff<i32, int_wasm_memory_atomic_wait32, or_is_add,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatImmOff<i64, int_wasm_memory_atomic_wait64, regPlusImm,
- "MEMORY_ATOMIC_WAIT64">;
-defm : WaitPatImmOff<i64, int_wasm_memory_atomic_wait64, or_is_add,
- "MEMORY_ATOMIC_WAIT64">;
-
-// Select waits with just a constant offset.
-multiclass WaitPatOffsetOnly<ValueType ty, Intrinsic kind, string inst> {
- def : Pat<(i32 (kind imm:$off, ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A32) 0, imm:$off, (CONST_I32 0), ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(i32 (kind imm:$off, ty:$exp, I64:$timeout)),
- (!cast<NI>(inst#_A64) 0, imm:$off, (CONST_I64 0), ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : WaitPatOffsetOnly<i32, int_wasm_memory_atomic_wait32,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatOffsetOnly<i64, int_wasm_memory_atomic_wait64,
- "MEMORY_ATOMIC_WAIT64">;
-
-multiclass WaitPatGlobalAddrOffOnly<ValueType ty, Intrinsic kind, string inst> {
- def : Pat<(i32 (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$exp,
- I64:$timeout)),
- (!cast<NI>(inst#_A32) 0, tglobaladdr:$off, (CONST_I32 0), ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
- def : Pat<(i32 (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$exp,
- I64:$timeout)),
- (!cast<NI>(inst#_A64) 0, tglobaladdr:$off, (CONST_I64 0), ty:$exp,
- I64:$timeout)>,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-}
-defm : WaitPatGlobalAddrOffOnly<i32, int_wasm_memory_atomic_wait32,
- "MEMORY_ATOMIC_WAIT32">;
-defm : WaitPatGlobalAddrOffOnly<i64, int_wasm_memory_atomic_wait64,
- "MEMORY_ATOMIC_WAIT64">;
+defm : WaitPat<i32, int_wasm_memory_atomic_wait32, "MEMORY_ATOMIC_WAIT32">;
+defm : WaitPat<i64, int_wasm_memory_atomic_wait64, "MEMORY_ATOMIC_WAIT64">;
//===----------------------------------------------------------------------===//
// Atomic fences
// store: (store $val, $ptr)
// atomic_store: (store $ptr, $val)
-
-// Select stores with no constant offset.
-multiclass AStorePatNoOffset<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind I32:$addr, ty:$val),
- (!cast<NI>(inst#_A32) 0, 0, I32:$addr, ty:$val)>,
+multiclass AStorePat<ValueType ty, PatFrag kind, string inst> {
+ def : Pat<(kind (AddrOps32 offset32_op:$offset, I32:$addr), ty:$val),
+ (!cast<NI>(inst#_A32) 0, $offset, $addr, $val)>,
Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(kind I64:$addr, ty:$val),
- (!cast<NI>(inst#_A64) 0, 0, I64:$addr, ty:$val)>,
+ def : Pat<(kind (AddrOps64 offset64_op:$offset, I64:$addr), ty:$val),
+ (!cast<NI>(inst#_A64) 0, $offset, $addr, $val)>,
Requires<[HasAddr64, HasAtomics]>;
}
-defm : AStorePatNoOffset<i32, atomic_store_32, "ATOMIC_STORE_I32">;
-defm : AStorePatNoOffset<i64, atomic_store_64, "ATOMIC_STORE_I64">;
-
-// Select stores with a constant offset.
-
-// Pattern with address + immediate offset
-multiclass AStorePatImmOff<ValueType ty, PatFrag kind, PatFrag operand,
- string inst> {
- def : Pat<(kind (operand I32:$addr, imm:$off), ty:$val),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, ty:$val)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(kind (operand I64:$addr, imm:$off), ty:$val),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, ty:$val)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : AStorePatImmOff<i32, atomic_store_32, regPlusImm, "ATOMIC_STORE_I32">;
-defm : AStorePatImmOff<i64, atomic_store_64, regPlusImm, "ATOMIC_STORE_I64">;
-
-// Select stores with just a constant offset.
-multiclass AStorePatOffsetOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind imm:$off, ty:$val),
- (!cast<NI>(inst#_A32) 0, imm:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(kind imm:$off, ty:$val),
- (!cast<NI>(inst#_A64) 0, imm:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-defm : AStorePatOffsetOnly<i32, atomic_store_32, "ATOMIC_STORE_I32">;
-defm : AStorePatOffsetOnly<i64, atomic_store_64, "ATOMIC_STORE_I64">;
-
-multiclass AStorePatGlobalAddrOffOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind (WebAssemblyWrapper tglobaladdr:$off), ty:$val),
- (!cast<NI>(inst#_A32) 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
- def : Pat<(kind (WebAssemblyWrapper tglobaladdr:$off), ty:$val),
- (!cast<NI>(inst#_A64) 0, tglobaladdr:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-}
-defm : AStorePatGlobalAddrOffOnly<i32, atomic_store_32, "ATOMIC_STORE_I32">;
-defm : AStorePatGlobalAddrOffOnly<i64, atomic_store_64, "ATOMIC_STORE_I64">;
-
+defm : AStorePat<i32, atomic_store_32, "ATOMIC_STORE_I32">;
+defm : AStorePat<i64, atomic_store_64, "ATOMIC_STORE_I64">;
// Truncating stores.
defm ATOMIC_STORE8_I32 : AtomicStore<I32, "i32.atomic.store8", 0x19>;
def trunc_astore_16_64 : trunc_astore_64<atomic_store_16>;
def trunc_astore_32_64 : trunc_astore_64<atomic_store_32>;
-
// Truncating stores with no constant offset
-defm : AStorePatNoOffset<i32, atomic_store_8, "ATOMIC_STORE8_I32">;
-defm : AStorePatNoOffset<i32, atomic_store_16, "ATOMIC_STORE16_I32">;
-defm : AStorePatNoOffset<i64, trunc_astore_8_64, "ATOMIC_STORE8_I64">;
-defm : AStorePatNoOffset<i64, trunc_astore_16_64, "ATOMIC_STORE16_I64">;
-defm : AStorePatNoOffset<i64, trunc_astore_32_64, "ATOMIC_STORE32_I64">;
-
-// Truncating stores with a constant offset
-defm : AStorePatImmOff<i32, atomic_store_8, regPlusImm, "ATOMIC_STORE8_I32">;
-defm : AStorePatImmOff<i32, atomic_store_16, regPlusImm, "ATOMIC_STORE16_I32">;
-defm : AStorePatImmOff<i64, trunc_astore_8_64, regPlusImm, "ATOMIC_STORE8_I64">;
-defm : AStorePatImmOff<i64, trunc_astore_16_64, regPlusImm,
- "ATOMIC_STORE16_I64">;
-defm : AStorePatImmOff<i64, trunc_astore_32_64, regPlusImm,
- "ATOMIC_STORE32_I64">;
-defm : AStorePatImmOff<i32, atomic_store_8, or_is_add, "ATOMIC_STORE8_I32">;
-defm : AStorePatImmOff<i32, atomic_store_16, or_is_add, "ATOMIC_STORE16_I32">;
-defm : AStorePatImmOff<i64, trunc_astore_8_64, or_is_add, "ATOMIC_STORE8_I64">;
-defm : AStorePatImmOff<i64, trunc_astore_16_64, or_is_add,
- "ATOMIC_STORE16_I64">;
-defm : AStorePatImmOff<i64, trunc_astore_32_64, or_is_add,
- "ATOMIC_STORE32_I64">;
-
-// Truncating stores with just a constant offset
-defm : AStorePatOffsetOnly<i32, atomic_store_8, "ATOMIC_STORE8_I32">;
-defm : AStorePatOffsetOnly<i32, atomic_store_16, "ATOMIC_STORE16_I32">;
-defm : AStorePatOffsetOnly<i64, trunc_astore_8_64, "ATOMIC_STORE8_I64">;
-defm : AStorePatOffsetOnly<i64, trunc_astore_16_64, "ATOMIC_STORE16_I64">;
-defm : AStorePatOffsetOnly<i64, trunc_astore_32_64, "ATOMIC_STORE32_I64">;
-
-defm : AStorePatGlobalAddrOffOnly<i32, atomic_store_8, "ATOMIC_STORE8_I32">;
-defm : AStorePatGlobalAddrOffOnly<i32, atomic_store_16, "ATOMIC_STORE16_I32">;
-defm : AStorePatGlobalAddrOffOnly<i64, trunc_astore_8_64, "ATOMIC_STORE8_I64">;
-defm : AStorePatGlobalAddrOffOnly<i64, trunc_astore_16_64, "ATOMIC_STORE16_I64">;
-defm : AStorePatGlobalAddrOffOnly<i64, trunc_astore_32_64, "ATOMIC_STORE32_I64">;
-
+defm : AStorePat<i32, atomic_store_8, "ATOMIC_STORE8_I32">;
+defm : AStorePat<i32, atomic_store_16, "ATOMIC_STORE16_I32">;
+defm : AStorePat<i64, trunc_astore_8_64, "ATOMIC_STORE8_I64">;
+defm : AStorePat<i64, trunc_astore_16_64, "ATOMIC_STORE16_I64">;
+defm : AStorePat<i64, trunc_astore_32_64, "ATOMIC_STORE32_I64">;
//===----------------------------------------------------------------------===//
// Atomic binary read-modify-writes
defm ATOMIC_RMW32_U_XCHG_I64 :
WebAssemblyBinRMW<I64, "i64.atomic.rmw32.xchg_u", 0x47>;
-// Select binary RMWs with no constant offset.
-multiclass BinRMWPatNoOffset<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind I32:$addr, ty:$val)),
- (!cast<NI>(inst#_A32) 0, 0, I32:$addr, ty:$val)>,
+multiclass BinRMWPat<ValueType ty, PatFrag kind, string inst> {
+ def : Pat<(ty (kind (AddrOps32 offset32_op:$offset, I32:$addr), ty:$val)),
+ (!cast<NI>(inst#_A32) 0, $offset, $addr, $val)>,
Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind I64:$addr, ty:$val)),
- (!cast<NI>(inst#_A64) 0, 0, I64:$addr, ty:$val)>,
+ def : Pat<(ty (kind (AddrOps64 offset64_op:$offset, I64:$addr), ty:$val)),
+ (!cast<NI>(inst#_A64) 0, $offset, $addr, $val)>,
Requires<[HasAddr64, HasAtomics]>;
}
-// Select binary RMWs with a constant offset.
-
-// Pattern with address + immediate offset
-multiclass BinRMWPatImmOff<ValueType ty, PatFrag kind, PatFrag operand,
- string inst> {
- def : Pat<(ty (kind (operand I32:$addr, imm:$off), ty:$val)),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, ty:$val)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind (operand I64:$addr, imm:$off), ty:$val)),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, ty:$val)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-
-// Select binary RMWs with just a constant offset.
-multiclass BinRMWPatOffsetOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind imm:$off, ty:$val)),
- (!cast<NI>(inst#_A32) 0, imm:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind imm:$off, ty:$val)),
- (!cast<NI>(inst#_A64) 0, imm:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-
-multiclass BinRMWPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$val)),
- (!cast<NI>(inst#_A32) 0, tglobaladdr:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$val)),
- (!cast<NI>(inst#_A64) 0, tglobaladdr:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-}
-
// Patterns for various addressing modes.
multiclass BinRMWPattern<PatFrag rmw_32, PatFrag rmw_64, string inst_32,
string inst_64> {
- defm : BinRMWPatNoOffset<i32, rmw_32, inst_32>;
- defm : BinRMWPatNoOffset<i64, rmw_64, inst_64>;
-
- defm : BinRMWPatImmOff<i32, rmw_32, regPlusImm, inst_32>;
- defm : BinRMWPatImmOff<i64, rmw_64, regPlusImm, inst_64>;
- defm : BinRMWPatImmOff<i32, rmw_32, or_is_add, inst_32>;
- defm : BinRMWPatImmOff<i64, rmw_64, or_is_add, inst_64>;
-
- defm : BinRMWPatOffsetOnly<i32, rmw_32, inst_32>;
- defm : BinRMWPatOffsetOnly<i64, rmw_64, inst_64>;
-
- defm : BinRMWPatGlobalAddrOffOnly<i32, rmw_32, inst_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, rmw_64, inst_64>;
+ defm : BinRMWPat<i32, rmw_32, inst_32>;
+ defm : BinRMWPat<i64, rmw_64, inst_64>;
}
defm : BinRMWPattern<atomic_load_add_32, atomic_load_add_64,
multiclass BinRMWTruncExtPattern<
PatFrag rmw_8, PatFrag rmw_16, PatFrag rmw_32,
string inst8_32, string inst16_32, string inst8_64, string inst16_64, string inst32_64> {
- // Truncating-extending binary RMWs with no constant offset
- defm : BinRMWPatNoOffset<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatNoOffset<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatNoOffset<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatNoOffset<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>;
- defm : BinRMWPatNoOffset<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : BinRMWPatNoOffset<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatNoOffset<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatNoOffset<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatNoOffset<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>;
-
- // Truncating-extending binary RMWs with a constant offset
- defm : BinRMWPatImmOff<i32, zext_bin_rmw_8_32<rmw_8>, regPlusImm, inst8_32>;
- defm : BinRMWPatImmOff<i32, zext_bin_rmw_16_32<rmw_16>, regPlusImm,
- inst16_32>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_8_64<rmw_8>, regPlusImm, inst8_64>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_16_64<rmw_16>, regPlusImm,
- inst16_64>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_32_64<rmw_32>, regPlusImm,
- inst32_64>;
- defm : BinRMWPatImmOff<i32, zext_bin_rmw_8_32<rmw_8>, or_is_add, inst8_32>;
- defm : BinRMWPatImmOff<i32, zext_bin_rmw_16_32<rmw_16>, or_is_add, inst16_32>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_8_64<rmw_8>, or_is_add, inst8_64>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_16_64<rmw_16>, or_is_add, inst16_64>;
- defm : BinRMWPatImmOff<i64, zext_bin_rmw_32_64<rmw_32>, or_is_add, inst32_64>;
-
- defm : BinRMWPatImmOff<i32, sext_bin_rmw_8_32<rmw_8>, regPlusImm, inst8_32>;
- defm : BinRMWPatImmOff<i32, sext_bin_rmw_16_32<rmw_16>, regPlusImm,
- inst16_32>;
- defm : BinRMWPatImmOff<i64, sext_bin_rmw_8_64<rmw_8>, regPlusImm, inst8_64>;
- defm : BinRMWPatImmOff<i64, sext_bin_rmw_16_64<rmw_16>, regPlusImm,
- inst16_64>;
- defm : BinRMWPatImmOff<i32, sext_bin_rmw_8_32<rmw_8>, or_is_add, inst8_32>;
- defm : BinRMWPatImmOff<i32, sext_bin_rmw_16_32<rmw_16>, or_is_add, inst16_32>;
- defm : BinRMWPatImmOff<i64, sext_bin_rmw_8_64<rmw_8>, or_is_add, inst8_64>;
- defm : BinRMWPatImmOff<i64, sext_bin_rmw_16_64<rmw_16>, or_is_add, inst16_64>;
-
- // Truncating-extending binary RMWs with just a constant offset
- defm : BinRMWPatOffsetOnly<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatOffsetOnly<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatOffsetOnly<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatOffsetOnly<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>;
- defm : BinRMWPatOffsetOnly<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : BinRMWPatOffsetOnly<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatOffsetOnly<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatOffsetOnly<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatOffsetOnly<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>;
-
- defm : BinRMWPatGlobalAddrOffOnly<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : BinRMWPatGlobalAddrOffOnly<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>;
- defm : BinRMWPatGlobalAddrOffOnly<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>;
+ // Truncating-extending binary RMWs
+ defm : BinRMWPat<i32, zext_bin_rmw_8_32<rmw_8>, inst8_32>;
+ defm : BinRMWPat<i32, zext_bin_rmw_16_32<rmw_16>, inst16_32>;
+ defm : BinRMWPat<i64, zext_bin_rmw_8_64<rmw_8>, inst8_64>;
+ defm : BinRMWPat<i64, zext_bin_rmw_16_64<rmw_16>, inst16_64>;
+ defm : BinRMWPat<i64, zext_bin_rmw_32_64<rmw_32>, inst32_64>;
+
+ defm : BinRMWPat<i32, sext_bin_rmw_8_32<rmw_8>, inst8_32>;
+ defm : BinRMWPat<i32, sext_bin_rmw_16_32<rmw_16>, inst16_32>;
+ defm : BinRMWPat<i64, sext_bin_rmw_8_64<rmw_8>, inst8_64>;
+ defm : BinRMWPat<i64, sext_bin_rmw_16_64<rmw_16>, inst16_64>;
}
defm : BinRMWTruncExtPattern<
defm ATOMIC_RMW32_U_CMPXCHG_I64 :
WebAssemblyTerRMW<I64, "i64.atomic.rmw32.cmpxchg_u", 0x4e>;
-// Select ternary RMWs with no constant offset.
-multiclass TerRMWPatNoOffset<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind I32:$addr, ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A32) 0, 0, I32:$addr, ty:$exp, ty:$new)>,
- Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind I64:$addr, ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A64) 0, 0, I64:$addr, ty:$exp, ty:$new)>,
- Requires<[HasAddr64, HasAtomics]>;
-}
-
-// Select ternary RMWs with a constant offset.
-
-// Pattern with address + immediate offset
-multiclass TerRMWPatImmOff<ValueType ty, PatFrag kind, PatFrag operand,
- string inst> {
- def : Pat<(ty (kind (operand I32:$addr, imm:$off), ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A32) 0, imm:$off, I32:$addr, ty:$exp, ty:$new)>,
+multiclass TerRMWPat<ValueType ty, PatFrag kind, string inst> {
+ def : Pat<(ty (kind (AddrOps32 offset32_op:$offset, I32:$addr), ty:$exp, ty:$new)),
+ (!cast<NI>(inst#_A32) 0, $offset, $addr, $exp, $new)>,
Requires<[HasAddr32, HasAtomics]>;
- def : Pat<(ty (kind (operand I64:$addr, imm:$off), ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A64) 0, imm:$off, I64:$addr, ty:$exp, ty:$new)>,
+ def : Pat<(ty (kind (AddrOps64 offset64_op:$offset, I64:$addr), ty:$exp, ty:$new)),
+ (!cast<NI>(inst#_A64) 0, $offset, $addr, $exp, $new)>,
Requires<[HasAddr64, HasAtomics]>;
}
-// Select ternary RMWs with just a constant offset.
-multiclass TerRMWPatOffsetOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind imm:$off, ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A32) 0, imm:$off, (CONST_I32 0), ty:$exp,
- ty:$new)>;
- def : Pat<(ty (kind imm:$off, ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A64) 0, imm:$off, (CONST_I64 0), ty:$exp,
- ty:$new)>;
-}
-
-multiclass TerRMWPatGlobalAddrOffOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A32) 0, tglobaladdr:$off, (CONST_I32 0), ty:$exp,
- ty:$new)>,
- Requires<[HasAddr32, HasAtomics, IsNotPIC]>;
- def : Pat<(ty (kind (WebAssemblyWrapper tglobaladdr:$off), ty:$exp, ty:$new)),
- (!cast<NI>(inst#_A64) 0, tglobaladdr:$off, (CONST_I64 0), ty:$exp,
- ty:$new)>,
- Requires<[HasAddr64, HasAtomics, IsNotPIC]>;
-}
-
-// Patterns for various addressing modes.
-multiclass TerRMWPattern<PatFrag rmw_32, PatFrag rmw_64, string inst_32,
- string inst_64> {
- defm : TerRMWPatNoOffset<i32, rmw_32, inst_32>;
- defm : TerRMWPatNoOffset<i64, rmw_64, inst_64>;
-
- defm : TerRMWPatImmOff<i32, rmw_32, regPlusImm, inst_32>;
- defm : TerRMWPatImmOff<i64, rmw_64, regPlusImm, inst_64>;
- defm : TerRMWPatImmOff<i32, rmw_32, or_is_add, inst_32>;
- defm : TerRMWPatImmOff<i64, rmw_64, or_is_add, inst_64>;
-
- defm : TerRMWPatOffsetOnly<i32, rmw_32, inst_32>;
- defm : TerRMWPatOffsetOnly<i64, rmw_64, inst_64>;
-
- defm : TerRMWPatGlobalAddrOffOnly<i32, rmw_32, inst_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, rmw_64, inst_64>;
-}
-
-defm : TerRMWPattern<atomic_cmp_swap_32, atomic_cmp_swap_64,
- "ATOMIC_RMW_CMPXCHG_I32", "ATOMIC_RMW_CMPXCHG_I64">;
+defm : TerRMWPat<i32, atomic_cmp_swap_32, "ATOMIC_RMW_CMPXCHG_I32">;
+defm : TerRMWPat<i64, atomic_cmp_swap_64, "ATOMIC_RMW_CMPXCHG_I64">;
// Truncating & zero-extending ternary RMW patterns.
// DAG legalization & optimization before instruction selection may introduce
class sext_ter_rmw_16_64<PatFrag kind> : sext_ter_rmw_8_64<kind>;
// 32->64 sext RMW gets selected as i32.atomic.rmw.***, i64.extend_i32_s
-// Patterns for various addressing modes for truncating-extending ternary RMWs.
-multiclass TerRMWTruncExtPattern<
- PatFrag rmw_8, PatFrag rmw_16, PatFrag rmw_32,
- string inst8_32, string inst16_32, string inst8_64, string inst16_64,
- string inst32_64> {
- // Truncating-extending ternary RMWs with no constant offset
- defm : TerRMWPatNoOffset<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatNoOffset<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatNoOffset<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatNoOffset<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>;
- defm : TerRMWPatNoOffset<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : TerRMWPatNoOffset<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatNoOffset<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatNoOffset<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatNoOffset<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>;
-
- // Truncating-extending ternary RMWs with a constant offset
- defm : TerRMWPatImmOff<i32, zext_ter_rmw_8_32<rmw_8>, regPlusImm, inst8_32>;
- defm : TerRMWPatImmOff<i32, zext_ter_rmw_16_32<rmw_16>, regPlusImm,
- inst16_32>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_8_64<rmw_8>, regPlusImm, inst8_64>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_16_64<rmw_16>, regPlusImm,
- inst16_64>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_32_64<rmw_32>, regPlusImm,
- inst32_64>;
- defm : TerRMWPatImmOff<i32, zext_ter_rmw_8_32<rmw_8>, or_is_add, inst8_32>;
- defm : TerRMWPatImmOff<i32, zext_ter_rmw_16_32<rmw_16>, or_is_add, inst16_32>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_8_64<rmw_8>, or_is_add, inst8_64>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_16_64<rmw_16>, or_is_add, inst16_64>;
- defm : TerRMWPatImmOff<i64, zext_ter_rmw_32_64<rmw_32>, or_is_add, inst32_64>;
-
- defm : TerRMWPatImmOff<i32, sext_ter_rmw_8_32<rmw_8>, regPlusImm, inst8_32>;
- defm : TerRMWPatImmOff<i32, sext_ter_rmw_16_32<rmw_16>, regPlusImm,
- inst16_32>;
- defm : TerRMWPatImmOff<i64, sext_ter_rmw_8_64<rmw_8>, regPlusImm, inst8_64>;
- defm : TerRMWPatImmOff<i64, sext_ter_rmw_16_64<rmw_16>, regPlusImm,
- inst16_64>;
- defm : TerRMWPatImmOff<i32, sext_ter_rmw_8_32<rmw_8>, or_is_add, inst8_32>;
- defm : TerRMWPatImmOff<i32, sext_ter_rmw_16_32<rmw_16>, or_is_add, inst16_32>;
- defm : TerRMWPatImmOff<i64, sext_ter_rmw_8_64<rmw_8>, or_is_add, inst8_64>;
- defm : TerRMWPatImmOff<i64, sext_ter_rmw_16_64<rmw_16>, or_is_add, inst16_64>;
-
- // Truncating-extending ternary RMWs with just a constant offset
- defm : TerRMWPatOffsetOnly<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatOffsetOnly<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatOffsetOnly<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatOffsetOnly<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>;
- defm : TerRMWPatOffsetOnly<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : TerRMWPatOffsetOnly<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatOffsetOnly<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatOffsetOnly<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatOffsetOnly<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>;
-
- defm : TerRMWPatGlobalAddrOffOnly<i32, zext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i32, zext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, zext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, zext_ter_rmw_16_64<rmw_16>, inst16_64>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, zext_ter_rmw_32_64<rmw_32>, inst32_64>;
-
- defm : TerRMWPatGlobalAddrOffOnly<i32, sext_ter_rmw_8_32<rmw_8>, inst8_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i32, sext_ter_rmw_16_32<rmw_16>, inst16_32>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, sext_ter_rmw_8_64<rmw_8>, inst8_64>;
- defm : TerRMWPatGlobalAddrOffOnly<i64, sext_ter_rmw_16_64<rmw_16>, inst16_64>;
-}
+defm : TerRMWPat<i32, zext_ter_rmw_8_32<atomic_cmp_swap_8>, "ATOMIC_RMW8_U_CMPXCHG_I32">;
+defm : TerRMWPat<i32, zext_ter_rmw_16_32<atomic_cmp_swap_16>, "ATOMIC_RMW16_U_CMPXCHG_I32">;
+defm : TerRMWPat<i64, zext_ter_rmw_8_64<atomic_cmp_swap_8>, "ATOMIC_RMW8_U_CMPXCHG_I64">;
+defm : TerRMWPat<i64, zext_ter_rmw_16_64<atomic_cmp_swap_16>, "ATOMIC_RMW16_U_CMPXCHG_I64">;
+defm : TerRMWPat<i64, zext_ter_rmw_32_64<atomic_cmp_swap_32>, "ATOMIC_RMW32_U_CMPXCHG_I64">;
-defm : TerRMWTruncExtPattern<
- atomic_cmp_swap_8, atomic_cmp_swap_16, atomic_cmp_swap_32,
- "ATOMIC_RMW8_U_CMPXCHG_I32", "ATOMIC_RMW16_U_CMPXCHG_I32",
- "ATOMIC_RMW8_U_CMPXCHG_I64", "ATOMIC_RMW16_U_CMPXCHG_I64",
- "ATOMIC_RMW32_U_CMPXCHG_I64">;
+defm : TerRMWPat<i32, sext_ter_rmw_8_32<atomic_cmp_swap_8>, "ATOMIC_RMW8_U_CMPXCHG_I32">;
+defm : TerRMWPat<i32, sext_ter_rmw_16_32<atomic_cmp_swap_16>, "ATOMIC_RMW16_U_CMPXCHG_I32">;
+defm : TerRMWPat<i64, sext_ter_rmw_8_64<atomic_cmp_swap_8>, "ATOMIC_RMW8_U_CMPXCHG_I64">;
+defm : TerRMWPat<i64, sext_ter_rmw_16_64<atomic_cmp_swap_16>, "ATOMIC_RMW16_U_CMPXCHG_I64">;
// local types. These memory-only types instead zero- or sign-extend into local
// types when loading, and truncate when storing.
-// WebAssembly constant offsets are performed as unsigned with infinite
-// precision, so we need to check for NoUnsignedWrap so that we don't fold an
-// offset for an add that needs wrapping.
-def regPlusImm : PatFrag<(ops node:$addr, node:$off),
- (add node:$addr, node:$off),
- [{ return N->getFlags().hasNoUnsignedWrap(); }]>;
+// Address Operands
-// Treat an 'or' node as an 'add' if the or'ed bits are known to be zero.
-def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{
- if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
- return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue());
-
- KnownBits Known0 = CurDAG->computeKnownBits(N->getOperand(0), 0);
- KnownBits Known1 = CurDAG->computeKnownBits(N->getOperand(1), 0);
- return (~Known0.Zero & ~Known1.Zero) == 0;
-}]>;
-
-// We don't need a regPlusES because external symbols never have constant
-// offsets folded into them, so we can just use add.
+// These patterns match the static (offset) and dynamic (address stack operand)
+// operands for loads and stores, based on a combination of target global
+// addresses and constants.
+// For example,
+// (load (add tga, x)) -> load offset=tga, addr=x
+// (store v, tga) -> store v, offset=tga, addr=0
+// (load (add const, x)) -> load offset=const, addr=x
+// (store v, const) -> store v, offset=const, addr=0
+// (load x) -> load offset=0, addr=x
+def AddrOps32 : ComplexPattern<i32, 2, "SelectAddrOperands32">;
+def AddrOps64 : ComplexPattern<i64, 2, "SelectAddrOperands64">;
// Defines atomic and non-atomic loads, regular and extending.
multiclass WebAssemblyLoad<WebAssemblyRegClass rc, string Name, int Opcode,
// Pattern matching
-// Patterns that match the static (offset) and dynamic (address stack operand)
-// operand) operands for loads, based on a combination of target global
-// addresses and constants.
-
-// For example,
-// (add tga x) -> load tga(x)
-// tga -> load tga(0)
-// (add const x) -> load const(x)
-// const -> load const(0)
-// x -> load 0(x)
-def LoadOps32 : ComplexPattern<i32, 2, "SelectLoadOperands32">;
-def LoadOps64 : ComplexPattern<i64, 2, "SelectLoadOperands64">;
-
multiclass LoadPat<ValueType ty, SDPatternOperator kind, string Name> {
- def : Pat<(ty (kind (LoadOps32 offset32_op:$offset, I32:$addr))),
+ def : Pat<(ty (kind (AddrOps32 offset32_op:$offset, I32:$addr))),
(!cast<NI>(Name # "_A32") 0,
offset32_op:$offset,
I32:$addr)>,
Requires<[HasAddr32]>;
- def : Pat<(ty (kind (LoadOps64 offset64_op:$offset, I64:$addr))),
+ def : Pat<(ty (kind (AddrOps64 offset64_op:$offset, I64:$addr))),
(!cast<NI>(Name # "_A64") 0,
offset64_op:$offset,
I64:$addr)>,
Requires<[HasAddr64]>;
-
}
defm : LoadPat<i32, load, "LOAD_I32">;
defm STORE_F32 : WebAssemblyStore<F32, "f32.store", 0x38>;
defm STORE_F64 : WebAssemblyStore<F64, "f64.store", 0x39>;
-// Select stores with no constant offset.
-multiclass StorePatNoOffset<ValueType ty, PatFrag node, string inst> {
- def : Pat<(node ty:$val, I32:$addr),
- (!cast<NI>(inst # "_A32") 0, 0, I32:$addr, ty:$val)>,
- Requires<[HasAddr32]>;
- def : Pat<(node ty:$val, I64:$addr),
- (!cast<NI>(inst # "_A64") 0, 0, I64:$addr, ty:$val)>,
- Requires<[HasAddr64]>;
+multiclass StorePat<ValueType ty, SDPatternOperator kind, string Name> {
+ def : Pat<(kind ty:$val, (AddrOps32 offset32_op:$offset, I32:$addr)),
+ (!cast<NI>(Name # "_A32") 0,
+ offset32_op:$offset,
+ I32:$addr,
+ ty:$val)>,
+ Requires<[HasAddr32]>;
+ def : Pat<(kind ty:$val, (AddrOps64 offset64_op:$offset, I64:$addr)),
+ (!cast<NI>(Name # "_A64") 0,
+ offset64_op:$offset,
+ I64:$addr,
+ ty:$val)>,
+ Requires<[HasAddr64]>;
}
-defm : StorePatNoOffset<i32, store, "STORE_I32">;
-defm : StorePatNoOffset<i64, store, "STORE_I64">;
-defm : StorePatNoOffset<f32, store, "STORE_F32">;
-defm : StorePatNoOffset<f64, store, "STORE_F64">;
-
-// Select stores with a constant offset.
-multiclass StorePatImmOff<ValueType ty, PatFrag kind, PatFrag operand,
- string inst> {
- def : Pat<(kind ty:$val, (operand I32:$addr, imm:$off)),
- (!cast<NI>(inst # "_A32") 0, imm:$off, I32:$addr, ty:$val)>,
- Requires<[HasAddr32]>;
- def : Pat<(kind ty:$val, (operand I64:$addr, imm:$off)),
- (!cast<NI>(inst # "_A64") 0, imm:$off, I64:$addr, ty:$val)>,
- Requires<[HasAddr64]>;
-}
-
-defm : StorePatImmOff<i32, store, regPlusImm, "STORE_I32">;
-defm : StorePatImmOff<i64, store, regPlusImm, "STORE_I64">;
-defm : StorePatImmOff<f32, store, regPlusImm, "STORE_F32">;
-defm : StorePatImmOff<f64, store, regPlusImm, "STORE_F64">;
-defm : StorePatImmOff<i32, store, or_is_add, "STORE_I32">;
-defm : StorePatImmOff<i64, store, or_is_add, "STORE_I64">;
-defm : StorePatImmOff<f32, store, or_is_add, "STORE_F32">;
-defm : StorePatImmOff<f64, store, or_is_add, "STORE_F64">;
-
-// Select stores with just a constant offset.
-multiclass StorePatOffsetOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind ty:$val, imm:$off),
- (!cast<NI>(inst # "_A32") 0, imm:$off, (CONST_I32 0), ty:$val)>,
- Requires<[HasAddr32]>;
- def : Pat<(kind ty:$val, imm:$off),
- (!cast<NI>(inst # "_A64") 0, imm:$off, (CONST_I64 0), ty:$val)>,
- Requires<[HasAddr64]>;
-}
-defm : StorePatOffsetOnly<i32, store, "STORE_I32">;
-defm : StorePatOffsetOnly<i64, store, "STORE_I64">;
-defm : StorePatOffsetOnly<f32, store, "STORE_F32">;
-defm : StorePatOffsetOnly<f64, store, "STORE_F64">;
-
-multiclass StorePatGlobalAddrOffOnly<ValueType ty, PatFrag kind, string inst> {
- def : Pat<(kind ty:$val, (WebAssemblyWrapper tglobaladdr:$off)),
- (!cast<NI>(inst # "_A32") 0, tglobaladdr:$off, (CONST_I32 0),
- ty:$val)>,
- Requires<[IsNotPIC, HasAddr32]>;
- def : Pat<(kind ty:$val, (WebAssemblyWrapper tglobaladdr:$off)),
- (!cast<NI>(inst # "_A64") 0, tglobaladdr:$off, (CONST_I64 0),
- ty:$val)>,
- Requires<[IsNotPIC, HasAddr64]>;
-}
-defm : StorePatGlobalAddrOffOnly<i32, store, "STORE_I32">;
-defm : StorePatGlobalAddrOffOnly<i64, store, "STORE_I64">;
-defm : StorePatGlobalAddrOffOnly<f32, store, "STORE_F32">;
-defm : StorePatGlobalAddrOffOnly<f64, store, "STORE_F64">;
+defm : StorePat<i32, store, "STORE_I32">;
+defm : StorePat<i64, store, "STORE_I64">;
+defm : StorePat<f32, store, "STORE_F32">;
+defm : StorePat<f64, store, "STORE_F64">;
// Truncating store.
defm STORE8_I32 : WebAssemblyStore<I32, "i32.store8", 0x3a>;
defm STORE16_I64 : WebAssemblyStore<I64, "i64.store16", 0x3d>;
defm STORE32_I64 : WebAssemblyStore<I64, "i64.store32", 0x3e>;
-// Select truncating stores with no constant offset.
-defm : StorePatNoOffset<i32, truncstorei8, "STORE8_I32">;
-defm : StorePatNoOffset<i32, truncstorei16, "STORE16_I32">;
-defm : StorePatNoOffset<i64, truncstorei8, "STORE8_I64">;
-defm : StorePatNoOffset<i64, truncstorei16, "STORE16_I64">;
-defm : StorePatNoOffset<i64, truncstorei32, "STORE32_I64">;
-
-// Select truncating stores with a constant offset.
-defm : StorePatImmOff<i32, truncstorei8, regPlusImm, "STORE8_I32">;
-defm : StorePatImmOff<i32, truncstorei16, regPlusImm, "STORE16_I32">;
-defm : StorePatImmOff<i64, truncstorei8, regPlusImm, "STORE8_I64">;
-defm : StorePatImmOff<i64, truncstorei16, regPlusImm, "STORE16_I64">;
-defm : StorePatImmOff<i64, truncstorei32, regPlusImm, "STORE32_I64">;
-defm : StorePatImmOff<i32, truncstorei8, or_is_add, "STORE8_I32">;
-defm : StorePatImmOff<i32, truncstorei16, or_is_add, "STORE16_I32">;
-defm : StorePatImmOff<i64, truncstorei8, or_is_add, "STORE8_I64">;
-defm : StorePatImmOff<i64, truncstorei16, or_is_add, "STORE16_I64">;
-defm : StorePatImmOff<i64, truncstorei32, or_is_add, "STORE32_I64">;
-
-// Select truncating stores with just a constant offset.
-defm : StorePatOffsetOnly<i32, truncstorei8, "STORE8_I32">;
-defm : StorePatOffsetOnly<i32, truncstorei16, "STORE16_I32">;
-defm : StorePatOffsetOnly<i64, truncstorei8, "STORE8_I64">;
-defm : StorePatOffsetOnly<i64, truncstorei16, "STORE16_I64">;
-defm : StorePatOffsetOnly<i64, truncstorei32, "STORE32_I64">;
-defm : StorePatGlobalAddrOffOnly<i32, truncstorei8, "STORE8_I32">;
-defm : StorePatGlobalAddrOffOnly<i32, truncstorei16, "STORE16_I32">;
-defm : StorePatGlobalAddrOffOnly<i64, truncstorei8, "STORE8_I64">;
-defm : StorePatGlobalAddrOffOnly<i64, truncstorei16, "STORE16_I64">;
-defm : StorePatGlobalAddrOffOnly<i64, truncstorei32, "STORE32_I64">;
+defm : StorePat<i32, truncstorei8, "STORE8_I32">;
+defm : StorePat<i32, truncstorei16, "STORE16_I32">;
+defm : StorePat<i64, truncstorei8, "STORE8_I64">;
+defm : StorePat<i64, truncstorei16, "STORE16_I64">;
+defm : StorePat<i64, truncstorei32, "STORE32_I64">;
multiclass MemoryOps<WebAssemblyRegClass rc, string B> {
// Current memory size.
; CHECK: .functype store_lane_i8_with_folded_offset (v128, i32) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: i32.const 24
-; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store8_lane 0, 0
+; CHECK-NEXT: v128.store8_lane 24, 0
; CHECK-NEXT: # fallthrough-return
%q = ptrtoint i8* %p to i32
%r = add nuw i32 %q, 24
; CHECK: .functype store_lane_i8_with_folded_gep_offset (v128, i32) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: i32.const 6
-; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store8_lane 0, 0
+; CHECK-NEXT: v128.store8_lane 6, 0
; CHECK-NEXT: # fallthrough-return
%s = getelementptr inbounds i8, i8* %p, i32 6
%x = extractelement <16 x i8> %v, i32 0
; CHECK-LABEL: store_lane_i8_to_numeric_address:
; CHECK: .functype store_lane_i8_to_numeric_address (v128) -> ()
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const 42
+; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store8_lane 0, 0
+; CHECK-NEXT: v128.store8_lane 42, 0
; CHECK-NEXT: # fallthrough-return
%s = inttoptr i32 42 to i8*
%x = extractelement <16 x i8> %v, i32 0
; CHECK-LABEL: store_lane_i8_from_global_address:
; CHECK: .functype store_lane_i8_from_global_address (v128) -> ()
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const gv_i8
+; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store8_lane 0, 0
+; CHECK-NEXT: v128.store8_lane gv_i8, 0
; CHECK-NEXT: # fallthrough-return
%x = extractelement <16 x i8> %v, i32 0
store i8 %x, i8* @gv_i8
; CHECK: .functype store_lane_i16_with_folded_offset (v128, i32) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: i32.const 24
-; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store16_lane 0, 0
+; CHECK-NEXT: v128.store16_lane 24, 0
; CHECK-NEXT: # fallthrough-return
%q = ptrtoint i16* %p to i32
%r = add nuw i32 %q, 24
; CHECK: .functype store_lane_i16_with_folded_gep_offset (v128, i32) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: i32.const 12
-; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store16_lane 0, 0
+; CHECK-NEXT: v128.store16_lane 12, 0
; CHECK-NEXT: # fallthrough-return
%s = getelementptr inbounds i16, i16* %p, i32 6
%x = extractelement <8 x i16> %v, i32 0
; CHECK-LABEL: store_lane_i16_to_numeric_address:
; CHECK: .functype store_lane_i16_to_numeric_address (v128) -> ()
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const 42
+; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store16_lane 0, 0
+; CHECK-NEXT: v128.store16_lane 42, 0
; CHECK-NEXT: # fallthrough-return
%s = inttoptr i32 42 to i16*
%x = extractelement <8 x i16> %v, i32 0
; CHECK-LABEL: store_lane_i16_from_global_address:
; CHECK: .functype store_lane_i16_from_global_address (v128) -> ()
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const gv_i16
+; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store16_lane 0, 0
+; CHECK-NEXT: v128.store16_lane gv_i16, 0
; CHECK-NEXT: # fallthrough-return
%x = extractelement <8 x i16> %v, i32 0
store i16 %x, i16* @gv_i16
; CHECK: .functype store_lane_i32_with_folded_offset (v128, i32) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: i32.const 24
-; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store32_lane 0, 0
+; CHECK-NEXT: v128.store32_lane 24, 0
; CHECK-NEXT: # fallthrough-return
%q = ptrtoint i32* %p to i32
%r = add nuw i32 %q, 24
; CHECK: .functype store_lane_i32_with_folded_gep_offset (v128, i32) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: i32.const 24
-; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store32_lane 0, 0
+; CHECK-NEXT: v128.store32_lane 24, 0
; CHECK-NEXT: # fallthrough-return
%s = getelementptr inbounds i32, i32* %p, i32 6
%x = extractelement <4 x i32> %v, i32 0
; CHECK-LABEL: store_lane_i32_to_numeric_address:
; CHECK: .functype store_lane_i32_to_numeric_address (v128) -> ()
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const 42
+; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store32_lane 0, 0
+; CHECK-NEXT: v128.store32_lane 42, 0
; CHECK-NEXT: # fallthrough-return
%s = inttoptr i32 42 to i32*
%x = extractelement <4 x i32> %v, i32 0
; CHECK-LABEL: store_lane_i32_from_global_address:
; CHECK: .functype store_lane_i32_from_global_address (v128) -> ()
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const gv_i32
+; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store32_lane 0, 0
+; CHECK-NEXT: v128.store32_lane gv_i32, 0
; CHECK-NEXT: # fallthrough-return
%x = extractelement <4 x i32> %v, i32 0
store i32 %x, i32* @gv_i32
; CHECK: .functype store_lane_i64_with_folded_offset (v128, i32) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: i32.const 24
-; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store64_lane 0, 0
+; CHECK-NEXT: v128.store64_lane 24, 0
; CHECK-NEXT: # fallthrough-return
%q = ptrtoint i64* %p to i32
%r = add nuw i32 %q, 24
; CHECK: .functype store_lane_i64_with_folded_gep_offset (v128, i32) -> ()
; CHECK-NEXT: # %bb.0:
; CHECK-NEXT: local.get 1
-; CHECK-NEXT: i32.const 48
-; CHECK-NEXT: i32.add
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store64_lane 0, 0
+; CHECK-NEXT: v128.store64_lane 48, 0
; CHECK-NEXT: # fallthrough-return
%s = getelementptr inbounds i64, i64* %p, i32 6
%x = extractelement <2 x i64> %v, i32 0
; CHECK-LABEL: store_lane_i64_to_numeric_address:
; CHECK: .functype store_lane_i64_to_numeric_address (v128) -> ()
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const 42
+; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store64_lane 0, 0
+; CHECK-NEXT: v128.store64_lane 42, 0
; CHECK-NEXT: # fallthrough-return
%s = inttoptr i32 42 to i64*
%x = extractelement <2 x i64> %v, i32 0
; CHECK-LABEL: store_lane_i64_from_global_address:
; CHECK: .functype store_lane_i64_from_global_address (v128) -> ()
; CHECK-NEXT: # %bb.0:
-; CHECK-NEXT: i32.const gv_i64
+; CHECK-NEXT: i32.const 0
; CHECK-NEXT: local.get 0
-; CHECK-NEXT: v128.store64_lane 0, 0
+; CHECK-NEXT: v128.store64_lane gv_i64, 0
; CHECK-NEXT: # fallthrough-return
%x = extractelement <2 x i64> %v, i32 0
store i64 %x, i64* @gv_i64