371 lines · plain
1; RUN: llc < %s -mattr=+atomics -asm-verbose=false -disable-wasm-fallthrough-return-opt -wasm-disable-explicit-locals -wasm-keep-registers | FileCheck %s2 3; Test loads and stores with custom alignment values.4 5target triple = "wasm32-unknown-unknown"6 7;===----------------------------------------------------------------------------8; Loads9;===----------------------------------------------------------------------------10 11; CHECK-LABEL: ldi64_a1:12; CHECK-NEXT: .functype ldi64_a1 (i32) -> (i64){{$}}13; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}14; CHECK-NEXT: return $pop[[NUM]]{{$}}15define i64 @ldi64_a1(ptr %p) {16 %v = load i64, ptr %p, align 117 ret i64 %v18}19 20; CHECK-LABEL: ldi64_a2:21; CHECK-NEXT: .functype ldi64_a2 (i32) -> (i64){{$}}22; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}23; CHECK-NEXT: return $pop[[NUM]]{{$}}24define i64 @ldi64_a2(ptr %p) {25 %v = load i64, ptr %p, align 226 ret i64 %v27}28 29; CHECK-LABEL: ldi64_a4:30; CHECK-NEXT: .functype ldi64_a4 (i32) -> (i64){{$}}31; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0):p2align=2{{$}}32; CHECK-NEXT: return $pop[[NUM]]{{$}}33define i64 @ldi64_a4(ptr %p) {34 %v = load i64, ptr %p, align 435 ret i64 %v36}37 38; 8 is the default alignment for i64 so no attribute is needed.39 40; CHECK-LABEL: ldi64_a8:41; CHECK-NEXT: .functype ldi64_a8 (i32) -> (i64){{$}}42; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}43; CHECK-NEXT: return $pop[[NUM]]{{$}}44define i64 @ldi64_a8(ptr %p) {45 %v = load i64, ptr %p, align 846 ret i64 %v47}48 49; The default alignment in LLVM is the same as the default alignment in wasm.50 51; CHECK-LABEL: ldi64:52; CHECK-NEXT: .functype ldi64 (i32) -> (i64){{$}}53; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}54; CHECK-NEXT: return $pop[[NUM]]{{$}}55define i64 @ldi64(ptr %p) {56 %v = load i64, ptr %p57 ret i64 %v58}59 60; 16 is greater than the default alignment so it is ignored.61 62; CHECK-LABEL: ldi64_a16:63; CHECK-NEXT: .functype ldi64_a16 (i32) -> (i64){{$}}64; CHECK-NEXT: i64.load $push[[NUM:[0-9]+]]=, 0($0){{$}}65; CHECK-NEXT: return $pop[[NUM]]{{$}}66define i64 @ldi64_a16(ptr %p) {67 %v = load i64, ptr %p, align 1668 ret i64 %v69}70 71;===----------------------------------------------------------------------------72; Extending loads73;===----------------------------------------------------------------------------74 75; CHECK-LABEL: ldi8_a1:76; CHECK-NEXT: .functype ldi8_a1 (i32) -> (i64){{$}}77; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}78; CHECK-NEXT: return $pop[[NUM]]{{$}}79define i64 @ldi8_a1(ptr %p) {80 %v = load i8, ptr %p, align 181 %w = zext i8 %v to i6482 ret i64 %w83}84 85; CHECK-LABEL: ldi8_a2:86; CHECK-NEXT: .functype ldi8_a2 (i32) -> (i64){{$}}87; CHECK-NEXT: i64.load8_u $push[[NUM:[0-9]+]]=, 0($0){{$}}88; CHECK-NEXT: return $pop[[NUM]]{{$}}89define i64 @ldi8_a2(ptr %p) {90 %v = load i8, ptr %p, align 291 %w = zext i8 %v to i6492 ret i64 %w93}94 95; CHECK-LABEL: ldi16_a1:96; CHECK-NEXT: .functype ldi16_a1 (i32) -> (i64){{$}}97; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}98; CHECK-NEXT: return $pop[[NUM]]{{$}}99define i64 @ldi16_a1(ptr %p) {100 %v = load i16, ptr %p, align 1101 %w = zext i16 %v to i64102 ret i64 %w103}104 105; CHECK-LABEL: ldi16_a2:106; CHECK-NEXT: .functype ldi16_a2 (i32) -> (i64){{$}}107; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}108; CHECK-NEXT: return $pop[[NUM]]{{$}}109define i64 @ldi16_a2(ptr %p) {110 %v = load i16, ptr %p, align 2111 %w = zext i16 %v to i64112 ret i64 %w113}114 115; CHECK-LABEL: ldi16_a4:116; CHECK-NEXT: .functype ldi16_a4 (i32) -> (i64){{$}}117; CHECK-NEXT: i64.load16_u $push[[NUM:[0-9]+]]=, 0($0){{$}}118; CHECK-NEXT: return $pop[[NUM]]{{$}}119define i64 @ldi16_a4(ptr %p) {120 %v = load i16, ptr %p, align 4121 %w = zext i16 %v to i64122 ret i64 %w123}124 125; CHECK-LABEL: ldi32_a1:126; CHECK-NEXT: .functype ldi32_a1 (i32) -> (i64){{$}}127; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=0{{$}}128; CHECK-NEXT: return $pop[[NUM]]{{$}}129define i64 @ldi32_a1(ptr %p) {130 %v = load i32, ptr %p, align 1131 %w = zext i32 %v to i64132 ret i64 %w133}134 135; CHECK-LABEL: ldi32_a2:136; CHECK-NEXT: .functype ldi32_a2 (i32) -> (i64){{$}}137; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0):p2align=1{{$}}138; CHECK-NEXT: return $pop[[NUM]]{{$}}139define i64 @ldi32_a2(ptr %p) {140 %v = load i32, ptr %p, align 2141 %w = zext i32 %v to i64142 ret i64 %w143}144 145; CHECK-LABEL: ldi32_a4:146; CHECK-NEXT: .functype ldi32_a4 (i32) -> (i64){{$}}147; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}148; CHECK-NEXT: return $pop[[NUM]]{{$}}149define i64 @ldi32_a4(ptr %p) {150 %v = load i32, ptr %p, align 4151 %w = zext i32 %v to i64152 ret i64 %w153}154 155; CHECK-LABEL: ldi32_a8:156; CHECK-NEXT: .functype ldi32_a8 (i32) -> (i64){{$}}157; CHECK-NEXT: i64.load32_u $push[[NUM:[0-9]+]]=, 0($0){{$}}158; CHECK-NEXT: return $pop[[NUM]]{{$}}159define i64 @ldi32_a8(ptr %p) {160 %v = load i32, ptr %p, align 8161 %w = zext i32 %v to i64162 ret i64 %w163}164 165;===----------------------------------------------------------------------------166; Stores167;===----------------------------------------------------------------------------168 169; CHECK-LABEL: sti64_a1:170; CHECK-NEXT: .functype sti64_a1 (i32, i64) -> (){{$}}171; CHECK-NEXT: i64.store 0($0):p2align=0, $1{{$}}172; CHECK-NEXT: return{{$}}173define void @sti64_a1(ptr %p, i64 %v) {174 store i64 %v, ptr %p, align 1175 ret void176}177 178; CHECK-LABEL: sti64_a2:179; CHECK-NEXT: .functype sti64_a2 (i32, i64) -> (){{$}}180; CHECK-NEXT: i64.store 0($0):p2align=1, $1{{$}}181; CHECK-NEXT: return{{$}}182define void @sti64_a2(ptr %p, i64 %v) {183 store i64 %v, ptr %p, align 2184 ret void185}186 187; CHECK-LABEL: sti64_a4:188; CHECK-NEXT: .functype sti64_a4 (i32, i64) -> (){{$}}189; CHECK-NEXT: i64.store 0($0):p2align=2, $1{{$}}190; CHECK-NEXT: return{{$}}191define void @sti64_a4(ptr %p, i64 %v) {192 store i64 %v, ptr %p, align 4193 ret void194}195 196; 8 is the default alignment for i32 so no attribute is needed.197 198; CHECK-LABEL: sti64_a8:199; CHECK-NEXT: .functype sti64_a8 (i32, i64) -> (){{$}}200; CHECK-NEXT: i64.store 0($0), $1{{$}}201; CHECK-NEXT: return{{$}}202define void @sti64_a8(ptr %p, i64 %v) {203 store i64 %v, ptr %p, align 8204 ret void205}206 207; The default alignment in LLVM is the same as the default alignment in wasm.208 209; CHECK-LABEL: sti64:210; CHECK-NEXT: .functype sti64 (i32, i64) -> (){{$}}211; CHECK-NEXT: i64.store 0($0), $1{{$}}212; CHECK-NEXT: return{{$}}213define void @sti64(ptr %p, i64 %v) {214 store i64 %v, ptr %p215 ret void216}217 218; CHECK-LABEL: sti64_a16:219; CHECK-NEXT: .functype sti64_a16 (i32, i64) -> (){{$}}220; CHECK-NEXT: i64.store 0($0), $1{{$}}221; CHECK-NEXT: return{{$}}222define void @sti64_a16(ptr %p, i64 %v) {223 store i64 %v, ptr %p, align 16224 ret void225}226 227;===----------------------------------------------------------------------------228; Truncating stores229;===----------------------------------------------------------------------------230 231; CHECK-LABEL: sti8_a1:232; CHECK-NEXT: .functype sti8_a1 (i32, i64) -> (){{$}}233; CHECK-NEXT: i64.store8 0($0), $1{{$}}234; CHECK-NEXT: return{{$}}235define void @sti8_a1(ptr %p, i64 %w) {236 %v = trunc i64 %w to i8237 store i8 %v, ptr %p, align 1238 ret void239}240 241; CHECK-LABEL: sti8_a2:242; CHECK-NEXT: .functype sti8_a2 (i32, i64) -> (){{$}}243; CHECK-NEXT: i64.store8 0($0), $1{{$}}244; CHECK-NEXT: return{{$}}245define void @sti8_a2(ptr %p, i64 %w) {246 %v = trunc i64 %w to i8247 store i8 %v, ptr %p, align 2248 ret void249}250 251; CHECK-LABEL: sti16_a1:252; CHECK-NEXT: .functype sti16_a1 (i32, i64) -> (){{$}}253; CHECK-NEXT: i64.store16 0($0):p2align=0, $1{{$}}254; CHECK-NEXT: return{{$}}255define void @sti16_a1(ptr %p, i64 %w) {256 %v = trunc i64 %w to i16257 store i16 %v, ptr %p, align 1258 ret void259}260 261; CHECK-LABEL: sti16_a2:262; CHECK-NEXT: .functype sti16_a2 (i32, i64) -> (){{$}}263; CHECK-NEXT: i64.store16 0($0), $1{{$}}264; CHECK-NEXT: return{{$}}265define void @sti16_a2(ptr %p, i64 %w) {266 %v = trunc i64 %w to i16267 store i16 %v, ptr %p, align 2268 ret void269}270 271; CHECK-LABEL: sti16_a4:272; CHECK-NEXT: .functype sti16_a4 (i32, i64) -> (){{$}}273; CHECK-NEXT: i64.store16 0($0), $1{{$}}274; CHECK-NEXT: return{{$}}275define void @sti16_a4(ptr %p, i64 %w) {276 %v = trunc i64 %w to i16277 store i16 %v, ptr %p, align 4278 ret void279}280 281; CHECK-LABEL: sti32_a1:282; CHECK-NEXT: .functype sti32_a1 (i32, i64) -> (){{$}}283; CHECK-NEXT: i64.store32 0($0):p2align=0, $1{{$}}284; CHECK-NEXT: return{{$}}285define void @sti32_a1(ptr %p, i64 %w) {286 %v = trunc i64 %w to i32287 store i32 %v, ptr %p, align 1288 ret void289}290 291; CHECK-LABEL: sti32_a2:292; CHECK-NEXT: .functype sti32_a2 (i32, i64) -> (){{$}}293; CHECK-NEXT: i64.store32 0($0):p2align=1, $1{{$}}294; CHECK-NEXT: return{{$}}295define void @sti32_a2(ptr %p, i64 %w) {296 %v = trunc i64 %w to i32297 store i32 %v, ptr %p, align 2298 ret void299}300 301; CHECK-LABEL: sti32_a4:302; CHECK-NEXT: .functype sti32_a4 (i32, i64) -> (){{$}}303; CHECK-NEXT: i64.store32 0($0), $1{{$}}304; CHECK-NEXT: return{{$}}305define void @sti32_a4(ptr %p, i64 %w) {306 %v = trunc i64 %w to i32307 store i32 %v, ptr %p, align 4308 ret void309}310 311; CHECK-LABEL: sti32_a8:312; CHECK-NEXT: .functype sti32_a8 (i32, i64) -> (){{$}}313; CHECK-NEXT: i64.store32 0($0), $1{{$}}314; CHECK-NEXT: return{{$}}315define void @sti32_a8(ptr %p, i64 %w) {316 %v = trunc i64 %w to i32317 store i32 %v, ptr %p, align 8318 ret void319}320 321;===----------------------------------------------------------------------------322; Atomic loads323;===----------------------------------------------------------------------------324 325; Wasm atomics have the alignment field, but it must always have the type's326; natural alignment.327 328; CHECK-LABEL: ldi64_atomic_a8:329; CHECK-NEXT: .functype ldi64_atomic_a8 (i32) -> (i64){{$}}330; CHECK-NEXT: i64.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}}331; CHECK-NEXT: return $pop[[NUM]]{{$}}332define i64 @ldi64_atomic_a8(ptr %p) {333 %v = load atomic i64, ptr %p seq_cst, align 8334 ret i64 %v335}336 337; 16 is greater than the default alignment so it is ignored.338 339; CHECK-LABEL: ldi64_atomic_a16:340; CHECK-NEXT: .functype ldi64_atomic_a16 (i32) -> (i64){{$}}341; CHECK-NEXT: i64.atomic.load $push[[NUM:[0-9]+]]=, 0($0){{$}}342; CHECK-NEXT: return $pop[[NUM]]{{$}}343define i64 @ldi64_atomic_a16(ptr %p) {344 %v = load atomic i64, ptr %p seq_cst, align 16345 ret i64 %v346}347 348;===----------------------------------------------------------------------------349; Atomic stores350;===----------------------------------------------------------------------------351 352; CHECK-LABEL: sti64_atomic_a4:353; CHECK-NEXT: .functype sti64_atomic_a4 (i32, i64) -> (){{$}}354; CHECK-NEXT: i64.atomic.store 0($0), $1{{$}}355; CHECK-NEXT: return{{$}}356define void @sti64_atomic_a4(ptr %p, i64 %v) {357 store atomic i64 %v, ptr %p seq_cst, align 8358 ret void359}360 361; 16 is greater than the default alignment so it is ignored.362 363; CHECK-LABEL: sti64_atomic_a8:364; CHECK-NEXT: .functype sti64_atomic_a8 (i32, i64) -> (){{$}}365; CHECK-NEXT: i64.atomic.store 0($0), $1{{$}}366; CHECK-NEXT: return{{$}}367define void @sti64_atomic_a8(ptr %p, i64 %v) {368 store atomic i64 %v, ptr %p seq_cst, align 16369 ret void370}371