Index: include/llvm/IR/IntrinsicsWebAssembly.td =================================================================== --- include/llvm/IR/IntrinsicsWebAssembly.td +++ include/llvm/IR/IntrinsicsWebAssembly.td @@ -64,4 +64,24 @@ // Returns LSDA address of the current function. def int_wasm_lsda : Intrinsic<[llvm_ptr_ty], [], [IntrNoMem]>; + +//===----------------------------------------------------------------------===// +// Atomic intrinsics +//===----------------------------------------------------------------------===// + +// wait / wake +def int_wasm_atomic_wait_i32 : + Intrinsic<[llvm_i32_ty], + [LLVMPointerType, llvm_i32_ty, llvm_i64_ty], + [IntrInaccessibleMemOrArgMemOnly, ReadOnly<0>, NoCapture<0>, + IntrHasSideEffects]>; +def int_wasm_atomic_wait_i64 : + Intrinsic<[llvm_i32_ty], + [LLVMPointerType, llvm_i64_ty, llvm_i64_ty], + [IntrInaccessibleMemOrArgMemOnly, ReadOnly<0>, NoCapture<0>, + IntrHasSideEffects]>; +def int_wasm_atomic_wake : + Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], + [IntrInaccessibleMemOnly, NoCapture<0>, IntrHasSideEffects]>; + } Index: lib/Target/WebAssembly/WebAssemblyInstrAtomics.td =================================================================== --- lib/Target/WebAssembly/WebAssemblyInstrAtomics.td +++ lib/Target/WebAssembly/WebAssemblyInstrAtomics.td @@ -655,3 +655,32 @@ ATOMIC_RMW8_U_XCHG_I32, ATOMIC_RMW16_U_XCHG_I32, ATOMIC_RMW8_U_XCHG_I64, ATOMIC_RMW16_U_XCHG_I64, ATOMIC_RMW32_U_XCHG_I64>; } // Predicates = [HasAtomics] + +//===----------------------------------------------------------------------===// +// Atomic wait / wake +//===----------------------------------------------------------------------===// + +let Defs = [ARGUMENTS] in { + +let Predicates = [HasAtomics] in { +let hasSideEffects = 1 in { +defm ATOMIC_WAKE : + I<(outs I64:$dst), (ins I32:$addr, I64:$wake_count), (outs), (ins), + [(set I64:$dst, (int_wasm_atomic_wake I32:$addr, I64:$wake_count))], + "atomic.wake \t$dst, $addr, $wake_count", "atomic.wake", 0xfe00>; +let mayLoad = 1 in { +defm ATOMIC_WAIT_I32 : + I<(outs I32:$dst), (ins I32:$addr, I32:$exp, I64:$timeout), (outs), (ins), + [(set I32:$dst, + (int_wasm_atomic_wait_i32 I32:$addr, I32:$exp, I64:$timeout))], + "i32.atomic.wait \t$dst, $addr, $exp, $timeout", "i32.atomic.wait", 0xfe01>; +defm ATOMIC_WAIT_I64 : + I<(outs I32:$dst), (ins I32:$addr, I64:$exp, I64:$timeout), (outs), (ins), + [(set I32:$dst, + (int_wasm_atomic_wait_i64 I32:$addr, I64:$exp, I64:$timeout))], + "i64.atomic.wait \t$dst, $addr, $exp, $timeout", "i64.atomic.wait", 0xfe02>; +} // mayLoad = 1 +} // hasSideEffects = 1 +} // Predicates = [HasAtomics] + +} // Defs = [ARGUMENTS] Index: test/CodeGen/WebAssembly/atomic-wait-wake.ll =================================================================== --- /dev/null +++ test/CodeGen/WebAssembly/atomic-wait-wake.ll @@ -0,0 +1,41 @@ +; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics | FileCheck --match-full-lines %s + +; Test atomic wait / wake instructions. + +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown" + +declare i32 @llvm.wasm.atomic.wait.i32(i32*, i32, i64) +declare i32 @llvm.wasm.atomic.wait.i64(i64*, i64, i64) +declare i64 @llvm.wasm.atomic.wake(i8*, i64) + +; CHECK-LABEL: test_atomic_wait_i32: +; CHECK-NEXT: .param i32, i32, i64 +; CHECK-NEXT: .result i32 +; CHECK-NEXT: i32.atomic.wait $push0=, $0, $1, $2 +; CHECK-NEXT: return $pop0 +define i32 @test_atomic_wait_i32(i32* %addr, i32 %exp, i64 %timeout) { + %ret = call i32 @llvm.wasm.atomic.wait.i32(i32* %addr, i32 %exp, i64 %timeout) + ret i32 %ret +} + +; CHECK-LABEL: test_atomic_wait_i64: +; CHECK-NEXT: .param i32, i64, i64 +; CHECK-NEXT: .result i32 +; CHECK-NEXT: i64.atomic.wait $push0=, $0, $1, $2 +; CHECK-NEXT: return $pop0 +define i32 @test_atomic_wait_i64(i64* %addr, i64 %exp, i64 %timeout) { + %ret = call i32 @llvm.wasm.atomic.wait.i64(i64* %addr, i64 %exp, i64 %timeout) + ret i32 %ret +} + +; CHECK-LABEL: test_atomic_wake: +; CHECK-NEXT: .param i32, i64 +; CHECK-NEXT: .result i64 +; CHECK-NEXT: atomic.wake $push0=, $0, $1 +; CHECK-NEXT: return $pop0 +define i64 @test_atomic_wake(i8* %addr, i64 %wake_count) { + %ret = call i64 @llvm.wasm.atomic.wake(i8* %addr, i64 %wake_count) + ret i64 %ret +}