1; RUN: llc -mtriple thumbv6m-arm-none-eabi -filetype asm -o - %s -frame-pointer=all --verify-machineinstrs | FileCheck %s --check-prefixes=FP,LEAF-FP 2; RUN: llc -mtriple thumbv6m-arm-none-eabi -filetype asm -o - %s -frame-pointer=all -mattr=+aapcs-frame-chain --verify-machineinstrs | FileCheck %s --check-prefixes=FP-AAPCS,LEAF-FP-AAPCS 3; RUN: llc -mtriple thumbv6m-arm-none-eabi -filetype asm -o - %s -frame-pointer=non-leaf --verify-machineinstrs | FileCheck %s --check-prefixes=FP,LEAF-NOFP 4; RUN: llc -mtriple thumbv6m-arm-none-eabi -filetype asm -o - %s -frame-pointer=non-leaf -mattr=+aapcs-frame-chain --verify-machineinstrs | FileCheck %s --check-prefixes=FP-AAPCS,LEAF-NOFP-AAPCS 5; RUN: llc -mtriple thumbv6m-arm-none-eabi -filetype asm -o - %s -frame-pointer=none --verify-machineinstrs | FileCheck %s --check-prefixes=NOFP,LEAF-NOFP 6; RUN: llc -mtriple thumbv6m-arm-none-eabi -filetype asm -o - %s -frame-pointer=none -mattr=+aapcs-frame-chain --verify-machineinstrs | FileCheck %s --check-prefixes=NOFP-AAPCS,LEAF-NOFP-AAPCS 7 8define dso_local noundef i32 @leaf(i32 noundef %0) { 9; LEAF-FP-LABEL: leaf: 10; LEAF-FP: @ %bb.0: 11; LEAF-FP-NEXT: .save {r7, lr} 12; LEAF-FP-NEXT: push {r7, lr} 13; LEAF-FP-NEXT: .setfp r7, sp 14; LEAF-FP-NEXT: add r7, sp, #0 15; LEAF-FP-NEXT: .pad #4 16; LEAF-FP-NEXT: sub sp, #4 17; LEAF-FP-NEXT: str r0, [sp] 18; LEAF-FP-NEXT: adds r0, r0, #4 19; LEAF-FP-NEXT: add sp, #4 20; LEAF-FP-NEXT: pop {r7, pc} 21; 22; LEAF-FP-AAPCS-LABEL: leaf: 23; LEAF-FP-AAPCS: @ %bb.0: 24; LEAF-FP-AAPCS-NEXT: .save {lr} 25; LEAF-FP-AAPCS-NEXT: push {lr} 26; LEAF-FP-AAPCS-NEXT: mov r3, r11 27; LEAF-FP-AAPCS-NEXT: .save {r11} 28; LEAF-FP-AAPCS-NEXT: push {r3} 29; LEAF-FP-AAPCS-NEXT: .setfp r11, sp 30; LEAF-FP-AAPCS-NEXT: mov r11, sp 31; LEAF-FP-AAPCS-NEXT: .pad #4 32; LEAF-FP-AAPCS-NEXT: sub sp, #4 33; LEAF-FP-AAPCS-NEXT: str r0, [sp] 34; LEAF-FP-AAPCS-NEXT: adds r0, r0, #4 35; LEAF-FP-AAPCS-NEXT: add sp, #4 36; LEAF-FP-AAPCS-NEXT: pop {r1} 37; LEAF-FP-AAPCS-NEXT: mov r11, r1 38; LEAF-FP-AAPCS-NEXT: pop {pc} 39; 40; LEAF-NOFP-LABEL: leaf: 41; LEAF-NOFP: @ %bb.0: 42; LEAF-NOFP-NEXT: .pad #4 43; LEAF-NOFP-NEXT: sub sp, #4 44; LEAF-NOFP-NEXT: str r0, [sp] 45; LEAF-NOFP-NEXT: adds r0, r0, #4 46; LEAF-NOFP-NEXT: add sp, #4 47; LEAF-NOFP-NEXT: bx lr 48; 49; LEAF-NOFP-AAPCS-LABEL: leaf: 50; LEAF-NOFP-AAPCS: @ %bb.0: 51; LEAF-NOFP-AAPCS-NEXT: .pad #4 52; LEAF-NOFP-AAPCS-NEXT: sub sp, #4 53; LEAF-NOFP-AAPCS-NEXT: str r0, [sp] 54; LEAF-NOFP-AAPCS-NEXT: adds r0, r0, #4 55; LEAF-NOFP-AAPCS-NEXT: add sp, #4 56; LEAF-NOFP-AAPCS-NEXT: bx lr 57 %2 = alloca i32, align 4 58 store i32 %0, ptr %2, align 4 59 %3 = load i32, ptr %2, align 4 60 %4 = add nsw i32 %3, 4 61 ret i32 %4 62} 63 64define dso_local noundef i32 @non_leaf(i32 noundef %0) { 65; FP-LABEL: non_leaf: 66; FP: @ %bb.0: 67; FP-NEXT: .save {r7, lr} 68; FP-NEXT: push {r7, lr} 69; FP-NEXT: .setfp r7, sp 70; FP-NEXT: add r7, sp, #0 71; FP-NEXT: .pad #8 72; FP-NEXT: sub sp, #8 73; FP-NEXT: str r0, [sp, #4] 74; FP-NEXT: bl leaf 75; FP-NEXT: adds r0, r0, #1 76; FP-NEXT: add sp, #8 77; FP-NEXT: pop {r7, pc} 78; 79; FP-AAPCS-LABEL: non_leaf: 80; FP-AAPCS: @ %bb.0: 81; FP-AAPCS-NEXT: .save {lr} 82; FP-AAPCS-NEXT: push {lr} 83; FP-AAPCS-NEXT: mov r3, r11 84; FP-AAPCS-NEXT: .save {r11} 85; FP-AAPCS-NEXT: push {r3} 86; FP-AAPCS-NEXT: .setfp r11, sp 87; FP-AAPCS-NEXT: mov r11, sp 88; FP-AAPCS-NEXT: .pad #8 89; FP-AAPCS-NEXT: sub sp, #8 90; FP-AAPCS-NEXT: str r0, [sp, #4] 91; FP-AAPCS-NEXT: bl leaf 92; FP-AAPCS-NEXT: adds r0, r0, #1 93; FP-AAPCS-NEXT: add sp, #8 94; FP-AAPCS-NEXT: pop {r1} 95; FP-AAPCS-NEXT: mov r11, r1 96; FP-AAPCS-NEXT: pop {pc} 97; 98; NOFP-LABEL: non_leaf: 99; NOFP: @ %bb.0: 100; NOFP-NEXT: .save {r7, lr} 101; NOFP-NEXT: push {r7, lr} 102; NOFP-NEXT: .pad #8 103; NOFP-NEXT: sub sp, #8 104; NOFP-NEXT: str r0, [sp, #4] 105; NOFP-NEXT: bl leaf 106; NOFP-NEXT: adds r0, r0, #1 107; NOFP-NEXT: add sp, #8 108; NOFP-NEXT: pop {r7, pc} 109; 110; NOFP-AAPCS-LABEL: non_leaf: 111; NOFP-AAPCS: @ %bb.0: 112; NOFP-AAPCS-NEXT: .save {r7, lr} 113; NOFP-AAPCS-NEXT: push {r7, lr} 114; NOFP-AAPCS-NEXT: .pad #8 115; NOFP-AAPCS-NEXT: sub sp, #8 116; NOFP-AAPCS-NEXT: str r0, [sp, #4] 117; NOFP-AAPCS-NEXT: bl leaf 118; NOFP-AAPCS-NEXT: adds r0, r0, #1 119; NOFP-AAPCS-NEXT: add sp, #8 120; NOFP-AAPCS-NEXT: pop {r7, pc} 121 %2 = alloca i32, align 4 122 store i32 %0, ptr %2, align 4 123 %3 = load i32, ptr %2, align 4 124 %4 = call noundef i32 @leaf(i32 noundef %3) 125 %5 = add nsw i32 %4, 1 126 ret i32 %5 127} 128 129declare ptr @llvm.stacksave() 130define dso_local void @required_fp(i32 %0, i32 %1) { 131; FP-LABEL: required_fp: 132; FP: @ %bb.0: 133; FP-NEXT: .save {r4, r6, r7, lr} 134; FP-NEXT: push {r4, r6, r7, lr} 135; FP-NEXT: .setfp r7, sp, #8 136; FP-NEXT: add r7, sp, #8 137; FP-NEXT: .pad #24 138; FP-NEXT: sub sp, #24 139; FP-NEXT: mov r6, sp 140; FP-NEXT: mov r2, r6 141; FP-NEXT: str r1, [r2, #16] 142; FP-NEXT: str r0, [r2, #20] 143; FP-NEXT: mov r1, sp 144; FP-NEXT: str r1, [r2, #8] 145; FP-NEXT: lsls r1, r0, #2 146; FP-NEXT: adds r1, r1, #7 147; FP-NEXT: movs r3, #7 148; FP-NEXT: bics r1, r3 149; FP-NEXT: mov r3, sp 150; FP-NEXT: subs r1, r3, r1 151; FP-NEXT: mov sp, r1 152; FP-NEXT: movs r1, #0 153; FP-NEXT: str r1, [r6, #4] 154; FP-NEXT: str r0, [r2] 155; FP-NEXT: subs r6, r7, #7 156; FP-NEXT: subs r6, #1 157; FP-NEXT: mov sp, r6 158; FP-NEXT: pop {r4, r6, r7, pc} 159; 160; FP-AAPCS-LABEL: required_fp: 161; FP-AAPCS: @ %bb.0: 162; FP-AAPCS-NEXT: .save {lr} 163; FP-AAPCS-NEXT: push {lr} 164; FP-AAPCS-NEXT: mov r3, r11 165; FP-AAPCS-NEXT: .save {r11} 166; FP-AAPCS-NEXT: push {r3} 167; FP-AAPCS-NEXT: .setfp r11, sp 168; FP-AAPCS-NEXT: mov r11, sp 169; FP-AAPCS-NEXT: .save {r4, r6} 170; FP-AAPCS-NEXT: push {r4, r6} 171; FP-AAPCS-NEXT: .pad #24 172; FP-AAPCS-NEXT: sub sp, #24 173; FP-AAPCS-NEXT: mov r6, sp 174; FP-AAPCS-NEXT: mov r2, r6 175; FP-AAPCS-NEXT: str r1, [r2, #16] 176; FP-AAPCS-NEXT: str r0, [r2, #20] 177; FP-AAPCS-NEXT: mov r1, sp 178; FP-AAPCS-NEXT: str r1, [r2, #8] 179; FP-AAPCS-NEXT: lsls r1, r0, #2 180; FP-AAPCS-NEXT: adds r1, r1, #7 181; FP-AAPCS-NEXT: movs r3, #7 182; FP-AAPCS-NEXT: bics r1, r3 183; FP-AAPCS-NEXT: mov r3, sp 184; FP-AAPCS-NEXT: subs r1, r3, r1 185; FP-AAPCS-NEXT: mov sp, r1 186; FP-AAPCS-NEXT: movs r1, #0 187; FP-AAPCS-NEXT: str r1, [r6, #4] 188; FP-AAPCS-NEXT: str r0, [r2] 189; FP-AAPCS-NEXT: mov r6, r11 190; FP-AAPCS-NEXT: subs r6, #8 191; FP-AAPCS-NEXT: mov sp, r6 192; FP-AAPCS-NEXT: pop {r4, r6} 193; FP-AAPCS-NEXT: pop {r0} 194; FP-AAPCS-NEXT: mov r11, r0 195; FP-AAPCS-NEXT: pop {pc} 196; 197; NOFP-LABEL: required_fp: 198; NOFP: @ %bb.0: 199; NOFP-NEXT: .save {r4, r6, r7, lr} 200; NOFP-NEXT: push {r4, r6, r7, lr} 201; NOFP-NEXT: .setfp r7, sp, #8 202; NOFP-NEXT: add r7, sp, #8 203; NOFP-NEXT: .pad #24 204; NOFP-NEXT: sub sp, #24 205; NOFP-NEXT: mov r6, sp 206; NOFP-NEXT: mov r2, r6 207; NOFP-NEXT: str r1, [r2, #16] 208; NOFP-NEXT: str r0, [r2, #20] 209; NOFP-NEXT: mov r1, sp 210; NOFP-NEXT: str r1, [r2, #8] 211; NOFP-NEXT: lsls r1, r0, #2 212; NOFP-NEXT: adds r1, r1, #7 213; NOFP-NEXT: movs r3, #7 214; NOFP-NEXT: bics r1, r3 215; NOFP-NEXT: mov r3, sp 216; NOFP-NEXT: subs r1, r3, r1 217; NOFP-NEXT: mov sp, r1 218; NOFP-NEXT: movs r1, #0 219; NOFP-NEXT: str r1, [r6, #4] 220; NOFP-NEXT: str r0, [r2] 221; NOFP-NEXT: subs r6, r7, #7 222; NOFP-NEXT: subs r6, #1 223; NOFP-NEXT: mov sp, r6 224; NOFP-NEXT: pop {r4, r6, r7, pc} 225; 226; NOFP-AAPCS-LABEL: required_fp: 227; NOFP-AAPCS: @ %bb.0: 228; NOFP-AAPCS-NEXT: .save {lr} 229; NOFP-AAPCS-NEXT: push {lr} 230; NOFP-AAPCS-NEXT: mov r3, r11 231; NOFP-AAPCS-NEXT: .save {r11} 232; NOFP-AAPCS-NEXT: push {r3} 233; NOFP-AAPCS-NEXT: .setfp r11, sp 234; NOFP-AAPCS-NEXT: mov r11, sp 235; NOFP-AAPCS-NEXT: .save {r4, r6} 236; NOFP-AAPCS-NEXT: push {r4, r6} 237; NOFP-AAPCS-NEXT: .pad #24 238; NOFP-AAPCS-NEXT: sub sp, #24 239; NOFP-AAPCS-NEXT: mov r6, sp 240; NOFP-AAPCS-NEXT: mov r2, r6 241; NOFP-AAPCS-NEXT: str r1, [r2, #16] 242; NOFP-AAPCS-NEXT: str r0, [r2, #20] 243; NOFP-AAPCS-NEXT: mov r1, sp 244; NOFP-AAPCS-NEXT: str r1, [r2, #8] 245; NOFP-AAPCS-NEXT: lsls r1, r0, #2 246; NOFP-AAPCS-NEXT: adds r1, r1, #7 247; NOFP-AAPCS-NEXT: movs r3, #7 248; NOFP-AAPCS-NEXT: bics r1, r3 249; NOFP-AAPCS-NEXT: mov r3, sp 250; NOFP-AAPCS-NEXT: subs r1, r3, r1 251; NOFP-AAPCS-NEXT: mov sp, r1 252; NOFP-AAPCS-NEXT: movs r1, #0 253; NOFP-AAPCS-NEXT: str r1, [r6, #4] 254; NOFP-AAPCS-NEXT: str r0, [r2] 255; NOFP-AAPCS-NEXT: mov r6, r11 256; NOFP-AAPCS-NEXT: subs r6, #8 257; NOFP-AAPCS-NEXT: mov sp, r6 258; NOFP-AAPCS-NEXT: pop {r4, r6} 259; NOFP-AAPCS-NEXT: pop {r0} 260; NOFP-AAPCS-NEXT: mov r11, r0 261; NOFP-AAPCS-NEXT: pop {pc} 262 %3 = alloca i32, align 4 263 %4 = alloca i32, align 4 264 %5 = alloca ptr, align 8 265 %6 = alloca i64, align 8 266 store i32 %0, ptr %3, align 4 267 store i32 %1, ptr %4, align 4 268 %7 = load i32, ptr %3, align 4 269 %8 = zext i32 %7 to i64 270 %9 = call ptr @llvm.stacksave() 271 store ptr %9, ptr %5, align 8 272 %10 = alloca i32, i64 %8, align 4 273 store i64 %8, ptr %6, align 8 274 ret void 275} 276