Set the correct memory ordering for relaxed atomics after ISel. This allows SelectionDAG to keep the simple generic selection for target-independent AtomicLoad nodes, but keeps the ordering immediate correct in the MIR. Notably, the MachineMemOperand still has the original memory ordering and MIR passes would use that rather than the ordering immedate to make their code motion decisions (if we had any for Wasm, which we don't).
144 lines
4.7 KiB
LLVM
144 lines
4.7 KiB
LLVM
; 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
|
|
|
|
; A multithread fence is lowered to an atomic.fence instruction.
|
|
define void @fence_acquire() {
|
|
; NO-ATOMICS-LABEL: fence_acquire:
|
|
; NO-ATOMICS: .functype fence_acquire () -> ()
|
|
; NO-ATOMICS-NEXT: # %bb.0:
|
|
; NO-ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; ATOMICS-LABEL: fence_acquire:
|
|
; ATOMICS: .functype fence_acquire () -> ()
|
|
; ATOMICS-NEXT: # %bb.0:
|
|
; ATOMICS-NEXT: atomic.fence
|
|
; ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED32-LABEL: fence_acquire:
|
|
; RELAXED32: .functype fence_acquire () -> ()
|
|
; RELAXED32-NEXT: # %bb.0:
|
|
; RELAXED32-NEXT: atomic.fence acqrel
|
|
; RELAXED32-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED64-LABEL: fence_acquire:
|
|
; RELAXED64: .functype fence_acquire () -> ()
|
|
; RELAXED64-NEXT: # %bb.0:
|
|
; RELAXED64-NEXT: atomic.fence acqrel
|
|
; RELAXED64-NEXT: # fallthrough-return
|
|
fence acquire
|
|
ret void
|
|
}
|
|
|
|
define void @fence_release() {
|
|
; NO-ATOMICS-LABEL: fence_release:
|
|
; NO-ATOMICS: .functype fence_release () -> ()
|
|
; NO-ATOMICS-NEXT: # %bb.0:
|
|
; NO-ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; ATOMICS-LABEL: fence_release:
|
|
; ATOMICS: .functype fence_release () -> ()
|
|
; ATOMICS-NEXT: # %bb.0:
|
|
; ATOMICS-NEXT: atomic.fence
|
|
; ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED32-LABEL: fence_release:
|
|
; RELAXED32: .functype fence_release () -> ()
|
|
; RELAXED32-NEXT: # %bb.0:
|
|
; RELAXED32-NEXT: atomic.fence acqrel
|
|
; RELAXED32-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED64-LABEL: fence_release:
|
|
; RELAXED64: .functype fence_release () -> ()
|
|
; RELAXED64-NEXT: # %bb.0:
|
|
; RELAXED64-NEXT: atomic.fence acqrel
|
|
; RELAXED64-NEXT: # fallthrough-return
|
|
fence release
|
|
ret void
|
|
}
|
|
|
|
define void @fence_acq_rel() {
|
|
; NO-ATOMICS-LABEL: fence_acq_rel:
|
|
; NO-ATOMICS: .functype fence_acq_rel () -> ()
|
|
; NO-ATOMICS-NEXT: # %bb.0:
|
|
; NO-ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; ATOMICS-LABEL: fence_acq_rel:
|
|
; ATOMICS: .functype fence_acq_rel () -> ()
|
|
; ATOMICS-NEXT: # %bb.0:
|
|
; ATOMICS-NEXT: atomic.fence
|
|
; ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED32-LABEL: fence_acq_rel:
|
|
; RELAXED32: .functype fence_acq_rel () -> ()
|
|
; RELAXED32-NEXT: # %bb.0:
|
|
; RELAXED32-NEXT: atomic.fence acqrel
|
|
; RELAXED32-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED64-LABEL: fence_acq_rel:
|
|
; RELAXED64: .functype fence_acq_rel () -> ()
|
|
; RELAXED64-NEXT: # %bb.0:
|
|
; RELAXED64-NEXT: atomic.fence acqrel
|
|
; RELAXED64-NEXT: # fallthrough-return
|
|
fence acq_rel
|
|
ret void
|
|
}
|
|
|
|
define void @fence_seq_cst() {
|
|
; NO-ATOMICS-LABEL: fence_seq_cst:
|
|
; NO-ATOMICS: .functype fence_seq_cst () -> ()
|
|
; NO-ATOMICS-NEXT: # %bb.0:
|
|
; NO-ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; ATOMICS-LABEL: fence_seq_cst:
|
|
; ATOMICS: .functype fence_seq_cst () -> ()
|
|
; ATOMICS-NEXT: # %bb.0:
|
|
; ATOMICS-NEXT: atomic.fence
|
|
; ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED32-LABEL: fence_seq_cst:
|
|
; RELAXED32: .functype fence_seq_cst () -> ()
|
|
; RELAXED32-NEXT: # %bb.0:
|
|
; RELAXED32-NEXT: atomic.fence seqcst
|
|
; RELAXED32-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED64-LABEL: fence_seq_cst:
|
|
; RELAXED64: .functype fence_seq_cst () -> ()
|
|
; RELAXED64-NEXT: # %bb.0:
|
|
; RELAXED64-NEXT: atomic.fence seqcst
|
|
; RELAXED64-NEXT: # fallthrough-return
|
|
fence seq_cst
|
|
ret void
|
|
}
|
|
|
|
; A singlethread fence becomes compiler_fence instruction, a pseudo instruction
|
|
; that acts as a compiler barrier. The barrier should not be emitted to .s file.
|
|
define void @singlethread_fence() {
|
|
; NO-ATOMICS-LABEL: singlethread_fence:
|
|
; NO-ATOMICS: .functype singlethread_fence () -> ()
|
|
; NO-ATOMICS-NEXT: # %bb.0:
|
|
; NO-ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; ATOMICS-LABEL: singlethread_fence:
|
|
; ATOMICS: .functype singlethread_fence () -> ()
|
|
; ATOMICS-NEXT: # %bb.0:
|
|
; ATOMICS-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED32-LABEL: singlethread_fence:
|
|
; RELAXED32: .functype singlethread_fence () -> ()
|
|
; RELAXED32-NEXT: # %bb.0:
|
|
; RELAXED32-NEXT: # fallthrough-return
|
|
;
|
|
; RELAXED64-LABEL: singlethread_fence:
|
|
; RELAXED64: .functype singlethread_fence () -> ()
|
|
; RELAXED64-NEXT: # %bb.0:
|
|
; RELAXED64-NEXT: # fallthrough-return
|
|
fence syncscope("singlethread") seq_cst
|
|
fence syncscope("singlethread") acquire
|
|
fence syncscope("singlethread") release
|
|
fence syncscope("singlethread") acq_rel
|
|
ret void
|
|
}
|