1; RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -disable-post-ra < %s | FileCheck %s 2; RUN: llc -verify-machineinstrs -mtriple=arm64-apple-ios -disable-post-ra < %s | FileCheck %s --check-prefix=CHECK-MACHO 3 4; This test aims to check basic correctness of frame layout & 5; frame access code. There are 8 functions in this test file, 6; each function implements one element in the cartesian product 7; of: 8; . a function having a VLA/noVLA 9; . a function with dynamic stack realignment/no dynamic stack realignment. 10; . a function needing a frame pionter/no frame pointer, 11; since the presence/absence of these has influence on the frame 12; layout and which pointer to use to access various part of the 13; frame (bp,sp,fp). 14; 15; Furthermore: in every test function: 16; . there is always one integer and 1 floating point argument to be able 17; to check those are accessed correctly. 18; . there is always one local variable to check that is accessed 19; correctly 20; 21; The LLVM-IR below was produced by clang on the following C++ code: 22;extern "C" int g(); 23;extern "C" int novla_nodynamicrealign_call(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, 24; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 25;{ 26; // use an argument passed on the stack. 27; volatile int l1; 28; return i10 + (int)d10 + l1 + g(); 29;} 30;extern "C" int novla_nodynamicrealign_nocall(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, 31; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 32;{ 33; // use an argument passed on the stack. 34; volatile int l1; 35; return i10 + (int)d10 + l1; 36;} 37;extern "C" int novla_dynamicrealign_call(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, 38; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 39;{ 40; // use an argument passed on the stack. 41; alignas(128) volatile int l1; 42; return i10 + (int)d10 + l1 + g(); 43;} 44;extern "C" int novla_dynamicrealign_nocall(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, 45; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 46;{ 47; // use an argument passed on the stack. 48; alignas(128) volatile int l1; 49; return i10 + (int)d10 + l1; 50;} 51; 52;extern "C" int vla_nodynamicrealign_call(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, 53; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 54;{ 55; // use an argument passed on the stack. 56; volatile int l1; 57; volatile int vla[i1]; 58; return i10 + (int)d10 + l1 + g() + vla[0]; 59;} 60;extern "C" int vla_nodynamicrealign_nocall(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, 61; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 62;{ 63; // use an argument passed on the stack. 64; volatile int l1; 65; volatile int vla[i1]; 66; return i10 + (int)d10 + l1 + vla[0]; 67;} 68;extern "C" int vla_dynamicrealign_call(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, 69; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 70;{ 71; // use an argument passed on the stack. 72; alignas(128) volatile int l1; 73; volatile int vla[i1]; 74; return i10 + (int)d10 + l1 + g() + vla[0]; 75;} 76;extern "C" int vla_dynamicrealign_nocall(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, 77; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 78;{ 79; // use an argument passed on the stack. 80; alignas(128) volatile int l1; 81; volatile int vla[i1]; 82; return i10 + (int)d10 + l1 + vla[0]; 83;} 84 85 86 87define i32 @novla_nodynamicrealign_call(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #0 { 88entry: 89 %l1 = alloca i32, align 4 90 %conv = fptosi double %d10 to i32 91 %add = add nsw i32 %conv, %i10 92 %l1.0.l1.0. = load volatile i32, i32* %l1, align 4 93 %add1 = add nsw i32 %add, %l1.0.l1.0. 94 %call = tail call i32 @g() 95 %add2 = add nsw i32 %add1, %call 96 ret i32 %add2 97} 98; CHECK-LABEL: novla_nodynamicrealign_call 99; CHECK: .cfi_startproc 100; Check that used callee-saved registers are saved 101; CHECK: str x19, [sp, #-32]! 102; Check that the frame pointer is created: 103; CHECK: stp x29, x30, [sp, #16] 104; CHECK: add x29, sp, #16 105; Check correctness of cfi pseudo-instructions 106; CHECK: .cfi_def_cfa w29, 16 107; CHECK: .cfi_offset w30, -8 108; CHECK: .cfi_offset w29, -16 109; CHECK: .cfi_offset w19, -32 110; Check correct access to arguments passed on the stack, through frame pointer 111; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 112; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 113; Check correct access to local variable on the stack, through stack pointer 114; CHECK: ldr w[[ILOC:[0-9]+]], [sp, #12] 115; Check epilogue: 116; CHECK: ldp x29, x30, [sp, #16] 117; CHECK: ldr x19, [sp], #32 118; CHECK: ret 119; CHECK: .cfi_endproc 120 121; CHECK-MACHO-LABEL: _novla_nodynamicrealign_call: 122; CHECK-MACHO: .cfi_startproc 123; Check that used callee-saved registers are saved 124; CHECK-MACHO: stp x20, x19, [sp, #-32]! 125; Check that the frame pointer is created: 126; CHECK-MACHO: stp x29, x30, [sp, #16] 127; CHECK-MACHO: add x29, sp, #16 128; Check correctness of cfi pseudo-instructions 129; CHECK-MACHO: .cfi_def_cfa w29, 16 130; CHECK-MACHO: .cfi_offset w30, -8 131; CHECK-MACHO: .cfi_offset w29, -16 132; CHECK-MACHO: .cfi_offset w19, -24 133; CHECK-MACHO: .cfi_offset w20, -32 134; Check correct access to arguments passed on the stack, through frame pointer 135; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32] 136; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20] 137; Check correct access to local variable on the stack, through stack pointer 138; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [sp, #12] 139; Check epilogue: 140; CHECK-MACHO: ldp x29, x30, [sp, #16] 141; CHECK-MACHO: ldp x20, x19, [sp], #32 142; CHECK-MACHO: ret 143; CHECK-MACHO: .cfi_endproc 144 145 146declare i32 @g() #0 147 148; Function Attrs: nounwind 149define i32 @novla_nodynamicrealign_nocall(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 { 150entry: 151 %l1 = alloca i32, align 4 152 %conv = fptosi double %d10 to i32 153 %add = add nsw i32 %conv, %i10 154 %l1.0.l1.0. = load volatile i32, i32* %l1, align 4 155 %add1 = add nsw i32 %add, %l1.0.l1.0. 156 ret i32 %add1 157} 158; CHECK-LABEL: novla_nodynamicrealign_nocall 159; Check that space is reserved for one local variable on the stack. 160; CHECK: sub sp, sp, #16 // =16 161; Check correct access to arguments passed on the stack, through stack pointer 162; CHECK: ldr d[[DARG:[0-9]+]], [sp, #40] 163; CHECK: ldr w[[IARG:[0-9]+]], [sp, #24] 164; Check correct access to local variable on the stack, through stack pointer 165; CHECK: ldr w[[ILOC:[0-9]+]], [sp, #12] 166; Check epilogue: 167; CHECK: add sp, sp, #16 // =16 168; CHECK: ret 169 170 171define i32 @novla_dynamicrealign_call(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #0 { 172entry: 173 %l1 = alloca i32, align 128 174 %conv = fptosi double %d10 to i32 175 %add = add nsw i32 %conv, %i10 176 %l1.0.l1.0. = load volatile i32, i32* %l1, align 128 177 %add1 = add nsw i32 %add, %l1.0.l1.0. 178 %call = tail call i32 @g() 179 %add2 = add nsw i32 %add1, %call 180 ret i32 %add2 181} 182 183; CHECK-LABEL: novla_dynamicrealign_call 184; CHECK: .cfi_startproc 185; Check that used callee-saved registers are saved 186; CHECK: str x19, [sp, #-32]! 187; Check that the frame pointer is created: 188; CHECK: stp x29, x30, [sp, #16] 189; CHECK: add x29, sp, #16 190; Check the dynamic realignment of the stack pointer to a 128-byte boundary 191; CHECK: sub x9, sp, #96 192; CHECK: and sp, x9, #0xffffffffffffff80 193; Check correctness of cfi pseudo-instructions 194; CHECK: .cfi_def_cfa w29, 16 195; CHECK: .cfi_offset w30, -8 196; CHECK: .cfi_offset w29, -16 197; CHECK: .cfi_offset w19, -32 198; Check correct access to arguments passed on the stack, through frame pointer 199; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 200; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 201; Check correct access to local variable on the stack, through re-aligned stack pointer 202; CHECK: ldr w[[ILOC:[0-9]+]], [sp] 203; Check epilogue: 204; Check that stack pointer get restored from frame pointer. 205; CHECK: sub sp, x29, #16 // =16 206; CHECK: ldp x29, x30, [sp, #16] 207; CHECK: ldr x19, [sp], #32 208; CHECK: ret 209; CHECK: .cfi_endproc 210 211; CHECK-MACHO-LABEL: _novla_dynamicrealign_call: 212; CHECK-MACHO: .cfi_startproc 213; Check that used callee-saved registers are saved 214; CHECK-MACHO: stp x20, x19, [sp, #-32]! 215; Check that the frame pointer is created: 216; CHECK-MACHO: stp x29, x30, [sp, #16] 217; CHECK-MACHO: add x29, sp, #16 218; Check the dynamic realignment of the stack pointer to a 128-byte boundary 219; CHECK-MACHO: sub x9, sp, #96 220; CHECK-MACHO: and sp, x9, #0xffffffffffffff80 221; Check correctness of cfi pseudo-instructions 222; CHECK-MACHO: .cfi_def_cfa w29, 16 223; CHECK-MACHO: .cfi_offset w30, -8 224; CHECK-MACHO: .cfi_offset w29, -16 225; CHECK-MACHO: .cfi_offset w19, -24 226; CHECK-MACHO: .cfi_offset w20, -32 227; Check correct access to arguments passed on the stack, through frame pointer 228; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32] 229; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20] 230; Check correct access to local variable on the stack, through re-aligned stack pointer 231; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [sp] 232; Check epilogue: 233; Check that stack pointer get restored from frame pointer. 234; CHECK-MACHO: sub sp, x29, #16 235; CHECK-MACHO: ldp x29, x30, [sp, #16] 236; CHECK-MACHO: ldp x20, x19, [sp], #32 237; CHECK-MACHO: ret 238; CHECK-MACHO: .cfi_endproc 239 240 241; Function Attrs: nounwind 242define i32 @novla_dynamicrealign_nocall(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 { 243entry: 244 %l1 = alloca i32, align 128 245 %conv = fptosi double %d10 to i32 246 %add = add nsw i32 %conv, %i10 247 %l1.0.l1.0. = load volatile i32, i32* %l1, align 128 248 %add1 = add nsw i32 %add, %l1.0.l1.0. 249 ret i32 %add1 250} 251 252; CHECK-LABEL: novla_dynamicrealign_nocall 253; Check that the frame pointer is created: 254; CHECK: stp x29, x30, [sp, #-16]! 255; CHECK: mov x29, sp 256; Check the dynamic realignment of the stack pointer to a 128-byte boundary 257; CHECK: sub x9, sp, #112 258; CHECK: and sp, x9, #0xffffffffffffff80 259; Check correct access to arguments passed on the stack, through frame pointer 260; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 261; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 262; Check correct access to local variable on the stack, through re-aligned stack pointer 263; CHECK: ldr w[[ILOC:[0-9]+]], [sp] 264; Check epilogue: 265; Check that stack pointer get restored from frame pointer. 266; CHECK: mov sp, x29 267; CHECK: ldp x29, x30, [sp], #16 268; CHECK: ret 269 270 271define i32 @vla_nodynamicrealign_call(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #0 { 272entry: 273 %l1 = alloca i32, align 4 274 %0 = zext i32 %i1 to i64 275 %vla = alloca i32, i64 %0, align 4 276 %conv = fptosi double %d10 to i32 277 %add = add nsw i32 %conv, %i10 278 %l1.0.l1.0. = load volatile i32, i32* %l1, align 4 279 %add1 = add nsw i32 %add, %l1.0.l1.0. 280 %call = tail call i32 @g() 281 %add2 = add nsw i32 %add1, %call 282 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 283 %add3 = add nsw i32 %add2, %1 284 ret i32 %add3 285} 286 287; CHECK-LABEL: vla_nodynamicrealign_call 288; CHECK: .cfi_startproc 289; Check that used callee-saved registers are saved 290; CHECK: stp x20, x19, [sp, #-32]! 291; Check that the frame pointer is created: 292; CHECK: stp x29, x30, [sp, #16] 293; CHECK: add x29, sp, #16 294; Check that space is reserved on the stack for the local variable, 295; rounded up to a multiple of 16 to keep the stack pointer 16-byte aligned. 296; CHECK: sub sp, sp, #16 297; Check correctness of cfi pseudo-instructions 298; CHECK: .cfi_def_cfa w29, 16 299; CHECK: .cfi_offset w30, -8 300; CHECK: .cfi_offset w29, -16 301; CHECK: .cfi_offset w19, -24 302; CHECK: .cfi_offset w20, -32 303; Check correct access to arguments passed on the stack, through frame pointer 304; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 305; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 306; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 307; CHECK: mov w9, w0 308; CHECK: mov x10, sp 309; CHECK: lsl x9, x9, #2 310; CHECK: add x9, x9, #15 311; CHECK: and x9, x9, #0x7fffffff0 312; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 313; CHECK: mov sp, x[[VLASPTMP]] 314; Check correct access to local variable, through frame pointer 315; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-20] 316; Check correct accessing of the VLA variable through the base pointer 317; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 318; Check epilogue: 319; Check that stack pointer get restored from frame pointer. 320; CHECK: sub sp, x29, #16 // =16 321; CHECK: ldp x29, x30, [sp, #16] 322; CHECK: ldp x20, x19, [sp], #32 323; CHECK: ret 324; CHECK: .cfi_endproc 325 326 327; Function Attrs: nounwind 328define i32 @vla_nodynamicrealign_nocall(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 { 329entry: 330 %l1 = alloca i32, align 4 331 %0 = zext i32 %i1 to i64 332 %vla = alloca i32, i64 %0, align 4 333 %conv = fptosi double %d10 to i32 334 %add = add nsw i32 %conv, %i10 335 %l1.0.l1.0. = load volatile i32, i32* %l1, align 4 336 %add1 = add nsw i32 %add, %l1.0.l1.0. 337 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 338 %add2 = add nsw i32 %add1, %1 339 ret i32 %add2 340} 341 342; CHECK-LABEL: vla_nodynamicrealign_nocall 343; Check that the frame pointer is created: 344; CHECK: stp x29, x30, [sp, #-16]! 345; CHECK: mov x29, sp 346; Check that space is reserved on the stack for the local variable, 347; rounded up to a multiple of 16 to keep the stack pointer 16-byte aligned. 348; CHECK: sub sp, sp, #16 349; Check correctness of cfi pseudo-instructions 350; Check correct access to arguments passed on the stack, through frame pointer 351; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 352; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 353; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 354; CHECK: mov w9, w0 355; CHECK: mov x10, sp 356; CHECK: lsl x9, x9, #2 357; CHECK: add x9, x9, #15 358; CHECK: and x9, x9, #0x7fffffff0 359; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 360; CHECK: mov sp, x[[VLASPTMP]] 361; Check correct access to local variable, through frame pointer 362; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-4] 363; Check correct accessing of the VLA variable through the base pointer 364; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 365; Check epilogue: 366; Check that stack pointer get restored from frame pointer. 367; CHECK: mov sp, x29 368; CHECK: ldp x29, x30, [sp], #16 369; CHECK: ret 370 371 372define i32 @vla_dynamicrealign_call(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #0 { 373entry: 374 %l1 = alloca i32, align 128 375 %0 = zext i32 %i1 to i64 376 %vla = alloca i32, i64 %0, align 4 377 %conv = fptosi double %d10 to i32 378 %add = add nsw i32 %conv, %i10 379 %l1.0.l1.0. = load volatile i32, i32* %l1, align 128 380 %add1 = add nsw i32 %add, %l1.0.l1.0. 381 %call = tail call i32 @g() 382 %add2 = add nsw i32 %add1, %call 383 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 384 %add3 = add nsw i32 %add2, %1 385 ret i32 %add3 386} 387 388; CHECK-LABEL: vla_dynamicrealign_call 389; CHECK: .cfi_startproc 390; Check that used callee-saved registers are saved 391; CHECK: str x21, [sp, #-48]! 392; CHECK: stp x20, x19, [sp, #16] 393; Check that the frame pointer is created: 394; CHECK: stp x29, x30, [sp, #32] 395; CHECK: add x29, sp, #32 396; Check that the stack pointer gets re-aligned to 128 397; bytes & the base pointer (x19) gets initialized to 398; this 128-byte aligned area for local variables & 399; spill slots 400; CHECK: sub x9, sp, #80 // =80 401; CHECK: and sp, x9, #0xffffffffffffff80 402; CHECK: mov x19, sp 403; Check correctness of cfi pseudo-instructions 404; CHECK: .cfi_def_cfa w29, 16 405; CHECK: .cfi_offset w30, -8 406; CHECK: .cfi_offset w29, -16 407; CHECK: .cfi_offset w19, -24 408; CHECK: .cfi_offset w20, -32 409; CHECK: .cfi_offset w21, -48 410; Check correct access to arguments passed on the stack, through frame pointer 411; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 412; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 413; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 414; and set-up of base pointer (x19). 415; CHECK: mov w9, w0 416; CHECK: mov x10, sp 417; CHECK: lsl x9, x9, #2 418; CHECK: add x9, x9, #15 419; CHECK: and x9, x9, #0x7fffffff0 420; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 421; CHECK: mov sp, x[[VLASPTMP]] 422; Check correct access to local variable, through base pointer 423; CHECK: ldr w[[ILOC:[0-9]+]], [x19] 424; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 425; Check epilogue: 426; Check that stack pointer get restored from frame pointer. 427; CHECK: sub sp, x29, #32 428; CHECK: ldp x29, x30, [sp, #32] 429; CHECK: ldp x20, x19, [sp, #16] 430; CHECK: ldr x21, [sp], #48 431; CHECK: ret 432; CHECK: .cfi_endproc 433 434; CHECK-MACHO-LABEL: _vla_dynamicrealign_call: 435; CHECK-MACHO: .cfi_startproc 436; Check that used callee-saved registers are saved 437; CHECK-MACHO: stp x22, x21, [sp, #-48]! 438; CHECK-MACHO: stp x20, x19, [sp, #16] 439; Check that the frame pointer is created: 440; CHECK-MACHO: stp x29, x30, [sp, #32] 441; CHECK-MACHO: add x29, sp, #32 442; Check that the stack pointer gets re-aligned to 128 443; bytes & the base pointer (x19) gets initialized to 444; this 128-byte aligned area for local variables & 445; spill slots 446; CHECK-MACHO: sub x9, sp, #80 447; CHECK-MACHO: and sp, x9, #0xffffffffffffff80 448; CHECK-MACHO: mov x19, sp 449; Check correctness of cfi pseudo-instructions 450; CHECK-MACHO: .cfi_def_cfa w29, 16 451; CHECK-MACHO: .cfi_offset w30, -8 452; CHECK-MACHO: .cfi_offset w29, -16 453; CHECK-MACHO: .cfi_offset w19, -24 454; CHECK-MACHO: .cfi_offset w20, -32 455; CHECK-MACHO: .cfi_offset w21, -40 456; CHECK-MACHO: .cfi_offset w22, -48 457; Check correct access to arguments passed on the stack, through frame pointer 458; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20] 459; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32] 460; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 461; and set-up of base pointer (x19). 462; CHECK-MACHO: mov w9, w0 463; CHECK-MACHO: mov x10, sp 464; CHECK-MACHO: lsl x9, x9, #2 465; CHECK-MACHO: add x9, x9, #15 466; CHECK-MACHO: and x9, x9, #0x7fffffff0 467; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x9 468; CHECK-MACHO: mov sp, x[[VLASPTMP]] 469; Check correct access to local variable, through base pointer 470; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19] 471; CHECK-MACHO: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 472; Check epilogue: 473; Check that stack pointer get restored from frame pointer. 474; CHECK-MACHO: sub sp, x29, #32 475; CHECK-MACHO: ldp x29, x30, [sp, #32] 476; CHECK-MACHO: ldp x20, x19, [sp, #16] 477; CHECK-MACHO: ldp x22, x21, [sp], #48 478; CHECK-MACHO: ret 479; CHECK-MACHO: .cfi_endproc 480 481 482; Function Attrs: nounwind 483define i32 @vla_dynamicrealign_nocall(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 { 484entry: 485 %l1 = alloca i32, align 128 486 %0 = zext i32 %i1 to i64 487 %vla = alloca i32, i64 %0, align 4 488 %conv = fptosi double %d10 to i32 489 %add = add nsw i32 %conv, %i10 490 %l1.0.l1.0. = load volatile i32, i32* %l1, align 128 491 %add1 = add nsw i32 %add, %l1.0.l1.0. 492 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 493 %add2 = add nsw i32 %add1, %1 494 ret i32 %add2 495} 496 497; CHECK-LABEL: vla_dynamicrealign_nocall 498; Check that used callee-saved registers are saved 499; CHECK: str x19, [sp, #-32]! 500; Check that the frame pointer is created: 501; CHECK: stp x29, x30, [sp, #16] 502; CHECK: add x29, sp, #16 503; Check that the stack pointer gets re-aligned to 128 504; bytes & the base pointer (x19) gets initialized to 505; this 128-byte aligned area for local variables & 506; spill slots 507; CHECK: sub x9, sp, #96 508; CHECK: and sp, x9, #0xffffffffffffff80 509; CHECK: mov x19, sp 510; Check correct access to arguments passed on the stack, through frame pointer 511; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 512; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 513; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 514; and set-up of base pointer (x19). 515; CHECK: mov w9, w0 516; CHECK: mov x10, sp 517; CHECK: lsl x9, x9, #2 518; CHECK: add x9, x9, #15 519; CHECK: and x9, x9, #0x7fffffff0 520; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 521; CHECK: mov sp, x[[VLASPTMP]] 522; Check correct access to local variable, through base pointer 523; CHECK: ldr w[[ILOC:[0-9]+]], [x19] 524; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 525; Check epilogue: 526; Check that stack pointer get restored from frame pointer. 527; CHECK: sub sp, x29, #16 528; CHECK: ldp x29, x30, [sp, #16] 529; CHECK: ldr x19, [sp], #32 530; CHECK: ret 531 532; CHECK-MACHO-LABEL: _vla_dynamicrealign_nocall: 533; Check that used callee-saved registers are saved 534; CHECK-MACHO: stp x20, x19, [sp, #-32]! 535; Check that the frame pointer is created: 536; CHECK-MACHO: stp x29, x30, [sp, #16] 537; CHECK-MACHO: add x29, sp, #16 538; Check that the stack pointer gets re-aligned to 128 539; bytes & the base pointer (x19) gets initialized to 540; this 128-byte aligned area for local variables & 541; spill slots 542; CHECK-MACHO: sub x9, sp, #96 543; CHECK-MACHO: and sp, x9, #0xffffffffffffff80 544; CHECK-MACHO: mov x19, sp 545; Check correct access to arguments passed on the stack, through frame pointer 546; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20] 547; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32] 548; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 549; and set-up of base pointer (x19). 550; CHECK-MACHO: mov w9, w0 551; CHECK-MACHO: mov x10, sp 552; CHECK-MACHO: lsl x9, x9, #2 553; CHECK-MACHO: add x9, x9, #15 554; CHECK-MACHO: and x9, x9, #0x7fffffff0 555; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x9 556; CHECK-MACHO: mov sp, x[[VLASPTMP]] 557; Check correct access to local variable, through base pointer 558; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19] 559; CHECK-MACHO: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 560; Check epilogue: 561; Check that stack pointer get restored from frame pointer. 562; CHECK-MACHO: sub sp, x29, #16 563; CHECK-MACHO: ldp x29, x30, [sp, #16] 564; CHECK-MACHO: ldp x20, x19, [sp], #32 565; CHECK-MACHO: ret 566 567 568; Function Attrs: nounwind 569define i32 @vla_dynamicrealign_nocall_large_align(i32 %i1, i32 %i2, i32 %i3, i32 %i4, i32 %i5, i32 %i6, i32 %i7, i32 %i8, i32 %i9, i32 %i10, double %d1, double %d2, double %d3, double %d4, double %d5, double %d6, double %d7, double %d8, double %d9, double %d10) #1 { 570entry: 571 %l1 = alloca i32, align 32768 572 %0 = zext i32 %i1 to i64 573 %vla = alloca i32, i64 %0, align 4 574 %conv = fptosi double %d10 to i32 575 %add = add nsw i32 %conv, %i10 576 %l1.0.l1.0. = load volatile i32, i32* %l1, align 32768 577 %add1 = add nsw i32 %add, %l1.0.l1.0. 578 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 579 %add2 = add nsw i32 %add1, %1 580 ret i32 %add2 581} 582 583; CHECK-LABEL: vla_dynamicrealign_nocall_large_align 584; Check that used callee-saved registers are saved 585; CHECK: stp x28, x19, [sp, #-32]! 586; Check that the frame pointer is created: 587; CHECK: stp x29, x30, [sp, #16] 588; CHECK: add x29, sp, #16 589; Check that the stack pointer gets re-aligned to 128 590; bytes & the base pointer (x19) gets initialized to 591; this 128-byte aligned area for local variables & 592; spill slots 593; CHECK: sub x9, sp, #7, lsl #12 594; CHECK: and sp, x9, #0xffffffffffff8000 595; CHECK: mov x19, sp 596; Check correct access to arguments passed on the stack, through frame pointer 597; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 598; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 599; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 600; and set-up of base pointer (x19). 601; CHECK: mov w9, w0 602; CHECK: mov x10, sp 603; CHECK: lsl x9, x9, #2 604; CHECK: add x9, x9, #15 605; CHECK: and x9, x9, #0x7fffffff0 606; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 607; CHECK: mov sp, x[[VLASPTMP]] 608; Check correct access to local variable, through base pointer 609; CHECK: ldr w[[ILOC:[0-9]+]], [x19] 610; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 611; Check epilogue: 612; Check that stack pointer get restored from frame pointer. 613; CHECK: sub sp, x29, #16 614; CHECK: ldp x29, x30, [sp, #16] 615; CHECK: ldp x28, x19, [sp], #32 616; CHECK: ret 617 618; CHECK-MACHO-LABEL: _vla_dynamicrealign_nocall_large_align: 619; Check that used callee-saved registers are saved 620; CHECK-MACHO: stp x20, x19, [sp, #-32]! 621; Check that the frame pointer is created: 622; CHECK-MACHO: stp x29, x30, [sp, #16] 623; CHECK-MACHO: add x29, sp, #16 624; Check that the stack pointer gets re-aligned to 128 625; bytes & the base pointer (x19) gets initialized to 626; this 128-byte aligned area for local variables & 627; spill slots 628; CHECK-MACHO: sub x9, sp, #7, lsl #12 629; CHECK-MACHO: and sp, x9, #0xffffffffffff8000 630; CHECK-MACHO: mov x19, sp 631; Check correct access to arguments passed on the stack, through frame pointer 632; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20] 633; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32] 634; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 635; and set-up of base pointer (x19). 636; CHECK-MACHO: mov w9, w0 637; CHECK-MACHO: mov x10, sp 638; CHECK-MACHO: lsl x9, x9, #2 639; CHECK-MACHO: add x9, x9, #15 640; CHECK-MACHO: and x9, x9, #0x7fffffff0 641; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x9 642; CHECK-MACHO: mov sp, x[[VLASPTMP]] 643; Check correct access to local variable, through base pointer 644; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19] 645; CHECK-MACHO: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 646; Check epilogue: 647; Check that stack pointer get restored from frame pointer. 648; CHECK-MACHO: sub sp, x29, #16 649; CHECK-MACHO: ldp x29, x30, [sp, #16] 650; CHECK-MACHO: ldp x20, x19, [sp], #32 651; CHECK-MACHO: ret 652 653 654define void @realign_conditional(i1 %b) { 655entry: 656 br i1 %b, label %bb0, label %bb1 657 658bb0: 659 %MyAlloca = alloca i8, i64 64, align 32 660 br label %bb1 661 662bb1: 663 ret void 664} 665 666; CHECK-LABEL: realign_conditional 667; No realignment in the prologue. 668; CHECK-NOT: and 669; CHECK-NOT: 0xffffffffffffffe0 670; CHECK: tbz {{.*}} .[[LABEL:.*]] 671; Stack is realigned in a non-entry BB. 672; CHECK: sub [[REG:x[01-9]+]], sp, #64 673; CHECK: and sp, [[REG]], #0xffffffffffffffe0 674; CHECK: .[[LABEL]]: 675; CHECK: ret 676 677 678define void @realign_conditional2(i1 %b) { 679entry: 680 %tmp = alloca i8, i32 4 681 br i1 %b, label %bb0, label %bb1 682 683bb0: 684 %MyAlloca = alloca i8, i64 64, align 32 685 br label %bb1 686 687bb1: 688 ret void 689} 690 691; CHECK-LABEL: realign_conditional2 692; Extra realignment in the prologue (performance issue). 693; CHECK: tbz {{.*}} .[[LABEL:.*]] 694; CHECK: sub x9, sp, #32 // =32 695; CHECK: and sp, x9, #0xffffffffffffffe0 696; CHECK: mov x19, sp 697; Stack is realigned in a non-entry BB. 698; CHECK: sub [[REG:x[01-9]+]], sp, #64 699; CHECK: and sp, [[REG]], #0xffffffffffffffe0 700; CHECK: .[[LABEL]]: 701; CHECK: ret 702 703attributes #0 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 704attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" } 705 706!1 = !{!2, !2, i64 0} 707!2 = !{!"int", !3, i64 0} 708!3 = !{!"omnipotent char", !4, i64 0} 709!4 = !{!"Simple C/C++ TBAA"} 710