Skip to content

Commit 88073d4

Browse files
committed
[PowerPC] Create a FixedStack object for CR save in linkage area.
hasReservedSpillSlot returns a dummy frame index of '0' on PPC64 for the non-volatile condition registers, which leads to the CalleSavedInfo either referencing an unrelated stack object, or an invalid object if there are no stack objects. The latter case causes the mir-printer to crash due to assertions that checks if the frame index referenced by a CalleeSavedInfo is valid. To fix the problem create an immutable FixedStack object at the correct offset in the linkage area of the previous stack frame (ie SP + positive offset). Differential Revision: https://reviews.llvm.org/D73709
1 parent 2785787 commit 88073d4

File tree

4 files changed

+150
-12
lines changed

4 files changed

+150
-12
lines changed

llvm/lib/Target/PowerPC/PPCFrameLowering.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1800,11 +1800,19 @@ void PPCFrameLowering::determineCalleeSaves(MachineFunction &MF,
18001800
}
18011801

18021802
// For 32-bit SVR4, allocate the nonvolatile CR spill slot iff the
1803-
// function uses CR 2, 3, or 4.
1804-
if (Subtarget.is32BitELFABI() &&
1803+
// function uses CR 2, 3, or 4. For 64-bit SVR4 we create a FixedStack
1804+
// object at the offset of the CR-save slot in the linkage area. The actual
1805+
// save and restore of the condition register will be created as part of the
1806+
// prologue and epilogue insertion, but the FixedStack object is needed to
1807+
// keep the CalleSavedInfo valid.
1808+
if (Subtarget.isSVR4ABI() &&
18051809
(SavedRegs.test(PPC::CR2) || SavedRegs.test(PPC::CR3) ||
18061810
SavedRegs.test(PPC::CR4))) {
1807-
int FrameIdx = MFI.CreateFixedObject((uint64_t)4, (int64_t)-4, true);
1811+
const uint64_t SpillSize = 4; // Condition register is always 4 bytes.
1812+
const int64_t SpillOffset = Subtarget.isPPC64() ? 8 : -4;
1813+
int FrameIdx =
1814+
MFI.CreateFixedObject(SpillSize, SpillOffset,
1815+
/* IsImmutable */ true, /* IsAliased */ false);
18081816
FI->setCRSpillFrameIndex(FrameIdx);
18091817
}
18101818
}

llvm/lib/Target/PowerPC/PPCRegisterInfo.cpp

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -929,16 +929,12 @@ bool PPCRegisterInfo::hasReservedSpillSlot(const MachineFunction &MF,
929929
const PPCSubtarget &Subtarget = MF.getSubtarget<PPCSubtarget>();
930930
// For the nonvolatile condition registers (CR2, CR3, CR4) in an SVR4
931931
// ABI, return true to prevent allocating an additional frame slot.
932-
// For 64-bit, the CR save area is at SP+8; the value of FrameIdx = 0
933-
// is arbitrary and will be subsequently ignored. For 32-bit, we have
934-
// previously created the stack slot if needed, so return its FrameIdx.
932+
// For 64-bit, the CR save area is in the linkage area at SP+8; but we have
933+
// created a FrameIndex to that spill slot to keep the CalleSaveInfos valid.
934+
// For 32-bit, we have previously created the stack slot if needed, so return
935+
// its FrameIdx.
935936
if (Subtarget.isSVR4ABI() && PPC::CR2 <= Reg && Reg <= PPC::CR4) {
936-
if (TM.isPPC64())
937-
FrameIdx = 0;
938-
else {
939-
const PPCFunctionInfo *FI = MF.getInfo<PPCFunctionInfo>();
940-
FrameIdx = FI->getCRSpillFrameIndex();
941-
}
937+
FrameIdx = MF.getInfo<PPCFunctionInfo>()->getCRSpillFrameIndex();
942938
return true;
943939
}
944940
return false;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
; RUN: llc -mtriple=powerpc64le-unknown-linux-gnu --verify-machineinstrs \
2+
; RUN: -stop-after=prologepilog < %s | FileCheck %s
3+
4+
define dso_local signext i32 @test(i32 signext %n) {
5+
entry:
6+
%conv = sext i32 %n to i64
7+
%0 = alloca double, i64 %conv, align 16
8+
tail call void asm sideeffect "", "~{cr2}"()
9+
%call = call signext i32 @do_something(double* nonnull %0)
10+
ret i32 %call
11+
}
12+
13+
declare signext i32 @do_something(double*)
14+
15+
; CHECK: name: test
16+
; CHECK: alignment: 16
17+
; CHECK: liveins:
18+
; CHECK: - { reg: '$x3', virtual-reg: '' }
19+
; CHECK: stackSize: 48
20+
; CHECK: maxCallFrameSize: 32
21+
22+
; CHECK: fixedStack:
23+
; CHECK-NEXT: - { id: 0, type: default, offset: 8, size: 4, alignment: 8, stack-id: default,
24+
; CHECK-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '$cr2',
25+
; CHECK-NEXT: callee-saved-restored: true, debug-info-variable: '', debug-info-expression: '',
26+
; CHECK-NEXT: debug-info-___location: '' }
27+
; CHECK-NEXT: - { id: 1, type: default, offset: -8, size: 8, alignment: 8, stack-id: default,
28+
; CHECK-NEXT: isImmutable: true, isAliased: false, callee-saved-register: '', callee-saved-restored: true,
29+
; CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-___location: '' }
30+
31+
; CHECK-NEXT: stack:
32+
; CHECK-NEXT: - { id: 0, name: '<unnamed alloca>', type: variable-sized, offset: -8,
33+
; CHECK-NEXT: alignment: 1, stack-id: default, callee-saved-register: '', callee-saved-restored: true,
34+
; CHECK-NEXT: local-offset: 0, debug-info-variable: '', debug-info-expression: '',
35+
; CHECK-NEXT: debug-info-___location: '' }
36+
; CHECK-NEXT: - { id: 1, name: '', type: default, offset: -16, size: 8, alignment: 8,
37+
; CHECK-NEXT: stack-id: default, callee-saved-register: '', callee-saved-restored: true,
38+
; CHECK-NEXT: debug-info-variable: '', debug-info-expression: '', debug-info-___location: '' }
39+
40+
; CHECK: bb.0.entry:
41+
; CHECK-NEXT: liveins: $x3, $cr2
42+
43+
; Prologue:
44+
; CHECK: $x0 = MFLR8 implicit $lr8
45+
; CHECK-NEXT: $x12 = MFOCRF8 killed $cr2
46+
; CHECK-DAG: STD $x31, -8, $x1
47+
; CHECK-DAG: STD killed $x0, 16, $x1
48+
; CHECK-DAG: STW8 killed $x12, 8, $x1
49+
; CHECK-NEXT: $x1 = STDU $x1, -48, $x1
50+
; CHECK: $x31 = OR8 $x1, $x1
51+
52+
; CHECK: $[[ORIGSP:x[0-9]+]] = ADDI8 $x31, 48
53+
; CHECK: $x1 = STDUX killed $[[ORIGSP]], $x1, killed $x{{[0-9]}}
54+
; CHECK: INLINEASM {{.*}} early-clobber $cr2
55+
; CHECK: BL8_NOP @do_something
56+
57+
58+
; Epilogue:
59+
; CHECK: $x1 = LD 0, $x1
60+
; CHECK-DAG: $x0 = LD 16, $x1
61+
; CHECK-DAG: $x12 = LWZ8 8, $x1
62+
; CHECK-DAG: $x31 = LD -8, $x1
63+
; CHECK: $cr2 = MTOCRF8 killed $x12
64+
; CHECK-NEXT: MTLR8 $x0, implicit-def $lr8
65+
; CHECK-NEXT: BLR8 implicit $lr8, implicit $rm, implicit $x3
66+
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# RUN: llc -mtriple powerpc64le-unknown-linux-gnu -x mir -mcpu=pwr8 \
2+
# RUN: -run-pass=prologepilog --verify-machineinstrs < %s | \
3+
# RUN: FileCheck %s --check-prefixes=CHECK,PWR8
4+
5+
# RUN: llc -mtriple powerpc64-unknown-linux-gnu -x mir -mcpu=pwr7 \
6+
# RUN: -run-pass=prologepilog --verify-machineinstrs < %s | \
7+
# RUN: FileCheck %s --check-prefixes=CHECK,PWR7
8+
9+
---
10+
name: CRAllSave
11+
alignment: 16
12+
tracksRegLiveness: true
13+
liveins:
14+
- { reg: '$x3', virtual-reg: '' }
15+
body: |
16+
bb.0.entry:
17+
liveins: $x3
18+
renamable $x29 = ANDI8_rec killed renamable $x3, 1, implicit-def dead $cr0, implicit-def $cr0gt
19+
renamable $cr2lt = COPY $cr0gt
20+
renamable $cr4lt = COPY $cr0gt
21+
renamable $x3 = COPY $x29
22+
BLR8 implicit $lr8, implicit $rm, implicit $x3
23+
24+
; Verify the proper live-ins have been added in the prologue.
25+
; CHECK: liveins: $x3, $x29, $cr2, $cr4
26+
27+
; CHECK: $x12 = MFCR8 implicit killed $cr2, implicit killed $cr4
28+
; CHECK-DAG: STD killed $x29, -24, $x1 :: (store 8 into %fixed-stack.0)
29+
; CHECK-DAG: STW8 killed $x12, 8, $x1
30+
31+
; CHECK: $x29 = LD -24, $x1 :: (load 8 from %fixed-stack.0)
32+
; CHECK: $x12 = LWZ8 8, $x1
33+
; CHECK: $cr2 = MTOCRF8 $x12
34+
; CHECK: $cr4 = MTOCRF8 killed $x12
35+
36+
37+
...
38+
---
39+
name: CR2Save
40+
alignment: 16
41+
tracksRegLiveness: true
42+
liveins:
43+
- { reg: '$x3', virtual-reg: '' }
44+
body: |
45+
bb.0.entry:
46+
liveins: $x3
47+
renamable $x14 = ANDI8_rec killed renamable $x3, 1, implicit-def dead $cr0, implicit-def $cr0gt
48+
renamable $cr2lt = COPY $cr0gt
49+
renamable $x3 = COPY $x14
50+
BLR8 implicit $lr8, implicit $rm, implicit $x3
51+
52+
; CHECK: CR2Save
53+
; Verify the proper live-ins have been added in the prologue.
54+
; CHECK: liveins: $x3, $x14, $cr2
55+
56+
; PWR8: $x12 = MFOCRF8 killed $cr2
57+
; PWR7: $x12 = MFCR8 implicit killed $cr2
58+
59+
; CHECK-DAG: STD killed $x14, -144, $x1 :: (store 8 into %fixed-stack.0, align 16)
60+
; CHECK-DAG: STW8 killed $x12, 8, $x1
61+
62+
; CHECK: $x14 = LD -144, $x1 :: (load 8 from %fixed-stack.0, align 16)
63+
; CHECK: $x12 = LWZ8 8, $x1
64+
; CHECK: $cr2 = MTOCRF8 killed $x12
65+
66+
67+
...
68+

0 commit comments

Comments
 (0)