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: ldi32_a1: 9; CHECK-NEXT: .param i32{{$}} 10; CHECK-NEXT: .result i32{{$}} 11; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}} 12; CHECK-NEXT: return $pop[[NUM]]{{$}} 13define i32 @ldi32_a1(i32 *%p) { 14 %v = load i32, i32* %p, align 1 15 ret i32 %v 16} 17 18; CHECK-LABEL: ldi32_a2: 19; CHECK-NEXT: .param i32{{$}} 20; CHECK-NEXT: .result i32{{$}} 21; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}} 22; CHECK-NEXT: return $pop[[NUM]]{{$}} 23define i32 @ldi32_a2(i32 *%p) { 24 %v = load i32, i32* %p, align 2 25 ret i32 %v 26} 27 28; 4 is the default alignment for i32 so no attribute is needed. 29 30; CHECK-LABEL: ldi32_a4: 31; CHECK-NEXT: .param i32{{$}} 32; CHECK-NEXT: .result i32{{$}} 33; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 34; CHECK-NEXT: return $pop[[NUM]]{{$}} 35define i32 @ldi32_a4(i32 *%p) { 36 %v = load i32, i32* %p, align 4 37 ret i32 %v 38} 39 40; The default alignment in LLVM is the same as the defualt alignment in wasm. 41 42; CHECK-LABEL: ldi32: 43; CHECK-NEXT: .param i32{{$}} 44; CHECK-NEXT: .result i32{{$}} 45; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 46; CHECK-NEXT: return $pop[[NUM]]{{$}} 47define i32 @ldi32(i32 *%p) { 48 %v = load i32, i32* %p 49 ret i32 %v 50} 51 52; 8 is greater than the default alignment so it is ignored. 53 54; CHECK-LABEL: ldi32_a8: 55; CHECK-NEXT: .param i32{{$}} 56; CHECK-NEXT: .result i32{{$}} 57; CHECK-NEXT: i32.load $push[[NUM:[0-9]+]]=, 0($0){{$}} 58; CHECK-NEXT: return $pop[[NUM]]{{$}} 59define i32 @ldi32_a8(i32 *%p) { 60 %v = load i32, i32* %p, align 8 61 ret i32 %v 62} 63 64; Extending loads. 65 66; CHECK-LABEL: ldi8_a1: 67; CHECK-NEXT: .param i32{{$}} 68; CHECK-NEXT: .result i32{{$}} 69; CHECK-NEXT: i32.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 70; CHECK-NEXT: return $pop[[NUM]]{{$}} 71define i8 @ldi8_a1(i8 *%p) { 72 %v = load i8, i8* %p, align 1 73 ret i8 %v 74} 75 76; CHECK-LABEL: ldi8_a2: 77; CHECK-NEXT: .param i32{{$}} 78; CHECK-NEXT: .result i32{{$}} 79; CHECK-NEXT: i32.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 80; CHECK-NEXT: return $pop[[NUM]]{{$}} 81define i8 @ldi8_a2(i8 *%p) { 82 %v = load i8, i8* %p, align 2 83 ret i8 %v 84} 85 86; CHECK-LABEL: ldi16_a1: 87; CHECK-NEXT: .param i32{{$}} 88; CHECK-NEXT: .result i32{{$}} 89; CHECK-NEXT: i32.load16_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}} 90; CHECK-NEXT: return $pop[[NUM]]{{$}} 91define i16 @ldi16_a1(i16 *%p) { 92 %v = load i16, i16* %p, align 1 93 ret i16 %v 94} 95 96; CHECK-LABEL: ldi16_a2: 97; CHECK-NEXT: .param i32{{$}} 98; CHECK-NEXT: .result i32{{$}} 99; CHECK-NEXT: i32.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 100; CHECK-NEXT: return $pop[[NUM]]{{$}} 101define i16 @ldi16_a2(i16 *%p) { 102 %v = load i16, i16* %p, align 2 103 ret i16 %v 104} 105 106; CHECK-LABEL: ldi16_a4: 107; CHECK-NEXT: .param i32{{$}} 108; CHECK-NEXT: .result i32{{$}} 109; CHECK-NEXT: i32.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}} 110; CHECK-NEXT: return $pop[[NUM]]{{$}} 111define i16 @ldi16_a4(i16 *%p) { 112 %v = load i16, i16* %p, align 4 113 ret i16 %v 114} 115 116; Stores. 117 118; CHECK-LABEL: sti32_a1: 119; CHECK-NEXT: .param i32, i32{{$}} 120; CHECK-NEXT: i32.store $drop=, 0($0):p2align=0, $1{{$}} 121; CHECK-NEXT: return{{$}} 122define void @sti32_a1(i32 *%p, i32 %v) { 123 store i32 %v, i32* %p, align 1 124 ret void 125} 126 127; CHECK-LABEL: sti32_a2: 128; CHECK-NEXT: .param i32, i32{{$}} 129; CHECK-NEXT: i32.store $drop=, 0($0):p2align=1, $1{{$}} 130; CHECK-NEXT: return{{$}} 131define void @sti32_a2(i32 *%p, i32 %v) { 132 store i32 %v, i32* %p, align 2 133 ret void 134} 135 136; 4 is the default alignment for i32 so no attribute is needed. 137 138; CHECK-LABEL: sti32_a4: 139; CHECK-NEXT: .param i32, i32{{$}} 140; CHECK-NEXT: i32.store $drop=, 0($0), $1{{$}} 141; CHECK-NEXT: return{{$}} 142define void @sti32_a4(i32 *%p, i32 %v) { 143 store i32 %v, i32* %p, align 4 144 ret void 145} 146 147; The default alignment in LLVM is the same as the defualt alignment in wasm. 148 149; CHECK-LABEL: sti32: 150; CHECK-NEXT: .param i32, i32{{$}} 151; CHECK-NEXT: i32.store $drop=, 0($0), $1{{$}} 152; CHECK-NEXT: return{{$}} 153define void @sti32(i32 *%p, i32 %v) { 154 store i32 %v, i32* %p 155 ret void 156} 157 158; CHECK-LABEL: sti32_a8: 159; CHECK-NEXT: .param i32, i32{{$}} 160; CHECK-NEXT: i32.store $drop=, 0($0), $1{{$}} 161; CHECK-NEXT: return{{$}} 162define void @sti32_a8(i32 *%p, i32 %v) { 163 store i32 %v, i32* %p, align 8 164 ret void 165} 166 167; Truncating stores. 168 169; CHECK-LABEL: sti8_a1: 170; CHECK-NEXT: .param i32, i32{{$}} 171; CHECK-NEXT: i32.store8 $drop=, 0($0), $1{{$}} 172; CHECK-NEXT: return{{$}} 173define void @sti8_a1(i8 *%p, i8 %v) { 174 store i8 %v, i8* %p, align 1 175 ret void 176} 177 178; CHECK-LABEL: sti8_a2: 179; CHECK-NEXT: .param i32, i32{{$}} 180; CHECK-NEXT: i32.store8 $drop=, 0($0), $1{{$}} 181; CHECK-NEXT: return{{$}} 182define void @sti8_a2(i8 *%p, i8 %v) { 183 store i8 %v, i8* %p, align 2 184 ret void 185} 186 187; CHECK-LABEL: sti16_a1: 188; CHECK-NEXT: .param i32, i32{{$}} 189; CHECK-NEXT: i32.store16 $drop=, 0($0):p2align=0, $1{{$}} 190; CHECK-NEXT: return{{$}} 191define void @sti16_a1(i16 *%p, i16 %v) { 192 store i16 %v, i16* %p, align 1 193 ret void 194} 195 196; CHECK-LABEL: sti16_a2: 197; CHECK-NEXT: .param i32, i32{{$}} 198; CHECK-NEXT: i32.store16 $drop=, 0($0), $1{{$}} 199; CHECK-NEXT: return{{$}} 200define void @sti16_a2(i16 *%p, i16 %v) { 201 store i16 %v, i16* %p, align 2 202 ret void 203} 204 205; CHECK-LABEL: sti16_a4: 206; CHECK-NEXT: .param i32, i32{{$}} 207; CHECK-NEXT: i32.store16 $drop=, 0($0), $1{{$}} 208; CHECK-NEXT: return{{$}} 209define void @sti16_a4(i16 *%p, i16 %v) { 210 store i16 %v, i16* %p, align 4 211 ret void 212} 213