summaryrefslogtreecommitdiff
path: root/test/CodeGen/PowerPC
diff options
context:
space:
mode:
authorHal Finkel <hfinkel@anl.gov>2013-07-17 00:45:52 +0000
committerHal Finkel <hfinkel@anl.gov>2013-07-17 00:45:52 +0000
commitfe47bf8fa07e12b70ff8b234fa1f6b97c8d2753d (patch)
treee2aea580e6331c70d20f3d01ec127e6f696d68c7 /test/CodeGen/PowerPC
parent63e22afdceda8e8eae59ba5ec122097e2755a522 (diff)
downloadllvm-fe47bf8fa07e12b70ff8b234fa1f6b97c8d2753d.tar.gz
llvm-fe47bf8fa07e12b70ff8b234fa1f6b97c8d2753d.tar.bz2
llvm-fe47bf8fa07e12b70ff8b234fa1f6b97c8d2753d.tar.xz
PPC: Implement base pointer and stack realignment
This builds on some frame-lowering code that has existed since 2005 (r24224) but was disabled in 2008 (r48188) because it needed base pointer support to function correctly. This implementation follows the strategy suggested by Dale Johannesen in r48188 where the following comment was added: This does not currently work, because the delta between old and new stack pointers is added to offsets that reference incoming parameters after the prolog is generated, and the code that does that doesn't handle a variable delta. You don't want to do that anyway; a better approach is to reserve another register that retains to the incoming stack pointer, and reference parameters relative to that. And now we do exactly that. If we don't need a frame pointer, then we use r31 as a base pointer. If we do need a frame pointer, then we use r30 as a base pointer. The base pointer retains the value of the stack pointer before it was decremented in the prologue. We then use the base pointer to resolve all negative frame indicies. The basic scheme follows that for base pointers in the X86 backend. We use a base pointer when we need to dynamically realign the incoming stack pointer. This currently applies only to static objects (dynamic allocas with large alignments, and base-pointer support in SjLj lowering will come in future commits). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@186478 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGen/PowerPC')
-rw-r--r--test/CodeGen/PowerPC/stack-realign.ll151
1 files changed, 151 insertions, 0 deletions
diff --git a/test/CodeGen/PowerPC/stack-realign.ll b/test/CodeGen/PowerPC/stack-realign.ll
new file mode 100644
index 0000000000..7bd28f6a7c
--- /dev/null
+++ b/test/CodeGen/PowerPC/stack-realign.ll
@@ -0,0 +1,151 @@
+; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 < %s | FileCheck %s
+; RUN: llc -mtriple=powerpc64-unknown-linux-gnu -mcpu=pwr7 -disable-fp-elim < %s | FileCheck -check-prefix=CHECK-FP %s
+target datalayout = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f128:128:128-v128:128:128-n32:64"
+target triple = "powerpc64-unknown-linux-gnu"
+
+%struct.s = type { i32, i32 }
+
+declare void @bar(i32*)
+
+define void @goo(%struct.s* byval nocapture readonly %a) {
+entry:
+ %x = alloca [2 x i32], align 32
+ %a1 = getelementptr inbounds %struct.s* %a, i64 0, i32 0
+ %0 = load i32* %a1, align 4, !tbaa !0
+ %arrayidx = getelementptr inbounds [2 x i32]* %x, i64 0, i64 0
+ store i32 %0, i32* %arrayidx, align 32, !tbaa !0
+ %b = getelementptr inbounds %struct.s* %a, i64 0, i32 1
+ %1 = load i32* %b, align 4, !tbaa !0
+ %arrayidx2 = getelementptr inbounds [2 x i32]* %x, i64 0, i64 1
+ store i32 %1, i32* %arrayidx2, align 4, !tbaa !0
+ call void @bar(i32* %arrayidx)
+ ret void
+}
+
+; CHECK-LABEL: @goo
+
+; CHECK-DAG: mflr 0
+; CHECK-DAG: rldicl [[REG:[0-9]+]], 1, 0, 59
+; CHECK-DAG: std 31, -8(1)
+; CHECK-DAG: mr 31, 1
+; CHECK-DAG: std 0, 16(1)
+; CHECK-DAG: subfic 0, [[REG]], -160
+; CHECK: stdux 1, 1, 0
+
+; CHECK: .cfi_offset r31, -8
+; CHECK: .cfi_offset lr, 16
+
+; CHECK: std 3, 48(31)
+
+; CHECK: ld 1, 0(1)
+; CHECK-DAG: ld 0, 16(1)
+; CHECK-DAG: ld 31, -8(1)
+; CHECK-DAG: mtlr 0
+; CHECK: blr
+
+; CHECK-FP-LABEL: @goo
+
+; CHECK-FP-DAG: mflr 0
+; CHECK-FP-DAG: rldicl [[REG:[0-9]+]], 1, 0, 59
+; CHECK-FP-DAG: std 31, -8(1)
+; CHECK-FP-DAG: std 30, -16(1)
+; CHECK-FP-DAG: mr 30, 1
+; CHECK-FP-DAG: std 0, 16(1)
+; CHECK-FP-DAG: subfic 0, [[REG]], -160
+; CHECK-FP: stdux 1, 1, 0
+
+; CHECK-FP: .cfi_offset r31, -8
+; CHECK-FP: .cfi_offset r30, -16
+; CHECK-FP: .cfi_offset lr, 16
+
+; CHECK-FP: mr 31, 1
+
+; CHECK-FP: std 3, 48(30)
+
+; CHECK-FP: ld 1, 0(1)
+; CHECK-FP-DAG: ld 0, 16(1)
+; CHECK-FP-DAG: ld 31, -8(1)
+; CHECK-FP-DAG: ld 30, -16(1)
+; CHECK-FP-DAG: mtlr 0
+; CHECK-FP: blr
+
+; The large-frame-size case.
+define void @hoo(%struct.s* byval nocapture readonly %a) {
+entry:
+ %x = alloca [200000 x i32], align 32
+ %a1 = getelementptr inbounds %struct.s* %a, i64 0, i32 0
+ %0 = load i32* %a1, align 4, !tbaa !0
+ %arrayidx = getelementptr inbounds [200000 x i32]* %x, i64 0, i64 0
+ store i32 %0, i32* %arrayidx, align 32, !tbaa !0
+ %b = getelementptr inbounds %struct.s* %a, i64 0, i32 1
+ %1 = load i32* %b, align 4, !tbaa !0
+ %arrayidx2 = getelementptr inbounds [200000 x i32]* %x, i64 0, i64 1
+ store i32 %1, i32* %arrayidx2, align 4, !tbaa !0
+ call void @bar(i32* %arrayidx)
+ ret void
+}
+
+; CHECK-LABEL: @hoo
+
+; CHECK-DAG: lis [[REG1:[0-9]+]], -13
+; CHECK-DAG: rldicl [[REG3:[0-9]+]], 1, 0, 59
+; CHECK-DAG: mflr 0
+; CHECK-DAG: ori [[REG2:[0-9]+]], [[REG1]], 51808
+; CHECK-DAG: std 31, -8(1)
+; CHECK-DAG: mr 31, 1
+; CHECK-DAG: std 0, 16(1)
+; CHECK-DAG: subfc 0, [[REG3]], [[REG2]]
+; CHECK: stdux 1, 1, 0
+
+; CHECK: blr
+
+; Make sure that the FP save area is still allocated correctly relative to
+; where r30 is saved.
+define void @loo(%struct.s* byval nocapture readonly %a) {
+entry:
+ %x = alloca [2 x i32], align 32
+ %a1 = getelementptr inbounds %struct.s* %a, i64 0, i32 0
+ %0 = load i32* %a1, align 4, !tbaa !0
+ %arrayidx = getelementptr inbounds [2 x i32]* %x, i64 0, i64 0
+ store i32 %0, i32* %arrayidx, align 32, !tbaa !0
+ %b = getelementptr inbounds %struct.s* %a, i64 0, i32 1
+ %1 = load i32* %b, align 4, !tbaa !0
+ %arrayidx2 = getelementptr inbounds [2 x i32]* %x, i64 0, i64 1
+ store i32 %1, i32* %arrayidx2, align 4, !tbaa !0
+ call void @bar(i32* %arrayidx)
+ call void asm sideeffect "", "~{f30}"() nounwind
+ ret void
+}
+
+; CHECK-LABEL: @loo
+
+; CHECK-DAG: mflr 0
+; CHECK-DAG: rldicl [[REG:[0-9]+]], 1, 0, 59
+; CHECK-DAG: std 31, -24(1)
+; CHECK-DAG: mr 31, 1
+; CHECK-DAG: std 0, 16(1)
+; CHECK-DAG: subfic 0, [[REG]], -160
+; CHECK: stdux 1, 1, 0
+
+; CHECK: stfd 30, -16(31)
+
+; CHECK: blr
+
+; CHECK-FP-LABEL: @loo
+
+; CHECK-FP-DAG: mflr 0
+; CHECK-FP-DAG: rldicl [[REG:[0-9]+]], 1, 0, 59
+; CHECK-FP-DAG: std 31, -24(1)
+; CHECK-FP-DAG: std 30, -32(1)
+; CHECK-FP-DAG: mr 30, 1
+; CHECK-FP-DAG: std 0, 16(1)
+; CHECK-FP-DAG: subfic 0, [[REG]], -192
+; CHECK-FP: stdux 1, 1, 0
+
+; CHECK-FP: stfd 30, -16(30)
+
+; CHECK-FP: blr
+
+!0 = metadata !{metadata !"int", metadata !1}
+!1 = metadata !{metadata !"omnipotent char", metadata !2}
+!2 = metadata !{metadata !"Simple C/C++ TBAA"}