816 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s --mtriple=wasm32-unknown-unknown -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck -DPTR=32 %s --check-prefix=CHECK-323; RUN: llc < %s --mtriple=wasm64-unknown-unknown -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck -DPTR=64 %s --check-prefix=CHECK-644 5declare void @ext_func(ptr %ptr)6declare void @ext_func_i32(ptr %ptr)7 8; Check that there is an extra local for the stack pointer.9define void @alloca32() noredzone {10; CHECK-32-LABEL: alloca32:11; CHECK-32: .functype alloca32 () -> ()12; CHECK-32-NEXT: .local i3213; CHECK-32-NEXT: # %bb.0:14; CHECK-32-NEXT: global.get $push1=, __stack_pointer15; CHECK-32-NEXT: i32.const $push2=, 1616; CHECK-32-NEXT: i32.sub $push6=, $pop1, $pop217; CHECK-32-NEXT: local.tee $push5=, 0, $pop618; CHECK-32-NEXT: global.set __stack_pointer, $pop519; CHECK-32-NEXT: local.get $push7=, 020; CHECK-32-NEXT: i32.const $push0=, 021; CHECK-32-NEXT: i32.store 12($pop7), $pop022; CHECK-32-NEXT: local.get $push8=, 023; CHECK-32-NEXT: i32.const $push3=, 1624; CHECK-32-NEXT: i32.add $push4=, $pop8, $pop325; CHECK-32-NEXT: global.set __stack_pointer, $pop426; CHECK-32-NEXT: return27;28; CHECK-64-LABEL: alloca32:29; CHECK-64: .functype alloca32 () -> ()30; CHECK-64-NEXT: .local i6431; CHECK-64-NEXT: # %bb.0:32; CHECK-64-NEXT: global.get $push1=, __stack_pointer33; CHECK-64-NEXT: i64.const $push2=, 1634; CHECK-64-NEXT: i64.sub $push6=, $pop1, $pop235; CHECK-64-NEXT: local.tee $push5=, 0, $pop636; CHECK-64-NEXT: global.set __stack_pointer, $pop537; CHECK-64-NEXT: local.get $push7=, 038; CHECK-64-NEXT: i32.const $push0=, 039; CHECK-64-NEXT: i32.store 12($pop7), $pop040; CHECK-64-NEXT: local.get $push8=, 041; CHECK-64-NEXT: i64.const $push3=, 1642; CHECK-64-NEXT: i64.add $push4=, $pop8, $pop343; CHECK-64-NEXT: global.set __stack_pointer, $pop444; CHECK-64-NEXT: return45 %retval = alloca i3246 store i32 0, ptr %retval47 ret void48}49 50define void @alloca3264() {51; CHECK-32-LABEL: alloca3264:52; CHECK-32: .functype alloca3264 () -> ()53; CHECK-32-NEXT: .local i3254; CHECK-32-NEXT: # %bb.0:55; CHECK-32-NEXT: global.get $push2=, __stack_pointer56; CHECK-32-NEXT: i32.const $push3=, 1657; CHECK-32-NEXT: i32.sub $push5=, $pop2, $pop358; CHECK-32-NEXT: local.tee $push4=, 0, $pop559; CHECK-32-NEXT: i64.const $push0=, 060; CHECK-32-NEXT: i64.store 0($pop4), $pop061; CHECK-32-NEXT: local.get $push6=, 062; CHECK-32-NEXT: i32.const $push1=, 063; CHECK-32-NEXT: i32.store 12($pop6), $pop164; CHECK-32-NEXT: return65;66; CHECK-64-LABEL: alloca3264:67; CHECK-64: .functype alloca3264 () -> ()68; CHECK-64-NEXT: .local i6469; CHECK-64-NEXT: # %bb.0:70; CHECK-64-NEXT: global.get $push2=, __stack_pointer71; CHECK-64-NEXT: i64.const $push3=, 1672; CHECK-64-NEXT: i64.sub $push5=, $pop2, $pop373; CHECK-64-NEXT: local.tee $push4=, 0, $pop574; CHECK-64-NEXT: i64.const $push0=, 075; CHECK-64-NEXT: i64.store 0($pop4), $pop076; CHECK-64-NEXT: local.get $push6=, 077; CHECK-64-NEXT: i32.const $push1=, 078; CHECK-64-NEXT: i32.store 12($pop6), $pop179; CHECK-64-NEXT: return80 %r1 = alloca i3281 %r2 = alloca double82 store i32 0, ptr %r183 store double 0.0, ptr %r284 ret void85}86 87define void @allocarray() {88; CHECK-32-LABEL: allocarray:89; CHECK-32: .functype allocarray () -> ()90; CHECK-32-NEXT: .local i3291; CHECK-32-NEXT: # %bb.0:92; CHECK-32-NEXT: global.get $push3=, __stack_pointer93; CHECK-32-NEXT: i32.const $push4=, 14494; CHECK-32-NEXT: i32.sub $push9=, $pop3, $pop495; CHECK-32-NEXT: local.tee $push8=, 0, $pop996; CHECK-32-NEXT: global.set __stack_pointer, $pop897; CHECK-32-NEXT: local.get $push10=, 098; CHECK-32-NEXT: i32.const $push0=, 2499; CHECK-32-NEXT: i32.add $push1=, $pop10, $pop0100; CHECK-32-NEXT: i32.const $push2=, 1101; CHECK-32-NEXT: i32.store 0($pop1), $pop2102; CHECK-32-NEXT: local.get $push11=, 0103; CHECK-32-NEXT: i32.const $push7=, 1104; CHECK-32-NEXT: i32.store 12($pop11), $pop7105; CHECK-32-NEXT: local.get $push12=, 0106; CHECK-32-NEXT: i32.const $push5=, 144107; CHECK-32-NEXT: i32.add $push6=, $pop12, $pop5108; CHECK-32-NEXT: global.set __stack_pointer, $pop6109; CHECK-32-NEXT: return110;111; CHECK-64-LABEL: allocarray:112; CHECK-64: .functype allocarray () -> ()113; CHECK-64-NEXT: .local i64114; CHECK-64-NEXT: # %bb.0:115; CHECK-64-NEXT: global.get $push3=, __stack_pointer116; CHECK-64-NEXT: i64.const $push4=, 144117; CHECK-64-NEXT: i64.sub $push9=, $pop3, $pop4118; CHECK-64-NEXT: local.tee $push8=, 0, $pop9119; CHECK-64-NEXT: global.set __stack_pointer, $pop8120; CHECK-64-NEXT: local.get $push10=, 0121; CHECK-64-NEXT: i64.const $push0=, 24122; CHECK-64-NEXT: i64.add $push1=, $pop10, $pop0123; CHECK-64-NEXT: i32.const $push2=, 1124; CHECK-64-NEXT: i32.store 0($pop1), $pop2125; CHECK-64-NEXT: local.get $push11=, 0126; CHECK-64-NEXT: i32.const $push7=, 1127; CHECK-64-NEXT: i32.store 12($pop11), $pop7128; CHECK-64-NEXT: local.get $push12=, 0129; CHECK-64-NEXT: i64.const $push5=, 144130; CHECK-64-NEXT: i64.add $push6=, $pop12, $pop5131; CHECK-64-NEXT: global.set __stack_pointer, $pop6132; CHECK-64-NEXT: return133 %r = alloca [33 x i32]134 store i32 1, ptr %r135 %p2 = getelementptr [33 x i32], ptr %r, i32 0, i32 3136 store i32 1, ptr %p2137 ret void138}139 140define void @non_mem_use(ptr %addr) {141; CHECK-32-LABEL: non_mem_use:142; CHECK-32: .functype non_mem_use (i32) -> ()143; CHECK-32-NEXT: .local i32144; CHECK-32-NEXT: # %bb.0:145; CHECK-32-NEXT: global.get $push0=, __stack_pointer146; CHECK-32-NEXT: i32.const $push1=, 48147; CHECK-32-NEXT: i32.sub $push9=, $pop0, $pop1148; CHECK-32-NEXT: local.tee $push8=, 1, $pop9149; CHECK-32-NEXT: global.set __stack_pointer, $pop8150; CHECK-32-NEXT: local.get $push10=, 1151; CHECK-32-NEXT: i32.const $push6=, 8152; CHECK-32-NEXT: i32.add $push7=, $pop10, $pop6153; CHECK-32-NEXT: call ext_func, $pop7154; CHECK-32-NEXT: local.get $push11=, 1155; CHECK-32-NEXT: call ext_func, $pop11156; CHECK-32-NEXT: local.get $push13=, 0157; CHECK-32-NEXT: local.get $push12=, 1158; CHECK-32-NEXT: i32.const $push4=, 16159; CHECK-32-NEXT: i32.add $push5=, $pop12, $pop4160; CHECK-32-NEXT: i32.store 0($pop13), $pop5161; CHECK-32-NEXT: local.get $push14=, 1162; CHECK-32-NEXT: i32.const $push2=, 48163; CHECK-32-NEXT: i32.add $push3=, $pop14, $pop2164; CHECK-32-NEXT: global.set __stack_pointer, $pop3165; CHECK-32-NEXT: return166;167; CHECK-64-LABEL: non_mem_use:168; CHECK-64: .functype non_mem_use (i64) -> ()169; CHECK-64-NEXT: .local i64170; CHECK-64-NEXT: # %bb.0:171; CHECK-64-NEXT: global.get $push0=, __stack_pointer172; CHECK-64-NEXT: i64.const $push1=, 48173; CHECK-64-NEXT: i64.sub $push9=, $pop0, $pop1174; CHECK-64-NEXT: local.tee $push8=, 1, $pop9175; CHECK-64-NEXT: global.set __stack_pointer, $pop8176; CHECK-64-NEXT: local.get $push10=, 1177; CHECK-64-NEXT: i64.const $push6=, 8178; CHECK-64-NEXT: i64.add $push7=, $pop10, $pop6179; CHECK-64-NEXT: call ext_func, $pop7180; CHECK-64-NEXT: local.get $push11=, 1181; CHECK-64-NEXT: call ext_func, $pop11182; CHECK-64-NEXT: local.get $push13=, 0183; CHECK-64-NEXT: local.get $push12=, 1184; CHECK-64-NEXT: i64.const $push4=, 16185; CHECK-64-NEXT: i64.add $push5=, $pop12, $pop4186; CHECK-64-NEXT: i64.store 0($pop13), $pop5187; CHECK-64-NEXT: local.get $push14=, 1188; CHECK-64-NEXT: i64.const $push2=, 48189; CHECK-64-NEXT: i64.add $push3=, $pop14, $pop2190; CHECK-64-NEXT: global.set __stack_pointer, $pop3191; CHECK-64-NEXT: return192 %buf = alloca [27 x i8], align 16193 %r = alloca i64194 %r2 = alloca i64195 ; %r is at SP+8196 call void @ext_func(ptr %r)197 ; %r2 is at SP+0, no add needed198 call void @ext_func(ptr %r2)199 ; Use as a value, but in a store200 ; %buf is at SP+16201 store ptr %buf, ptr %addr202 ret void203}204 205define void @allocarray_inbounds() {206; CHECK-32-LABEL: allocarray_inbounds:207; CHECK-32: .functype allocarray_inbounds () -> ()208; CHECK-32-NEXT: .local i32209; CHECK-32-NEXT: # %bb.0:210; CHECK-32-NEXT: global.get $push2=, __stack_pointer211; CHECK-32-NEXT: i32.const $push3=, 32212; CHECK-32-NEXT: i32.sub $push8=, $pop2, $pop3213; CHECK-32-NEXT: local.tee $push7=, 0, $pop8214; CHECK-32-NEXT: global.set __stack_pointer, $pop7215; CHECK-32-NEXT: local.get $push9=, 0216; CHECK-32-NEXT: i32.const $push0=, 1217; CHECK-32-NEXT: i32.store 24($pop9), $pop0218; CHECK-32-NEXT: local.get $push10=, 0219; CHECK-32-NEXT: i32.const $push6=, 1220; CHECK-32-NEXT: i32.store 12($pop10), $pop6221; CHECK-32-NEXT: i32.const $push1=, 0222; CHECK-32-NEXT: call ext_func, $pop1223; CHECK-32-NEXT: local.get $push11=, 0224; CHECK-32-NEXT: i32.const $push4=, 32225; CHECK-32-NEXT: i32.add $push5=, $pop11, $pop4226; CHECK-32-NEXT: global.set __stack_pointer, $pop5227; CHECK-32-NEXT: return228;229; CHECK-64-LABEL: allocarray_inbounds:230; CHECK-64: .functype allocarray_inbounds () -> ()231; CHECK-64-NEXT: .local i64232; CHECK-64-NEXT: # %bb.0:233; CHECK-64-NEXT: global.get $push2=, __stack_pointer234; CHECK-64-NEXT: i64.const $push3=, 32235; CHECK-64-NEXT: i64.sub $push8=, $pop2, $pop3236; CHECK-64-NEXT: local.tee $push7=, 0, $pop8237; CHECK-64-NEXT: global.set __stack_pointer, $pop7238; CHECK-64-NEXT: local.get $push9=, 0239; CHECK-64-NEXT: i32.const $push0=, 1240; CHECK-64-NEXT: i32.store 24($pop9), $pop0241; CHECK-64-NEXT: local.get $push10=, 0242; CHECK-64-NEXT: i32.const $push6=, 1243; CHECK-64-NEXT: i32.store 12($pop10), $pop6244; CHECK-64-NEXT: i64.const $push1=, 0245; CHECK-64-NEXT: call ext_func, $pop1246; CHECK-64-NEXT: local.get $push11=, 0247; CHECK-64-NEXT: i64.const $push4=, 32248; CHECK-64-NEXT: i64.add $push5=, $pop11, $pop4249; CHECK-64-NEXT: global.set __stack_pointer, $pop5250; CHECK-64-NEXT: return251 %r = alloca [5 x i32]252 store i32 1, ptr %r253 ; This store should have both the GEP and the FI folded into it.254 %p2 = getelementptr inbounds [5 x i32], ptr %r, i32 0, i32 3255 store i32 1, ptr %p2256 call void @ext_func(ptr null);257 ret void258}259 260define void @dynamic_alloca(i32 %alloc) {261 ; Target independent codegen bumps the stack pointer.262 ; Check that SP is written back to memory after decrement263; CHECK-32-LABEL: dynamic_alloca:264; CHECK-32: .functype dynamic_alloca (i32) -> ()265; CHECK-32-NEXT: .local i32266; CHECK-32-NEXT: # %bb.0:267; CHECK-32-NEXT: global.get $push10=, __stack_pointer268; CHECK-32-NEXT: local.tee $push9=, 1, $pop10269; CHECK-32-NEXT: local.get $push11=, 0270; CHECK-32-NEXT: i32.const $push0=, 2271; CHECK-32-NEXT: i32.shl $push1=, $pop11, $pop0272; CHECK-32-NEXT: i32.const $push2=, 15273; CHECK-32-NEXT: i32.add $push3=, $pop1, $pop2274; CHECK-32-NEXT: i32.const $push4=, -16275; CHECK-32-NEXT: i32.and $push5=, $pop3, $pop4276; CHECK-32-NEXT: i32.sub $push8=, $pop9, $pop5277; CHECK-32-NEXT: local.tee $push7=, 0, $pop8278; CHECK-32-NEXT: global.set __stack_pointer, $pop7279; CHECK-32-NEXT: local.get $push12=, 0280; CHECK-32-NEXT: call ext_func_i32, $pop12281; CHECK-32-NEXT: local.get $push6=, 1282; CHECK-32-NEXT: global.set __stack_pointer, $pop6283; CHECK-32-NEXT: return284;285; CHECK-64-LABEL: dynamic_alloca:286; CHECK-64: .functype dynamic_alloca (i32) -> ()287; CHECK-64-NEXT: .local i64, i64288; CHECK-64-NEXT: # %bb.0:289; CHECK-64-NEXT: global.get $push11=, __stack_pointer290; CHECK-64-NEXT: local.tee $push10=, 1, $pop11291; CHECK-64-NEXT: local.get $push12=, 0292; CHECK-64-NEXT: i64.extend_i32_u $push0=, $pop12293; CHECK-64-NEXT: i64.const $push1=, 2294; CHECK-64-NEXT: i64.shl $push2=, $pop0, $pop1295; CHECK-64-NEXT: i64.const $push3=, 15296; CHECK-64-NEXT: i64.add $push4=, $pop2, $pop3297; CHECK-64-NEXT: i64.const $push5=, 34359738352298; CHECK-64-NEXT: i64.and $push6=, $pop4, $pop5299; CHECK-64-NEXT: i64.sub $push9=, $pop10, $pop6300; CHECK-64-NEXT: local.tee $push8=, 2, $pop9301; CHECK-64-NEXT: global.set __stack_pointer, $pop8302; CHECK-64-NEXT: local.get $push13=, 2303; CHECK-64-NEXT: call ext_func_i32, $pop13304; CHECK-64-NEXT: local.get $push7=, 1305; CHECK-64-NEXT: global.set __stack_pointer, $pop7306; CHECK-64-NEXT: return307 %r = alloca i32, i32 %alloc308 ; Target-independent codegen also calculates the store addr309 call void @ext_func_i32(ptr %r)310 ret void311}312 313define void @dynamic_alloca_redzone(i32 %alloc) {314 ; Target independent codegen bumps the stack pointer315; CHECK-32-LABEL: dynamic_alloca_redzone:316; CHECK-32: .functype dynamic_alloca_redzone (i32) -> ()317; CHECK-32-NEXT: .local i32318; CHECK-32-NEXT: # %bb.0:319; CHECK-32-NEXT: global.get $push8=, __stack_pointer320; CHECK-32-NEXT: local.tee $push9=, 1, $pop8321; CHECK-32-NEXT: drop $pop9322; CHECK-32-NEXT: local.get $push11=, 1323; CHECK-32-NEXT: local.get $push10=, 0324; CHECK-32-NEXT: i32.const $push0=, 2325; CHECK-32-NEXT: i32.shl $push1=, $pop10, $pop0326; CHECK-32-NEXT: i32.const $push2=, 15327; CHECK-32-NEXT: i32.add $push3=, $pop1, $pop2328; CHECK-32-NEXT: i32.const $push4=, -16329; CHECK-32-NEXT: i32.and $push5=, $pop3, $pop4330; CHECK-32-NEXT: i32.sub $push7=, $pop11, $pop5331; CHECK-32-NEXT: local.tee $push12=, 0, $pop7332; CHECK-32-NEXT: drop $pop12333; CHECK-32-NEXT: local.get $push13=, 0334; CHECK-32-NEXT: i32.const $push6=, 0335; CHECK-32-NEXT: i32.store 0($pop13), $pop6336; CHECK-32-NEXT: return337;338; CHECK-64-LABEL: dynamic_alloca_redzone:339; CHECK-64: .functype dynamic_alloca_redzone (i32) -> ()340; CHECK-64-NEXT: .local i64341; CHECK-64-NEXT: # %bb.0:342; CHECK-64-NEXT: global.get $push9=, __stack_pointer343; CHECK-64-NEXT: local.tee $push10=, 1, $pop9344; CHECK-64-NEXT: drop $pop10345; CHECK-64-NEXT: local.get $push12=, 1346; CHECK-64-NEXT: local.get $push11=, 0347; CHECK-64-NEXT: i64.extend_i32_u $push0=, $pop11348; CHECK-64-NEXT: i64.const $push1=, 2349; CHECK-64-NEXT: i64.shl $push2=, $pop0, $pop1350; CHECK-64-NEXT: i64.const $push3=, 15351; CHECK-64-NEXT: i64.add $push4=, $pop2, $pop3352; CHECK-64-NEXT: i64.const $push5=, 34359738352353; CHECK-64-NEXT: i64.and $push6=, $pop4, $pop5354; CHECK-64-NEXT: i64.sub $push8=, $pop12, $pop6355; CHECK-64-NEXT: local.tee $push13=, 1, $pop8356; CHECK-64-NEXT: drop $pop13357; CHECK-64-NEXT: local.get $push14=, 1358; CHECK-64-NEXT: i32.const $push7=, 0359; CHECK-64-NEXT: i32.store 0($pop14), $pop7360; CHECK-64-NEXT: return361 %r = alloca i32, i32 %alloc362 store i32 0, ptr %r363 ret void364}365 366define void @dynamic_static_alloca(i32 %alloc) noredzone {367 ; Decrement SP in the prolog by the static amount and writeback to memory.368 ; Alloc and write to a static alloca369; CHECK-32-LABEL: dynamic_static_alloca:370; CHECK-32: .functype dynamic_static_alloca (i32) -> ()371; CHECK-32-NEXT: .local i32, i32, i32372; CHECK-32-NEXT: # %bb.0:373; CHECK-32-NEXT: global.get $push11=, __stack_pointer374; CHECK-32-NEXT: i32.const $push12=, 16375; CHECK-32-NEXT: i32.sub $push25=, $pop11, $pop12376; CHECK-32-NEXT: local.tee $push24=, 1, $pop25377; CHECK-32-NEXT: global.set __stack_pointer, $pop24378; CHECK-32-NEXT: local.get $push23=, 1379; CHECK-32-NEXT: local.tee $push22=, 2, $pop23380; CHECK-32-NEXT: i32.const $push0=, 101381; CHECK-32-NEXT: i32.store 12($pop22), $pop0382; CHECK-32-NEXT: local.get $push27=, 1383; CHECK-32-NEXT: local.get $push26=, 0384; CHECK-32-NEXT: i32.const $push1=, 2385; CHECK-32-NEXT: i32.shl $push2=, $pop26, $pop1386; CHECK-32-NEXT: i32.const $push3=, 15387; CHECK-32-NEXT: i32.add $push4=, $pop2, $pop3388; CHECK-32-NEXT: i32.const $push5=, -16389; CHECK-32-NEXT: i32.and $push21=, $pop4, $pop5390; CHECK-32-NEXT: local.tee $push20=, 0, $pop21391; CHECK-32-NEXT: i32.sub $push19=, $pop27, $pop20392; CHECK-32-NEXT: local.tee $push18=, 1, $pop19393; CHECK-32-NEXT: local.tee $push17=, 3, $pop18394; CHECK-32-NEXT: global.set __stack_pointer, $pop17395; CHECK-32-NEXT: local.get $push28=, 2396; CHECK-32-NEXT: i32.const $push6=, 102397; CHECK-32-NEXT: i32.store 12($pop28), $pop6398; CHECK-32-NEXT: local.get $push29=, 1399; CHECK-32-NEXT: i32.const $push7=, 103400; CHECK-32-NEXT: i32.store 0($pop29), $pop7401; CHECK-32-NEXT: local.get $push31=, 3402; CHECK-32-NEXT: local.get $push30=, 0403; CHECK-32-NEXT: i32.sub $push16=, $pop31, $pop30404; CHECK-32-NEXT: local.tee $push15=, 0, $pop16405; CHECK-32-NEXT: global.set __stack_pointer, $pop15406; CHECK-32-NEXT: local.get $push32=, 2407; CHECK-32-NEXT: i32.const $push8=, 104408; CHECK-32-NEXT: i32.store 12($pop32), $pop8409; CHECK-32-NEXT: local.get $push33=, 1410; CHECK-32-NEXT: i32.const $push9=, 105411; CHECK-32-NEXT: i32.store 0($pop33), $pop9412; CHECK-32-NEXT: local.get $push34=, 0413; CHECK-32-NEXT: i32.const $push10=, 106414; CHECK-32-NEXT: i32.store 0($pop34), $pop10415; CHECK-32-NEXT: local.get $push35=, 2416; CHECK-32-NEXT: i32.const $push13=, 16417; CHECK-32-NEXT: i32.add $push14=, $pop35, $pop13418; CHECK-32-NEXT: global.set __stack_pointer, $pop14419; CHECK-32-NEXT: return420;421; CHECK-64-LABEL: dynamic_static_alloca:422; CHECK-64: .functype dynamic_static_alloca (i32) -> ()423; CHECK-64-NEXT: .local i64, i64, i64, i64424; CHECK-64-NEXT: # %bb.0:425; CHECK-64-NEXT: global.get $push12=, __stack_pointer426; CHECK-64-NEXT: i64.const $push13=, 16427; CHECK-64-NEXT: i64.sub $push26=, $pop12, $pop13428; CHECK-64-NEXT: local.tee $push25=, 1, $pop26429; CHECK-64-NEXT: global.set __stack_pointer, $pop25430; CHECK-64-NEXT: local.get $push24=, 1431; CHECK-64-NEXT: local.tee $push23=, 2, $pop24432; CHECK-64-NEXT: i32.const $push0=, 101433; CHECK-64-NEXT: i32.store 12($pop23), $pop0434; CHECK-64-NEXT: local.get $push28=, 1435; CHECK-64-NEXT: local.get $push27=, 0436; CHECK-64-NEXT: i64.extend_i32_u $push1=, $pop27437; CHECK-64-NEXT: i64.const $push2=, 2438; CHECK-64-NEXT: i64.shl $push3=, $pop1, $pop2439; CHECK-64-NEXT: i64.const $push4=, 15440; CHECK-64-NEXT: i64.add $push5=, $pop3, $pop4441; CHECK-64-NEXT: i64.const $push6=, 34359738352442; CHECK-64-NEXT: i64.and $push22=, $pop5, $pop6443; CHECK-64-NEXT: local.tee $push21=, 3, $pop22444; CHECK-64-NEXT: i64.sub $push20=, $pop28, $pop21445; CHECK-64-NEXT: local.tee $push19=, 1, $pop20446; CHECK-64-NEXT: local.tee $push18=, 4, $pop19447; CHECK-64-NEXT: global.set __stack_pointer, $pop18448; CHECK-64-NEXT: local.get $push29=, 2449; CHECK-64-NEXT: i32.const $push7=, 102450; CHECK-64-NEXT: i32.store 12($pop29), $pop7451; CHECK-64-NEXT: local.get $push30=, 1452; CHECK-64-NEXT: i32.const $push8=, 103453; CHECK-64-NEXT: i32.store 0($pop30), $pop8454; CHECK-64-NEXT: local.get $push32=, 4455; CHECK-64-NEXT: local.get $push31=, 3456; CHECK-64-NEXT: i64.sub $push17=, $pop32, $pop31457; CHECK-64-NEXT: local.tee $push16=, 3, $pop17458; CHECK-64-NEXT: global.set __stack_pointer, $pop16459; CHECK-64-NEXT: local.get $push33=, 2460; CHECK-64-NEXT: i32.const $push9=, 104461; CHECK-64-NEXT: i32.store 12($pop33), $pop9462; CHECK-64-NEXT: local.get $push34=, 1463; CHECK-64-NEXT: i32.const $push10=, 105464; CHECK-64-NEXT: i32.store 0($pop34), $pop10465; CHECK-64-NEXT: local.get $push35=, 3466; CHECK-64-NEXT: i32.const $push11=, 106467; CHECK-64-NEXT: i32.store 0($pop35), $pop11468; CHECK-64-NEXT: local.get $push36=, 2469; CHECK-64-NEXT: i64.const $push14=, 16470; CHECK-64-NEXT: i64.add $push15=, $pop36, $pop14471; CHECK-64-NEXT: global.set __stack_pointer, $pop15472; CHECK-64-NEXT: return473 %static = alloca i32474 store volatile i32 101, ptr %static475 ; Decrement SP in the body by the dynamic amount.476 %dynamic = alloca i32, i32 %alloc477 ; Ensure we don't modify the frame pointer after assigning it.478 ; Ensure the static address doesn't change after modifying the stack pointer.479 store volatile i32 102, ptr %static480 store volatile i32 103, ptr %dynamic481 ; Decrement SP in the body by the dynamic amount.482 %dynamic.2 = alloca i32, i32 %alloc483 ; Ensure neither the static nor dynamic address changes after the second484 ; modification of the stack pointer.485 store volatile i32 104, ptr %static486 store volatile i32 105, ptr %dynamic487 store volatile i32 106, ptr %dynamic.2488 ; Writeback to memory.489 ret void490}491 492declare ptr @llvm.stacksave()493declare void @llvm.stackrestore(ptr)494 495define void @llvm_stack_builtins(i32 %alloc) noredzone {496; CHECK-32-LABEL: llvm_stack_builtins:497; CHECK-32: .functype llvm_stack_builtins (i32) -> ()498; CHECK-32-NEXT: .local i32, i32, i32499; CHECK-32-NEXT: # %bb.0:500; CHECK-32-NEXT: global.get $push7=, __stack_pointer501; CHECK-32-NEXT: local.tee $push8=, 1, $pop7502; CHECK-32-NEXT: local.set 2, $pop8503; CHECK-32-NEXT: local.get $push9=, 1504; CHECK-32-NEXT: local.set 3, $pop9505; CHECK-32-NEXT: local.get $push11=, 1506; CHECK-32-NEXT: local.get $push10=, 0507; CHECK-32-NEXT: i32.const $push0=, 2508; CHECK-32-NEXT: i32.shl $push1=, $pop10, $pop0509; CHECK-32-NEXT: i32.const $push2=, 15510; CHECK-32-NEXT: i32.add $push3=, $pop1, $pop2511; CHECK-32-NEXT: i32.const $push4=, -16512; CHECK-32-NEXT: i32.and $push5=, $pop3, $pop4513; CHECK-32-NEXT: i32.sub $push6=, $pop11, $pop5514; CHECK-32-NEXT: global.set __stack_pointer, $pop6515; CHECK-32-NEXT: local.get $push12=, 3516; CHECK-32-NEXT: drop $pop12517; CHECK-32-NEXT: local.get $push13=, 2518; CHECK-32-NEXT: global.set __stack_pointer, $pop13519; CHECK-32-NEXT: return520;521; CHECK-64-LABEL: llvm_stack_builtins:522; CHECK-64: .functype llvm_stack_builtins (i32) -> ()523; CHECK-64-NEXT: .local i64, i64, i64524; CHECK-64-NEXT: # %bb.0:525; CHECK-64-NEXT: global.get $push8=, __stack_pointer526; CHECK-64-NEXT: local.tee $push9=, 1, $pop8527; CHECK-64-NEXT: local.set 2, $pop9528; CHECK-64-NEXT: local.get $push10=, 1529; CHECK-64-NEXT: local.set 3, $pop10530; CHECK-64-NEXT: local.get $push12=, 1531; CHECK-64-NEXT: local.get $push11=, 0532; CHECK-64-NEXT: i64.extend_i32_u $push0=, $pop11533; CHECK-64-NEXT: i64.const $push1=, 2534; CHECK-64-NEXT: i64.shl $push2=, $pop0, $pop1535; CHECK-64-NEXT: i64.const $push3=, 15536; CHECK-64-NEXT: i64.add $push4=, $pop2, $pop3537; CHECK-64-NEXT: i64.const $push5=, 34359738352538; CHECK-64-NEXT: i64.and $push6=, $pop4, $pop5539; CHECK-64-NEXT: i64.sub $push7=, $pop12, $pop6540; CHECK-64-NEXT: global.set __stack_pointer, $pop7541; CHECK-64-NEXT: local.get $push13=, 3542; CHECK-64-NEXT: drop $pop13543; CHECK-64-NEXT: local.get $push14=, 2544; CHECK-64-NEXT: global.set __stack_pointer, $pop14545; CHECK-64-NEXT: return546 %stack = call ptr @llvm.stacksave()547 ; Ensure we don't reassign the stacksave local548 %dynamic = alloca i32, i32 %alloc549 call void @llvm.stackrestore(ptr %stack)550 ret void551}552 553; Use of stacksave requires local SP definition even without dymamic alloca.554; CHECK-LABEL: llvm_stacksave_noalloca:555define void @llvm_stacksave_noalloca() noredzone {556 ; CHECK: global.get $push[[L11:.+]]=, __stack_pointer{{$}}557 %stack = call ptr @llvm.stacksave()558 559 ; CHECK-NEXT: call use_i8_star, $pop[[L11:.+]]560 call void @use_i8_star(ptr %stack)561 562 ret void563}564 565; Not actually using the alloca'd variables exposed an issue with register566; stackification, where copying the stack pointer into the frame pointer was567; moved after the stack pointer was updated for the dynamic alloca.568define void @dynamic_alloca_nouse(i32 %alloc) noredzone {569; CHECK-32-LABEL: dynamic_alloca_nouse:570; CHECK-32: .functype dynamic_alloca_nouse (i32) -> ()571; CHECK-32-NEXT: .local i32, i32572; CHECK-32-NEXT: # %bb.0:573; CHECK-32-NEXT: global.get $push7=, __stack_pointer574; CHECK-32-NEXT: local.tee $push8=, 1, $pop7575; CHECK-32-NEXT: local.set 2, $pop8576; CHECK-32-NEXT: local.get $push10=, 1577; CHECK-32-NEXT: local.get $push9=, 0578; CHECK-32-NEXT: i32.const $push0=, 2579; CHECK-32-NEXT: i32.shl $push1=, $pop9, $pop0580; CHECK-32-NEXT: i32.const $push2=, 15581; CHECK-32-NEXT: i32.add $push3=, $pop1, $pop2582; CHECK-32-NEXT: i32.const $push4=, -16583; CHECK-32-NEXT: i32.and $push5=, $pop3, $pop4584; CHECK-32-NEXT: i32.sub $push6=, $pop10, $pop5585; CHECK-32-NEXT: global.set __stack_pointer, $pop6586; CHECK-32-NEXT: local.get $push11=, 2587; CHECK-32-NEXT: global.set __stack_pointer, $pop11588; CHECK-32-NEXT: return589;590; CHECK-64-LABEL: dynamic_alloca_nouse:591; CHECK-64: .functype dynamic_alloca_nouse (i32) -> ()592; CHECK-64-NEXT: .local i64, i64593; CHECK-64-NEXT: # %bb.0:594; CHECK-64-NEXT: global.get $push8=, __stack_pointer595; CHECK-64-NEXT: local.tee $push9=, 1, $pop8596; CHECK-64-NEXT: local.set 2, $pop9597; CHECK-64-NEXT: local.get $push11=, 1598; CHECK-64-NEXT: local.get $push10=, 0599; CHECK-64-NEXT: i64.extend_i32_u $push0=, $pop10600; CHECK-64-NEXT: i64.const $push1=, 2601; CHECK-64-NEXT: i64.shl $push2=, $pop0, $pop1602; CHECK-64-NEXT: i64.const $push3=, 15603; CHECK-64-NEXT: i64.add $push4=, $pop2, $pop3604; CHECK-64-NEXT: i64.const $push5=, 34359738352605; CHECK-64-NEXT: i64.and $push6=, $pop4, $pop5606; CHECK-64-NEXT: i64.sub $push7=, $pop11, $pop6607; CHECK-64-NEXT: global.set __stack_pointer, $pop7608; CHECK-64-NEXT: local.get $push12=, 2609; CHECK-64-NEXT: global.set __stack_pointer, $pop12610; CHECK-64-NEXT: return611 %dynamic = alloca i32, i32 %alloc612 ret void613}614 615; The use of the alloca in a phi causes a CopyToReg DAG node to be generated,616; which has to have special handling because CopyToReg can't have a FI operand617define void @copytoreg_fi(i1 %cond, ptr %b) {618; CHECK-32-LABEL: copytoreg_fi:619; CHECK-32: .functype copytoreg_fi (i32, i32) -> ()620; CHECK-32-NEXT: .local i32621; CHECK-32-NEXT: # %bb.0: # %entry622; CHECK-32-NEXT: global.get $push0=, __stack_pointer623; CHECK-32-NEXT: i32.const $push1=, 16624; CHECK-32-NEXT: i32.sub $push3=, $pop0, $pop1625; CHECK-32-NEXT: i32.const $push2=, 12626; CHECK-32-NEXT: i32.add $push6=, $pop3, $pop2627; CHECK-32-NEXT: local.set 2, $pop6628; CHECK-32-NEXT: local.get $push8=, 0629; CHECK-32-NEXT: i32.const $push4=, 1630; CHECK-32-NEXT: i32.and $push7=, $pop8, $pop4631; CHECK-32-NEXT: local.set 0, $pop7632; CHECK-32-NEXT: # %body633; CHECK-32-NEXT: # =>This Inner Loop Header: Depth=1634; CHECK-32-NEXT: loop # label0:635; CHECK-32-NEXT: local.get $push9=, 2636; CHECK-32-NEXT: i32.const $push5=, 1637; CHECK-32-NEXT: i32.store 0($pop9), $pop5638; CHECK-32-NEXT: local.get $push10=, 1639; CHECK-32-NEXT: local.set 2, $pop10640; CHECK-32-NEXT: local.get $push11=, 0641; CHECK-32-NEXT: br_if 0, $pop11 # 0: up to label0642; CHECK-32-NEXT: # %bb.2: # %exit643; CHECK-32-NEXT: end_loop644; CHECK-32-NEXT: return645;646; CHECK-64-LABEL: copytoreg_fi:647; CHECK-64: .functype copytoreg_fi (i32, i64) -> ()648; CHECK-64-NEXT: .local i64649; CHECK-64-NEXT: # %bb.0: # %entry650; CHECK-64-NEXT: global.get $push0=, __stack_pointer651; CHECK-64-NEXT: i64.const $push1=, 16652; CHECK-64-NEXT: i64.sub $push3=, $pop0, $pop1653; CHECK-64-NEXT: i64.const $push2=, 12654; CHECK-64-NEXT: i64.add $push6=, $pop3, $pop2655; CHECK-64-NEXT: local.set 2, $pop6656; CHECK-64-NEXT: local.get $push8=, 0657; CHECK-64-NEXT: i32.const $push4=, 1658; CHECK-64-NEXT: i32.and $push7=, $pop8, $pop4659; CHECK-64-NEXT: local.set 0, $pop7660; CHECK-64-NEXT: # %body661; CHECK-64-NEXT: # =>This Inner Loop Header: Depth=1662; CHECK-64-NEXT: loop # label0:663; CHECK-64-NEXT: local.get $push9=, 2664; CHECK-64-NEXT: i32.const $push5=, 1665; CHECK-64-NEXT: i32.store 0($pop9), $pop5666; CHECK-64-NEXT: local.get $push10=, 1667; CHECK-64-NEXT: local.set 2, $pop10668; CHECK-64-NEXT: local.get $push11=, 0669; CHECK-64-NEXT: br_if 0, $pop11 # 0: up to label0670; CHECK-64-NEXT: # %bb.2: # %exit671; CHECK-64-NEXT: end_loop672; CHECK-64-NEXT: return673entry:674 %addr = alloca i32675 br label %body676body:677 %a = phi ptr [%addr, %entry], [%b, %body]678 store i32 1, ptr %a679 br i1 %cond, label %body, label %exit680exit:681 ret void682}683 684declare void @use_i8_star(ptr)685declare ptr @llvm.frameaddress(i32)686 687; Test __builtin_frame_address(0).688define void @frameaddress_0() {689; CHECK-32-LABEL: frameaddress_0:690; CHECK-32: .functype frameaddress_0 () -> ()691; CHECK-32-NEXT: .local i32692; CHECK-32-NEXT: # %bb.0:693; CHECK-32-NEXT: global.get $push1=, __stack_pointer694; CHECK-32-NEXT: local.tee $push0=, 0, $pop1695; CHECK-32-NEXT: call use_i8_star, $pop0696; CHECK-32-NEXT: local.get $push2=, 0697; CHECK-32-NEXT: global.set __stack_pointer, $pop2698; CHECK-32-NEXT: return699;700; CHECK-64-LABEL: frameaddress_0:701; CHECK-64: .functype frameaddress_0 () -> ()702; CHECK-64-NEXT: .local i64703; CHECK-64-NEXT: # %bb.0:704; CHECK-64-NEXT: global.get $push1=, __stack_pointer705; CHECK-64-NEXT: local.tee $push0=, 0, $pop1706; CHECK-64-NEXT: call use_i8_star, $pop0707; CHECK-64-NEXT: local.get $push2=, 0708; CHECK-64-NEXT: global.set __stack_pointer, $pop2709; CHECK-64-NEXT: return710 %t = call ptr @llvm.frameaddress(i32 0)711 call void @use_i8_star(ptr %t)712 ret void713}714 715; Test __builtin_frame_address(1).716define void @frameaddress_1() {717; CHECK-32-LABEL: frameaddress_1:718; CHECK-32: .functype frameaddress_1 () -> ()719; CHECK-32-NEXT: # %bb.0:720; CHECK-32-NEXT: i32.const $push0=, 0721; CHECK-32-NEXT: call use_i8_star, $pop0722; CHECK-32-NEXT: return723;724; CHECK-64-LABEL: frameaddress_1:725; CHECK-64: .functype frameaddress_1 () -> ()726; CHECK-64-NEXT: # %bb.0:727; CHECK-64-NEXT: i64.const $push0=, 0728; CHECK-64-NEXT: call use_i8_star, $pop0729; CHECK-64-NEXT: return730 %t = call ptr @llvm.frameaddress(i32 1)731 call void @use_i8_star(ptr %t)732 ret void733}734 735; Test a stack address passed to an inline asm.736define void @inline_asm() {737; CHECK-32-LABEL: inline_asm:738; CHECK-32: .functype inline_asm () -> ()739; CHECK-32-NEXT: .local i32740; CHECK-32-NEXT: # %bb.0:741; CHECK-32-NEXT: global.get $push0=, __stack_pointer742; CHECK-32-NEXT: i32.const $push1=, 16743; CHECK-32-NEXT: i32.sub $push3=, $pop0, $pop1744; CHECK-32-NEXT: i32.const $push2=, 15745; CHECK-32-NEXT: i32.add $push4=, $pop3, $pop2746; CHECK-32-NEXT: local.set 0, $pop4747; CHECK-32-NEXT: #APP748; CHECK-32-NEXT: # %0749; CHECK-32-NEXT: #NO_APP750; CHECK-32-NEXT: return751;752; CHECK-64-LABEL: inline_asm:753; CHECK-64: .functype inline_asm () -> ()754; CHECK-64-NEXT: .local i64755; CHECK-64-NEXT: # %bb.0:756; CHECK-64-NEXT: global.get $push0=, __stack_pointer757; CHECK-64-NEXT: i64.const $push1=, 16758; CHECK-64-NEXT: i64.sub $push3=, $pop0, $pop1759; CHECK-64-NEXT: i64.const $push2=, 15760; CHECK-64-NEXT: i64.add $push4=, $pop3, $pop2761; CHECK-64-NEXT: local.set 0, $pop4762; CHECK-64-NEXT: #APP763; CHECK-64-NEXT: # %0764; CHECK-64-NEXT: #NO_APP765; CHECK-64-NEXT: return766 %tmp = alloca i8767 call void asm sideeffect "# %0", "r"(ptr %tmp)768 ret void769}770 771; We optimize the format of "frame offset + operand" by folding it, but this is772; only possible when that operand is an immediate. In this example it is a773; global address, so we should not fold it.774@str = local_unnamed_addr global [3 x i8] c"abc", align 16775define i8 @frame_offset_with_global_address() {776; CHECK-32-LABEL: frame_offset_with_global_address:777; CHECK-32: .functype frame_offset_with_global_address () -> (i32)778; CHECK-32-NEXT: # %bb.0:779; CHECK-32-NEXT: i32.const $push0=, str780; CHECK-32-NEXT: global.get $push5=, __stack_pointer781; CHECK-32-NEXT: i32.const $push6=, 16782; CHECK-32-NEXT: i32.sub $push9=, $pop5, $pop6783; CHECK-32-NEXT: i32.const $push7=, 12784; CHECK-32-NEXT: i32.add $push8=, $pop9, $pop7785; CHECK-32-NEXT: i32.add $push1=, $pop0, $pop8786; CHECK-32-NEXT: i32.load8_u $push2=, 0($pop1)787; CHECK-32-NEXT: i32.const $push3=, 67788; CHECK-32-NEXT: i32.and $push4=, $pop2, $pop3789; CHECK-32-NEXT: return $pop4790;791; CHECK-64-LABEL: frame_offset_with_global_address:792; CHECK-64: .functype frame_offset_with_global_address () -> (i32)793; CHECK-64-NEXT: # %bb.0:794; CHECK-64-NEXT: i64.const $push1=, str795; CHECK-64-NEXT: global.get $push6=, __stack_pointer796; CHECK-64-NEXT: i64.const $push7=, 16797; CHECK-64-NEXT: i64.sub $push10=, $pop6, $pop7798; CHECK-64-NEXT: i64.const $push8=, 12799; CHECK-64-NEXT: i64.add $push9=, $pop10, $pop8800; CHECK-64-NEXT: i64.extend32_s $push0=, $pop9801; CHECK-64-NEXT: i64.add $push2=, $pop1, $pop0802; CHECK-64-NEXT: i32.load8_u $push3=, 0($pop2)803; CHECK-64-NEXT: i32.const $push4=, 67804; CHECK-64-NEXT: i32.and $push5=, $pop3, $pop4805; CHECK-64-NEXT: return $pop5806 %1 = alloca i8, align 4807 %2 = ptrtoint ptr %1 to i32808 ;; Here @str is a global address and not an immediate, so cannot be folded809 %3 = getelementptr [3 x i8], ptr @str, i32 0, i32 %2810 %4 = load i8, ptr %3, align 8811 %5 = and i8 %4, 67812 ret i8 %5813}814 815; TODO: test over-aligned alloca816