diff --git a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp --- a/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp +++ b/llvm/lib/Target/PowerPC/PPCFrameLowering.cpp @@ -60,7 +60,7 @@ } static unsigned computeFramePointerSaveOffset(const PPCSubtarget &STI) { - // SVR4 ABI: First slot in the general register save area. + // First slot in the general register save area. return STI.isPPC64() ? -8U : -4U; } @@ -2416,8 +2416,6 @@ } unsigned PPCFrameLowering::getFramePointerSaveOffset() const { - if (Subtarget.isAIXABI()) - report_fatal_error("FramePointer is not implemented on AIX yet."); return FramePointerSaveOffset; } diff --git a/llvm/lib/Target/PowerPC/PPCSubtarget.h b/llvm/lib/Target/PowerPC/PPCSubtarget.h --- a/llvm/lib/Target/PowerPC/PPCSubtarget.h +++ b/llvm/lib/Target/PowerPC/PPCSubtarget.h @@ -290,8 +290,15 @@ return Align(16); } - // PPC32 SVR4ABI has no red zone and PPC64 SVR4ABI has a 288-byte red zone. - unsigned getRedZoneSize() const { return isPPC64() ? 288 : 0; } + unsigned getRedZoneSize() const { + if (isPPC64()) + // 288 bytes = 18*8 (FPRs) + 18*8 (GPRs, GPR13 reserved) + return 288; + + // AIX PPC32: 220 bytes = 18*8 (FPRs) + 19*4 (GPRs); + // PPC32 SVR4ABI has no redzone. + return isAIXABI() ? 220 : 0; + } bool hasHTM() const { return HasHTM; } bool hasFloat128() const { return HasFloat128; } diff --git a/llvm/test/CodeGen/PowerPC/Frames-alloca.ll b/llvm/test/CodeGen/PowerPC/Frames-alloca.ll deleted file mode 100644 --- a/llvm/test/CodeGen/PowerPC/Frames-alloca.ll +++ /dev/null @@ -1,26 +0,0 @@ -; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s -check-prefix=CHECK-PPC32 -; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=CHECK-PPC64 -; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -frame-pointer=all | FileCheck %s -check-prefix=CHECK-PPC32-NOFP -; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -frame-pointer=all | FileCheck %s -check-prefix=CHECK-PPC64-NOFP -; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s -check-prefix=CHECK-PPC32 - -; CHECK-PPC32: stwu 1, -32(1) -; CHECK-PPC32: stw 31, 28(1) -; CHECK-PPC32: lwz 31, 0(1) -; CHECK-PPC32-NOFP: stwu 1, -32(1) -; CHECK-PPC32-NOFP: stw 31, 28(1) -; CHECK-PPC32-NOFP: lwz 31, 0(1) - -; CHECK-PPC64: std 31, -8(1) -; CHECK-PPC64: stdu 1, -64(1) -; CHECK-PPC64: ld 1, 0(1) -; CHECK-PPC64: ld 31, -8(1) -; CHECK-PPC64-NOFP: std 31, -8(1) -; CHECK-PPC64-NOFP: stdu 1, -64(1) -; CHECK-PPC64-NOFP: ld 1, 0(1) -; CHECK-PPC64-NOFP: ld 31, -8(1) - -define i32* @f1(i32 %n) nounwind { - %tmp = alloca i32, i32 %n ; [#uses=1] - ret i32* %tmp -} diff --git a/llvm/test/CodeGen/PowerPC/Frames-dyn-alloca-with-func-call.ll b/llvm/test/CodeGen/PowerPC/Frames-dyn-alloca-with-func-call.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/Frames-dyn-alloca-with-func-call.ll @@ -0,0 +1,113 @@ +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu | \ +; RUN: FileCheck %s -check-prefix=PPC32-LINUX + +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu \ +; RUN: -frame-pointer=all | FileCheck %s -check-prefix=PPC32-LINUX + +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu | \ +; RUN: FileCheck %s -check-prefix=PPC64-LINUX + +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -frame-pointer=all | FileCheck %s -check-prefix=PPC64-LINUX + +; RUN: not llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff 2>&1 | FileCheck %s \ +; RUN: -check-prefix=CHECK-AIX + +; RUN: not llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff -frame-pointer=all 2>&1 | FileCheck %s \ +; RUN: -check-prefix=CHECK-AIX + +; RUN: not llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff 2>&1 | FileCheck %s \ +; RUN: -check-prefix=CHECK-AIX + +; RUN: not llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff -frame-pointer=all 2>&1 | FileCheck %s \ +; RUN: -check-prefix=CHECK-AIX + +; Test verifies: +; - Frame pointer register (r31) is saved/defined/restored. +; - Allocated area and parameter save area are referred by stack pointer with +; correct offset, while local variable space is referred by frame pointer +; with correct offset. +; - Allocated area is 4 bytes aligned in the case of int. +; - We actually have 9 instances of dynamic stack allocation, +; identified by the stdux used to update the back-chain link. + +define dso_local signext i32 @foo(i32 %n) { +entry: + %ptr0 = alloca i32* + %0 = alloca i32, i32 %n + store i32* %0, i32** %ptr0 + %1 = alloca i32, i32 %n + %2 = alloca i32, i32 %n + %3 = alloca i32, i32 %n + %4 = alloca i32, i32 %n + %5 = alloca i32, i32 %n + %6 = alloca i32, i32 %n + %7 = alloca i32, i32 %n + %8 = alloca i32, i32 %n + %9 = load i32*, i32** %ptr0 + + %call = call i32 @bar(i32* %1, i32* %2, i32* %3, i32* %4, i32* %5, i32* %6, i32* %7, i32* %8, i32* %9) + ret i32 %call +} + +declare i32 @bar(i32*, i32*, i32*, i32*, i32*, i32*, i32*, i32*, i32*) + +; PPC32-LINUX-LABEL: foo +; PPC32-LINUX: mflr 0 +; PPC32-LINUX: stw 0, 4(1) +; PPC32-LINUX: stwu 1, -32(1) +; PPC32-LINUX: stw 31, 28(1) +; PPC32-LINUX: mr 31, 1 +; PPC32-LINUX: addi 3, 31, 32 +; PPC32-LINUX: stwux 3, 1, 10 +; PPC32-LINUX: addi 11, 1, 16 +; PPC32-LINUX: stw 11, 24(31) +; PPC32-LINUX: stwux +; PPC32-LINUX: stwux +; PPC32-LINUX: stwux +; PPC32-LINUX: stwux +; PPC32-LINUX: stwux +; PPC32-LINUX: stwux +; PPC32-LINUX: stwux +; PPC32-LINUX: stwux +; PPC32-LINUX: stw 11, 8(1) +; PPC32-LINUX: bl bar +; PPC32-LINUX: lwz 31, 0(1) +; PPC32-LINUX: lwz 0, -4(31) +; PPC32-LINUX: mr 1, 31 +; PPC32-LINUX: mr 31, 0 +; PPC32-LINUX: lwz 0, 4(1) +; PPC32-LINUX: mtlr 0 +; PPC32-LINUX: blr + +; PPC64-LINUX-LABEL: foo +; PPC64-LINUX: mflr 0 +; PPC64-LINUX: std 31, -8(1) +; PPC64-LINUX: std 0, 16(1) +; PPC64-LINUX: stdu 1, -160(1) +; PPC64-LINUX: mr 31, 1 +; PPC64-LINUX: addi 3, 31, 160 +; PPC64-LINUX: stdux 3, 1, 10 +; PPC64-LINUX: addi 11, 1, 128 +; PPC64-LINUX: std 11, 144(31) +; PPC64-LINUX: stdux +; PPC64-LINUX: stdux +; PPC64-LINUX: stdux +; PPC64-LINUX: stdux +; PPC64-LINUX: stdux +; PPC64-LINUX: stdux +; PPC64-LINUX: stdux +; PPC64-LINUX: stdux +; PPC64-LINUX: std 11, 112(1) +; PPC64-LINUX: bl bar +; PPC64-LINUX: ld 1, 0(1) +; PPC64-LINUX: ld 0, 16(1) +; PPC64-LINUX: ld 31, -8(1) +; PPC64-LINUX: mtlr 0 +; PPC64-LINUX: blr + +; CHECK-AIX: LLVM ERROR: Handling of placing parameters on the stack is unimplemented! diff --git a/llvm/test/CodeGen/PowerPC/Frames-dyn-alloca.ll b/llvm/test/CodeGen/PowerPC/Frames-dyn-alloca.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/Frames-dyn-alloca.ll @@ -0,0 +1,100 @@ +; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s -check-prefix=PPC32-LINUX +; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=PPC64-LINUX +; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu -frame-pointer=all | FileCheck %s -check-prefix=PPC32-LINUX +; RUN: llc < %s -mtriple=powerpc64-unknown-linux-gnu -frame-pointer=all | FileCheck %s -check-prefix=PPC64-LINUX +; RUN: llc < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s -check-prefix=PPC32-LINUX + +; RUN: llc < %s -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff | FileCheck %s -check-prefix=PPC32-AIX + +; RUN: llc < %s -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff -frame-pointer=all | FileCheck %s \ +; RUN: -check-prefix=PPC32-AIX + +; RUN: llc < %s -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff | FileCheck %s -check-prefix=PPC64-AIX + +; RUN: llc < %s -mcpu=pwr4 -mattr=-altivec -verify-machineinstrs \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff -frame-pointer=all | FileCheck %s \ +; RUN: -check-prefix=PPC64-AIX + +define i32* @f1(i32 %n) nounwind { + %tmp = alloca i32, i32 %n ; [#uses=1] + ret i32* %tmp +} + +; Test verifies: +; - Frame pointer register (r31) is saved/defined/restored. +; - Allocated area is referred by frame pointer with correct offset. +; - Allocated area is 4 bytes aligned in the case of int. +; - Stack pointer is always 16 bytes aligned. +; - Only one instance of dynamic stack allocation in this case, identified by +; the stdux used to update the back-chain link. + +; PPC32-LINUX-LABEL: f1 +; PPC32-LINUX: stwu 1, -32(1) +; PPC32-LINUX-NEXT: slwi 3, 3, 2 +; PPC32-LINUX-NEXT: addi 3, 3, 15 +; PPC32-LINUX-NEXT: stw 31, 28(1) +; PPC32-LINUX-NEXT: mr 31, 1 +; PPC32-LINUX-NEXT: rlwinm 3, 3, 0, 0, 27 +; PPC32-LINUX-NEXT: neg 3, 3 +; PPC32-LINUX-NEXT: addi 4, 31, 32 +; PPC32-LINUX-NEXT: stwux 4, 1, 3 +; PPC32-LINUX-NEXT: lwz 31, 0(1) +; PPC32-LINUX-NEXT: addi 3, 1, 16 +; PPC32-LINUX-NEXT: lwz 0, -4(31) +; PPC32-LINUX-NEXT: mr 1, 31 +; PPC32-LINUX-NEXT: mr 31, 0 +; PPC32-LINUX-NEXT: blr + +; PPC64-LINUX-LABEL: f1 +; PPC64-LINUX: std 31, -8(1) +; PPC64-LINUX-NEXT: stdu 1, -64(1) +; PPC64-LINUX-NEXT: lis 4, 32767 +; PPC64-LINUX-NEXT: rldic 3, 3, 2, 30 +; PPC64-LINUX-NEXT: ori 4, 4, 65535 +; PPC64-LINUX-NEXT: addi 3, 3, 15 +; PPC64-LINUX-NEXT: sldi 4, 4, 4 +; PPC64-LINUX-NEXT: mr 31, 1 +; PPC64-LINUX-NEXT: and 3, 3, 4 +; PPC64-LINUX-NEXT: neg 3, 3 +; PPC64-LINUX-NEXT: addi 4, 31, 64 +; PPC64-LINUX-NEXT: stdux 4, 1, 3 +; PPC64-LINUX-NEXT: addi 3, 1, 48 +; PPC64-LINUX-NEXT: ld 1, 0(1) +; PPC64-LINUX-NEXT: ld 31, -8(1) +; PPC64-LINUX-NEXT: blr + +; PPC32-AIX-LABEL: f1 +; PPC32-AIX: stw 31, -4(1) +; PPC32-AIX-NEXT: stwu 1, -48(1) +; PPC32-AIX-NEXT: slwi 3, 3, 2 +; PPC32-AIX-NEXT: mr 31, 1 +; PPC32-AIX-NEXT: addi 3, 3, 15 +; PPC32-AIX-NEXT: addi 4, 31, 48 +; PPC32-AIX-NEXT: rlwinm 3, 3, 0, 0, 27 +; PPC32-AIX-NEXT: neg 3, 3 +; PPC32-AIX-NEXT: stwux 4, 1, 3 +; PPC32-AIX-NEXT: addi 3, 1, 32 +; PPC32-AIX-NEXT: lwz 1, 0(1) +; PPC32-AIX-NEXT: lwz 31, -4(1) +; PPC32-AIX-NEXT: blr + +; PPC64-AIX-LABEL: f1 +; PPC64-AIX: std 31, -8(1) +; PPC64-AIX-NEXT: stdu 1, -64(1) +; PPC64-AIX-NEXT: lis 4, 32767 +; PPC64-AIX-NEXT: rldic 3, 3, 2, 30 +; PPC64-AIX-NEXT: ori 4, 4, 65535 +; PPC64-AIX-NEXT: addi 3, 3, 15 +; PPC64-AIX-NEXT: sldi 4, 4, 4 +; PPC64-AIX-NEXT: mr 31, 1 +; PPC64-AIX-NEXT: and 3, 3, 4 +; PPC64-AIX-NEXT: addi 4, 31, 64 +; PPC64-AIX-NEXT: neg 3, 3 +; PPC64-AIX-NEXT: stdux 4, 1, 3 +; PPC64-AIX-NEXT: addi 3, 1, 48 +; PPC64-AIX-NEXT: ld 1, 0(1) +; PPC64-AIX-NEXT: ld 31, -8(1) +; PPC64-AIX-NEXT: blr diff --git a/llvm/test/CodeGen/PowerPC/Frames-large.ll b/llvm/test/CodeGen/PowerPC/Frames-large.ll --- a/llvm/test/CodeGen/PowerPC/Frames-large.ll +++ b/llvm/test/CodeGen/PowerPC/Frames-large.ll @@ -1,53 +1,125 @@ -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s -check-prefix=PPC32-NOFP -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu -frame-pointer=all | FileCheck %s -check-prefix=PPC32-FP +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu | \ +; RUN: FileCheck %s -check-prefix=PPC32-LINUX-NOFP -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=PPC64-NOFP -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -frame-pointer=all | FileCheck %s -check-prefix=PPC64-FP +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu \ +; RUN: -frame-pointer=all | FileCheck %s -check-prefix=PPC32-LINUX-FP + +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu | \ +; RUN: FileCheck %s -check-prefix=PPC64-LINUX-NOFP + +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -frame-pointer=all | FileCheck %s -check-prefix=PPC64-LINUX-FP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff | FileCheck %s \ +; RUN: -check-prefix=PPC32-AIX-NOFP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff -frame-pointer=all | FileCheck %s \ +; RUN: -check-prefix=PPC32-AIX-FP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff | FileCheck %s \ +; RUN: -check-prefix=PPC64-AIX-NOFP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff -frame-pointer=all | FileCheck %s \ +; RUN: -check-prefix=PPC64-AIX-FP + +; Test verifies: +; - Frame pointer register (r31) is saved/defined/restored when frame pointer +; elimination is disabled. +; - Allocated area is referred by stack pointer with correct offset. +; - Allocated area is 4 bytes aligned in the case of int. +; - Only one instance of dynamic stack allocation in this case, identified by +; the stdux used to update the back-chain link when allocated frame is large +; that we can not address it by a 16-bit signed integer. define i32* @f1() nounwind { %tmp = alloca i32, i32 8191 ; [#uses=1] ret i32* %tmp } -; PPC32-NOFP: f1: -; PPC32-NOFP: lis 0, -1 -; PPC32-NOFP: ori 0, 0, 32752 -; PPC32-NOFP: stwux 1, 1, 0 -; PPC32-NOFP-DAG: addi 3, 1, 20 -; PPC32-NOFP-DAG: lwz 31, 0(1) -; PPC32-NOFP: mr 1, 31 -; PPC32-NOFP: mr 31, 0 -; PPC32-NOFP: blr - -; PPC32-FP: lis 0, -1 -; PPC32-FP: ori 0, 0, 32752 -; PPC32-FP: stwux 1, 1, 0 -; PPC32-FP: subf 0, 0, 1 -; PPC32-FP: addic 0, 0, -4 -; PPC32-FP: stwx 31, 0, 0 -; PPC32-FP: mr 31, 1 -; PPC32-FP: addi 3, 31, 16 -; PPC32-FP: lwz 31, 0(1) -; PPC32-FP: lwz 0, -4(31) -; PPC32-FP: mr 1, 31 -; PPC32-FP: mr 31, 0 -; PPC32-FP: blr - -; PPC64-NOFP: f1: -; PPC64-NOFP: lis 0, -1 -; PPC64-NOFP: ori 0, 0, 32720 -; PPC64-NOFP: stdux 1, 1, 0 -; PPC64-NOFP: addi 3, 1, 52 -; PPC64-NOFP: ld 1, 0(1) -; PPC64-NOFP: blr - -; PPC64-FP: f1: -; PPC64-FP: lis 0, -1 -; PPC64-FP: ori 0, 0, 32704 -; PPC64-FP: std 31, -8(1) -; PPC64-FP: stdux 1, 1, 0 -; PPC64-FP: mr 31, 1 -; PPC64-FP: addi 3, 31, 60 -; PPC64-FP: ld 1, 0(1) -; PPC64-FP: ld 31, -8(1) -; PPC64-FP: blr +; PPC32-LINUX-NOFP-LABEL: f1 +; PPC32-LINUX-NOFP: lis 0, -1 +; PPC32-LINUX-NOFP-NEXT: ori 0, 0, 32752 +; PPC32-LINUX-NOFP-NEXT: stwux 1, 1, 0 +; PPC32-LINUX-NOFP-NEXT: subf 0, 0, 1 +; PPC32-LINUX-NOFP-NEXT: mr 0, 31 +; PPC32-LINUX-NOFP-DAG: addi 3, 1, 20 +; PPC32-LINUX-NOFP-DAG: lwz 31, 0(1) +; PPC32-LINUX-NOFP-NEXT: mr 1, 31 +; PPC32-LINUX-NOFP-NEXT: mr 31, 0 +; PPC32-LINUX-NOFP-NEXT: blr + +; PPC32-LINUX-FP-LABEL: f1 +; PPC32-LINUX-FP: lis 0, -1 +; PPC32-LINUX-FP-NEXT: ori 0, 0, 32752 +; PPC32-LINUX-FP-NEXT: stwux 1, 1, 0 +; PPC32-LINUX-FP-NEXT: subf 0, 0, 1 +; PPC32-LINUX-FP-NEXT: addic 0, 0, -4 +; PPC32-LINUX-FP-NEXT: stwx 31, 0, 0 +; PPC32-LINUX-FP-NEXT: mr 31, 1 +; PPC32-LINUX-FP-NEXT: addi 3, 31, 16 +; PPC32-LINUX-FP-NEXT: lwz 31, 0(1) +; PPC32-LINUX-FP-NEXT: lwz 0, -4(31) +; PPC32-LINUX-FP-NEXT: mr 1, 31 +; PPC32-LINUX-FP-NEXT: mr 31, 0 +; PPC32-LINUX-FP-NEXT: blr + +; PPC64-LINUX-NOFP-LABEL: f1: +; PPC64-LINUX-NOFP: lis 0, -1 +; PPC64-LINUX-NOFP-NEXT: ori 0, 0, 32720 +; PPC64-LINUX-NOFP-NEXT: stdux 1, 1, 0 +; PPC64-LINUX-NOFP-NEXT: addi 3, 1, 52 +; PPC64-LINUX-NOFP-NEXT: ld 1, 0(1) +; PPC64-LINUX-NOFP-NEXT: blr + +; PPC64-LINUX-FP-LABEL: f1: +; PPC64-LINUX-FP: lis 0, -1 +; PPC64-LINUX-FP-NEXT: ori 0, 0, 32704 +; PPC64-LINUX-FP-NEXT: std 31, -8(1) +; PPC64-LINUX-FP-NEXT: stdux 1, 1, 0 +; PPC64-LINUX-FP-NEXT: mr 31, 1 +; PPC64-LINUX-FP-NEXT: addi 3, 31, 60 +; PPC64-LINUX-FP-NEXT: ld 1, 0(1) +; PPC64-LINUX-FP-NEXT: ld 31, -8(1) +; PPC64-LINUX-FP-NEXT: blr + +; PPC32-AIX-NOFP-LABEL: f1 +; PPC32-AIX-NOFP: lis 0, -1 +; PPC32-AIX-NOFP-NEXT: ori 0, 0, 32736 +; PPC32-AIX-NOFP-NEXT: stwux 1, 1, 0 +; PPC32-AIX-NOFP-NEXT: addi 3, 1, 36 +; PPC32-AIX-NOFP-NEXT: lwz 1, 0(1) +; PPC32-AIX-NOFP-NEXT: blr + +; PPC32-AIX-FP-LABEL: f1 +; PPC32-AIX-FP: lis 0, -1 +; PPC32-AIX-FP-NEXT: stw 31, -4(1) +; PPC32-AIX-FP-NEXT: ori 0, 0, 32736 +; PPC32-AIX-FP-NEXT: stwux 1, 1, 0 +; PPC32-AIX-FP-NEXT: mr 31, 1 +; PPC32-AIX-FP-NEXT: addi 3, 31, 32 +; PPC32-AIX-FP-NEXT: lwz 1, 0(1) +; PPC32-AIX-FP-NEXT: lwz 31, -4(1) +; PPC32-AIX-FP-NEXT: blr + +; PPC64-AIX-NOFP-LABEL: f1 +; PPC64-AIX-NOFP: lis 0, -1 +; PPC64-AIX-NOFP-NEXT: ori 0, 0, 32720 +; PPC64-AIX-NOFP-NEXT: stdux 1, 1, 0 +; PPC64-AIX-NOFP-NEXT: addi 3, 1, 52 +; PPC64-AIX-NOFP-NEXT: ld 1, 0(1) +; PPC64-AIX-NOFP-NEXT: blr + +; PPC64-AIX-FP-LABEL: f1 +; PPC64-AIX-FP: lis 0, -1 +; PPC64-AIX-FP-NEXT: std 31, -8(1) +; PPC64-AIX-FP-NEXT: ori 0, 0, 32704 +; PPC64-AIX-FP-NEXT: stdux 1, 1, 0 +; PPC64-AIX-FP-NEXT: mr 31, 1 +; PPC64-AIX-FP-NEXT: addi 3, 31, 60 +; PPC64-AIX-FP-NEXT: ld 1, 0(1) +; PPC64-AIX-FP-NEXT: ld 31, -8(1) +; PPC64-AIX-FP-NEXT: blr diff --git a/llvm/test/CodeGen/PowerPC/Frames-small.ll b/llvm/test/CodeGen/PowerPC/Frames-small.ll --- a/llvm/test/CodeGen/PowerPC/Frames-small.ll +++ b/llvm/test/CodeGen/PowerPC/Frames-small.ll @@ -1,36 +1,101 @@ -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu | FileCheck %s -check-prefix=PPC32-FP -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu -frame-pointer=all | FileCheck %s -check-prefix=PPC32-NOFP -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu | FileCheck %s -check-prefix=PPC64-FP -; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu -frame-pointer=all | FileCheck %s -check-prefix=PPC64-NOFP - -;PPC32-FP: f1: -;PPC32-FP: stwu 1, -16400(1) -;PPC32-FP: addi 3, 1, 20 -;PPC32-FP: addi 1, 1, 16400 -;PPC32-FP: blr - -;PPC32-NOFP: f1: -;PPC32-NOFP: stwu 1, -16400(1) -;PPC32-NOFP: stw 31, 16396(1) -;PPC32-NOFP: lwz 31, 16396(1) -;PPC32-NOFP: addi 1, 1, 16400 -;PPC32-NOFP: blr - -;PPC64-FP: f1: -;PPC64-FP: stdu 1, -16432(1) -;PPC64-FP: addi 1, 1, 16432 -;PPC64-FP: blr - -;PPC64-NOFP: f1: -;PPC64-NOFP: std 31, -8(1) -;PPC64-NOFP: stdu 1, -16448(1) -;PPC64-NOFP: addi 1, 1, 16448 -;PPC64-NOFP: ld 31, -8(1) -;PPC64-NOFP: blr - - -define i32* @f1() { - %tmp = alloca i32, i32 4095 ; [#uses=1] +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu | \ +; RUN: FileCheck %s -check-prefix=PPC32-LINUX-NOFP + +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc-unknown-linux-gnu \ +; RUN: -frame-pointer=all | FileCheck %s -check-prefix=PPC32-LINUX-FP + +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu | \ +; RUN: FileCheck %s -check-prefix=PPC64-LINUX-NOFP + +; RUN: llc -verify-machineinstrs < %s -mtriple=powerpc64-unknown-linux-gnu \ +; RUN: -frame-pointer=all | FileCheck %s -check-prefix=PPC64-LINUX-FP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff | FileCheck %s \ +; RUN: -check-prefix=PPC32-AIX-NOFP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff -frame-pointer=all | FileCheck %s \ +; RUN: -check-prefix=PPC32-AIX-FP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff | FileCheck %s \ +; RUN: -check-prefix=PPC64-AIX-NOFP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff -frame-pointer=all | FileCheck %s \ +; RUN: -check-prefix=PPC64-AIX-FP + +; Test verifies: +; - Frame pointer register (r31) is saved/defined/restored when frame pointer +; elimination is disabled. +; - Allocated area is referred by stack pointer with correct offset. +; - Allocated area is 4 bytes aligned in the case of int. +; - Only one instance of dynamic stack allocation in this case, identified by +; the stdu used to update the back-chain link when allocated frame is small +; that we can address it by a 16-bit signed integer. + +define i32* @frame_small() { + %tmp = alloca i32, i32 95 ret i32* %tmp } +; PPC32-LINUX-NOFP-LABEL: frame_small +; PPC32-LINUX-NOFP: stwu 1, -400(1) +; PPC32-LINUX-NOFP: addi 3, 1, 20 +; PPC32-LINUX-NOFP: addi 1, 1, 400 +; PPC32-LINUX-NOFP: blr + +; PPC32-LINUX-FP-LABEL: frame_small +; PPC32-LINUX-FP: stwu 1, -400(1) +; PPC32-LINUX-FP: stw 31, 396(1) +; PPC32-LINUX-FP: mr 31, 1 +; PPC32-LINUX-FP: addi 3, 31, 16 +; PPC32-LINUX-FP: lwz 31, 396(1) +; PPC32-LINUX-FP: addi 1, 1, 400 +; PPC32-LINUX-FP: blr + +; PPC64-LINUX-NOFP-LABEL: frame_small +; PPC64-LINUX-NOFP: stdu 1, -432(1) +; PPC64-LINUX-NOFP: addi 3, 1, 52 +; PPC64-LINUX-NOFP: addi 1, 1, 432 +; PPC64-LINUX-NOFP: blr + +; PPC64-LINUX-FP-LABEL: frame_small +; PPC64-LINUX-FP: std 31, -8(1) +; PPC64-LINUX-FP: stdu 1, -448(1) +; PPC64-LINUX-FP: mr 31, 1 +; PPC64-LINUX-FP: addi 3, 31, 60 +; PPC64-LINUX-FP: addi 1, 1, 448 +; PPC64-LINUX-FP: ld 31, -8(1) +; PPC64-LINUX-FP: blr + +; PPC32-AIX-NOFP-LABEL: frame_small +; PPC32-AIX-NOFP: stwu 1, -416(1) +; PPC32-AIX-NOFP-NEXT: addi 3, 1, 36 +; PPC32-AIX-NOFP-NEXT: addi 1, 1, 416 +; PPC32-AIX-NOFP-NEXT: blr + +; PPC32-AIX-FP-LABEL: frame_small +; PPC32-AIX-FP: stw 31, -4(1) +; PPC32-AIX-FP-NEXT: stwu 1, -416(1) +; PPC32-AIX-FP-NEXT: mr 31, 1 +; PPC32-AIX-FP-NEXT: addi 3, 31, 32 +; PPC32-AIX-FP-NEXT: addi 1, 1, 416 +; PPC32-AIX-FP-NEXT: lwz 31, -4(1) +; PPC32-AIX-FP-NEXT: blr + +; PPC64-AIX-NOFP-LABEL: frame_small +; PPC64-AIX-NOFP: stdu 1, -432(1) +; PPC64-AIX-NOFP-NEXT: addi 3, 1, 52 +; PPC64-AIX-NOFP-NEXT: addi 1, 1, 432 +; PPC64-AIX-NOFP-NEXT: blr + +; PPC64-AIX-FP-LABEL: frame_small +; PPC64-AIX-FP: std 31, -8(1) +; PPC64-AIX-FP-NEXT: stdu 1, -448(1) +; PPC64-AIX-FP-NEXT: mr 31, 1 +; PPC64-AIX-FP-NEXT: addi 3, 31, 60 +; PPC64-AIX-FP-NEXT: addi 1, 1, 448 +; PPC64-AIX-FP-NEXT: ld 31, -8(1) +; PPC64-AIX-FP-NEXT: blr diff --git a/llvm/test/CodeGen/PowerPC/aix-frames-stack-floor.ll b/llvm/test/CodeGen/PowerPC/aix-frames-stack-floor.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/aix-frames-stack-floor.ll @@ -0,0 +1,96 @@ +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff | FileCheck %s -check-prefix=PPC32-NOFP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc-ibm-aix-xcoff -frame-pointer=all | FileCheck %s -check-prefix=PPC32-FP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff | FileCheck %s -check-prefix=PPC64-NOFP + +; RUN: llc -verify-machineinstrs < %s -mcpu=pwr4 -mattr=-altivec \ +; RUN: -mtriple=powerpc64-ibm-aix-xcoff -frame-pointer=all | FileCheck %s -check-prefix=PPC64-FP + +; Test verifies: +; - Frame pointer register (r31) is saved/defined/restored when frame pointer +; elimination is disabled. +; - Allocated area is referred by stack pointer with correct offset. +; - Allocated area is 4 bytes aligned in the case of int. +; - On AIX, a stackless leaf function does not acquire its own stack when the +; save area the function requires is less than 220 bytes in 32-bit mode and +; 288 bytes in 64-bit mode. + +define i32* @in_stack_floor_32() { + %tmp = alloca i32, i32 55 + ret i32* %tmp +} + +define i32* @out_stack_floor_32() { + %tmp = alloca i32, i32 56 + ret i32* %tmp +} + +define i32* @in_stack_floor_64() { + %tmp = alloca i32, i32 72 + ret i32* %tmp +} + +define i32* @out_stack_floor_64() { + %tmp = alloca i32, i32 73 + ret i32* %tmp +} + +; PPC32-NOFP-LABEL: in_stack_floor_32 +; PPC32-NOFP: addi 3, 1, -220 +; PPC32-NOFP-NEXT: blr + +; PPC32-NOFP-LABEL: out_stack_floor_32 +; PPC32-NOFP: stwu 1, -256(1) +; PPC32-NOFP-NEXT: addi 3, 1, 32 +; PPC32-NOFP-NEXT: addi 1, 1, 256 +; PPC32-NOFP-NEXT: blr + +; PPC32-FP-LABEL: in_stack_floor_32 +; PPC32-FP: stw 31, -4(1) +; PPC32-FP-NEXT: stwu 1, -256(1) +; PPC32-FP-NEXT: mr 31, 1 +; PPC32-FP-NEXT: addi 3, 31, 32 +; PPC32-FP-NEXT: addi 1, 1, 256 +; PPC32-FP-NEXT: lwz 31, -4(1) +; PPC32-FP-NEXT: blr + +; PPC32-FP-LABEL: out_stack_floor_32 +; PPC32-FP: stw 31, -4(1) +; PPC32-FP-NEXT: stwu 1, -256(1) +; PPC32-FP-NEXT: mr 31, 1 +; PPC32-FP-NEXT: addi 3, 31, 28 +; PPC32-FP-NEXT: addi 1, 1, 256 +; PPC32-FP-NEXT: lwz 31, -4(1) +; PPC32-FP-NEXT: blr + +; PPC64-NOFP-LABEL: in_stack_floor_64 +; PPC64-NOFP: addi 3, 1, -288 +; PPC64-NOFP-NEXT: blr + +; PPC64-NOFP-LABEL: out_stack_floor_64 +; PPC64-NOFP: stdu 1, -352(1) +; PPC64-NOFP-NEXT: addi 3, 1, 60 +; PPC64-NOFP-NEXT: addi 1, 1, 352 +; PPC64-NOFP-NEXT: blr + +; PPC64-FP-LABEL: in_stack_floor_64 +; PPC64-FP: std 31, -8(1) +; PPC64-FP-NEXT: stdu 1, -352(1) +; PPC64-FP-NEXT: mr 31, 1 +; PPC64-FP-NEXT: addi 3, 31, 56 +; PPC64-FP-NEXT: addi 1, 1, 352 +; PPC64-FP-NEXT: ld 31, -8(1) +; PPC64-FP-NEXT: blr + +; PPC64-FP-LABEL: out_stack_floor_64 +; PPC64-FP: std 31, -8(1) +; PPC64-FP-NEXT: stdu 1, -352(1) +; PPC64-FP-NEXT: mr 31, 1 +; PPC64-FP-NEXT: addi 3, 31, 52 +; PPC64-FP-NEXT: addi 1, 1, 352 +; PPC64-FP-NEXT: ld 31, -8(1) +; PPC64-FP-NEXT: blr