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