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