Files
clang-p2996/llvm/test/CodeGen/AArch64/aarch64-dynamic-stack-layout.ll
David Green 6a353c7756 [AArch64] Add GPR rr instructions to isAssociativeAndCommutative
This adds some more scalar instructions that are both associative and
commutative to isAssociativeAndCommutative, allowing the machine
combiner to reassociate them to reduce critical path length.

Differential Revision: https://reviews.llvm.org/D134260
2022-11-27 12:53:10 +00:00

705 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, i32* %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: .cfi_def_cfa_offset 32
; CHECK: stp x30, x19, [sp, #16]
; Check correctness of cfi pseudo-instructions
; 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:.cfi_def_cfa_offset 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, i32* %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, i32* %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: .cfi_def_cfa_offset 32
; Check that the frame pointer is created:
; CHECK: str x19, [sp, #16]
; CHECK: mov x29, sp
; 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 the dynamic realignment of the stack pointer to a 128-byte boundary
; CHECK: sub x9, sp, #96
; CHECK: and sp, x9, #0xffffffffffffff80
; 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-MACHO: .cfi_def_cfa_offset 32
; Check that the frame pointer is created:
; CHECK-MACHO: stp x29, x30, [sp, #16]
; CHECK-MACHO: add x29, sp, #16
; 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 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 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, i32* %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, i32* %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, i32* %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: .cfi_def_cfa_offset 32
; Check that the frame pointer is created:
; CHECK: stp x20, x19, [sp, #16]
; CHECK: mov x29, sp
; 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 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 access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; CHECK: ubfiz x9, x0, #2, #32
; CHECK: add x9, x9, #15
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
; CHECK: and x9, x9, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9
; 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, i32* %l1, align 4
%add1 = add nsw i32 %add, %l1.0.l1.0.
%1 = load volatile i32, i32* %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 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 correct reservation of 16-byte aligned VLA (size in w0) on stack
; CHECK: ubfiz x9, x0, #2, #32
; CHECK: add x9, x9, #15
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #40]
; CHECK: and x9, x9, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9
; 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, i32* %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, i32* %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: .cfi_def_cfa_offset 48
; CHECK: str x21, [sp, #16]
; CHECK: stp x20, x19, [sp, #32]
; Check that the frame pointer is created:
; CHECK: mov x29, 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 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 correct access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #56]
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK: ubfiz x9, x0, #2, #32
; CHECK: add x9, x9, #15
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #72]
; CHECK: and x9, x9, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9
; 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: .cfi_def_cfa_offset 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-MACHO: .cfi_offset w21, -40
; CHECK-MACHO: .cfi_offset w22, -48
; 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 correct access to arguments passed on the stack, through frame pointer
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x9, x0, #2, #32
; CHECK-MACHO: add x9, x9, #15
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
; CHECK-MACHO: and x9, x9, #0x7fffffff0
; CHECK-MACHO: mov x10, sp
; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x9
; 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, i32* %l1, align 128
%add1 = add nsw i32 %add, %l1.0.l1.0.
%1 = load volatile i32, i32* %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 access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK: ubfiz x9, x0, #2, #32
; CHECK: add x9, x9, #15
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
; CHECK: and x9, x9, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9
; 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 access to arguments passed on the stack, through frame pointer
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x9, x0, #2, #32
; CHECK-MACHO: add x9, x9, #15
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
; CHECK-MACHO: and x9, x9, #0x7fffffff0
; CHECK-MACHO: mov x10, sp
; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x9
; 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, i32* %l1, align 32768
%add1 = add nsw i32 %add, %l1.0.l1.0.
%1 = load volatile i32, i32* %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 access to arguments passed on the stack, through frame pointer
; CHECK: ldr w[[IARG:[0-9]+]], [x29, #40]
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK: ubfiz x9, x0, #2, #32
; CHECK: add x9, x9, #15
; CHECK: ldr d[[DARG:[0-9]+]], [x29, #56]
; CHECK: and x9, x9, #0x7fffffff0
; CHECK: mov x10, sp
; CHECK: sub x[[VLASPTMP:[0-9]+]], x10, x9
; 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 access to arguments passed on the stack, through frame pointer
; CHECK-MACHO: ldr w[[IARG:[0-9]+]], [x29, #20]
; Check correct reservation of 16-byte aligned VLA (size in w0) on stack
; and set-up of base pointer (x19).
; CHECK-MACHO: ubfiz x9, x0, #2, #32
; CHECK-MACHO: add x9, x9, #15
; CHECK-MACHO: ldr d[[DARG:[0-9]+]], [x29, #32]
; CHECK-MACHO: and x9, x9, #0x7fffffff0
; CHECK-MACHO: mov x10, sp
; CHECK-MACHO: sub x[[VLASPTMP:[0-9]+]], x10, x9
; 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
define void @realign_conditional(i1 %b) {
entry:
br i1 %b, label %bb0, label %bb1
bb0:
%MyAlloca = alloca i8, i64 64, align 32
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 sp, [[REG]], #0xffffffffffffffe0
; CHECK: .[[LABEL]]:
; CHECK: ret
define void @realign_conditional2(i1 %b) {
entry:
%tmp = alloca i8, i32 16
br i1 %b, label %bb0, label %bb1
bb0:
%MyAlloca = alloca i8, i64 64, align 32
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 sp, [[REG]], #0xffffffffffffffe0
; 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"}