1; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals | FileCheck %s 2 3; Test loads and stores with custom alignment values. 4 5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" 6target triple = "wasm32-unknown-unknown" 7 8;===---------------------------------------------------------------------------- 9; Loads 10;===---------------------------------------------------------------------------- 11 12; CHECK-LABEL: ldi32_a1: 13; CHECK-NEXT: .param i32{{$}} 14; CHECK-NEXT: .result i32{{$}} 15; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}} 16; CHECK-NEXT: return $pop[[NUM]]{{$}} 17define i32 @ldi32_a1(i32 *%p) { 18 %v = load i32, i32* %p, align 1 19 ret i32 %v 20} 21 22; CHECK-LABEL: ldi32_a2: 23; CHECK-NEXT: .param i32{{$}} 24; CHECK-NEXT: .result i32{{$}} 25; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}} 26; CHECK-NEXT: return $pop[[NUM]]{{$}} 27define i32 @ldi32_a2(i32 *%p) { 28 %v = load i32, i32* %p, align 2 29 ret i32 %v 30} 31 32; 4 is the default alignment for i32 so no attribute is needed. 33 34; CHECK-LABEL: ldi32_a4: 35; CHECK-NEXT: .param i32{{$}} 36; CHECK-NEXT: .result i32{{$}} 37; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 38; CHECK-NEXT: return $pop[[NUM]]{{$}} 39define i32 @ldi32_a4(i32 *%p) { 40 %v = load i32, i32* %p, align 4 41 ret i32 %v 42} 43 44; The default alignment in LLVM is the same as the defualt alignment in wasm. 45 46; CHECK-LABEL: ldi32: 47; CHECK-NEXT: .param i32{{$}} 48; CHECK-NEXT: .result i32{{$}} 49; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 50; CHECK-NEXT: return $pop[[NUM]]{{$}} 51define i32 @ldi32(i32 *%p) { 52 %v = load i32, i32* %p 53 ret i32 %v 54} 55 56; 8 is greater than the default alignment so it is ignored. 57 58; CHECK-LABEL: ldi32_a8: 59; CHECK-NEXT: .param i32{{$}} 60; CHECK-NEXT: .result i32{{$}} 61; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 62; CHECK-NEXT: return $pop[[NUM]]{{$}} 63define i32 @ldi32_a8(i32 *%p) { 64 %v = load i32, i32* %p, align 8 65 ret i32 %v 66} 67 68;===---------------------------------------------------------------------------- 69; Extending loads 70;===---------------------------------------------------------------------------- 71 72; CHECK-LABEL: ldi8_a1: 73; CHECK-NEXT: .param i32{{$}} 74; CHECK-NEXT: .result i32{{$}} 75; CHECK-NEXT: i32.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 76; CHECK-NEXT: return $pop[[NUM]]{{$}} 77define i8 @ldi8_a1(i8 *%p) { 78 %v = load i8, i8* %p, align 1 79 ret i8 %v 80} 81 82; CHECK-LABEL: ldi8_a2: 83; CHECK-NEXT: .param i32{{$}} 84; CHECK-NEXT: .result i32{{$}} 85; CHECK-NEXT: i32.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 86; CHECK-NEXT: return $pop[[NUM]]{{$}} 87define i8 @ldi8_a2(i8 *%p) { 88 %v = load i8, i8* %p, align 2 89 ret i8 %v 90} 91 92; CHECK-LABEL: ldi16_a1: 93; CHECK-NEXT: .param i32{{$}} 94; CHECK-NEXT: .result i32{{$}} 95; CHECK-NEXT: i32.load16_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}} 96; CHECK-NEXT: return $pop[[NUM]]{{$}} 97define i16 @ldi16_a1(i16 *%p) { 98 %v = load i16, i16* %p, align 1 99 ret i16 %v 100} 101 102; CHECK-LABEL: ldi16_a2: 103; CHECK-NEXT: .param i32{{$}} 104; CHECK-NEXT: .result i32{{$}} 105; CHECK-NEXT: i32.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 106; CHECK-NEXT: return $pop[[NUM]]{{$}} 107define i16 @ldi16_a2(i16 *%p) { 108 %v = load i16, i16* %p, align 2 109 ret i16 %v 110} 111 112; CHECK-LABEL: ldi16_a4: 113; CHECK-NEXT: .param i32{{$}} 114; CHECK-NEXT: .result i32{{$}} 115; CHECK-NEXT: i32.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 116; CHECK-NEXT: return $pop[[NUM]]{{$}} 117define i16 @ldi16_a4(i16 *%p) { 118 %v = load i16, i16* %p, align 4 119 ret i16 %v 120} 121 122;===---------------------------------------------------------------------------- 123; Stores 124;===---------------------------------------------------------------------------- 125 126; CHECK-LABEL: sti32_a1: 127; CHECK-NEXT: .param i32, i32{{$}} 128; CHECK-NEXT: i32.store 0($0):p2align=0, $1{{$}} 129; CHECK-NEXT: return{{$}} 130define void @sti32_a1(i32 *%p, i32 %v) { 131 store i32 %v, i32* %p, align 1 132 ret void 133} 134 135; CHECK-LABEL: sti32_a2: 136; CHECK-NEXT: .param i32, i32{{$}} 137; CHECK-NEXT: i32.store 0($0):p2align=1, $1{{$}} 138; CHECK-NEXT: return{{$}} 139define void @sti32_a2(i32 *%p, i32 %v) { 140 store i32 %v, i32* %p, align 2 141 ret void 142} 143 144; 4 is the default alignment for i32 so no attribute is needed. 145 146; CHECK-LABEL: sti32_a4: 147; CHECK-NEXT: .param i32, i32{{$}} 148; CHECK-NEXT: i32.store 0($0), $1{{$}} 149; CHECK-NEXT: return{{$}} 150define void @sti32_a4(i32 *%p, i32 %v) { 151 store i32 %v, i32* %p, align 4 152 ret void 153} 154 155; The default alignment in LLVM is the same as the defualt alignment in wasm. 156 157; CHECK-LABEL: sti32: 158; CHECK-NEXT: .param i32, i32{{$}} 159; CHECK-NEXT: i32.store 0($0), $1{{$}} 160; CHECK-NEXT: return{{$}} 161define void @sti32(i32 *%p, i32 %v) { 162 store i32 %v, i32* %p 163 ret void 164} 165 166; CHECK-LABEL: sti32_a8: 167; CHECK-NEXT: .param i32, i32{{$}} 168; CHECK-NEXT: i32.store 0($0), $1{{$}} 169; CHECK-NEXT: return{{$}} 170define void @sti32_a8(i32 *%p, i32 %v) { 171 store i32 %v, i32* %p, align 8 172 ret void 173} 174 175;===---------------------------------------------------------------------------- 176; Truncating stores 177;===---------------------------------------------------------------------------- 178 179; CHECK-LABEL: sti8_a1: 180; CHECK-NEXT: .param i32, i32{{$}} 181; CHECK-NEXT: i32.store8 0($0), $1{{$}} 182; CHECK-NEXT: return{{$}} 183define void @sti8_a1(i8 *%p, i8 %v) { 184 store i8 %v, i8* %p, align 1 185 ret void 186} 187 188; CHECK-LABEL: sti8_a2: 189; CHECK-NEXT: .param i32, i32{{$}} 190; CHECK-NEXT: i32.store8 0($0), $1{{$}} 191; CHECK-NEXT: return{{$}} 192define void @sti8_a2(i8 *%p, i8 %v) { 193 store i8 %v, i8* %p, align 2 194 ret void 195} 196 197; CHECK-LABEL: sti16_a1: 198; CHECK-NEXT: .param i32, i32{{$}} 199; CHECK-NEXT: i32.store16 0($0):p2align=0, $1{{$}} 200; CHECK-NEXT: return{{$}} 201define void @sti16_a1(i16 *%p, i16 %v) { 202 store i16 %v, i16* %p, align 1 203 ret void 204} 205 206; CHECK-LABEL: sti16_a2: 207; CHECK-NEXT: .param i32, i32{{$}} 208; CHECK-NEXT: i32.store16 0($0), $1{{$}} 209; CHECK-NEXT: return{{$}} 210define void @sti16_a2(i16 *%p, i16 %v) { 211 store i16 %v, i16* %p, align 2 212 ret void 213} 214 215; CHECK-LABEL: sti16_a4: 216; CHECK-NEXT: .param i32, i32{{$}} 217; CHECK-NEXT: i32.store16 0($0), $1{{$}} 218; CHECK-NEXT: return{{$}} 219define void @sti16_a4(i16 *%p, i16 %v) { 220 store i16 %v, i16* %p, align 4 221 ret void 222} 223 224;===---------------------------------------------------------------------------- 225; Atomic loads 226;===---------------------------------------------------------------------------- 227 228; Wasm atomics have the alignment field, but it must always have the type's 229; natural alignment. 230 231; CHECK-LABEL: ldi32_atomic_a4: 232; CHECK-NEXT: .param i32{{$}} 233; CHECK-NEXT: .result i32{{$}} 234; CHECK-NEXT: i32.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 235; CHECK-NEXT: return $pop[[NUM]]{{$}} 236define i32 @ldi32_atomic_a4(i32 *%p) { 237 %v = load atomic i32, i32* %p seq_cst, align 4 238 ret i32 %v 239} 240 241; 8 is greater than the default alignment so it is ignored. 242 243; CHECK-LABEL: ldi32_atomic_a8: 244; CHECK-NEXT: .param i32{{$}} 245; CHECK-NEXT: .result i32{{$}} 246; CHECK-NEXT: i32.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 247; CHECK-NEXT: return $pop[[NUM]]{{$}} 248define i32 @ldi32_atomic_a8(i32 *%p) { 249 %v = load atomic i32, i32* %p seq_cst, align 8 250 ret i32 %v 251} 252 253;===---------------------------------------------------------------------------- 254; Atomic stores 255;===---------------------------------------------------------------------------- 256 257; CHECK-LABEL: sti32_atomic_a4: 258; CHECK-NEXT: .param i32, i32{{$}} 259; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}} 260; CHECK-NEXT: return{{$}} 261define void @sti32_atomic_a4(i32 *%p, i32 %v) { 262 store atomic i32 %v, i32* %p seq_cst, align 4 263 ret void 264} 265 266; 8 is greater than the default alignment so it is ignored. 267 268; CHECK-LABEL: sti32_atomic_a8: 269; CHECK-NEXT: .param i32, i32{{$}} 270; CHECK-NEXT: i32.atomic.store 0($0), $1{{$}} 271; CHECK-NEXT: return{{$}} 272define void @sti32_atomic_a8(i32 *%p, i32 %v) { 273 store atomic i32 %v, i32* %p seq_cst, align 8 274 ret void 275} 276