Home | History | Annotate | Download | only in AArch64
      1 ; RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -disable-post-ra < %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 
     86 define 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 {
     87 entry:
     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 
    122 declare i32 @g() #0
    123 
    124 ; Function Attrs: nounwind
    125 define 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 {
    126 entry:
    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 
    147 define 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 {
    148 entry:
    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
    190 define 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 {
    191 entry:
    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 
    219 define 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 {
    220 entry:
    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: mov	w9, w0
    256 ; CHECK: mov	 x10, sp
    257 ; CHECK: lsl	x9, x9, #2
    258 ; CHECK: add	x9, x9, #15
    259 ; CHECK: and	x9, x9, #0x7fffffff0
    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
    276 define 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 {
    277 entry:
    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: mov	w9, w0
    303 ; CHECK: mov	 x10, sp
    304 ; CHECK: lsl	x9, x9, #2
    305 ; CHECK: add	x9, x9, #15
    306 ; CHECK: and	x9, x9, #0x7fffffff0
    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 
    320 define 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 {
    321 entry:
    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: mov	w9, w0
    365 ; CHECK: mov	 x10, sp
    366 ; CHECK: lsl	x9, x9, #2
    367 ; CHECK: add	x9, x9, #15
    368 ; CHECK: and	x9, x9, #0x7fffffff0
    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
    385 define 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 {
    386 entry:
    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: mov	w9, w0
    418 ; CHECK: mov	 x10, sp
    419 ; CHECK: lsl	x9, x9, #2
    420 ; CHECK: add	x9, x9, #15
    421 ; CHECK: and	x9, x9, #0x7fffffff0
    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
    436 define 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 {
    437 entry:
    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: mov	w9, w0
    469 ; CHECK: mov	 x10, sp
    470 ; CHECK: lsl	x9, x9, #2
    471 ; CHECK: add	x9, x9, #15
    472 ; CHECK: and	x9, x9, #0x7fffffff0
    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 
    485 
    486 define void @realign_conditional(i1 %b) {
    487 entry:
    488   br i1 %b, label %bb0, label %bb1
    489 
    490 bb0:
    491   %MyAlloca = alloca i8, i64 64, align 32
    492   br label %bb1
    493 
    494 bb1:
    495   ret void
    496 }
    497 
    498 ; CHECK-LABEL: realign_conditional
    499 ; No realignment in the prologue.
    500 ; CHECK-NOT:  and
    501 ; CHECK-NOT:  0xffffffffffffffe0
    502 ; CHECK:  tbz  {{.*}} .[[LABEL:.*]]
    503 ; Stack is realigned in a non-entry BB.
    504 ; CHECK:  sub  [[REG:x[01-9]+]], sp, #64
    505 ; CHECK:  and  sp, [[REG]], #0xffffffffffffffe0
    506 ; CHECK:  .[[LABEL]]:
    507 ; CHECK:  ret
    508 
    509 
    510 define void @realign_conditional2(i1 %b) {
    511 entry:
    512   %tmp = alloca i8, i32 4
    513   br i1 %b, label %bb0, label %bb1
    514 
    515 bb0:
    516   %MyAlloca = alloca i8, i64 64, align 32
    517   br label %bb1
    518 
    519 bb1:
    520   ret void
    521 }
    522 
    523 ; CHECK-LABEL: realign_conditional2
    524 ; Extra realignment in the prologue (performance issue).
    525 ; CHECK:  tbz  {{.*}} .[[LABEL:.*]]
    526 ; CHECK:  sub  x9, sp, #32            // =32
    527 ; CHECK:  and  sp, x9, #0xffffffffffffffe0
    528 ; CHECK:  mov   x19, sp
    529 ; Stack is realigned in a non-entry BB.
    530 ; CHECK:  sub  [[REG:x[01-9]+]], sp, #64
    531 ; CHECK:  and  sp, [[REG]], #0xffffffffffffffe0
    532 ; CHECK:  .[[LABEL]]:
    533 ; CHECK:  ret
    534 
    535 attributes #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" }
    536 attributes #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" }
    537 
    538 !1 = !{!2, !2, i64 0}
    539 !2 = !{!"int", !3, i64 0}
    540 !3 = !{!"omnipotent char", !4, i64 0}
    541 !4 = !{!"Simple C/C++ TBAA"}
    542