1; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt | 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; CHECK-LABEL: ldi64_a1: 9; CHECK-NEXT: .param i32{{$}} 10; CHECK-NEXT: .result i64{{$}} 11; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}} 12; CHECK-NEXT: return $pop[[NUM]]{{$}} 13define i64 @ldi64_a1(i64 *%p) { 14 %v = load i64, i64* %p, align 1 15 ret i64 %v 16} 17 18; CHECK-LABEL: ldi64_a2: 19; CHECK-NEXT: .param i32{{$}} 20; CHECK-NEXT: .result i64{{$}} 21; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}} 22; CHECK-NEXT: return $pop[[NUM]]{{$}} 23define i64 @ldi64_a2(i64 *%p) { 24 %v = load i64, i64* %p, align 2 25 ret i64 %v 26} 27 28; CHECK-LABEL: ldi64_a4: 29; CHECK-NEXT: .param i32{{$}} 30; CHECK-NEXT: .result i64{{$}} 31; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=2{{$}} 32; CHECK-NEXT: return $pop[[NUM]]{{$}} 33define i64 @ldi64_a4(i64 *%p) { 34 %v = load i64, i64* %p, align 4 35 ret i64 %v 36} 37 38; 8 is the default alignment for i64 so no attribute is needed. 39 40; CHECK-LABEL: ldi64_a8: 41; CHECK-NEXT: .param i32{{$}} 42; CHECK-NEXT: .result i64{{$}} 43; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 44; CHECK-NEXT: return $pop[[NUM]]{{$}} 45define i64 @ldi64_a8(i64 *%p) { 46 %v = load i64, i64* %p, align 8 47 ret i64 %v 48} 49 50; The default alignment in LLVM is the same as the defualt alignment in wasm. 51 52; CHECK-LABEL: ldi64: 53; CHECK-NEXT: .param i32{{$}} 54; CHECK-NEXT: .result i64{{$}} 55; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 56; CHECK-NEXT: return $pop[[NUM]]{{$}} 57define i64 @ldi64(i64 *%p) { 58 %v = load i64, i64* %p 59 ret i64 %v 60} 61 62; 16 is greater than the default alignment so it is ignored. 63 64; CHECK-LABEL: ldi64_a16: 65; CHECK-NEXT: .param i32{{$}} 66; CHECK-NEXT: .result i64{{$}} 67; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 68; CHECK-NEXT: return $pop[[NUM]]{{$}} 69define i64 @ldi64_a16(i64 *%p) { 70 %v = load i64, i64* %p, align 16 71 ret i64 %v 72} 73 74; Extending loads. 75 76; CHECK-LABEL: ldi8_a1: 77; CHECK-NEXT: .param i32{{$}} 78; CHECK-NEXT: .result i64{{$}} 79; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 80; CHECK-NEXT: return $pop[[NUM]]{{$}} 81define i64 @ldi8_a1(i8 *%p) { 82 %v = load i8, i8* %p, align 1 83 %w = zext i8 %v to i64 84 ret i64 %w 85} 86 87; CHECK-LABEL: ldi8_a2: 88; CHECK-NEXT: .param i32{{$}} 89; CHECK-NEXT: .result i64{{$}} 90; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 91; CHECK-NEXT: return $pop[[NUM]]{{$}} 92define i64 @ldi8_a2(i8 *%p) { 93 %v = load i8, i8* %p, align 2 94 %w = zext i8 %v to i64 95 ret i64 %w 96} 97 98; CHECK-LABEL: ldi16_a1: 99; CHECK-NEXT: .param i32{{$}} 100; CHECK-NEXT: .result i64{{$}} 101; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}} 102; CHECK-NEXT: return $pop[[NUM]]{{$}} 103define i64 @ldi16_a1(i16 *%p) { 104 %v = load i16, i16* %p, align 1 105 %w = zext i16 %v to i64 106 ret i64 %w 107} 108 109; CHECK-LABEL: ldi16_a2: 110; CHECK-NEXT: .param i32{{$}} 111; CHECK-NEXT: .result i64{{$}} 112; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 113; CHECK-NEXT: return $pop[[NUM]]{{$}} 114define i64 @ldi16_a2(i16 *%p) { 115 %v = load i16, i16* %p, align 2 116 %w = zext i16 %v to i64 117 ret i64 %w 118} 119 120; CHECK-LABEL: ldi16_a4: 121; CHECK-NEXT: .param i32{{$}} 122; CHECK-NEXT: .result i64{{$}} 123; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 124; CHECK-NEXT: return $pop[[NUM]]{{$}} 125define i64 @ldi16_a4(i16 *%p) { 126 %v = load i16, i16* %p, align 4 127 %w = zext i16 %v to i64 128 ret i64 %w 129} 130 131; CHECK-LABEL: ldi32_a1: 132; CHECK-NEXT: .param i32{{$}} 133; CHECK-NEXT: .result i64{{$}} 134; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}} 135; CHECK-NEXT: return $pop[[NUM]]{{$}} 136define i64 @ldi32_a1(i32 *%p) { 137 %v = load i32, i32* %p, align 1 138 %w = zext i32 %v to i64 139 ret i64 %w 140} 141 142; CHECK-LABEL: ldi32_a2: 143; CHECK-NEXT: .param i32{{$}} 144; CHECK-NEXT: .result i64{{$}} 145; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}} 146; CHECK-NEXT: return $pop[[NUM]]{{$}} 147define i64 @ldi32_a2(i32 *%p) { 148 %v = load i32, i32* %p, align 2 149 %w = zext i32 %v to i64 150 ret i64 %w 151} 152 153; CHECK-LABEL: ldi32_a4: 154; CHECK-NEXT: .param i32{{$}} 155; CHECK-NEXT: .result i64{{$}} 156; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 157; CHECK-NEXT: return $pop[[NUM]]{{$}} 158define i64 @ldi32_a4(i32 *%p) { 159 %v = load i32, i32* %p, align 4 160 %w = zext i32 %v to i64 161 ret i64 %w 162} 163 164; CHECK-LABEL: ldi32_a8: 165; CHECK-NEXT: .param i32{{$}} 166; CHECK-NEXT: .result i64{{$}} 167; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 168; CHECK-NEXT: return $pop[[NUM]]{{$}} 169define i64 @ldi32_a8(i32 *%p) { 170 %v = load i32, i32* %p, align 8 171 %w = zext i32 %v to i64 172 ret i64 %w 173} 174 175; Stores. 176 177; CHECK-LABEL: sti64_a1: 178; CHECK-NEXT: .param i32, i64{{$}} 179; CHECK-NEXT: i64.store $drop=, 0($0):p2align=0, $1{{$}} 180; CHECK-NEXT: return{{$}} 181define void @sti64_a1(i64 *%p, i64 %v) { 182 store i64 %v, i64* %p, align 1 183 ret void 184} 185 186; CHECK-LABEL: sti64_a2: 187; CHECK-NEXT: .param i32, i64{{$}} 188; CHECK-NEXT: i64.store $drop=, 0($0):p2align=1, $1{{$}} 189; CHECK-NEXT: return{{$}} 190define void @sti64_a2(i64 *%p, i64 %v) { 191 store i64 %v, i64* %p, align 2 192 ret void 193} 194 195; CHECK-LABEL: sti64_a4: 196; CHECK-NEXT: .param i32, i64{{$}} 197; CHECK-NEXT: i64.store $drop=, 0($0):p2align=2, $1{{$}} 198; CHECK-NEXT: return{{$}} 199define void @sti64_a4(i64 *%p, i64 %v) { 200 store i64 %v, i64* %p, align 4 201 ret void 202} 203 204; 8 is the default alignment for i32 so no attribute is needed. 205 206; CHECK-LABEL: sti64_a8: 207; CHECK-NEXT: .param i32, i64{{$}} 208; CHECK-NEXT: i64.store $drop=, 0($0), $1{{$}} 209; CHECK-NEXT: return{{$}} 210define void @sti64_a8(i64 *%p, i64 %v) { 211 store i64 %v, i64* %p, align 8 212 ret void 213} 214 215; The default alignment in LLVM is the same as the defualt alignment in wasm. 216 217; CHECK-LABEL: sti64: 218; CHECK-NEXT: .param i32, i64{{$}} 219; CHECK-NEXT: i64.store $drop=, 0($0), $1{{$}} 220; CHECK-NEXT: return{{$}} 221define void @sti64(i64 *%p, i64 %v) { 222 store i64 %v, i64* %p 223 ret void 224} 225 226; CHECK-LABEL: sti64_a16: 227; CHECK-NEXT: .param i32, i64{{$}} 228; CHECK-NEXT: i64.store $drop=, 0($0), $1{{$}} 229; CHECK-NEXT: return{{$}} 230define void @sti64_a16(i64 *%p, i64 %v) { 231 store i64 %v, i64* %p, align 16 232 ret void 233} 234 235; Truncating stores. 236 237; CHECK-LABEL: sti8_a1: 238; CHECK-NEXT: .param i32, i64{{$}} 239; CHECK-NEXT: i64.store8 $drop=, 0($0), $1{{$}} 240; CHECK-NEXT: return{{$}} 241define void @sti8_a1(i8 *%p, i64 %w) { 242 %v = trunc i64 %w to i8 243 store i8 %v, i8* %p, align 1 244 ret void 245} 246 247; CHECK-LABEL: sti8_a2: 248; CHECK-NEXT: .param i32, i64{{$}} 249; CHECK-NEXT: i64.store8 $drop=, 0($0), $1{{$}} 250; CHECK-NEXT: return{{$}} 251define void @sti8_a2(i8 *%p, i64 %w) { 252 %v = trunc i64 %w to i8 253 store i8 %v, i8* %p, align 2 254 ret void 255} 256 257; CHECK-LABEL: sti16_a1: 258; CHECK-NEXT: .param i32, i64{{$}} 259; CHECK-NEXT: i64.store16 $drop=, 0($0):p2align=0, $1{{$}} 260; CHECK-NEXT: return{{$}} 261define void @sti16_a1(i16 *%p, i64 %w) { 262 %v = trunc i64 %w to i16 263 store i16 %v, i16* %p, align 1 264 ret void 265} 266 267; CHECK-LABEL: sti16_a2: 268; CHECK-NEXT: .param i32, i64{{$}} 269; CHECK-NEXT: i64.store16 $drop=, 0($0), $1{{$}} 270; CHECK-NEXT: return{{$}} 271define void @sti16_a2(i16 *%p, i64 %w) { 272 %v = trunc i64 %w to i16 273 store i16 %v, i16* %p, align 2 274 ret void 275} 276 277; CHECK-LABEL: sti16_a4: 278; CHECK-NEXT: .param i32, i64{{$}} 279; CHECK-NEXT: i64.store16 $drop=, 0($0), $1{{$}} 280; CHECK-NEXT: return{{$}} 281define void @sti16_a4(i16 *%p, i64 %w) { 282 %v = trunc i64 %w to i16 283 store i16 %v, i16* %p, align 4 284 ret void 285} 286 287; CHECK-LABEL: sti32_a1: 288; CHECK-NEXT: .param i32, i64{{$}} 289; CHECK-NEXT: i64.store32 $drop=, 0($0):p2align=0, $1{{$}} 290; CHECK-NEXT: return{{$}} 291define void @sti32_a1(i32 *%p, i64 %w) { 292 %v = trunc i64 %w to i32 293 store i32 %v, i32* %p, align 1 294 ret void 295} 296 297; CHECK-LABEL: sti32_a2: 298; CHECK-NEXT: .param i32, i64{{$}} 299; CHECK-NEXT: i64.store32 $drop=, 0($0):p2align=1, $1{{$}} 300; CHECK-NEXT: return{{$}} 301define void @sti32_a2(i32 *%p, i64 %w) { 302 %v = trunc i64 %w to i32 303 store i32 %v, i32* %p, align 2 304 ret void 305} 306 307; CHECK-LABEL: sti32_a4: 308; CHECK-NEXT: .param i32, i64{{$}} 309; CHECK-NEXT: i64.store32 $drop=, 0($0), $1{{$}} 310; CHECK-NEXT: return{{$}} 311define void @sti32_a4(i32 *%p, i64 %w) { 312 %v = trunc i64 %w to i32 313 store i32 %v, i32* %p, align 4 314 ret void 315} 316 317; CHECK-LABEL: sti32_a8: 318; CHECK-NEXT: .param i32, i64{{$}} 319; CHECK-NEXT: i64.store32 $drop=, 0($0), $1{{$}} 320; CHECK-NEXT: return{{$}} 321define void @sti32_a8(i32 *%p, i64 %w) { 322 %v = trunc i64 %w to i32 323 store i32 %v, i32* %p, align 8 324 ret void 325} 326