1; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -disable-fp-elim -tailcallopt | FileCheck %s -check-prefix CHECK-TAIL 2; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -disable-fp-elim | FileCheck %s 3; RUN: llc -verify-machineinstrs < %s -mtriple=aarch64-none-linux-gnu -disable-fp-elim -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() { 9; CHECK-LABEL: func_stack0: 10; CHECK: mov x29, sp 11; CHECK: str w{{[0-9]+}}, [sp, #-32]! 12 13; CHECK-TAIL-LABEL: func_stack0: 14; CHECK-TAIL: stp x29, x30, [sp, #-16]! 15; CHECK-TAIL-NEXT: mov x29, sp 16; CHECK-TAIL: str w{{[0-9]+}}, [sp, #-32]! 17 18 19 call fastcc void @func_stack8([8 x i32] undef, i32 42) 20; CHECK: bl func_stack8 21; CHECK-NOT: sub sp, sp, 22 23; CHECK-TAIL: bl func_stack8 24; CHECK-TAIL: sub sp, sp, #16 25 26 27 call fastcc void @func_stack32([8 x i32] undef, i128 0, i128 9) 28; CHECK: bl func_stack32 29; CHECK-NOT: sub sp, sp, 30 31 32; CHECK-TAIL: bl func_stack32 33; CHECK-TAIL: sub sp, sp, #32 34 35 36 call fastcc void @func_stack0() 37; CHECK: bl func_stack0 38; CHECK-NOT: sub sp, sp 39 40 41; CHECK-TAIL: bl func_stack0 42; CHECK-TAIL-NOT: sub sp, sp 43 44 ret void 45; CHECK: add sp, sp, #32 46; CHECK-NEXT: ldp x29, x30, [sp], #16 47; CHECK-NEXT: ret 48 49 50; CHECK-TAIL: add sp, sp, #32 51; CHECK-TAIL-NEXT: ldp x29, x30, [sp], #16 52; CHECK-TAIL-NEXT: ret 53} 54 55define fastcc void @func_stack8([8 x i32], i32 %stacked) { 56; CHECK-LABEL: func_stack8: 57; CHECK: stp x29, x30, [sp, #-16]! 58; CHECK: mov x29, sp 59; CHECK: str w{{[0-9]+}}, [sp, #-32]! 60 61 62; CHECK-TAIL-LABEL: func_stack8: 63; CHECK-TAIL: stp x29, x30, [sp, #-16]! 64; CHECK-TAIL: mov x29, sp 65; CHECK-TAIL: str w{{[0-9]+}}, [sp, #-32]! 66 67 68 call fastcc void @func_stack8([8 x i32] undef, i32 42) 69; CHECK: bl func_stack8 70; CHECK-NOT: sub sp, sp, 71 72 73; CHECK-TAIL: bl func_stack8 74; CHECK-TAIL: sub sp, sp, #16 75 76 77 call fastcc void @func_stack32([8 x i32] undef, i128 0, i128 9) 78; CHECK: bl func_stack32 79; CHECK-NOT: sub sp, sp, 80 81 82; CHECK-TAIL: bl func_stack32 83; CHECK-TAIL: sub sp, sp, #32 84 85 86 call fastcc void @func_stack0() 87; CHECK: bl func_stack0 88; CHECK-NOT: sub sp, sp 89 90; CHECK-TAIL: bl func_stack0 91; CHECK-TAIL-NOT: sub sp, sp 92 93 ret void 94; CHECK: add sp, sp, #32 95; CHECK-NEXT: ldp x29, x30, [sp], #16 96; CHECK-NEXT: ret 97 98 99; CHECK-TAIL: add sp, sp, #32 100; CHECK-TAIL-NEXT: ldp x29, x30, [sp], #16 101; CHECK-TAIL-NEXT: add sp, sp, #16 102; CHECK-TAIL-NEXT: ret 103} 104 105define fastcc void @func_stack32([8 x i32], i128 %stacked0, i128 %stacked1) { 106; CHECK-LABEL: func_stack32: 107; CHECK: mov x29, sp 108 109; CHECK-TAIL-LABEL: func_stack32: 110; CHECK-TAIL: mov x29, sp 111 112 113 call fastcc void @func_stack8([8 x i32] undef, i32 42) 114; CHECK: bl func_stack8 115; CHECK-NOT: sub sp, sp, 116 117; CHECK-TAIL: bl func_stack8 118; CHECK-TAIL: sub sp, sp, #16 119 120 121 call fastcc void @func_stack32([8 x i32] undef, i128 0, i128 9) 122; CHECK: bl func_stack32 123; CHECK-NOT: sub sp, sp, 124 125 126; CHECK-TAIL: bl func_stack32 127; CHECK-TAIL: sub sp, sp, #32 128 129 130 call fastcc void @func_stack0() 131; CHECK: bl func_stack0 132; CHECK-NOT: sub sp, sp 133 134 135; CHECK-TAIL: bl func_stack0 136; CHECK-TAIL-NOT: sub sp, sp 137 138 ret void 139; CHECK: add sp, sp, #32 140; CHECK-NEXT: ldp x29, x30, [sp], #16 141; CHECK-NEXT: ret 142 143; CHECK-TAIL: add sp, sp, #32 144; CHECK-TAIL-NEXT: ldp x29, x30, [sp], #16 145; CHECK-TAIL-NEXT: add sp, sp, #32 146; CHECK-TAIL-NEXT: ret 147} 148 149; Check that arg stack pop is done after callee-save restore when no frame pointer is used. 150define fastcc void @func_stack32_leaf([8 x i32], i128 %stacked0, i128 %stacked1) { 151; CHECK-LABEL: func_stack32_leaf: 152; CHECK: str x20, [sp, #-16]! 153; CHECK: nop 154; CHECK-NEXT: //NO_APP 155; CHECK-NEXT: ldr x20, [sp], #16 156; CHECK-NEXT: ret 157 158; CHECK-TAIL-LABEL: func_stack32_leaf: 159; CHECK-TAIL: str x20, [sp, #-16]! 160; CHECK-TAIL: nop 161; CHECK-TAIL-NEXT: //NO_APP 162; CHECK-TAIL-NEXT: ldr x20, [sp], #16 163; CHECK-TAIL-NEXT: add sp, sp, #32 164; CHECK-TAIL-NEXT: ret 165 166; CHECK-TAIL-RZ-LABEL: func_stack32_leaf: 167; CHECK-TAIL-RZ: str x20, [sp, #-16]! 168; CHECK-TAIL-RZ-NOT: sub sp, sp 169; CHECK-TAIL-RZ: nop 170; CHECK-TAIL-RZ-NEXT: //NO_APP 171; CHECK-TAIL-RZ-NEXT: ldr x20, [sp], #16 172; CHECK-TAIL-RZ-NEXT: add sp, sp, #32 173; CHECK-TAIL-RZ-NEXT: ret 174 175 ; Make sure there is a callee-save register to save/restore. 176 call void asm sideeffect "nop", "~{x20}"() nounwind 177 ret void 178} 179 180; Check that arg stack pop is done after callee-save restore when no frame pointer is used. 181define fastcc void @func_stack32_leaf_local([8 x i32], i128 %stacked0, i128 %stacked1) { 182; CHECK-LABEL: func_stack32_leaf_local: 183; CHECK: str x20, [sp, #-16]! 184; CHECK-NEXT: sub sp, sp, #16 185; CHECK: nop 186; CHECK-NEXT: //NO_APP 187; CHECK-NEXT: add sp, sp, #16 188; CHECK-NEXT: ldr x20, [sp], #16 189; CHECK-NEXT: ret 190 191; CHECK-TAIL-LABEL: func_stack32_leaf_local: 192; CHECK-TAIL: str x20, [sp, #-16]! 193; CHECK-TAIL-NEXT: sub sp, sp, #16 194; CHECK-TAIL: nop 195; CHECK-TAIL-NEXT: //NO_APP 196; CHECK-TAIL-NEXT: add sp, sp, #16 197; CHECK-TAIL-NEXT: ldr x20, [sp], #16 198; CHECK-TAIL-NEXT: add sp, sp, #32 199; CHECK-TAIL-NEXT: ret 200 201; CHECK-TAIL-RZ-LABEL: func_stack32_leaf_local: 202; CHECK-TAIL-RZ: str x20, [sp, #-16]! 203; CHECK-TAIL-RZ-NOT: sub sp, sp 204; CHECK-TAIL-RZ: nop 205; CHECK-TAIL-RZ-NEXT: //NO_APP 206; CHECK-TAIL-RZ-NEXT: ldr x20, [sp], #16 207; CHECK-TAIL-RZ-NEXT: add sp, sp, #32 208; CHECK-TAIL-RZ-NEXT: ret 209 210 %val0 = alloca [2 x i64], align 8 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_nocs([8 x i32], i128 %stacked0, i128 %stacked1) { 219; CHECK-LABEL: func_stack32_leaf_local_nocs: 220; CHECK: sub sp, sp, #16 221; CHECK: add sp, sp, #16 222; CHECK-NEXT: ret 223 224; CHECK-TAIL-LABEL: func_stack32_leaf_local_nocs: 225; CHECK-TAIL: sub sp, sp, #16 226; CHECK-TAIL: add sp, sp, #48 227; CHECK-TAIL-NEXT: ret 228 229; CHECK-TAIL-RZ-LABEL: func_stack32_leaf_local_nocs: 230; CHECK-TAIL-RZ: add sp, sp, #32 231; CHECK-TAIL-RZ-NEXT: ret 232 233 %val0 = alloca [2 x i64], align 8 234 235 ret void 236} 237