blob: 116c5fbba34d99b471ba9d3b7b8699ecf184d993 [file] [log] [blame] [edit]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
; RUN: llc < %s --mtriple=wasm32 | FileCheck %s --check-prefixes=NO-ATOMICS
; RUN: llc < %s --mtriple=wasm32 -mattr=+atomics | FileCheck %s --check-prefixes=ATOMICS
; RUN: llc < %s --mtriple=wasm32 -mattr=+atomics,+relaxed-atomics | FileCheck %s --check-prefixes=RELAXED32
; RUN: llc < %s --mtriple=wasm64 -mattr=+atomics,+relaxed-atomics | FileCheck %s --check-prefixes=RELAXED64
; Currently Wasm supports a constrained set of atomic memory orderings.
; Originally it supported only sequential consistency, but now it also
; supports relaxed atomics. Weaker orderings in LLVM IR are "upgraded" to
; the next supported ordering.
target triple = "wasm32-unknown-unknown"
;===----------------------------------------------------------------------------
; Atomic loads
;===----------------------------------------------------------------------------
; The 'release' and 'acq_rel' orderings are not valid on load instructions.
define i32 @load_i32_unordered(ptr %p) {
; NO-ATOMICS-LABEL: load_i32_unordered:
; NO-ATOMICS: .functype load_i32_unordered (i32) -> (i32)
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: load_i32_unordered:
; ATOMICS: .functype load_i32_unordered (i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: i32.atomic.load 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: load_i32_unordered:
; RELAXED32: .functype load_i32_unordered (i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: i32.atomic.load acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: load_i32_unordered:
; RELAXED64: .functype load_i32_unordered (i64) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: i32.atomic.load acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%v = load atomic i32, ptr %p unordered, align 4
ret i32 %v
}
define i32 @load_i32_monotonic(ptr %p) {
; NO-ATOMICS-LABEL: load_i32_monotonic:
; NO-ATOMICS: .functype load_i32_monotonic (i32) -> (i32)
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: load_i32_monotonic:
; ATOMICS: .functype load_i32_monotonic (i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: i32.atomic.load 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: load_i32_monotonic:
; RELAXED32: .functype load_i32_monotonic (i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: i32.atomic.load acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: load_i32_monotonic:
; RELAXED64: .functype load_i32_monotonic (i64) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: i32.atomic.load acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%v = load atomic i32, ptr %p monotonic, align 4
ret i32 %v
}
define i32 @load_i32_acquire(ptr %p) {
; NO-ATOMICS-LABEL: load_i32_acquire:
; NO-ATOMICS: .functype load_i32_acquire (i32) -> (i32)
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: load_i32_acquire:
; ATOMICS: .functype load_i32_acquire (i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: i32.atomic.load 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: load_i32_acquire:
; RELAXED32: .functype load_i32_acquire (i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: i32.atomic.load acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: load_i32_acquire:
; RELAXED64: .functype load_i32_acquire (i64) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: i32.atomic.load acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%v = load atomic i32, ptr %p acquire, align 4
ret i32 %v
}
define i32 @load_i32_seq_cst(ptr %p) {
; NO-ATOMICS-LABEL: load_i32_seq_cst:
; NO-ATOMICS: .functype load_i32_seq_cst (i32) -> (i32)
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: load_i32_seq_cst:
; ATOMICS: .functype load_i32_seq_cst (i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: i32.atomic.load 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: load_i32_seq_cst:
; RELAXED32: .functype load_i32_seq_cst (i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: i32.atomic.load seqcst 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: load_i32_seq_cst:
; RELAXED64: .functype load_i32_seq_cst (i64) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: i32.atomic.load seqcst 0
; RELAXED64-NEXT: # fallthrough-return
%v = load atomic i32, ptr %p seq_cst, align 4
ret i32 %v
}
;===----------------------------------------------------------------------------
; Atomic stores
;===----------------------------------------------------------------------------
; The 'acquire' and 'acq_rel' orderings aren’t valid on store instructions.
define void @store_i32_unordered(ptr %p, i32 %v) {
; NO-ATOMICS-LABEL: store_i32_unordered:
; NO-ATOMICS: .functype store_i32_unordered (i32, i32) -> ()
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: store_i32_unordered:
; ATOMICS: .functype store_i32_unordered (i32, i32) -> ()
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: i32.atomic.store 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: store_i32_unordered:
; RELAXED32: .functype store_i32_unordered (i32, i32) -> ()
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: i32.atomic.store acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: store_i32_unordered:
; RELAXED64: .functype store_i32_unordered (i64, i32) -> ()
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: i32.atomic.store acqrel 0
; RELAXED64-NEXT: # fallthrough-return
store atomic i32 %v, ptr %p unordered, align 4
ret void
}
define void @store_i32_monotonic(ptr %p, i32 %v) {
; NO-ATOMICS-LABEL: store_i32_monotonic:
; NO-ATOMICS: .functype store_i32_monotonic (i32, i32) -> ()
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: store_i32_monotonic:
; ATOMICS: .functype store_i32_monotonic (i32, i32) -> ()
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: i32.atomic.store 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: store_i32_monotonic:
; RELAXED32: .functype store_i32_monotonic (i32, i32) -> ()
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: i32.atomic.store acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: store_i32_monotonic:
; RELAXED64: .functype store_i32_monotonic (i64, i32) -> ()
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: i32.atomic.store acqrel 0
; RELAXED64-NEXT: # fallthrough-return
store atomic i32 %v, ptr %p monotonic, align 4
ret void
}
define void @store_i32_release(ptr %p, i32 %v) {
; NO-ATOMICS-LABEL: store_i32_release:
; NO-ATOMICS: .functype store_i32_release (i32, i32) -> ()
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: store_i32_release:
; ATOMICS: .functype store_i32_release (i32, i32) -> ()
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: i32.atomic.store 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: store_i32_release:
; RELAXED32: .functype store_i32_release (i32, i32) -> ()
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: i32.atomic.store acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: store_i32_release:
; RELAXED64: .functype store_i32_release (i64, i32) -> ()
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: i32.atomic.store acqrel 0
; RELAXED64-NEXT: # fallthrough-return
store atomic i32 %v, ptr %p release, align 4
ret void
}
define void @store_i32_seq_cst(ptr %p, i32 %v) {
; NO-ATOMICS-LABEL: store_i32_seq_cst:
; NO-ATOMICS: .functype store_i32_seq_cst (i32, i32) -> ()
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: store_i32_seq_cst:
; ATOMICS: .functype store_i32_seq_cst (i32, i32) -> ()
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: i32.atomic.store 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: store_i32_seq_cst:
; RELAXED32: .functype store_i32_seq_cst (i32, i32) -> ()
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: i32.atomic.store seqcst 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: store_i32_seq_cst:
; RELAXED64: .functype store_i32_seq_cst (i64, i32) -> ()
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: i32.atomic.store seqcst 0
; RELAXED64-NEXT: # fallthrough-return
store atomic i32 %v, ptr %p seq_cst, align 4
ret void
}
;===----------------------------------------------------------------------------
; Atomic read-modify-writes
;===----------------------------------------------------------------------------
; Out of several binary RMW instructions, here we test 'add' as an example.
; The 'unordered' ordering is not valid on atomicrmw instructions.
define i32 @add_i32_monotonic(ptr %p, i32 %v) {
; NO-ATOMICS-LABEL: add_i32_monotonic:
; NO-ATOMICS: .functype add_i32_monotonic (i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 2
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.add
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: add_i32_monotonic:
; ATOMICS: .functype add_i32_monotonic (i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: i32.atomic.rmw.add 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: add_i32_monotonic:
; RELAXED32: .functype add_i32_monotonic (i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: i32.atomic.rmw.add acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: add_i32_monotonic:
; RELAXED64: .functype add_i32_monotonic (i64, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: i32.atomic.rmw.add acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%old = atomicrmw add ptr %p, i32 %v monotonic
ret i32 %old
}
define i32 @add_i32_acquire(ptr %p, i32 %v) {
; NO-ATOMICS-LABEL: add_i32_acquire:
; NO-ATOMICS: .functype add_i32_acquire (i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 2
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.add
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: add_i32_acquire:
; ATOMICS: .functype add_i32_acquire (i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: i32.atomic.rmw.add 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: add_i32_acquire:
; RELAXED32: .functype add_i32_acquire (i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: i32.atomic.rmw.add acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: add_i32_acquire:
; RELAXED64: .functype add_i32_acquire (i64, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: i32.atomic.rmw.add acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%old = atomicrmw add ptr %p, i32 %v acquire
ret i32 %old
}
define i32 @add_i32_release(ptr %p, i32 %v) {
; NO-ATOMICS-LABEL: add_i32_release:
; NO-ATOMICS: .functype add_i32_release (i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 2
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.add
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: add_i32_release:
; ATOMICS: .functype add_i32_release (i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: i32.atomic.rmw.add 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: add_i32_release:
; RELAXED32: .functype add_i32_release (i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: i32.atomic.rmw.add acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: add_i32_release:
; RELAXED64: .functype add_i32_release (i64, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: i32.atomic.rmw.add acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%old = atomicrmw add ptr %p, i32 %v release
ret i32 %old
}
define i32 @add_i32_acq_rel(ptr %p, i32 %v) {
; NO-ATOMICS-LABEL: add_i32_acq_rel:
; NO-ATOMICS: .functype add_i32_acq_rel (i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 2
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.add
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: add_i32_acq_rel:
; ATOMICS: .functype add_i32_acq_rel (i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: i32.atomic.rmw.add 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: add_i32_acq_rel:
; RELAXED32: .functype add_i32_acq_rel (i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: i32.atomic.rmw.add acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: add_i32_acq_rel:
; RELAXED64: .functype add_i32_acq_rel (i64, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: i32.atomic.rmw.add acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%old = atomicrmw add ptr %p, i32 %v acq_rel
ret i32 %old
}
define i32 @add_i32_seq_cst(ptr %p, i32 %v) {
; NO-ATOMICS-LABEL: add_i32_seq_cst:
; NO-ATOMICS: .functype add_i32_seq_cst (i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 2
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.add
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: add_i32_seq_cst:
; ATOMICS: .functype add_i32_seq_cst (i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: i32.atomic.rmw.add 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: add_i32_seq_cst:
; RELAXED32: .functype add_i32_seq_cst (i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: i32.atomic.rmw.add seqcst 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: add_i32_seq_cst:
; RELAXED64: .functype add_i32_seq_cst (i64, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: i32.atomic.rmw.add seqcst 0
; RELAXED64-NEXT: # fallthrough-return
%old = atomicrmw add ptr %p, i32 %v seq_cst
ret i32 %old
}
; Ternary RMW instruction: cmpxchg
; The success and failure ordering arguments specify how this cmpxchg
; synchronizes with other atomic operations. Both ordering parameters must be at
; least monotonic, the ordering constraint on failure must be no stronger than
; that on success, and the failure ordering cannot be either release or acq_rel.
define i32 @cmpxchg_i32_monotonic_monotonic(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_monotonic_monotonic:
; NO-ATOMICS: .functype cmpxchg_i32_monotonic_monotonic (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_monotonic_monotonic:
; ATOMICS: .functype cmpxchg_i32_monotonic_monotonic (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_monotonic_monotonic:
; RELAXED32: .functype cmpxchg_i32_monotonic_monotonic (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_monotonic_monotonic:
; RELAXED64: .functype cmpxchg_i32_monotonic_monotonic (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new monotonic monotonic
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}
define i32 @cmpxchg_i32_acquire_monotonic(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_acquire_monotonic:
; NO-ATOMICS: .functype cmpxchg_i32_acquire_monotonic (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_acquire_monotonic:
; ATOMICS: .functype cmpxchg_i32_acquire_monotonic (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_acquire_monotonic:
; RELAXED32: .functype cmpxchg_i32_acquire_monotonic (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_acquire_monotonic:
; RELAXED64: .functype cmpxchg_i32_acquire_monotonic (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new acquire monotonic
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}
define i32 @cmpxchg_i32_release_monotonic(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_release_monotonic:
; NO-ATOMICS: .functype cmpxchg_i32_release_monotonic (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_release_monotonic:
; ATOMICS: .functype cmpxchg_i32_release_monotonic (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_release_monotonic:
; RELAXED32: .functype cmpxchg_i32_release_monotonic (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_release_monotonic:
; RELAXED64: .functype cmpxchg_i32_release_monotonic (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new release monotonic
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}
define i32 @cmpxchg_i32_acq_rel_monotonic(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_acq_rel_monotonic:
; NO-ATOMICS: .functype cmpxchg_i32_acq_rel_monotonic (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_acq_rel_monotonic:
; ATOMICS: .functype cmpxchg_i32_acq_rel_monotonic (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_acq_rel_monotonic:
; RELAXED32: .functype cmpxchg_i32_acq_rel_monotonic (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_acq_rel_monotonic:
; RELAXED64: .functype cmpxchg_i32_acq_rel_monotonic (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new acq_rel monotonic
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}
define i32 @cmpxchg_i32_seq_cst_monotonic(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_seq_cst_monotonic:
; NO-ATOMICS: .functype cmpxchg_i32_seq_cst_monotonic (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_seq_cst_monotonic:
; ATOMICS: .functype cmpxchg_i32_seq_cst_monotonic (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_seq_cst_monotonic:
; RELAXED32: .functype cmpxchg_i32_seq_cst_monotonic (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg seqcst 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_seq_cst_monotonic:
; RELAXED64: .functype cmpxchg_i32_seq_cst_monotonic (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg seqcst 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new seq_cst monotonic
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}
define i32 @cmpxchg_i32_acquire_acquire(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_acquire_acquire:
; NO-ATOMICS: .functype cmpxchg_i32_acquire_acquire (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_acquire_acquire:
; ATOMICS: .functype cmpxchg_i32_acquire_acquire (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_acquire_acquire:
; RELAXED32: .functype cmpxchg_i32_acquire_acquire (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_acquire_acquire:
; RELAXED64: .functype cmpxchg_i32_acquire_acquire (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new acquire acquire
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}
define i32 @cmpxchg_i32_release_acquire(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_release_acquire:
; NO-ATOMICS: .functype cmpxchg_i32_release_acquire (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_release_acquire:
; ATOMICS: .functype cmpxchg_i32_release_acquire (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_release_acquire:
; RELAXED32: .functype cmpxchg_i32_release_acquire (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_release_acquire:
; RELAXED64: .functype cmpxchg_i32_release_acquire (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new release acquire
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}
define i32 @cmpxchg_i32_acq_rel_acquire(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_acq_rel_acquire:
; NO-ATOMICS: .functype cmpxchg_i32_acq_rel_acquire (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_acq_rel_acquire:
; ATOMICS: .functype cmpxchg_i32_acq_rel_acquire (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_acq_rel_acquire:
; RELAXED32: .functype cmpxchg_i32_acq_rel_acquire (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_acq_rel_acquire:
; RELAXED64: .functype cmpxchg_i32_acq_rel_acquire (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg acqrel 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new acq_rel acquire
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}
; CHECK-LABEL: cmpxchg_i32_seq_cst_acquire:
; CHECK-NEXT: .functype cmpxchg_i32_seq_cst_acquire (i32, i32, i32) -> (i32){{$}}
; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}
; CHECK-NEXT: return $pop0{{$}}
define i32 @cmpxchg_i32_seq_cst_acquire(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_seq_cst_acquire:
; NO-ATOMICS: .functype cmpxchg_i32_seq_cst_acquire (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_seq_cst_acquire:
; ATOMICS: .functype cmpxchg_i32_seq_cst_acquire (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_seq_cst_acquire:
; RELAXED32: .functype cmpxchg_i32_seq_cst_acquire (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg seqcst 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_seq_cst_acquire:
; RELAXED64: .functype cmpxchg_i32_seq_cst_acquire (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg seqcst 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new seq_cst acquire
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}
define i32 @cmpxchg_i32_seq_cst_seq_cst(ptr %p, i32 %exp, i32 %new) {
; NO-ATOMICS-LABEL: cmpxchg_i32_seq_cst_seq_cst:
; NO-ATOMICS: .functype cmpxchg_i32_seq_cst_seq_cst (i32, i32, i32) -> (i32)
; NO-ATOMICS-NEXT: .local i32
; NO-ATOMICS-NEXT: # %bb.0:
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: local.get 2
; NO-ATOMICS-NEXT: local.get 0
; NO-ATOMICS-NEXT: i32.load 0
; NO-ATOMICS-NEXT: local.tee 3
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: local.get 1
; NO-ATOMICS-NEXT: i32.eq
; NO-ATOMICS-NEXT: i32.select
; NO-ATOMICS-NEXT: i32.store 0
; NO-ATOMICS-NEXT: local.get 3
; NO-ATOMICS-NEXT: # fallthrough-return
;
; ATOMICS-LABEL: cmpxchg_i32_seq_cst_seq_cst:
; ATOMICS: .functype cmpxchg_i32_seq_cst_seq_cst (i32, i32, i32) -> (i32)
; ATOMICS-NEXT: # %bb.0:
; ATOMICS-NEXT: local.get 0
; ATOMICS-NEXT: local.get 1
; ATOMICS-NEXT: local.get 2
; ATOMICS-NEXT: i32.atomic.rmw.cmpxchg 0
; ATOMICS-NEXT: # fallthrough-return
;
; RELAXED32-LABEL: cmpxchg_i32_seq_cst_seq_cst:
; RELAXED32: .functype cmpxchg_i32_seq_cst_seq_cst (i32, i32, i32) -> (i32)
; RELAXED32-NEXT: # %bb.0:
; RELAXED32-NEXT: local.get 0
; RELAXED32-NEXT: local.get 1
; RELAXED32-NEXT: local.get 2
; RELAXED32-NEXT: i32.atomic.rmw.cmpxchg seqcst 0
; RELAXED32-NEXT: # fallthrough-return
;
; RELAXED64-LABEL: cmpxchg_i32_seq_cst_seq_cst:
; RELAXED64: .functype cmpxchg_i32_seq_cst_seq_cst (i64, i32, i32) -> (i32)
; RELAXED64-NEXT: # %bb.0:
; RELAXED64-NEXT: local.get 0
; RELAXED64-NEXT: local.get 1
; RELAXED64-NEXT: local.get 2
; RELAXED64-NEXT: i32.atomic.rmw.cmpxchg seqcst 0
; RELAXED64-NEXT: # fallthrough-return
%pair = cmpxchg ptr %p, i32 %exp, i32 %new seq_cst seq_cst
%old = extractvalue { i32, i1 } %pair, 0
ret i32 %old
}