247 lines · plain
1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt2; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers -mattr=+atomics,+sign-ext | FileCheck %s3 4; Currently all wasm atomic memory access instructions are sequentially5; consistent, so even if LLVM IR specifies weaker orderings than that, we6; should upgrade them to sequential ordering and treat them in the same way.7 8target triple = "wasm32-unknown-unknown"9 10;===----------------------------------------------------------------------------11; Atomic loads12;===----------------------------------------------------------------------------13 14; The 'release' and 'acq_rel' orderings are not valid on load instructions.15 16; CHECK-LABEL: load_i32_unordered:17; CHECK: i32.atomic.load $push0=, 0($0){{$}}18; CHECK-NEXT: return $pop0{{$}}19define i32 @load_i32_unordered(ptr %p) {20 %v = load atomic i32, ptr %p unordered, align 421 ret i32 %v22}23 24; CHECK-LABEL: load_i32_monotonic:25; CHECK: i32.atomic.load $push0=, 0($0){{$}}26; CHECK-NEXT: return $pop0{{$}}27define i32 @load_i32_monotonic(ptr %p) {28 %v = load atomic i32, ptr %p monotonic, align 429 ret i32 %v30}31 32; CHECK-LABEL: load_i32_acquire:33; CHECK: i32.atomic.load $push0=, 0($0){{$}}34; CHECK-NEXT: return $pop0{{$}}35define i32 @load_i32_acquire(ptr %p) {36 %v = load atomic i32, ptr %p acquire, align 437 ret i32 %v38}39 40; CHECK-LABEL: load_i32_seq_cst:41; CHECK: i32.atomic.load $push0=, 0($0){{$}}42; CHECK-NEXT: return $pop0{{$}}43define i32 @load_i32_seq_cst(ptr %p) {44 %v = load atomic i32, ptr %p seq_cst, align 445 ret i32 %v46}47 48;===----------------------------------------------------------------------------49; Atomic stores50;===----------------------------------------------------------------------------51 52; The 'acquire' and 'acq_rel' orderings aren’t valid on store instructions.53 54; CHECK-LABEL: store_i32_unordered:55; CHECK-NEXT: .functype store_i32_unordered (i32, i32) -> (){{$}}56; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}57; CHECK-NEXT: return{{$}}58define void @store_i32_unordered(ptr %p, i32 %v) {59 store atomic i32 %v, ptr %p unordered, align 460 ret void61}62 63; CHECK-LABEL: store_i32_monotonic:64; CHECK-NEXT: .functype store_i32_monotonic (i32, i32) -> (){{$}}65; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}66; CHECK-NEXT: return{{$}}67define void @store_i32_monotonic(ptr %p, i32 %v) {68 store atomic i32 %v, ptr %p monotonic, align 469 ret void70}71 72; CHECK-LABEL: store_i32_release:73; CHECK-NEXT: .functype store_i32_release (i32, i32) -> (){{$}}74; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}75; CHECK-NEXT: return{{$}}76define void @store_i32_release(ptr %p, i32 %v) {77 store atomic i32 %v, ptr %p release, align 478 ret void79}80 81; CHECK-LABEL: store_i32_seq_cst:82; CHECK-NEXT: .functype store_i32_seq_cst (i32, i32) -> (){{$}}83; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}}84; CHECK-NEXT: return{{$}}85define void @store_i32_seq_cst(ptr %p, i32 %v) {86 store atomic i32 %v, ptr %p seq_cst, align 487 ret void88}89 90;===----------------------------------------------------------------------------91; Atomic read-modify-writes92;===----------------------------------------------------------------------------93 94; Out of several binary RMW instructions, here we test 'add' as an example.95; The 'unordered' ordering is not valid on atomicrmw instructions.96 97; CHECK-LABEL: add_i32_monotonic:98; CHECK-NEXT: .functype add_i32_monotonic (i32, i32) -> (i32){{$}}99; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}100; CHECK-NEXT: return $pop0{{$}}101define i32 @add_i32_monotonic(ptr %p, i32 %v) {102 %old = atomicrmw add ptr %p, i32 %v monotonic103 ret i32 %old104}105 106; CHECK-LABEL: add_i32_acquire:107; CHECK-NEXT: .functype add_i32_acquire (i32, i32) -> (i32){{$}}108; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}109; CHECK-NEXT: return $pop0{{$}}110define i32 @add_i32_acquire(ptr %p, i32 %v) {111 %old = atomicrmw add ptr %p, i32 %v acquire112 ret i32 %old113}114 115; CHECK-LABEL: add_i32_release:116; CHECK-NEXT: .functype add_i32_release (i32, i32) -> (i32){{$}}117; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}118; CHECK-NEXT: return $pop0{{$}}119define i32 @add_i32_release(ptr %p, i32 %v) {120 %old = atomicrmw add ptr %p, i32 %v release121 ret i32 %old122}123 124; CHECK-LABEL: add_i32_acq_rel:125; CHECK-NEXT: .functype add_i32_acq_rel (i32, i32) -> (i32){{$}}126; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}127; CHECK-NEXT: return $pop0{{$}}128define i32 @add_i32_acq_rel(ptr %p, i32 %v) {129 %old = atomicrmw add ptr %p, i32 %v acq_rel130 ret i32 %old131}132 133; CHECK-LABEL: add_i32_seq_cst:134; CHECK-NEXT: .functype add_i32_seq_cst (i32, i32) -> (i32){{$}}135; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}}136; CHECK-NEXT: return $pop0{{$}}137define i32 @add_i32_seq_cst(ptr %p, i32 %v) {138 %old = atomicrmw add ptr %p, i32 %v seq_cst139 ret i32 %old140}141 142; Ternary RMW instruction: cmpxchg143; The success and failure ordering arguments specify how this cmpxchg144; synchronizes with other atomic operations. Both ordering parameters must be at145; least monotonic, the ordering constraint on failure must be no stronger than146; that on success, and the failure ordering cannot be either release or acq_rel.147 148; CHECK-LABEL: cmpxchg_i32_monotonic_monotonic:149; CHECK-NEXT: .functype cmpxchg_i32_monotonic_monotonic (i32, i32, i32) -> (i32){{$}}150; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}151; CHECK-NEXT: return $pop0{{$}}152define i32 @cmpxchg_i32_monotonic_monotonic(ptr %p, i32 %exp, i32 %new) {153 %pair = cmpxchg ptr %p, i32 %exp, i32 %new monotonic monotonic154 %old = extractvalue { i32, i1 } %pair, 0155 ret i32 %old156}157 158; CHECK-LABEL: cmpxchg_i32_acquire_monotonic:159; CHECK-NEXT: .functype cmpxchg_i32_acquire_monotonic (i32, i32, i32) -> (i32){{$}}160; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}161; CHECK-NEXT: return $pop0{{$}}162define i32 @cmpxchg_i32_acquire_monotonic(ptr %p, i32 %exp, i32 %new) {163 %pair = cmpxchg ptr %p, i32 %exp, i32 %new acquire monotonic164 %old = extractvalue { i32, i1 } %pair, 0165 ret i32 %old166}167 168; CHECK-LABEL: cmpxchg_i32_release_monotonic:169; CHECK-NEXT: .functype cmpxchg_i32_release_monotonic (i32, i32, i32) -> (i32){{$}}170; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}171; CHECK-NEXT: return $pop0{{$}}172define i32 @cmpxchg_i32_release_monotonic(ptr %p, i32 %exp, i32 %new) {173 %pair = cmpxchg ptr %p, i32 %exp, i32 %new release monotonic174 %old = extractvalue { i32, i1 } %pair, 0175 ret i32 %old176}177 178; CHECK-LABEL: cmpxchg_i32_acq_rel_monotonic:179; CHECK-NEXT: .functype cmpxchg_i32_acq_rel_monotonic (i32, i32, i32) -> (i32){{$}}180; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}181; CHECK-NEXT: return $pop0{{$}}182define i32 @cmpxchg_i32_acq_rel_monotonic(ptr %p, i32 %exp, i32 %new) {183 %pair = cmpxchg ptr %p, i32 %exp, i32 %new acq_rel monotonic184 %old = extractvalue { i32, i1 } %pair, 0185 ret i32 %old186}187 188; CHECK-LABEL: cmpxchg_i32_seq_cst_monotonic:189; CHECK-NEXT: .functype cmpxchg_i32_seq_cst_monotonic (i32, i32, i32) -> (i32){{$}}190; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}191; CHECK-NEXT: return $pop0{{$}}192define i32 @cmpxchg_i32_seq_cst_monotonic(ptr %p, i32 %exp, i32 %new) {193 %pair = cmpxchg ptr %p, i32 %exp, i32 %new seq_cst monotonic194 %old = extractvalue { i32, i1 } %pair, 0195 ret i32 %old196}197 198; CHECK-LABEL: cmpxchg_i32_acquire_acquire:199; CHECK-NEXT: .functype cmpxchg_i32_acquire_acquire (i32, i32, i32) -> (i32){{$}}200; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}201; CHECK-NEXT: return $pop0{{$}}202define i32 @cmpxchg_i32_acquire_acquire(ptr %p, i32 %exp, i32 %new) {203 %pair = cmpxchg ptr %p, i32 %exp, i32 %new acquire acquire204 %old = extractvalue { i32, i1 } %pair, 0205 ret i32 %old206}207 208; CHECK-LABEL: cmpxchg_i32_release_acquire:209; CHECK-NEXT: .functype cmpxchg_i32_release_acquire (i32, i32, i32) -> (i32){{$}}210; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}211; CHECK-NEXT: return $pop0{{$}}212define i32 @cmpxchg_i32_release_acquire(ptr %p, i32 %exp, i32 %new) {213 %pair = cmpxchg ptr %p, i32 %exp, i32 %new release acquire214 %old = extractvalue { i32, i1 } %pair, 0215 ret i32 %old216}217 218; CHECK-LABEL: cmpxchg_i32_acq_rel_acquire:219; CHECK-NEXT: .functype cmpxchg_i32_acq_rel_acquire (i32, i32, i32) -> (i32){{$}}220; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}221; CHECK-NEXT: return $pop0{{$}}222define i32 @cmpxchg_i32_acq_rel_acquire(ptr %p, i32 %exp, i32 %new) {223 %pair = cmpxchg ptr %p, i32 %exp, i32 %new acq_rel acquire224 %old = extractvalue { i32, i1 } %pair, 0225 ret i32 %old226}227 228; CHECK-LABEL: cmpxchg_i32_seq_cst_acquire:229; CHECK-NEXT: .functype cmpxchg_i32_seq_cst_acquire (i32, i32, i32) -> (i32){{$}}230; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}231; CHECK-NEXT: return $pop0{{$}}232define i32 @cmpxchg_i32_seq_cst_acquire(ptr %p, i32 %exp, i32 %new) {233 %pair = cmpxchg ptr %p, i32 %exp, i32 %new seq_cst acquire234 %old = extractvalue { i32, i1 } %pair, 0235 ret i32 %old236}237 238; CHECK-LABEL: cmpxchg_i32_seq_cst_seq_cst:239; CHECK-NEXT: .functype cmpxchg_i32_seq_cst_seq_cst (i32, i32, i32) -> (i32){{$}}240; CHECK: i32.atomic.rmw.cmpxchg $push0=, 0($0), $1, $2{{$}}241; CHECK-NEXT: return $pop0{{$}}242define i32 @cmpxchg_i32_seq_cst_seq_cst(ptr %p, i32 %exp, i32 %new) {243 %pair = cmpxchg ptr %p, i32 %exp, i32 %new seq_cst seq_cst244 %old = extractvalue { i32, i1 } %pair, 0245 ret i32 %old246}247