1; RUN: not llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt 2; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -mattr=+atomics,+sign-ext | FileCheck %s 3 4; Currently all wasm atomic memory access instructions are sequentially 5; consistent, so even if LLVM IR specifies weaker orderings than that, we 6; should upgrade them to sequential ordering and treat them in the same way. 7 8target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 9target triple = "wasm32-unknown-unknown" 10 11;===---------------------------------------------------------------------------- 12; Atomic loads 13;===---------------------------------------------------------------------------- 14 15; The 'release' and 'acq_rel' orderings are not valid on load instructions. 16 17; CHECK-LABEL: load_i32_unordered: 18; CHECK: i32.atomic.load $push0=, 0($0){{$}} 19; CHECK-NEXT: return $pop0{{$}} 20define i32 @load_i32_unordered(i32 *%p) { 21 %v = load atomic i32, i32* %p unordered, align 4 22 ret i32 %v 23} 24 25; CHECK-LABEL: load_i32_monotonic: 26; CHECK: i32.atomic.load $push0=, 0($0){{$}} 27; CHECK-NEXT: return $pop0{{$}} 28define i32 @load_i32_monotonic(i32 *%p) { 29 %v = load atomic i32, i32* %p monotonic, align 4 30 ret i32 %v 31} 32 33; CHECK-LABEL: load_i32_acquire: 34; CHECK: i32.atomic.load $push0=, 0($0){{$}} 35; CHECK-NEXT: return $pop0{{$}} 36define i32 @load_i32_acquire(i32 *%p) { 37 %v = load atomic i32, i32* %p acquire, align 4 38 ret i32 %v 39} 40 41; CHECK-LABEL: load_i32_seq_cst: 42; CHECK: i32.atomic.load $push0=, 0($0){{$}} 43; CHECK-NEXT: return $pop0{{$}} 44define i32 @load_i32_seq_cst(i32 *%p) { 45 %v = load atomic i32, i32* %p seq_cst, align 4 46 ret i32 %v 47} 48 49;===---------------------------------------------------------------------------- 50; Atomic stores 51;===---------------------------------------------------------------------------- 52 53; The 'acquire' and 'acq_rel' orderings aren’t valid on store instructions. 54 55; CHECK-LABEL: store_i32_unordered: 56; CHECK-NEXT: .param i32, i32{{$}} 57; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}} 58; CHECK-NEXT: return{{$}} 59define void @store_i32_unordered(i32 *%p, i32 %v) { 60 store atomic i32 %v, i32* %p unordered, align 4 61 ret void 62} 63 64; CHECK-LABEL: store_i32_monotonic: 65; CHECK-NEXT: .param i32, i32{{$}} 66; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}} 67; CHECK-NEXT: return{{$}} 68define void @store_i32_monotonic(i32 *%p, i32 %v) { 69 store atomic i32 %v, i32* %p monotonic, align 4 70 ret void 71} 72 73; CHECK-LABEL: store_i32_release: 74; CHECK-NEXT: .param i32, i32{{$}} 75; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}} 76; CHECK-NEXT: return{{$}} 77define void @store_i32_release(i32 *%p, i32 %v) { 78 store atomic i32 %v, i32* %p release, align 4 79 ret void 80} 81 82; CHECK-LABEL: store_i32_seq_cst: 83; CHECK-NEXT: .param i32, i32{{$}} 84; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}} 85; CHECK-NEXT: return{{$}} 86define void @store_i32_seq_cst(i32 *%p, i32 %v) { 87 store atomic i32 %v, i32* %p seq_cst, align 4 88 ret void 89} 90 91;===---------------------------------------------------------------------------- 92; Atomic read-modify-writes 93;===---------------------------------------------------------------------------- 94 95; Out of several binary RMW instructions, here we test 'add' as an example. 96; The 'unordered' ordering is not valid on atomicrmw instructions. 97 98; CHECK-LABEL: add_i32_monotonic: 99; CHECK-NEXT: .param i32, i32{{$}} 100; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}} 101; CHECK-NEXT: return $pop0{{$}} 102define i32 @add_i32_monotonic(i32* %p, i32 %v) { 103 %old = atomicrmw add i32* %p, i32 %v monotonic 104 ret i32 %old 105} 106 107; CHECK-LABEL: add_i32_acquire: 108; CHECK-NEXT: .param i32, i32{{$}} 109; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}} 110; CHECK-NEXT: return $pop0{{$}} 111define i32 @add_i32_acquire(i32* %p, i32 %v) { 112 %old = atomicrmw add i32* %p, i32 %v acquire 113 ret i32 %old 114} 115 116; CHECK-LABEL: add_i32_release: 117; CHECK-NEXT: .param i32, i32{{$}} 118; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}} 119; CHECK-NEXT: return $pop0{{$}} 120define i32 @add_i32_release(i32* %p, i32 %v) { 121 %old = atomicrmw add i32* %p, i32 %v release 122 ret i32 %old 123} 124 125; CHECK-LABEL: add_i32_acq_rel: 126; CHECK-NEXT: .param i32, i32{{$}} 127; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}} 128; CHECK-NEXT: return $pop0{{$}} 129define i32 @add_i32_acq_rel(i32* %p, i32 %v) { 130 %old = atomicrmw add i32* %p, i32 %v acq_rel 131 ret i32 %old 132} 133 134; CHECK-LABEL: add_i32_seq_cst: 135; CHECK-NEXT: .param i32, i32{{$}} 136; CHECK: i32.atomic.rmw.add $push0=, 0($0), $1{{$}} 137; CHECK-NEXT: return $pop0{{$}} 138define i32 @add_i32_seq_cst(i32* %p, i32 %v) { 139 %old = atomicrmw add i32* %p, i32 %v seq_cst 140 ret i32 %old 141} 142