1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[WebAssembly] Rename atomic.notify and *.atomic.wait

- atomic.notify -> memory.atomic.notify
- i32.atomic.wait -> memory.atomic.wait32
- i64.atomic.wait -> memory.atomic.wait64

See https://github.com/WebAssembly/threads/pull/149.

Reviewed By: tlively

Differential Revision: https://reviews.llvm.org/D91447
This commit is contained in:
Heejin Ahn 2020-11-13 04:24:47 -08:00
parent e65607b8ff
commit fb835643a1
8 changed files with 172 additions and 163 deletions

View File

@ -79,22 +79,23 @@ def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>;
//===----------------------------------------------------------------------===//
// wait / notify
def int_wasm_atomic_wait_i32 :
def int_wasm_memory_atomic_wait32 :
Intrinsic<[llvm_i32_ty],
[LLVMPointerType<llvm_i32_ty>, llvm_i32_ty, llvm_i64_ty],
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>,
IntrHasSideEffects],
"", [SDNPMemOperand]>;
def int_wasm_atomic_wait_i64 :
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
NoCapture<ArgIndex<0>>, IntrHasSideEffects],
"", [SDNPMemOperand]>;
def int_wasm_memory_atomic_wait64 :
Intrinsic<[llvm_i32_ty],
[LLVMPointerType<llvm_i64_ty>, llvm_i64_ty, llvm_i64_ty],
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>, NoCapture<ArgIndex<0>>,
IntrHasSideEffects],
"", [SDNPMemOperand]>;
def int_wasm_atomic_notify:
[IntrInaccessibleMemOrArgMemOnly, ReadOnly<ArgIndex<0>>,
NoCapture<ArgIndex<0>>, IntrHasSideEffects],
"", [SDNPMemOperand]>;
def int_wasm_memory_atomic_notify:
Intrinsic<[llvm_i32_ty], [LLVMPointerType<llvm_i32_ty>, llvm_i32_ty],
[IntrInaccessibleMemOnly, NoCapture<ArgIndex<0>>, IntrHasSideEffects], "",
[SDNPMemOperand]>;
[IntrInaccessibleMemOnly, NoCapture<ArgIndex<0>>,
IntrHasSideEffects],
"", [SDNPMemOperand]>;
//===----------------------------------------------------------------------===//
// SIMD intrinsics

View File

@ -249,8 +249,8 @@ inline unsigned GetDefaultP2AlignAny(unsigned Opc) {
WASM_LOAD_STORE(ATOMIC_RMW32_U_XCHG_I64)
WASM_LOAD_STORE(ATOMIC_RMW_CMPXCHG_I32)
WASM_LOAD_STORE(ATOMIC_RMW32_U_CMPXCHG_I64)
WASM_LOAD_STORE(ATOMIC_NOTIFY)
WASM_LOAD_STORE(ATOMIC_WAIT_I32)
WASM_LOAD_STORE(MEMORY_ATOMIC_NOTIFY)
WASM_LOAD_STORE(MEMORY_ATOMIC_WAIT32)
WASM_LOAD_STORE(LOAD_SPLAT_v32x4)
WASM_LOAD_STORE(LOAD_ZERO_v4i32)
WASM_LOAD_STORE(LOAD_LANE_v4i32)
@ -269,7 +269,7 @@ inline unsigned GetDefaultP2AlignAny(unsigned Opc) {
WASM_LOAD_STORE(ATOMIC_RMW_XOR_I64)
WASM_LOAD_STORE(ATOMIC_RMW_XCHG_I64)
WASM_LOAD_STORE(ATOMIC_RMW_CMPXCHG_I64)
WASM_LOAD_STORE(ATOMIC_WAIT_I64)
WASM_LOAD_STORE(MEMORY_ATOMIC_WAIT64)
WASM_LOAD_STORE(LOAD_SPLAT_v64x2)
WASM_LOAD_STORE(LOAD_EXTEND_S_v8i16)
WASM_LOAD_STORE(LOAD_EXTEND_U_v8i16)

View File

@ -646,7 +646,7 @@ bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
MachineFunction &MF,
unsigned Intrinsic) const {
switch (Intrinsic) {
case Intrinsic::wasm_atomic_notify:
case Intrinsic::wasm_memory_atomic_notify:
Info.opc = ISD::INTRINSIC_W_CHAIN;
Info.memVT = MVT::i32;
Info.ptrVal = I.getArgOperand(0);
@ -660,7 +660,7 @@ bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
// consistent. The same applies for wasm_atomic_wait intrinsics too.
Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
return true;
case Intrinsic::wasm_atomic_wait_i32:
case Intrinsic::wasm_memory_atomic_wait32:
Info.opc = ISD::INTRINSIC_W_CHAIN;
Info.memVT = MVT::i32;
Info.ptrVal = I.getArgOperand(0);
@ -668,7 +668,7 @@ bool WebAssemblyTargetLowering::getTgtMemIntrinsic(IntrinsicInfo &Info,
Info.align = Align(4);
Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
return true;
case Intrinsic::wasm_atomic_wait_i64:
case Intrinsic::wasm_memory_atomic_wait64:
Info.opc = ISD::INTRINSIC_W_CHAIN;
Info.memVT = MVT::i64;
Info.ptrVal = I.getArgOperand(0);

View File

@ -33,96 +33,98 @@ multiclass ATOMIC_NRI<dag oops, dag iops, list<dag> pattern, string asmstr = "",
//===----------------------------------------------------------------------===//
let hasSideEffects = 1 in {
defm ATOMIC_NOTIFY_A32 :
defm MEMORY_ATOMIC_NOTIFY_A32 :
ATOMIC_I<(outs I32:$dst),
(ins P2Align:$p2align, offset32_op:$off, I32:$addr, I32:$count),
(outs), (ins P2Align:$p2align, offset32_op:$off), [],
"atomic.notify \t$dst, ${off}(${addr})${p2align}, $count",
"atomic.notify \t${off}${p2align}", 0x00, "false">;
defm ATOMIC_NOTIFY_A64 :
"memory.atomic.notify \t$dst, ${off}(${addr})${p2align}, $count",
"memory.atomic.notify \t${off}${p2align}", 0x00, "false">;
defm MEMORY_ATOMIC_NOTIFY_A64 :
ATOMIC_I<(outs I32:$dst),
(ins P2Align:$p2align, offset64_op:$off, I64:$addr, I32:$count),
(outs), (ins P2Align:$p2align, offset64_op:$off), [],
"atomic.notify \t$dst, ${off}(${addr})${p2align}, $count",
"atomic.notify \t${off}${p2align}", 0x00, "true">;
"memory.atomic.notify \t$dst, ${off}(${addr})${p2align}, $count",
"memory.atomic.notify \t${off}${p2align}", 0x00, "true">;
let mayLoad = 1 in {
defm ATOMIC_WAIT_I32_A32 :
defm MEMORY_ATOMIC_WAIT32_A32 :
ATOMIC_I<(outs I32:$dst),
(ins P2Align:$p2align, offset32_op:$off, I32:$addr, I32:$exp,
I64:$timeout),
(outs), (ins P2Align:$p2align, offset32_op:$off), [],
"i32.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
"i32.atomic.wait \t${off}${p2align}", 0x01, "false">;
defm ATOMIC_WAIT_I32_A64 :
"memory.atomic.wait32 \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
"memory.atomic.wait32 \t${off}${p2align}", 0x01, "false">;
defm MEMORY_ATOMIC_WAIT32_A64 :
ATOMIC_I<(outs I32:$dst),
(ins P2Align:$p2align, offset64_op:$off, I64:$addr, I32:$exp,
I64:$timeout),
(outs), (ins P2Align:$p2align, offset64_op:$off), [],
"i32.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
"i32.atomic.wait \t${off}${p2align}", 0x01, "true">;
defm ATOMIC_WAIT_I64_A32 :
"memory.atomic.wait32 \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
"memory.atomic.wait32 \t${off}${p2align}", 0x01, "true">;
defm MEMORY_ATOMIC_WAIT64_A32 :
ATOMIC_I<(outs I32:$dst),
(ins P2Align:$p2align, offset32_op:$off, I32:$addr, I64:$exp,
I64:$timeout),
(outs), (ins P2Align:$p2align, offset32_op:$off), [],
"i64.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
"i64.atomic.wait \t${off}${p2align}", 0x02, "false">;
defm ATOMIC_WAIT_I64_A64 :
"memory.atomic.wait64 \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
"memory.atomic.wait64 \t${off}${p2align}", 0x02, "false">;
defm MEMORY_ATOMIC_WAIT64_A64 :
ATOMIC_I<(outs I32:$dst),
(ins P2Align:$p2align, offset64_op:$off, I64:$addr, I64:$exp,
I64:$timeout),
(outs), (ins P2Align:$p2align, offset64_op:$off), [],
"i64.atomic.wait \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
"i64.atomic.wait \t${off}${p2align}", 0x02, "true">;
"memory.atomic.wait64 \t$dst, ${off}(${addr})${p2align}, $exp, $timeout",
"memory.atomic.wait64 \t${off}${p2align}", 0x02, "true">;
} // mayLoad = 1
} // hasSideEffects = 1
let Predicates = [HasAtomics] in {
// Select notifys with no constant offset.
def NotifyPatNoOffset_A32 :
Pat<(i32 (int_wasm_atomic_notify I32:$addr, I32:$count)),
(ATOMIC_NOTIFY_A32 0, 0, I32:$addr, I32:$count)>,
Pat<(i32 (int_wasm_memory_atomic_notify I32:$addr, I32:$count)),
(MEMORY_ATOMIC_NOTIFY_A32 0, 0, I32:$addr, I32:$count)>,
Requires<[HasAddr32]>;
def NotifyPatNoOffset_A64 :
Pat<(i32 (int_wasm_atomic_notify I64:$addr, I32:$count)),
(ATOMIC_NOTIFY_A64 0, 0, I64:$addr, I32:$count)>,
Pat<(i32 (int_wasm_memory_atomic_notify I64:$addr, I32:$count)),
(MEMORY_ATOMIC_NOTIFY_A64 0, 0, I64:$addr, I32:$count)>,
Requires<[HasAddr64]>;
// Select notifys with a constant offset.
// Pattern with address + immediate offset
multiclass NotifyPatImmOff<PatFrag operand, string inst> {
def : Pat<(i32 (int_wasm_atomic_notify (operand I32:$addr, imm:$off),
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]>;
def : Pat<(i32 (int_wasm_atomic_notify (operand I64:$addr, imm:$off),
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]>;
}
defm : NotifyPatImmOff<regPlusImm, "ATOMIC_NOTIFY">;
defm : NotifyPatImmOff<or_is_add, "ATOMIC_NOTIFY">;
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_atomic_notify imm:$off, I32:$count)),
(ATOMIC_NOTIFY_A32 0, imm:$off, (CONST_I32 0), I32:$count)>,
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]>;
def NotifyPatOffsetOnly_A64 :
Pat<(i32 (int_wasm_atomic_notify imm:$off, I32:$count)),
(ATOMIC_NOTIFY_A64 0, imm:$off, (CONST_I64 0), I32:$count)>,
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]>;
def NotifyPatGlobalAddrOffOnly_A32 :
Pat<(i32 (int_wasm_atomic_notify (WebAssemblywrapper tglobaladdr:$off),
I32:$count)),
(ATOMIC_NOTIFY_A32 0, tglobaladdr:$off, (CONST_I32 0), I32:$count)>,
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]>;
def NotifyPatGlobalAddrOffOnly_A64 :
Pat<(i32 (int_wasm_atomic_notify (WebAssemblywrapper tglobaladdr:$off),
I32:$count)),
(ATOMIC_NOTIFY_A64 0, tglobaladdr:$off, (CONST_I64 0), I32:$count)>,
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]>;
// Select waits with no constant offset.
@ -135,10 +137,14 @@ multiclass WaitPatNoOffset<ValueType ty, Intrinsic kind,
(!cast<NI>(inst#_A64) 0, 0, I64:$addr, ty:$exp, I64:$timeout)>,
Requires<[HasAddr64]>;
}
defm : WaitPatNoOffset<i32, int_wasm_atomic_wait_i32, "ATOMIC_WAIT_I32">;
defm : WaitPatNoOffset<i64, int_wasm_atomic_wait_i64, "ATOMIC_WAIT_I64">;
defm : WaitPatNoOffset<i32, int_wasm_atomic_wait_i32, "ATOMIC_WAIT_I32">;
defm : WaitPatNoOffset<i64, int_wasm_atomic_wait_i64, "ATOMIC_WAIT_I64">;
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.
@ -154,16 +160,16 @@ multiclass WaitPatImmOff<ValueType ty, Intrinsic kind, PatFrag operand,
I64:$timeout)>,
Requires<[HasAddr64]>;
}
defm : WaitPatImmOff<i32, int_wasm_atomic_wait_i32, regPlusImm,
"ATOMIC_WAIT_I32">;
defm : WaitPatImmOff<i32, int_wasm_atomic_wait_i32, or_is_add,
"ATOMIC_WAIT_I32">;
defm : WaitPatImmOff<i64, int_wasm_atomic_wait_i64, regPlusImm,
"ATOMIC_WAIT_I64">;
defm : WaitPatImmOff<i64, int_wasm_atomic_wait_i64, or_is_add,
"ATOMIC_WAIT_I64">;
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 wait_i32, "ATOMIC_WAIT_I32s with just a constant offset.
// 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,
@ -174,8 +180,10 @@ multiclass WaitPatOffsetOnly<ValueType ty, Intrinsic kind, string inst> {
I64:$timeout)>,
Requires<[HasAddr64]>;
}
defm : WaitPatOffsetOnly<i32, int_wasm_atomic_wait_i32, "ATOMIC_WAIT_I32">;
defm : WaitPatOffsetOnly<i64, int_wasm_atomic_wait_i64, "ATOMIC_WAIT_I64">;
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,
@ -189,10 +197,10 @@ multiclass WaitPatGlobalAddrOffOnly<ValueType ty, Intrinsic kind, string inst> {
I64:$timeout)>,
Requires<[HasAddr64]>;
}
defm : WaitPatGlobalAddrOffOnly<i32, int_wasm_atomic_wait_i32,
"ATOMIC_WAIT_I32">;
defm : WaitPatGlobalAddrOffOnly<i64, int_wasm_atomic_wait_i64,
"ATOMIC_WAIT_I64">;
defm : WaitPatGlobalAddrOffOnly<i32, int_wasm_memory_atomic_wait32,
"MEMORY_ATOMIC_WAIT32">;
defm : WaitPatGlobalAddrOffOnly<i64, int_wasm_memory_atomic_wait64,
"MEMORY_ATOMIC_WAIT64">;
} // Predicates = [HasAtomics]
//===----------------------------------------------------------------------===//

View File

@ -1,10 +1,10 @@
# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass wasm-reg-stackify -run-pass wasm-explicit-locals %s -o - | FileCheck %s
# In the two tests below, without compiler_fence or atomic.fence in between,
# atomic.notify and i32.add will be reordered by register stackify pass to meet
# 'call @foo''s requirements. But because we have fences between atomic.notify
# and i32.add, they cannot be reordered, and local.set and local.get are
# inserted to save and load atomic.notify's return value.
# memory.atomic.notify and i32.add will be reordered by register stackify pass
# to meet 'call @foo''s requirements. But because we have fences between
# memory.atomic.notify and i32.add, they cannot be reordered, and local.set and
# local.get are inserted to save and load memory.atomic.notify's return value.
--- |
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
@ -26,7 +26,7 @@ liveins:
tracksRegLiveness: true
body: |
bb.0:
; CHECK: %[[REG:[0-9]+]]:i32 = ATOMIC_NOTIFY_A32
; CHECK: %[[REG:[0-9]+]]:i32 = MEMORY_ATOMIC_NOTIFY_A32
; CHECK: LOCAL_SET_I32 [[LOCAL:[0-9]+]], %[[REG]]
; CHECK: COMPILER_FENCE
; CHECK: ADD_I32
@ -35,7 +35,7 @@ body: |
liveins: $arguments
%0:i32 = CONST_I32 0, implicit-def $arguments
%1:i32 = ATOMIC_NOTIFY_A32 2, 0, %0:i32, %0:i32, implicit-def $arguments
%1:i32 = MEMORY_ATOMIC_NOTIFY_A32 2, 0, %0:i32, %0:i32, implicit-def $arguments
COMPILER_FENCE implicit-def $arguments
%2:i32 = ADD_I32 %0:i32, %0:i32, implicit-def $arguments
CALL @foo, %2:i32, %1:i32, implicit-def $arguments
@ -50,7 +50,7 @@ liveins:
tracksRegLiveness: true
body: |
bb.0:
; CHECK: %[[REG:[0-9]+]]:i32 = ATOMIC_NOTIFY_A32
; CHECK: %[[REG:[0-9]+]]:i32 = MEMORY_ATOMIC_NOTIFY_A32
; CHECK: LOCAL_SET_I32 [[LOCAL:[0-9]+]], %[[REG]]
; CHECK: ATOMIC_FENCE
; CHECK: ADD_I32
@ -59,7 +59,7 @@ body: |
liveins: $arguments
%0:i32 = CONST_I32 0, implicit-def $arguments
%1:i32 = ATOMIC_NOTIFY_A32 2, 0, %0:i32, %0:i32, implicit-def $arguments
%1:i32 = MEMORY_ATOMIC_NOTIFY_A32 2, 0, %0:i32, %0:i32, implicit-def $arguments
ATOMIC_FENCE 0, implicit-def $arguments
%2:i32 = ADD_I32 %0:i32, %0:i32, implicit-def $arguments
CALL @foo, %2:i32, %1:i32, implicit-def $arguments

View File

@ -1530,94 +1530,94 @@ define i32 @cmpxchg_i8_i32_z_from_global_address(i32 %exp, i32 %new) {
; Waits: 32-bit
;===----------------------------------------------------------------------------
declare i32 @llvm.wasm.atomic.wait.i32(i32*, i32, i64)
declare i32 @llvm.wasm.memory.atomic.wait32(i32*, i32, i64)
; Basic wait.
; CHECK-LABEL: wait_i32_no_offset:
; CHECK: i32.atomic.wait $push0=, 0($0), $1, $2{{$}}
; CHECK-LABEL: wait32_no_offset:
; CHECK: memory.atomic.wait32 $push0=, 0($0), $1, $2{{$}}
; CHECK-NEXT: return $pop0{{$}}
define i32 @wait_i32_no_offset(i32* %p, i32 %exp, i64 %timeout) {
%v = call i32 @llvm.wasm.atomic.wait.i32(i32* %p, i32 %exp, i64 %timeout)
define i32 @wait32_no_offset(i32* %p, i32 %exp, i64 %timeout) {
%v = call i32 @llvm.wasm.memory.atomic.wait32(i32* %p, i32 %exp, i64 %timeout)
ret i32 %v
}
; With an nuw add, we can fold an offset.
; CHECK-LABEL: wait_i32_with_folded_offset:
; CHECK: i32.atomic.wait $push0=, 24($0), $1, $2{{$}}
define i32 @wait_i32_with_folded_offset(i32* %p, i32 %exp, i64 %timeout) {
; CHECK-LABEL: wait32_with_folded_offset:
; CHECK: memory.atomic.wait32 $push0=, 24($0), $1, $2{{$}}
define i32 @wait32_with_folded_offset(i32* %p, i32 %exp, i64 %timeout) {
%q = ptrtoint i32* %p to i32
%r = add nuw i32 %q, 24
%s = inttoptr i32 %r to i32*
%t = call i32 @llvm.wasm.atomic.wait.i32(i32* %s, i32 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait32(i32* %s, i32 %exp, i64 %timeout)
ret i32 %t
}
; With an inbounds gep, we can fold an offset.
; CHECK-LABEL: wait_i32_with_folded_gep_offset:
; CHECK: i32.atomic.wait $push0=, 24($0), $1, $2{{$}}
define i32 @wait_i32_with_folded_gep_offset(i32* %p, i32 %exp, i64 %timeout) {
; CHECK-LABEL: wait32_with_folded_gep_offset:
; CHECK: memory.atomic.wait32 $push0=, 24($0), $1, $2{{$}}
define i32 @wait32_with_folded_gep_offset(i32* %p, i32 %exp, i64 %timeout) {
%s = getelementptr inbounds i32, i32* %p, i32 6
%t = call i32 @llvm.wasm.atomic.wait.i32(i32* %s, i32 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait32(i32* %s, i32 %exp, i64 %timeout)
ret i32 %t
}
; We can't fold a negative offset though, even with an inbounds gep.
; CHECK-LABEL: wait_i32_with_unfolded_gep_negative_offset:
; CHECK-LABEL: wait32_with_unfolded_gep_negative_offset:
; CHECK: i32.const $push0=, -24{{$}}
; CHECK: i32.add $push1=, $0, $pop0{{$}}
; CHECK: i32.atomic.wait $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait_i32_with_unfolded_gep_negative_offset(i32* %p, i32 %exp, i64 %timeout) {
; CHECK: memory.atomic.wait32 $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait32_with_unfolded_gep_negative_offset(i32* %p, i32 %exp, i64 %timeout) {
%s = getelementptr inbounds i32, i32* %p, i32 -6
%t = call i32 @llvm.wasm.atomic.wait.i32(i32* %s, i32 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait32(i32* %s, i32 %exp, i64 %timeout)
ret i32 %t
}
; Without nuw, and even with nsw, we can't fold an offset.
; CHECK-LABEL: wait_i32_with_unfolded_offset:
; CHECK-LABEL: wait32_with_unfolded_offset:
; CHECK: i32.const $push0=, 24{{$}}
; CHECK: i32.add $push1=, $0, $pop0{{$}}
; CHECK: i32.atomic.wait $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait_i32_with_unfolded_offset(i32* %p, i32 %exp, i64 %timeout) {
; CHECK: memory.atomic.wait32 $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait32_with_unfolded_offset(i32* %p, i32 %exp, i64 %timeout) {
%q = ptrtoint i32* %p to i32
%r = add nsw i32 %q, 24
%s = inttoptr i32 %r to i32*
%t = call i32 @llvm.wasm.atomic.wait.i32(i32* %s, i32 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait32(i32* %s, i32 %exp, i64 %timeout)
ret i32 %t
}
; Without inbounds, we can't fold a gep offset.
; CHECK-LABEL: wait_i32_with_unfolded_gep_offset:
; CHECK-LABEL: wait32_with_unfolded_gep_offset:
; CHECK: i32.const $push0=, 24{{$}}
; CHECK: i32.add $push1=, $0, $pop0{{$}}
; CHECK: i32.atomic.wait $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait_i32_with_unfolded_gep_offset(i32* %p, i32 %exp, i64 %timeout) {
; CHECK: memory.atomic.wait32 $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait32_with_unfolded_gep_offset(i32* %p, i32 %exp, i64 %timeout) {
%s = getelementptr i32, i32* %p, i32 6
%t = call i32 @llvm.wasm.atomic.wait.i32(i32* %s, i32 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait32(i32* %s, i32 %exp, i64 %timeout)
ret i32 %t
}
; When waiting from a fixed address, materialize a zero.
; CHECK-LABEL: wait_i32_from_numeric_address
; CHECK-LABEL: wait32_from_numeric_address
; CHECK: i32.const $push0=, 0{{$}}
; CHECK: i32.atomic.wait $push1=, 42($pop0), $0, $1{{$}}
define i32 @wait_i32_from_numeric_address(i32 %exp, i64 %timeout) {
; CHECK: memory.atomic.wait32 $push1=, 42($pop0), $0, $1{{$}}
define i32 @wait32_from_numeric_address(i32 %exp, i64 %timeout) {
%s = inttoptr i32 42 to i32*
%t = call i32 @llvm.wasm.atomic.wait.i32(i32* %s, i32 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait32(i32* %s, i32 %exp, i64 %timeout)
ret i32 %t
}
; CHECK-LABEL: wait_i32_from_global_address
; CHECK-LABEL: wait32_from_global_address
; CHECK: i32.const $push0=, 0{{$}}
; CHECK: i32.atomic.wait $push1=, gv($pop0), $0, $1{{$}}
define i32 @wait_i32_from_global_address(i32 %exp, i64 %timeout) {
%t = call i32 @llvm.wasm.atomic.wait.i32(i32* @gv, i32 %exp, i64 %timeout)
; CHECK: memory.atomic.wait32 $push1=, gv($pop0), $0, $1{{$}}
define i32 @wait32_from_global_address(i32 %exp, i64 %timeout) {
%t = call i32 @llvm.wasm.memory.atomic.wait32(i32* @gv, i32 %exp, i64 %timeout)
ret i32 %t
}
@ -1625,75 +1625,75 @@ define i32 @wait_i32_from_global_address(i32 %exp, i64 %timeout) {
; Waits: 64-bit
;===----------------------------------------------------------------------------
declare i32 @llvm.wasm.atomic.wait.i64(i64*, i64, i64)
declare i32 @llvm.wasm.memory.atomic.wait64(i64*, i64, i64)
; Basic wait.
; CHECK-LABEL: wait_i64_no_offset:
; CHECK: i64.atomic.wait $push0=, 0($0), $1, $2{{$}}
; CHECK-LABEL: wait64_no_offset:
; CHECK: memory.atomic.wait64 $push0=, 0($0), $1, $2{{$}}
; CHECK-NEXT: return $pop0{{$}}
define i32 @wait_i64_no_offset(i64* %p, i64 %exp, i64 %timeout) {
%v = call i32 @llvm.wasm.atomic.wait.i64(i64* %p, i64 %exp, i64 %timeout)
define i32 @wait64_no_offset(i64* %p, i64 %exp, i64 %timeout) {
%v = call i32 @llvm.wasm.memory.atomic.wait64(i64* %p, i64 %exp, i64 %timeout)
ret i32 %v
}
; With an nuw add, we can fold an offset.
; CHECK-LABEL: wait_i64_with_folded_offset:
; CHECK: i64.atomic.wait $push0=, 24($0), $1, $2{{$}}
define i32 @wait_i64_with_folded_offset(i64* %p, i64 %exp, i64 %timeout) {
; CHECK-LABEL: wait64_with_folded_offset:
; CHECK: memory.atomic.wait64 $push0=, 24($0), $1, $2{{$}}
define i32 @wait64_with_folded_offset(i64* %p, i64 %exp, i64 %timeout) {
%q = ptrtoint i64* %p to i32
%r = add nuw i32 %q, 24
%s = inttoptr i32 %r to i64*
%t = call i32 @llvm.wasm.atomic.wait.i64(i64* %s, i64 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait64(i64* %s, i64 %exp, i64 %timeout)
ret i32 %t
}
; With an inbounds gep, we can fold an offset.
; CHECK-LABEL: wait_i64_with_folded_gep_offset:
; CHECK: i64.atomic.wait $push0=, 24($0), $1, $2{{$}}
define i32 @wait_i64_with_folded_gep_offset(i64* %p, i64 %exp, i64 %timeout) {
; CHECK-LABEL: wait64_with_folded_gep_offset:
; CHECK: memory.atomic.wait64 $push0=, 24($0), $1, $2{{$}}
define i32 @wait64_with_folded_gep_offset(i64* %p, i64 %exp, i64 %timeout) {
%s = getelementptr inbounds i64, i64* %p, i32 3
%t = call i32 @llvm.wasm.atomic.wait.i64(i64* %s, i64 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait64(i64* %s, i64 %exp, i64 %timeout)
ret i32 %t
}
; We can't fold a negative offset though, even with an inbounds gep.
; CHECK-LABEL: wait_i64_with_unfolded_gep_negative_offset:
; CHECK-LABEL: wait64_with_unfolded_gep_negative_offset:
; CHECK: i32.const $push0=, -24{{$}}
; CHECK: i32.add $push1=, $0, $pop0{{$}}
; CHECK: i64.atomic.wait $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait_i64_with_unfolded_gep_negative_offset(i64* %p, i64 %exp, i64 %timeout) {
; CHECK: memory.atomic.wait64 $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait64_with_unfolded_gep_negative_offset(i64* %p, i64 %exp, i64 %timeout) {
%s = getelementptr inbounds i64, i64* %p, i32 -3
%t = call i32 @llvm.wasm.atomic.wait.i64(i64* %s, i64 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait64(i64* %s, i64 %exp, i64 %timeout)
ret i32 %t
}
; Without nuw, and even with nsw, we can't fold an offset.
; CHECK-LABEL: wait_i64_with_unfolded_offset:
; CHECK-LABEL: wait64_with_unfolded_offset:
; CHECK: i32.const $push0=, 24{{$}}
; CHECK: i32.add $push1=, $0, $pop0{{$}}
; CHECK: i64.atomic.wait $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait_i64_with_unfolded_offset(i64* %p, i64 %exp, i64 %timeout) {
; CHECK: memory.atomic.wait64 $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait64_with_unfolded_offset(i64* %p, i64 %exp, i64 %timeout) {
%q = ptrtoint i64* %p to i32
%r = add nsw i32 %q, 24
%s = inttoptr i32 %r to i64*
%t = call i32 @llvm.wasm.atomic.wait.i64(i64* %s, i64 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait64(i64* %s, i64 %exp, i64 %timeout)
ret i32 %t
}
; Without inbounds, we can't fold a gep offset.
; CHECK-LABEL: wait_i64_with_unfolded_gep_offset:
; CHECK-LABEL: wait64_with_unfolded_gep_offset:
; CHECK: i32.const $push0=, 24{{$}}
; CHECK: i32.add $push1=, $0, $pop0{{$}}
; CHECK: i64.atomic.wait $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait_i64_with_unfolded_gep_offset(i64* %p, i64 %exp, i64 %timeout) {
; CHECK: memory.atomic.wait64 $push2=, 0($pop1), $1, $2{{$}}
define i32 @wait64_with_unfolded_gep_offset(i64* %p, i64 %exp, i64 %timeout) {
%s = getelementptr i64, i64* %p, i32 3
%t = call i32 @llvm.wasm.atomic.wait.i64(i64* %s, i64 %exp, i64 %timeout)
%t = call i32 @llvm.wasm.memory.atomic.wait64(i64* %s, i64 %exp, i64 %timeout)
ret i32 %t
}
@ -1701,37 +1701,37 @@ define i32 @wait_i64_with_unfolded_gep_offset(i64* %p, i64 %exp, i64 %timeout) {
; Notifies
;===----------------------------------------------------------------------------
declare i32 @llvm.wasm.atomic.notify(i32*, i32)
declare i32 @llvm.wasm.memory.atomic.notify(i32*, i32)
; Basic notify.
; CHECK-LABEL: notify_no_offset:
; CHECK: atomic.notify $push0=, 0($0), $1{{$}}
; CHECK: memory.atomic.notify $push0=, 0($0), $1{{$}}
; CHECK-NEXT: return $pop0{{$}}
define i32 @notify_no_offset(i32* %p, i32 %notify_count) {
%v = call i32 @llvm.wasm.atomic.notify(i32* %p, i32 %notify_count)
%v = call i32 @llvm.wasm.memory.atomic.notify(i32* %p, i32 %notify_count)
ret i32 %v
}
; With an nuw add, we can fold an offset.
; CHECK-LABEL: notify_with_folded_offset:
; CHECK: atomic.notify $push0=, 24($0), $1{{$}}
; CHECK: memory.atomic.notify $push0=, 24($0), $1{{$}}
define i32 @notify_with_folded_offset(i32* %p, i32 %notify_count) {
%q = ptrtoint i32* %p to i32
%r = add nuw i32 %q, 24
%s = inttoptr i32 %r to i32*
%t = call i32 @llvm.wasm.atomic.notify(i32* %s, i32 %notify_count)
%t = call i32 @llvm.wasm.memory.atomic.notify(i32* %s, i32 %notify_count)
ret i32 %t
}
; With an inbounds gep, we can fold an offset.
; CHECK-LABEL: notify_with_folded_gep_offset:
; CHECK: atomic.notify $push0=, 24($0), $1{{$}}
; CHECK: memory.atomic.notify $push0=, 24($0), $1{{$}}
define i32 @notify_with_folded_gep_offset(i32* %p, i32 %notify_count) {
%s = getelementptr inbounds i32, i32* %p, i32 6
%t = call i32 @llvm.wasm.atomic.notify(i32* %s, i32 %notify_count)
%t = call i32 @llvm.wasm.memory.atomic.notify(i32* %s, i32 %notify_count)
ret i32 %t
}
@ -1740,10 +1740,10 @@ define i32 @notify_with_folded_gep_offset(i32* %p, i32 %notify_count) {
; CHECK-LABEL: notify_with_unfolded_gep_negative_offset:
; CHECK: i32.const $push0=, -24{{$}}
; CHECK: i32.add $push1=, $0, $pop0{{$}}
; CHECK: atomic.notify $push2=, 0($pop1), $1{{$}}
; CHECK: memory.atomic.notify $push2=, 0($pop1), $1{{$}}
define i32 @notify_with_unfolded_gep_negative_offset(i32* %p, i32 %notify_count) {
%s = getelementptr inbounds i32, i32* %p, i32 -6
%t = call i32 @llvm.wasm.atomic.notify(i32* %s, i32 %notify_count)
%t = call i32 @llvm.wasm.memory.atomic.notify(i32* %s, i32 %notify_count)
ret i32 %t
}
@ -1752,12 +1752,12 @@ define i32 @notify_with_unfolded_gep_negative_offset(i32* %p, i32 %notify_count)
; CHECK-LABEL: notify_with_unfolded_offset:
; CHECK: i32.const $push0=, 24{{$}}
; CHECK: i32.add $push1=, $0, $pop0{{$}}
; CHECK: atomic.notify $push2=, 0($pop1), $1{{$}}
; CHECK: memory.atomic.notify $push2=, 0($pop1), $1{{$}}
define i32 @notify_with_unfolded_offset(i32* %p, i32 %notify_count) {
%q = ptrtoint i32* %p to i32
%r = add nsw i32 %q, 24
%s = inttoptr i32 %r to i32*
%t = call i32 @llvm.wasm.atomic.notify(i32* %s, i32 %notify_count)
%t = call i32 @llvm.wasm.memory.atomic.notify(i32* %s, i32 %notify_count)
ret i32 %t
}
@ -1766,10 +1766,10 @@ define i32 @notify_with_unfolded_offset(i32* %p, i32 %notify_count) {
; CHECK-LABEL: notify_with_unfolded_gep_offset:
; CHECK: i32.const $push0=, 24{{$}}
; CHECK: i32.add $push1=, $0, $pop0{{$}}
; CHECK: atomic.notify $push2=, 0($pop1), $1{{$}}
; CHECK: memory.atomic.notify $push2=, 0($pop1), $1{{$}}
define i32 @notify_with_unfolded_gep_offset(i32* %p, i32 %notify_count) {
%s = getelementptr i32, i32* %p, i32 6
%t = call i32 @llvm.wasm.atomic.notify(i32* %s, i32 %notify_count)
%t = call i32 @llvm.wasm.memory.atomic.notify(i32* %s, i32 %notify_count)
ret i32 %t
}
@ -1777,17 +1777,17 @@ define i32 @notify_with_unfolded_gep_offset(i32* %p, i32 %notify_count) {
; CHECK-LABEL: notify_from_numeric_address
; CHECK: i32.const $push0=, 0{{$}}
; CHECK: atomic.notify $push1=, 42($pop0), $0{{$}}
; CHECK: memory.atomic.notify $push1=, 42($pop0), $0{{$}}
define i32 @notify_from_numeric_address(i32 %notify_count) {
%s = inttoptr i32 42 to i32*
%t = call i32 @llvm.wasm.atomic.notify(i32* %s, i32 %notify_count)
%t = call i32 @llvm.wasm.memory.atomic.notify(i32* %s, i32 %notify_count)
ret i32 %t
}
; CHECK-LABEL: notify_from_global_address
; CHECK: i32.const $push0=, 0{{$}}
; CHECK: atomic.notify $push1=, gv($pop0), $0{{$}}
; CHECK: memory.atomic.notify $push1=, gv($pop0), $0{{$}}
define i32 @notify_from_global_address(i32 %notify_count) {
%t = call i32 @llvm.wasm.atomic.notify(i32* @gv, i32 %notify_count)
%t = call i32 @llvm.wasm.memory.atomic.notify(i32* @gv, i32 %notify_count)
ret i32 %t
}

View File

@ -3,12 +3,12 @@
main:
.functype main () -> ()
# CHECK: atomic.notify 0 # encoding: [0xfe,0x00,0x02,0x00]
atomic.notify 0
# CHECK: i32.atomic.wait 0 # encoding: [0xfe,0x01,0x02,0x00]
i32.atomic.wait 0
# CHECK: i64.atomic.wait 0 # encoding: [0xfe,0x02,0x03,0x00]
i64.atomic.wait 0
# CHECK: memory.atomic.notify 0 # encoding: [0xfe,0x00,0x02,0x00]
memory.atomic.notify 0
# CHECK: memory.atomic.wait32 0 # encoding: [0xfe,0x01,0x02,0x00]
memory.atomic.wait32 0
# CHECK: memory.atomic.wait64 0 # encoding: [0xfe,0x02,0x03,0x00]
memory.atomic.wait64 0
# CHECK: atomic.fence # encoding: [0xfe,0x03,0x00]
atomic.fence

View File

@ -83,7 +83,7 @@ test0:
i32.trunc_f32_s
try exnref
i32.atomic.load 0
atomic.notify 0
memory.atomic.notify 0
.LBB0_3:
catch
local.set 0
@ -201,7 +201,7 @@ empty_fref_table:
# CHECK-NEXT: i32.trunc_f32_s
# CHECK-NEXT: try exnref
# CHECK-NEXT: i32.atomic.load 0
# CHECK-NEXT: atomic.notify 0
# CHECK-NEXT: memory.atomic.notify 0
# CHECK-NEXT: .LBB0_3:
# CHECK-NEXT: catch
# CHECK-NEXT: local.set 0