1; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -frame-pointer=non-leaf -tailcallopt | FileCheck %s -check-prefix CHECK-TAIL 2; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -frame-pointer=non-leaf | FileCheck %s 3; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -frame-pointer=non-leaf -tailcallopt -aarch64-redzone | FileCheck %s -check-prefix CHECK-TAIL-RZ 4 5; Without tailcallopt fastcc still means the caller cleans up the 6; stack, so try to make sure this is respected. 7 8define fastcc void @func_stack0() uwtable { 9; CHECK-LABEL: func_stack0: 10; CHECK: sub sp, sp, #48 11; CHECK: add x29, sp, #32 12; CHECK: str w{{[0-9]+}}, [sp] 13 14; CHECK-TAIL-LABEL: func_stack0: 15; CHECK-TAIL: sub sp, sp, #48 16; CHECK-TAIL-NEXT: .cfi_def_cfa_offset 48 17; CHECK-TAIL-NEXT: stp x29, x30, [sp, #32] 18; CHECK-TAIL-NEXT: add x29, sp, #32 19; CHECK-TAIL: str w{{[0-9]+}}, [sp] 20 21 22 call fastcc void @func_stack8([8 x i64] undef, i32 42) 23; CHECK: bl func_stack8 24; CHECK-NOT: sub sp, sp, 25; CHECK-NOT: [sp, #{{[-0-9]+}}]! 26; CHECK-NOT: [sp], #{{[-0-9]+}} 27 28; CHECK-TAIL: bl func_stack8 29; CHECK-TAIL: stp xzr, xzr, [sp, #-16]! 30 31 32 call fastcc void @func_stack32([8 x i64] undef, i128 0, i128 9) 33; CHECK: bl func_stack32 34; CHECK-NOT: sub sp, sp, 35 36 37; CHECK-TAIL: bl func_stack32 38; CHECK-TAIL: sub sp, sp, #32 39 40 41 call fastcc void @func_stack0() 42; CHECK: bl func_stack0 43; CHECK-NOT: sub sp, sp 44 45 46; CHECK-TAIL: bl func_stack0 47; CHECK-TAIL-NOT: sub sp, sp 48 49 ret void 50; CHECK: ldp x29, x30, [sp, #32] 51; CHECK-NEXT: add sp, sp, #48 52; CHECK-NEXT: .cfi_def_cfa_offset 0 53; CHECK-NEXT: .cfi_restore w30 54; CHECK-NEXT: .cfi_restore w29 55; CHECK-NEXT: ret 56 57 58; CHECK-TAIL: ldp x29, x30, [sp, #32] 59; CHECK-TAIL-NEXT: add sp, sp, #48 60; CHECK-TAIL-NEXT: .cfi_def_cfa_offset 0 61; CHECK-TAIL-NEXT: .cfi_restore w30 62; CHECK-TAIL-NEXT: .cfi_restore w29 63; CHECK-TAIL-NEXT: ret 64} 65 66define fastcc void @func_stack8([8 x i64], i32 %stacked) uwtable { 67; CHECK-LABEL: func_stack8: 68; CHECK: sub sp, sp, #48 69; CHECK: stp x29, x30, [sp, #32] 70; CHECK: add x29, sp, #32 71; CHECK: str w{{[0-9]+}}, [sp] 72 73 74; CHECK-TAIL-LABEL: func_stack8: 75; CHECK-TAIL: sub sp, sp, #48 76; CHECK-TAIL: stp x29, x30, [sp, #32] 77; CHECK-TAIL: add x29, sp, #32 78; CHECK-TAIL: str w{{[0-9]+}}, [sp] 79 80 81 call fastcc void @func_stack8([8 x i64] undef, i32 42) 82; CHECK: bl func_stack8 83; CHECK-NOT: sub sp, sp, 84; CHECK-NOT: [sp, #{{[-0-9]+}}]! 85; CHECK-NOT: [sp], #{{[-0-9]+}} 86 87 88; CHECK-TAIL: bl func_stack8 89; CHECK-TAIL: stp xzr, xzr, [sp, #-16]! 90 91 92 call fastcc void @func_stack32([8 x i64] undef, i128 0, i128 9) 93; CHECK: bl func_stack32 94; CHECK-NOT: sub sp, sp, 95 96 97; CHECK-TAIL: bl func_stack32 98; CHECK-TAIL: sub sp, sp, #32 99 100 101 call fastcc void @func_stack0() 102; CHECK: bl func_stack0 103; CHECK-NOT: sub sp, sp 104 105; CHECK-TAIL: bl func_stack0 106; CHECK-TAIL-NOT: sub sp, sp 107 108 ret void 109; CHECK-NEXT: .cfi_def_cfa wsp, 48 110; CHECK-NEXT: ldp x29, x30, [sp, #32] 111; CHECK-NEXT: add sp, sp, #48 112; CHECK-NEXT: .cfi_def_cfa_offset 0 113; CHECK-NEXT: .cfi_restore w30 114; CHECK-NEXT: .cfi_restore w29 115; CHECK-NEXT: ret 116 117 118; CHECK-TAIL: ldp x29, x30, [sp, #32] 119; CHECK-TAIL-NEXT: add sp, sp, #64 120; CHECK-TAIL-NEXT: .cfi_def_cfa_offset -16 121; CHECK-TAIL-NEXT: .cfi_restore w30 122; CHECK-TAIL-NEXT: .cfi_restore w29 123; CHECK-TAIL-NEXT: ret 124} 125 126define fastcc void @func_stack32([8 x i64], i128 %stacked0, i128 %stacked1) uwtable { 127; CHECK-LABEL: func_stack32: 128; CHECK: add x29, sp, #32 129 130; CHECK-TAIL-LABEL: func_stack32: 131; CHECK-TAIL: add x29, sp, #32 132 133 134 call fastcc void @func_stack8([8 x i64] undef, i32 42) 135; CHECK: bl func_stack8 136; CHECK-NOT: sub sp, sp, 137; CHECK-NOT: [sp, #{{[-0-9]+}}]! 138; CHECK-NOT: [sp], #{{[-0-9]+}} 139 140; CHECK-TAIL: bl func_stack8 141; CHECK-TAIL: stp xzr, xzr, [sp, #-16]! 142 143 144 call fastcc void @func_stack32([8 x i64] undef, i128 0, i128 9) 145; CHECK: bl func_stack32 146; CHECK-NOT: sub sp, sp, 147 148 149; CHECK-TAIL: bl func_stack32 150; CHECK-TAIL: sub sp, sp, #32 151 152 153 call fastcc void @func_stack0() 154; CHECK: bl func_stack0 155; CHECK-NOT: sub sp, sp 156 157 158; CHECK-TAIL: bl func_stack0 159; CHECK-TAIL-NOT: sub sp, sp 160 161 ret void 162; CHECK: .cfi_def_cfa wsp, 48 163; CHECK-NEXT: ldp x29, x30, [sp, #32] 164; CHECK-NEXT: add sp, sp, #48 165; CHECK-NEXT: .cfi_def_cfa_offset 0 166; CHECK-NEXT: .cfi_restore w30 167; CHECK-NEXT: .cfi_restore w29 168; CHECK-NEXT: ret 169 170; CHECK-TAIL: ldp x29, x30, [sp, #32] 171; CHECK-TAIL-NEXT: add sp, sp, #80 172; CHECK-TAIL-NEXT: .cfi_def_cfa_offset -32 173; CHECK-TAIL-NEXT: .cfi_restore w30 174; CHECK-TAIL-NEXT: .cfi_restore w29 175; CHECK-TAIL-NEXT: ret 176} 177 178; Check that arg stack pop is done after callee-save restore when no frame pointer is used. 179define fastcc void @func_stack32_leaf([8 x i64], i128 %stacked0, i128 %stacked1) uwtable { 180; CHECK-LABEL: func_stack32_leaf: 181; CHECK: str x20, [sp, #-16]! 182; CHECK: nop 183; CHECK-NEXT: //NO_APP 184; CHECK-NEXT: ldr x20, [sp], #16 185; CHECK-NEXT: .cfi_def_cfa_offset 0 186; CHECK-NEXT: .cfi_restore w20 187; CHECK-NEXT: ret 188 189; CHECK-TAIL-LABEL: func_stack32_leaf: 190; CHECK-TAIL: str x20, [sp, #-16]! 191; CHECK-TAIL: nop 192; CHECK-TAIL-NEXT: //NO_APP 193; CHECK-TAIL-NEXT: ldr x20, [sp], #16 194; CHECK-TAIL-NEXT: .cfi_def_cfa_offset 0 195; CHECK-TAIL-NEXT: add sp, sp, #32 196; CHECK-TAIL-NEXT: .cfi_def_cfa_offset -32 197; CHECK-TAIL-NEXT: .cfi_restore w20 198; CHECK-TAIL-NEXT: ret 199 200; CHECK-TAIL-RZ-LABEL: func_stack32_leaf: 201; CHECK-TAIL-RZ: str x20, [sp, #-16]! 202; CHECK-TAIL-RZ-NOT: sub sp, sp 203; CHECK-TAIL-RZ: nop 204; CHECK-TAIL-RZ-NEXT: //NO_APP 205; CHECK-TAIL-RZ-NEXT: ldr x20, [sp], #16 206; CHECK-TAIL-RZ-NEXT: .cfi_def_cfa_offset 0 207; CHECK-TAIL-RZ-NEXT: add sp, sp, #32 208; CHECK-TAIL-RZ-NEXT: .cfi_def_cfa_offset -32 209; CHECK-TAIL-RZ-NEXT: .cfi_restore w20 210; CHECK-TAIL-RZ-NEXT: ret 211 212 ; Make sure there is a callee-save register to save/restore. 213 call void asm sideeffect "nop", "~{x20}"() nounwind 214 ret void 215} 216 217; Check that arg stack pop is done after callee-save restore when no frame pointer is used. 218define fastcc void @func_stack32_leaf_local([8 x i64], i128 %stacked0, i128 %stacked1) uwtable { 219; CHECK-LABEL: func_stack32_leaf_local: 220; CHECK: sub sp, sp, #32 221; CHECK-NEXT: .cfi_def_cfa_offset 32 222; CHECK-NEXT: str x20, [sp, #16] 223; CHECK: nop 224; CHECK-NEXT: //NO_APP 225; CHECK-NEXT: ldr x20, [sp, #16] 226; CHECK-NEXT: add sp, sp, #32 227; CHECK-NEXT: .cfi_def_cfa_offset 0 228; CHECK-NEXT: .cfi_restore w20 229; CHECK-NEXT: ret 230 231; CHECK-TAIL-LABEL: func_stack32_leaf_local: 232; CHECK-TAIL: sub sp, sp, #32 233; CHECK-TAIL-NEXT: .cfi_def_cfa_offset 32 234; CHECK-TAIL-NEXT: str x20, [sp, #16] 235; CHECK-TAIL: nop 236; CHECK-TAIL-NEXT: //NO_APP 237; CHECK-TAIL-NEXT: ldr x20, [sp, #16] 238; CHECK-TAIL-NEXT: add sp, sp, #64 239; CHECK-TAIL-NEXT: .cfi_def_cfa_offset -32 240; CHECK-TAIL-NEXT: .cfi_restore w20 241; CHECK-TAIL-NEXT: ret 242 243; CHECK-TAIL-RZ-LABEL: func_stack32_leaf_local: 244; CHECK-TAIL-RZ: str x20, [sp, #-16]! 245; CHECK-TAIL-RZ-NOT: sub sp, sp 246; CHECK-TAIL-RZ: nop 247; CHECK-TAIL-RZ-NEXT: //NO_APP 248; CHECK-TAIL-RZ-NEXT: ldr x20, [sp], #16 249; CHECK-TAIL-RZ-NEXT: .cfi_def_cfa_offset 0 250; CHECK-TAIL-RZ-NEXT: add sp, sp, #32 251; CHECK-TAIL-RZ-NEXT: .cfi_def_cfa_offset -32 252; CHECK-TAIL-RZ-NEXT: .cfi_restore w20 253; CHECK-TAIL-RZ-NEXT: ret 254 255 %val0 = alloca [2 x i64], align 8 256 257 ; Make sure there is a callee-save register to save/restore. 258 call void asm sideeffect "nop", "~{x20}"() nounwind 259 ret void 260} 261 262; Check that arg stack pop is done after callee-save restore when no frame pointer is used. 263define fastcc void @func_stack32_leaf_local_nocs([8 x i64], i128 %stacked0, i128 %stacked1) uwtable { 264; CHECK-LABEL: func_stack32_leaf_local_nocs: 265; CHECK: sub sp, sp, #16 266; CHECK-NEXT: .cfi_def_cfa_offset 16 267; CHECK-NEXT: add sp, sp, #16 268; CHECK-NEXT: .cfi_def_cfa_offset 0 269; CHECK-NEXT: ret 270 271; CHECK-TAIL-LABEL: func_stack32_leaf_local_nocs: 272; CHECK-TAIL: sub sp, sp, #16 273; CHECK-TAIL-NEXT: .cfi_def_cfa_offset 16 274; CHECK-TAIL-NEXT: add sp, sp, #48 275; CHECK-TAIL-NEXT: .cfi_def_cfa_offset -32 276; CHECK-TAIL-NEXT: ret 277 278; CHECK-TAIL-RZ-LABEL: func_stack32_leaf_local_nocs: 279; CHECK-TAIL-RZ: add sp, sp, #32 280; CHECK-TAIL-RZ-NEXT: .cfi_def_cfa_offset -32 281; CHECK-TAIL-RZ-NEXT: ret 282 283 %val0 = alloca [2 x i64], align 8 284 285 ret void 286} 287