1; RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu < %s | FileCheck %s 2 3; This test aims to check basic correctness of frame layout & 4; frame access code. There are 8 functions in this test file, 5; each function implements one element in the cartesian product 6; of: 7; . a function having a VLA/noVLA 8; . a function with dynamic stack realignment/no dynamic stack realignment. 9; . a function needing a frame pionter/no frame pointer, 10; since the presence/absence of these has influence on the frame 11; layout and which pointer to use to access various part of the 12; frame (bp,sp,fp). 13; 14; Furthermore: in every test function: 15; . there is always one integer and 1 floating point argument to be able 16; to check those are accessed correctly. 17; . there is always one local variable to check that is accessed 18; correctly 19; 20; The LLVM-IR below was produced by clang on the following C++ code: 21;extern "C" int g(); 22;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, 23; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 24;{ 25; // use an argument passed on the stack. 26; volatile int l1; 27; return i10 + (int)d10 + l1 + g(); 28;} 29;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, 30; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 31;{ 32; // use an argument passed on the stack. 33; volatile int l1; 34; return i10 + (int)d10 + l1; 35;} 36;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, 37; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 38;{ 39; // use an argument passed on the stack. 40; alignas(128) volatile int l1; 41; return i10 + (int)d10 + l1 + g(); 42;} 43;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, 44; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 45;{ 46; // use an argument passed on the stack. 47; alignas(128) volatile int l1; 48; return i10 + (int)d10 + l1; 49;} 50; 51;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, 52; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 53;{ 54; // use an argument passed on the stack. 55; volatile int l1; 56; volatile int vla[i1]; 57; return i10 + (int)d10 + l1 + g() + vla[0]; 58;} 59;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, 60; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 61;{ 62; // use an argument passed on the stack. 63; volatile int l1; 64; volatile int vla[i1]; 65; return i10 + (int)d10 + l1 + vla[0]; 66;} 67;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, 68; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 69;{ 70; // use an argument passed on the stack. 71; alignas(128) volatile int l1; 72; volatile int vla[i1]; 73; return i10 + (int)d10 + l1 + g() + vla[0]; 74;} 75;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, 76; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10) 77;{ 78; // use an argument passed on the stack. 79; alignas(128) volatile int l1; 80; volatile int vla[i1]; 81; return i10 + (int)d10 + l1 + vla[0]; 82;} 83 84 85 86define 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 { 87entry: 88 %l1 = alloca i32, align 4 89 %conv = fptosi double %d10 to i32 90 %add = add nsw i32 %conv, %i10 91 %l1.0.l1.0. = load volatile i32, i32* %l1, align 4 92 %add1 = add nsw i32 %add, %l1.0.l1.0. 93 %call = tail call i32 @g() 94 %add2 = add nsw i32 %add1, %call 95 ret i32 %add2 96} 97; CHECK-LABEL: novla_nodynamicrealign_call 98; CHECK: .cfi_startproc 99; Check that used callee-saved registers are saved 100; CHECK: stp x20, x19, [sp, #-32]! 101; Check that the frame pointer is created: 102; CHECK: stp x29, x30, [sp, #16] 103; CHECK: add x29, sp, #16 104; Check correctness of cfi pseudo-instructions 105; CHECK: .cfi_def_cfa w29, 16 106; CHECK: .cfi_offset w30, -8 107; CHECK: .cfi_offset w29, -16 108; CHECK: .cfi_offset w19, -24 109; CHECK: .cfi_offset w20, -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: ldp x20, x19, [sp], #32 118; CHECK: ret 119; CHECK: .cfi_endproc 120 121 122declare i32 @g() #0 123 124; Function Attrs: nounwind 125define 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 { 126entry: 127 %l1 = alloca i32, align 4 128 %conv = fptosi double %d10 to i32 129 %add = add nsw i32 %conv, %i10 130 %l1.0.l1.0. = load volatile i32, i32* %l1, align 4 131 %add1 = add nsw i32 %add, %l1.0.l1.0. 132 ret i32 %add1 133} 134; CHECK-LABEL: novla_nodynamicrealign_nocall 135; Check that space is reserved for one local variable on the stack. 136; CHECK: sub sp, sp, #16 // =16 137; Check correct access to arguments passed on the stack, through stack pointer 138; CHECK: ldr d[[DARG:[0-9]+]], [sp, #40] 139; CHECK: ldr w[[IARG:[0-9]+]], [sp, #24] 140; Check correct access to local variable on the stack, through stack pointer 141; CHECK: ldr w[[ILOC:[0-9]+]], [sp, #12] 142; Check epilogue: 143; CHECK: add sp, sp, #16 // =16 144; CHECK: ret 145 146 147define 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 { 148entry: 149 %l1 = alloca i32, align 128 150 %conv = fptosi double %d10 to i32 151 %add = add nsw i32 %conv, %i10 152 %l1.0.l1.0. = load volatile i32, i32* %l1, align 128 153 %add1 = add nsw i32 %add, %l1.0.l1.0. 154 %call = tail call i32 @g() 155 %add2 = add nsw i32 %add1, %call 156 ret i32 %add2 157} 158 159; CHECK-LABEL: novla_dynamicrealign_call 160; CHECK: .cfi_startproc 161; Check that used callee-saved registers are saved 162; CHECK: stp x20, x19, [sp, #-32]! 163; Check that the frame pointer is created: 164; CHECK: stp x29, x30, [sp, #16] 165; CHECK: add x29, sp, #16 166; Check the dynamic realignment of the stack pointer to a 128-byte boundary 167; CHECK: sub x9, sp, #96 168; CHECK: and sp, x9, #0xffffffffffffff80 169; Check correctness of cfi pseudo-instructions 170; CHECK: .cfi_def_cfa w29, 16 171; CHECK: .cfi_offset w30, -8 172; CHECK: .cfi_offset w29, -16 173; CHECK: .cfi_offset w19, -24 174; CHECK: .cfi_offset w20, -32 175; Check correct access to arguments passed on the stack, through frame pointer 176; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 177; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 178; Check correct access to local variable on the stack, through re-aligned stack pointer 179; CHECK: ldr w[[ILOC:[0-9]+]], [sp] 180; Check epilogue: 181; Check that stack pointer get restored from frame pointer. 182; CHECK: sub sp, x29, #16 // =16 183; CHECK: ldp x29, x30, [sp, #16] 184; CHECK: ldp x20, x19, [sp], #32 185; CHECK: ret 186; CHECK: .cfi_endproc 187 188 189; Function Attrs: nounwind 190define 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 { 191entry: 192 %l1 = alloca i32, align 128 193 %conv = fptosi double %d10 to i32 194 %add = add nsw i32 %conv, %i10 195 %l1.0.l1.0. = load volatile i32, i32* %l1, align 128 196 %add1 = add nsw i32 %add, %l1.0.l1.0. 197 ret i32 %add1 198} 199 200; CHECK-LABEL: novla_dynamicrealign_nocall 201; Check that the frame pointer is created: 202; CHECK: stp x29, x30, [sp, #-16]! 203; CHECK: mov x29, sp 204; Check the dynamic realignment of the stack pointer to a 128-byte boundary 205; CHECK: sub x9, sp, #112 206; CHECK: and sp, x9, #0xffffffffffffff80 207; Check correct access to arguments passed on the stack, through frame pointer 208; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 209; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 210; Check correct access to local variable on the stack, through re-aligned stack pointer 211; CHECK: ldr w[[ILOC:[0-9]+]], [sp] 212; Check epilogue: 213; Check that stack pointer get restored from frame pointer. 214; CHECK: mov sp, x29 215; CHECK: ldp x29, x30, [sp], #16 216; CHECK: ret 217 218 219define 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 { 220entry: 221 %l1 = alloca i32, align 4 222 %0 = zext i32 %i1 to i64 223 %vla = alloca i32, i64 %0, align 4 224 %conv = fptosi double %d10 to i32 225 %add = add nsw i32 %conv, %i10 226 %l1.0.l1.0. = load volatile i32, i32* %l1, align 4 227 %add1 = add nsw i32 %add, %l1.0.l1.0. 228 %call = tail call i32 @g() 229 %add2 = add nsw i32 %add1, %call 230 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 231 %add3 = add nsw i32 %add2, %1 232 ret i32 %add3 233} 234 235; CHECK-LABEL: vla_nodynamicrealign_call 236; CHECK: .cfi_startproc 237; Check that used callee-saved registers are saved 238; CHECK: stp x20, x19, [sp, #-32]! 239; Check that the frame pointer is created: 240; CHECK: stp x29, x30, [sp, #16] 241; CHECK: add x29, sp, #16 242; Check that space is reserved on the stack for the local variable, 243; rounded up to a multiple of 16 to keep the stack pointer 16-byte aligned. 244; CHECK: sub sp, sp, #16 245; Check correctness of cfi pseudo-instructions 246; CHECK: .cfi_def_cfa w29, 16 247; CHECK: .cfi_offset w30, -8 248; CHECK: .cfi_offset w29, -16 249; CHECK: .cfi_offset w19, -24 250; CHECK: .cfi_offset w20, -32 251; Check correct access to arguments passed on the stack, through frame pointer 252; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 253; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 254; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 255; CHECK: ubfx x9, x0, #0, #32 256; CHECK: lsl x9, x9, #2 257; CHECK: add x9, x9, #15 258; CHECK: and x9, x9, #0xfffffffffffffff0 259; CHECK: mov x10, sp 260; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 261; CHECK: mov sp, x[[VLASPTMP]] 262; Check correct access to local variable, through frame pointer 263; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-20] 264; Check correct accessing of the VLA variable through the base pointer 265; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 266; Check epilogue: 267; Check that stack pointer get restored from frame pointer. 268; CHECK: sub sp, x29, #16 // =16 269; CHECK: ldp x29, x30, [sp, #16] 270; CHECK: ldp x20, x19, [sp], #32 271; CHECK: ret 272; CHECK: .cfi_endproc 273 274 275; Function Attrs: nounwind 276define 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 { 277entry: 278 %l1 = alloca i32, align 4 279 %0 = zext i32 %i1 to i64 280 %vla = alloca i32, i64 %0, align 4 281 %conv = fptosi double %d10 to i32 282 %add = add nsw i32 %conv, %i10 283 %l1.0.l1.0. = load volatile i32, i32* %l1, align 4 284 %add1 = add nsw i32 %add, %l1.0.l1.0. 285 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 286 %add2 = add nsw i32 %add1, %1 287 ret i32 %add2 288} 289 290; CHECK-LABEL: vla_nodynamicrealign_nocall 291; Check that the frame pointer is created: 292; CHECK: stp x29, x30, [sp, #-16]! 293; CHECK: mov x29, sp 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 correct access to arguments passed on the stack, through frame pointer 299; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 300; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 301; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 302; CHECK: ubfx x9, x0, #0, #32 303; CHECK: lsl x9, x9, #2 304; CHECK: add x9, x9, #15 305; CHECK: and x9, x9, #0xfffffffffffffff0 306; CHECK: mov x10, sp 307; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 308; CHECK: mov sp, x[[VLASPTMP]] 309; Check correct access to local variable, through frame pointer 310; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-4] 311; Check correct accessing of the VLA variable through the base pointer 312; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 313; Check epilogue: 314; Check that stack pointer get restored from frame pointer. 315; CHECK: mov sp, x29 316; CHECK: ldp x29, x30, [sp], #16 317; CHECK: ret 318 319 320define 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 { 321entry: 322 %l1 = alloca i32, align 128 323 %0 = zext i32 %i1 to i64 324 %vla = alloca i32, i64 %0, align 4 325 %conv = fptosi double %d10 to i32 326 %add = add nsw i32 %conv, %i10 327 %l1.0.l1.0. = load volatile i32, i32* %l1, align 128 328 %add1 = add nsw i32 %add, %l1.0.l1.0. 329 %call = tail call i32 @g() 330 %add2 = add nsw i32 %add1, %call 331 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 332 %add3 = add nsw i32 %add2, %1 333 ret i32 %add3 334} 335 336; CHECK-LABEL: vla_dynamicrealign_call 337; CHECK: .cfi_startproc 338; Check that used callee-saved registers are saved 339; CHECK: stp x22, x21, [sp, #-48]! 340; CHECK: stp x20, x19, [sp, #16] 341; Check that the frame pointer is created: 342; CHECK: stp x29, x30, [sp, #32] 343; CHECK: add x29, sp, #32 344; Check that the stack pointer gets re-aligned to 128 345; bytes & the base pointer (x19) gets initialized to 346; this 128-byte aligned area for local variables & 347; spill slots 348; CHECK: sub x9, sp, #80 // =80 349; CHECK: and sp, x9, #0xffffffffffffff80 350; CHECK: mov x19, sp 351; Check correctness of cfi pseudo-instructions 352; CHECK: .cfi_def_cfa w29, 16 353; CHECK: .cfi_offset w30, -8 354; CHECK: .cfi_offset w29, -16 355; CHECK: .cfi_offset w19, -24 356; CHECK: .cfi_offset w20, -32 357; CHECK: .cfi_offset w21, -40 358; CHECK: .cfi_offset w22, -48 359; Check correct access to arguments passed on the stack, through frame pointer 360; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 361; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 362; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 363; and set-up of base pointer (x19). 364; CHECK: ubfx x9, x0, #0, #32 365; CHECK: lsl x9, x9, #2 366; CHECK: add x9, x9, #15 367; CHECK: and x9, x9, #0xfffffffffffffff0 368; CHECK: mov x10, sp 369; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 370; CHECK: mov sp, x[[VLASPTMP]] 371; Check correct access to local variable, through base pointer 372; CHECK: ldr w[[ILOC:[0-9]+]], [x19] 373; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 374; Check epilogue: 375; Check that stack pointer get restored from frame pointer. 376; CHECK: sub sp, x29, #32 377; CHECK: ldp x29, x30, [sp, #32] 378; CHECK: ldp x20, x19, [sp, #16] 379; CHECK: ldp x22, x21, [sp], #48 380; CHECK: ret 381; CHECK: .cfi_endproc 382 383 384; Function Attrs: nounwind 385define 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 { 386entry: 387 %l1 = alloca i32, align 128 388 %0 = zext i32 %i1 to i64 389 %vla = alloca i32, i64 %0, align 4 390 %conv = fptosi double %d10 to i32 391 %add = add nsw i32 %conv, %i10 392 %l1.0.l1.0. = load volatile i32, i32* %l1, align 128 393 %add1 = add nsw i32 %add, %l1.0.l1.0. 394 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 395 %add2 = add nsw i32 %add1, %1 396 ret i32 %add2 397} 398 399; CHECK-LABEL: vla_dynamicrealign_nocall 400; Check that used callee-saved registers are saved 401; CHECK: stp x20, x19, [sp, #-32]! 402; Check that the frame pointer is created: 403; CHECK: stp x29, x30, [sp, #16] 404; CHECK: add x29, sp, #16 405; Check that the stack pointer gets re-aligned to 128 406; bytes & the base pointer (x19) gets initialized to 407; this 128-byte aligned area for local variables & 408; spill slots 409; CHECK: sub x9, sp, #96 410; CHECK: and sp, x9, #0xffffffffffffff80 411; CHECK: mov x19, sp 412; Check correct access to arguments passed on the stack, through frame pointer 413; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 414; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 415; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 416; and set-up of base pointer (x19). 417; CHECK: ubfx x9, x0, #0, #32 418; CHECK: lsl x9, x9, #2 419; CHECK: add x9, x9, #15 420; CHECK: and x9, x9, #0xfffffffffffffff0 421; CHECK: mov x10, sp 422; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 423; CHECK: mov sp, x[[VLASPTMP]] 424; Check correct access to local variable, through base pointer 425; CHECK: ldr w[[ILOC:[0-9]+]], [x19] 426; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 427; Check epilogue: 428; Check that stack pointer get restored from frame pointer. 429; CHECK: sub sp, x29, #16 430; CHECK: ldp x29, x30, [sp, #16] 431; CHECK: ldp x20, x19, [sp], #32 432; CHECK: ret 433 434 435; Function Attrs: nounwind 436define 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 { 437entry: 438 %l1 = alloca i32, align 32768 439 %0 = zext i32 %i1 to i64 440 %vla = alloca i32, i64 %0, align 4 441 %conv = fptosi double %d10 to i32 442 %add = add nsw i32 %conv, %i10 443 %l1.0.l1.0. = load volatile i32, i32* %l1, align 32768 444 %add1 = add nsw i32 %add, %l1.0.l1.0. 445 %1 = load volatile i32, i32* %vla, align 4, !tbaa !1 446 %add2 = add nsw i32 %add1, %1 447 ret i32 %add2 448} 449 450; CHECK-LABEL: vla_dynamicrealign_nocall_large_align 451; Check that used callee-saved registers are saved 452; CHECK: stp x20, x19, [sp, #-32]! 453; Check that the frame pointer is created: 454; CHECK: stp x29, x30, [sp, #16] 455; CHECK: add x29, sp, #16 456; Check that the stack pointer gets re-aligned to 128 457; bytes & the base pointer (x19) gets initialized to 458; this 128-byte aligned area for local variables & 459; spill slots 460; CHECK: sub x9, sp, #7, lsl #12 461; CHECK: and sp, x9, #0xffffffffffff8000 462; CHECK: mov x19, sp 463; Check correct access to arguments passed on the stack, through frame pointer 464; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24] 465; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40] 466; Check correct reservation of 16-byte aligned VLA (size in w0) on stack 467; and set-up of base pointer (x19). 468; CHECK: ubfx x9, x0, #0, #32 469; CHECK: lsl x9, x9, #2 470; CHECK: add x9, x9, #15 471; CHECK: and x9, x9, #0xfffffffffffffff0 472; CHECK: mov x10, sp 473; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9 474; CHECK: mov sp, x[[VLASPTMP]] 475; Check correct access to local variable, through base pointer 476; CHECK: ldr w[[ILOC:[0-9]+]], [x19] 477; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]] 478; Check epilogue: 479; Check that stack pointer get restored from frame pointer. 480; CHECK: sub sp, x29, #16 481; CHECK: ldp x29, x30, [sp, #16] 482; CHECK: ldp x20, x19, [sp], #32 483; CHECK: ret 484 485attributes #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" } 486attributes #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" } 487 488!1 = !{!2, !2, i64 0} 489!2 = !{!"int", !3, i64 0} 490!3 = !{!"omnipotent char", !4, i64 0} 491!4 = !{!"Simple C/C++ TBAA"} 492