Files
clang-p2996/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll
Harvin Iriawan db158c7c83 [AArch64] Update generic sched model to A510
Refresh of the generic scheduling model to use A510 instead of A55.
  Main benefits are to the little core, and introducing SVE scheduling information.
  Changes tested on various OoO cores, no performance degradation is seen.

  Differential Revision: https://reviews.llvm.org/D156799
2023-08-21 12:25:15 +01:00

704 lines
28 KiB
LLVM

; RUN: llc -verify-machineinstrs -mtriple=aarch64-none-linux-gnu -disable-post-ra < %s | FileCheck %s
; RUN: llc -verify-machineinstrs -mtriple=arm64-apple-ios -frame-pointer=all -disable-post-ra < %s | FileCheck %s --check-prefix=CHECK-MACHO
; This test aims to check basic correctness of frame layout &
; frame access code. There are 8 functions in this test file,
; each function implements one element in the cartesian product
; of:
; . a function having a VLA/noVLA
; . a function with dynamic stack realignment/no dynamic stack realignment.
; . a function needing a frame pionter/no frame pointer,
; since the presence/absence of these has influence on the frame
; layout and which pointer to use to access various part of the
; frame (bp,sp,fp).
;
; Furthermore: in every test function:
; . there is always one integer and 1 floating point argument to be able
; to check those are accessed correctly.
; . there is always one local variable to check that is accessed
; correctly
;
; The LLVM-IR below was produced by clang on the following C++ code:
;extern "C" int g();
;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,
; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
;{
; // use an argument passed on the stack.
; volatile int l1;
; return i10 + (int)d10 + l1 + g();
;}
;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,
; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
;{
; // use an argument passed on the stack.
; volatile int l1;
; return i10 + (int)d10 + l1;
;}
;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,
; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
;{
; // use an argument passed on the stack.
; alignas(128) volatile int l1;
; return i10 + (int)d10 + l1 + g();
;}
;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,
; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
;{
; // use an argument passed on the stack.
; alignas(128) volatile int l1;
; return i10 + (int)d10 + l1;
;}
;
;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,
; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
;{
; // use an argument passed on the stack.
; volatile int l1;
; volatile int vla[i1];
; return i10 + (int)d10 + l1 + g() + vla[0];
;}
;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,
; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
;{
; // use an argument passed on the stack.
; volatile int l1;
; volatile int vla[i1];
; return i10 + (int)d10 + l1 + vla[0];
;}
;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,
; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
;{
; // use an argument passed on the stack.
; alignas(128) volatile int l1;
; volatile int vla[i1];
; return i10 + (int)d10 + l1 + g() + vla[0];
;}
;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,
; double d1, double d2, double d3, double d4, double d5, double d6, double d7, double d8, double d9, double d10)
;{
; // use an argument passed on the stack.
; alignas(128) volatile int l1;
; volatile int vla[i1];
; return i10 + (int)d10 + l1 + vla[0];
;}
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 {
entry:
%l1 = alloca i32, align 4
%conv = fptosi double %d10 to i32
%add = add nsw i32 %conv, %i10
%l1.0.l1.0. = load volatile i32, ptr %l1, align 4
%add1 = or i32 %add, %l1.0.l1.0.
%call = tail call i32 @g()
%add2 = add nsw i32 %add1, %call
ret i32 %add2
}
; CHECK-LABEL: novla_nodynamicrealign_call
; CHECK: .cfi_startproc
; Check that used callee-saved registers are saved
; CHECK: sub sp, sp, #32
; CHECK: stp x30, x19, [sp, #16]
; Check correctness of cfi pseudo-instructions
; CHECK: .cfi_def_cfa_offset 32
; CHECK: .cfi_offset w19, -8
; CHECK: .cfi_offset w30, -16
; Check correct access to arguments passed on the stack, through stack pointer
; CHECK: ldr d[[DARG:[0-9]+]], [sp, #56]
; CHECK: ldr w[[IARG:[0-9]+]], [sp, #40]
; Check correct access to local variable on the stack, through stack pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [sp, #12]
; Check epilogue:
; CHECK: ldp x30, x19, [sp, #16]
; CHECK: ret
; CHECK: .cfi_endproc
; CHECK-MACHO-LABEL: _novla_nodynamicrealign_call:
; CHECK-MACHO: .cfi_startproc
; Check that used callee-saved registers are saved
; CHECK-MACHO: sub sp, sp, #48
; CHECK-MACHO: stp x20, x19, [sp, #16]
; Check that the frame pointer is created:
; CHECK-MACHO: stp x29, x30, [sp, #32]
; CHECK-MACHO: add x29, sp, #32
; Check correctness of cfi pseudo-instructions
; CHECK-MACHO: .cfi_def_cfa w29, 16
; CHECK-MACHO: .cfi_offset w30, -8
; CHECK-MACHO: .cfi_offset w29, -16
; CHECK-MACHO: .cfi_offset w19, -24
; CHECK-MACHO: .cfi_offset w20, -32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; Check correct access to local variable on the stack, through stack pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [sp, #12]
; Check epilogue:
; CHECK-MACHO: ldp x29, x30, [sp, #32]
; CHECK-MACHO: ldp x20, x19, [sp, #16]
; CHECK-MACHO: ret
; CHECK-MACHO: .cfi_endproc
declare i32 @g() #0
; Function Attrs: nounwind
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 {
entry:
%l1 = alloca i32, align 4
%conv = fptosi double %d10 to i32
%add = add nsw i32 %conv, %i10
%l1.0.l1.0. = load volatile i32, ptr %l1, align 4
%add1 = add nsw i32 %add, %l1.0.l1.0.
ret i32 %add1
}
; CHECK-LABEL: novla_nodynamicrealign_nocall
; Check that space is reserved for one local variable on the stack.
; CHECK: sub sp, sp, #16
; Check correct access to arguments passed on the stack, through stack pointer
; CHECK: ldr d[[DARG:[0-9]+]], [sp, #40]
; CHECK: ldr w[[IARG:[0-9]+]], [sp, #24]
; Check correct access to local variable on the stack, through stack pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [sp, #12]
; Check epilogue:
; CHECK: add sp, sp, #16
; CHECK: ret
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 {
entry:
%l1 = alloca i32, align 128
%conv = fptosi double %d10 to i32
%add = add nsw i32 %conv, %i10
%l1.0.l1.0. = load volatile i32, ptr %l1, align 128
%add1 = or i32 %add, %l1.0.l1.0.
%call = tail call i32 @g()
%add2 = add nsw i32 %add1, %call
ret i32 %add2
}
; CHECK-LABEL: novla_dynamicrealign_call
; CHECK: .cfi_startproc
; Check that used callee-saved registers are saved
; CHECK: stp x29, x30, [sp, #-32]!
; Check that the frame pointer is created:
; CHECK: str x19, [sp, #16]
; CHECK: mov x29, sp
; Check the dynamic realignment of the stack pointer to a 128-byte boundary
; CHECK: sub x9, sp, #96
; CHECK: and sp, x9, #0xffffffffffffff80
; Check correctness of cfi pseudo-instructions
; CHECK: .cfi_def_cfa w29, 32
; CHECK: .cfi_offset w19, -16
; CHECK: .cfi_offset w30, -24
; CHECK: .cfi_offset w29, -32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; Check correct access to local variable on the stack, through re-aligned stack pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [sp]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK: mov sp, x29
; CHECK: ldr x19, [sp, #16]
; CHECK: ldp x29, x30, [sp], #32
; CHECK: ret
; CHECK: .cfi_endproc
; CHECK-MACHO-LABEL: _novla_dynamicrealign_call:
; CHECK-MACHO: .cfi_startproc
; Check that used callee-saved registers are saved
; CHECK-MACHO: stp x20, x19, [sp, #-32]!
; Check that the frame pointer is created:
; CHECK-MACHO: stp x29, x30, [sp, #16]
; CHECK-MACHO: add x29, sp, #16
; Check the dynamic realignment of the stack pointer to a 128-byte boundary
; CHECK-MACHO: sub x9, sp, #96
; CHECK-MACHO: and sp, x9, #0xffffffffffffff80
; Check correctness of cfi pseudo-instructions
; CHECK-MACHO: .cfi_def_cfa w29, 16
; CHECK-MACHO: .cfi_offset w30, -8
; CHECK-MACHO: .cfi_offset w29, -16
; CHECK-MACHO: .cfi_offset w19, -24
; CHECK-MACHO: .cfi_offset w20, -32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; Check correct access to local variable on the stack, through re-aligned stack pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [sp]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK-MACHO: sub sp, x29, #16
; CHECK-MACHO: ldp x29, x30, [sp, #16]
; CHECK-MACHO: ldp x20, x19, [sp], #32
; CHECK-MACHO: ret
; CHECK-MACHO: .cfi_endproc
; Function Attrs: nounwind
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 {
entry:
%l1 = alloca i32, align 128
%conv = fptosi double %d10 to i32
%add = add nsw i32 %conv, %i10
%l1.0.l1.0. = load volatile i32, ptr %l1, align 128
%add1 = add nsw i32 %add, %l1.0.l1.0.
ret i32 %add1
}
; CHECK-LABEL: novla_dynamicrealign_nocall
; Check that the frame pointer is created:
; CHECK: stp x29, x30, [sp, #-16]!
; CHECK: mov x29, sp
; Check the dynamic realignment of the stack pointer to a 128-byte boundary
; CHECK: sub x9, sp, #112
; CHECK: and sp, x9, #0xffffffffffffff80
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40]
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24]
; Check correct access to local variable on the stack, through re-aligned stack pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [sp]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK: mov sp, x29
; CHECK: ldp x29, x30, [sp], #16
; CHECK: ret
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 {
entry:
%l1 = alloca i32, align 4
%0 = zext i32 %i1 to i64
%vla = alloca i32, i64 %0, align 4
%conv = fptosi double %d10 to i32
%add = add nsw i32 %conv, %i10
%l1.0.l1.0. = load volatile i32, ptr %l1, align 4
%add1 = or i32 %add, %l1.0.l1.0.
%call = tail call i32 @g()
%add2 = add nsw i32 %add1, %call
%1 = load volatile i32, ptr %vla, align 4, !tbaa !1
%add3 = add nsw i32 %add2, %1
ret i32 %add3
}
; CHECK-LABEL: vla_nodynamicrealign_call
; CHECK: .cfi_startproc
; Check that used callee-saved registers are saved
; CHECK: stp x29, x30, [sp, #-32]!
; Check that the frame pointer is created:
; CHECK: stp x20, x19, [sp, #16]
; CHECK: mov x29, sp
; Check that space is reserved on the stack for the local variable,
; rounded up to a multiple of 16 to keep the stack pointer 16-byte aligned.
; CHECK: sub sp, sp, #16
; Check correctness of cfi pseudo-instructions
; CHECK: .cfi_def_cfa w29, 32
; CHECK: .cfi_offset w19, -8
; CHECK: .cfi_offset w20, -16
; CHECK: .cfi_offset w30, -24
; CHECK: .cfi_offset w29, -32
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through frame pointer
; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-4]
; Check correct accessing of the VLA variable through the base pointer
; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK: mov sp, x29
; CHECK: ldp x20, x19, [sp, #16]
; CHECK: ldp x29, x30, [sp], #32
; CHECK: ret
; CHECK: .cfi_endproc
; Function Attrs: nounwind
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 {
entry:
%l1 = alloca i32, align 4
%0 = zext i32 %i1 to i64
%vla = alloca i32, i64 %0, align 4
%conv = fptosi double %d10 to i32
%add = add nsw i32 %conv, %i10
%l1.0.l1.0. = load volatile i32, ptr %l1, align 4
%add1 = add nsw i32 %add, %l1.0.l1.0.
%1 = load volatile i32, ptr %vla, align 4, !tbaa !1
%add2 = add nsw i32 %add1, %1
ret i32 %add2
}
; CHECK-LABEL: vla_nodynamicrealign_nocall
; Check that the frame pointer is created:
; CHECK: stp x29, x30, [sp, #-16]!
; CHECK: mov x29, sp
; Check that space is reserved on the stack for the local variable,
; rounded up to a multiple of 16 to keep the stack pointer 16-byte aligned.
; CHECK: sub sp, sp, #16
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; CHECK: ubfiz x8, x0, #2, #32
; Check correctness of cfi pseudo-instructions
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #24]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40]
; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through frame pointer
; CHECK: ldur w[[ILOC:[0-9]+]], [x29, #-4]
; Check correct accessing of the VLA variable through the base pointer
; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK: mov sp, x29
; CHECK: ldp x29, x30, [sp], #16
; CHECK: ret
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 {
entry:
%l1 = alloca i32, align 128
%0 = zext i32 %i1 to i64
%vla = alloca i32, i64 %0, align 4
%conv = fptosi double %d10 to i32
%add = add nsw i32 %conv, %i10
%l1.0.l1.0. = load volatile i32, ptr %l1, align 128
%add1 = or i32 %add, %l1.0.l1.0.
%call = tail call i32 @g()
%add2 = add nsw i32 %add1, %call
%1 = load volatile i32, ptr %vla, align 4, !tbaa !1
%add3 = add nsw i32 %add2, %1
ret i32 %add3
}
; CHECK-LABEL: vla_dynamicrealign_call
; CHECK: .cfi_startproc
; Check that used callee-saved registers are saved
; CHECK: stp x29, x30, [sp, #-48]!
; CHECK: str x21, [sp, #16]
; CHECK: stp x20, x19, [sp, #32]
; Check that the frame pointer is created:
; CHECK: mov x29, sp
; Check that the stack pointer gets re-aligned to 128
; bytes & the base pointer (x19) gets initialized to
; this 128-byte aligned area for local variables &
; spill slots
; CHECK: sub x9, sp, #80
; CHECK: and sp, x9, #0xffffffffffffff80
; CHECK: mov x19, sp
; Check correctness of cfi pseudo-instructions
; CHECK: .cfi_def_cfa w29, 48
; CHECK: .cfi_offset w19, -8
; CHECK: .cfi_offset w20, -16
; CHECK: .cfi_offset w21, -32
; CHECK: .cfi_offset w30, -40
; CHECK: .cfi_offset w29, -48
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #56]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #72]
; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [x19]
; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK: mov sp, x29
; CHECK: ldp x20, x19, [sp, #32]
; CHECK: ldr x21, [sp, #16]
; CHECK: ldp x29, x30, [sp], #48
; CHECK: ret
; CHECK: .cfi_endproc
; CHECK-MACHO-LABEL: _vla_dynamicrealign_call:
; CHECK-MACHO: .cfi_startproc
; Check that used callee-saved registers are saved
; CHECK-MACHO: stp x22, x21, [sp, #-48]!
; CHECK-MACHO: stp x20, x19, [sp, #16]
; Check that the frame pointer is created:
; CHECK-MACHO: stp x29, x30, [sp, #32]
; CHECK-MACHO: add x29, sp, #32
; Check that the stack pointer gets re-aligned to 128
; bytes & the base pointer (x19) gets initialized to
; this 128-byte aligned area for local variables &
; spill slots
; CHECK-MACHO: sub x9, sp, #80
; CHECK-MACHO: and sp, x9, #0xffffffffffffff80
; CHECK-MACHO: mov x19, sp
; Check correctness of cfi pseudo-instructions
; CHECK-MACHO: .cfi_def_cfa w29, 16
; CHECK-MACHO: .cfi_offset w30, -8
; CHECK-MACHO: .cfi_offset w29, -16
; CHECK-MACHO: .cfi_offset w19, -24
; CHECK-MACHO: .cfi_offset w20, -32
; CHECK-MACHO: .cfi_offset w21, -40
; CHECK-MACHO: .cfi_offset w22, -48
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: and x8, x8, #0x7fffffff0
; CHECK-MACHO: mov x10, sp
; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK-MACHO: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19]
; CHECK-MACHO: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK-MACHO: sub sp, x29, #32
; CHECK-MACHO: ldp x29, x30, [sp, #32]
; CHECK-MACHO: ldp x20, x19, [sp, #16]
; CHECK-MACHO: ldp x22, x21, [sp], #48
; CHECK-MACHO: ret
; CHECK-MACHO: .cfi_endproc
; Function Attrs: nounwind
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 {
entry:
%l1 = alloca i32, align 128
%0 = zext i32 %i1 to i64
%vla = alloca i32, i64 %0, align 4
%conv = fptosi double %d10 to i32
%add = add nsw i32 %conv, %i10
%l1.0.l1.0. = load volatile i32, ptr %l1, align 128
%add1 = add nsw i32 %add, %l1.0.l1.0.
%1 = load volatile i32, ptr %vla, align 4, !tbaa !1
%add2 = add nsw i32 %add1, %1
ret i32 %add2
}
; CHECK-LABEL: vla_dynamicrealign_nocall
; Check that used callee-saved registers are saved
; CHECK: stp x29, x30, [sp, #-32]!
; CHECK: str x19, [sp, #16]
; Check that the frame pointer is created:
; CHECK: mov x29, sp
; Check that the stack pointer gets re-aligned to 128
; bytes & the base pointer (x19) gets initialized to
; this 128-byte aligned area for local variables &
; spill slots
; CHECK: sub x9, sp, #96
; CHECK: and sp, x9, #0xffffffffffffff80
; CHECK: mov x19, sp
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [x19]
; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK: mov sp, x29
; CHECK: ldr x19, [sp, #16]
; CHECK: ldp x29, x30, [sp], #32
; CHECK: ret
; CHECK-MACHO-LABEL: _vla_dynamicrealign_nocall:
; Check that used callee-saved registers are saved
; CHECK-MACHO: stp x20, x19, [sp, #-32]!
; Check that the frame pointer is created:
; CHECK-MACHO: stp x29, x30, [sp, #16]
; CHECK-MACHO: add x29, sp, #16
; Check that the stack pointer gets re-aligned to 128
; bytes & the base pointer (x19) gets initialized to
; this 128-byte aligned area for local variables &
; spill slots
; CHECK-MACHO: sub x9, sp, #96
; CHECK-MACHO: and sp, x9, #0xffffffffffffff80
; CHECK-MACHO: mov x19, sp
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: and x8, x8, #0x7fffffff0
; CHECK-MACHO: mov x10, sp
; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK-MACHO: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19]
; CHECK-MACHO: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK-MACHO: sub sp, x29, #16
; CHECK-MACHO: ldp x29, x30, [sp, #16]
; CHECK-MACHO: ldp x20, x19, [sp], #32
; CHECK-MACHO: ret
; Function Attrs: nounwind
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 {
entry:
%l1 = alloca i32, align 32768
%0 = zext i32 %i1 to i64
%vla = alloca i32, i64 %0, align 4
%conv = fptosi double %d10 to i32
%add = add nsw i32 %conv, %i10
%l1.0.l1.0. = load volatile i32, ptr %l1, align 32768
%add1 = add nsw i32 %add, %l1.0.l1.0.
%1 = load volatile i32, ptr %vla, align 4, !tbaa !1
%add2 = add nsw i32 %add1, %1
ret i32 %add2
}
; CHECK-LABEL: vla_dynamicrealign_nocall_large_align
; Check that used callee-saved registers are saved
; CHECK: stp x29, x30, [sp, #-32]!
; CHECK: str x19, [sp, #16]
; Check that the frame pointer is created:
; CHECK: mov x29, sp
; Check that the stack pointer gets re-aligned to 128
; bytes & the base pointer (x19) gets initialized to
; this 128-byte aligned area for local variables &
; spill slots
; CHECK: sub x9, sp, #7, lsl #12
; CHECK: and sp, x9, #0xffffffffffff8000
; CHECK: mov x19, sp
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
; CHECK: add x8, x8, #15
; CHECK: and x8, x8, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK: ldr w[[ILOC:[0-9]+]], [x19]
; CHECK: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK: mov sp, x29
; CHECK: ldr x19, [sp, #16]
; CHECK: ldp x29, x30, [sp], #32
; CHECK: ret
; CHECK-MACHO-LABEL: _vla_dynamicrealign_nocall_large_align:
; Check that used callee-saved registers are saved
; CHECK-MACHO: stp x20, x19, [sp, #-32]!
; Check that the frame pointer is created:
; CHECK-MACHO: stp x29, x30, [sp, #16]
; CHECK-MACHO: add x29, sp, #16
; Check that the stack pointer gets re-aligned to 128
; bytes & the base pointer (x19) gets initialized to
; this 128-byte aligned area for local variables &
; spill slots
; CHECK-MACHO: sub x9, sp, #7, lsl #12
; CHECK-MACHO: and sp, x9, #0xffffffffffff8000
; CHECK-MACHO: mov x19, sp
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x8, x0, #2, #32
; Check correct access to arguments passed on the stack, through frame pointer
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
; CHECK-MACHO: add x8, x8, #15
; CHECK-MACHO: and x8, x8, #0x7fffffff0
; CHECK-MACHO: mov x10, sp
; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x8
; CHECK-MACHO: mov sp, x[[VLASPTMP]]
; Check correct access to local variable, through base pointer
; CHECK-MACHO: ldr w[[ILOC:[0-9]+]], [x19]
; CHECK-MACHO: ldr w[[VLA:[0-9]+]], [x[[VLASPTMP]]]
; Check epilogue:
; Check that stack pointer get restored from frame pointer.
; CHECK-MACHO: sub sp, x29, #16
; CHECK-MACHO: ldp x29, x30, [sp, #16]
; CHECK-MACHO: ldp x20, x19, [sp], #32
; CHECK-MACHO: ret
declare void @use(ptr)
define void @realign_conditional(i1 %b, ptr %p) {
entry:
br i1 %b, label %bb0, label %bb1
bb0:
%MyAlloca = alloca i8, i64 64, align 32
store ptr %MyAlloca, ptr %p
br label %bb1
bb1:
ret void
}
; CHECK-LABEL: realign_conditional
; No realignment in the prologue.
; CHECK-NOT: and
; CHECK-NOT: 0xffffffffffffffe0
; CHECK: tbz {{.*}} .[[LABEL:.*]]
; Stack is realigned in a non-entry BB.
; CHECK: sub [[REG:x[01-9]+]], sp, #64
; CHECK: and [[REG]], [[REG]], #0xffffffffffffffe0
; CHECK: mov sp, [[REG]]
; CHECK: .[[LABEL]]:
; CHECK: ret
define void @realign_conditional2(i1 %b, ptr %p) {
entry:
%tmp = alloca i8, i32 16
br i1 %b, label %bb0, label %bb1
bb0:
%MyAlloca = alloca i8, i64 64, align 32
store ptr %MyAlloca, ptr %p
br label %bb1
bb1:
ret void
}
; CHECK-LABEL: realign_conditional2
; Extra realignment in the prologue (performance issue).
; CHECK: tbz {{.*}} .[[LABEL:.*]]
; CHECK: sub x9, sp, #32
; CHECK: and sp, x9, #0xffffffffffffffe0
; CHECK: mov x19, sp
; Stack is realigned in a non-entry BB.
; CHECK: sub [[REG:x[01-9]+]], sp, #64
; CHECK: and [[REG]], [[REG]], #0xffffffffffffffe0
; CHECK: mov sp, [[REG]]
; CHECK: .[[LABEL]]:
; CHECK: ret
attributes #0 = { "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { nounwind "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
!1 = !{!2, !2, i64 0}
!2 = !{!"int", !3, i64 0}
!3 = !{!"omnipotent char", !4, i64 0}
!4 = !{!"Simple C/C++ TBAA"}