Skip to content

Commit dc2a7f5

Browse files
committed
[AArch64][DebugInfo] Do not recompute CalleeSavedStackSize
This patch fixes a bug exposed by D65653 where a subsequent invocation of `determineCalleeSaves` ends up with a different size for the callee save area, leading to different frame-offsets in debug information. In the invocation by PEI, `determineCalleeSaves` tries to determine whether it needs to spill an extra callee-saved register to get an emergency spill slot. To do this, it calls 'estimateStackSize' and manually adds the size of the callee-saves to this. PEI then allocates the spill objects for the callee saves and the remaining frame layout is calculated accordingly. A second invocation in LiveDebugValues causes estimateStackSize to return the size of the stack frame including the callee-saves. Given that the size of the callee-saves is added to this, these callee-saves are counted twice, which leads `determineCalleeSaves` to believe the stack has become big enough to require spilling an extra callee-save as emergency spillslot. It then updates CalleeSavedStackSize with a larger value. Since CalleeSavedStackSize is used in the calculation of the frame offset in getFrameIndexReference, this leads to incorrect offsets for variables/locals when this information is recalculated after PEI. Reviewers: omjavaid, eli.friedman, thegameg, efriedma Reviewed By: efriedma Differential Revision: https://reviews.llvm.org/D66935 llvm-svn: 372204
1 parent 1442efe commit dc2a7f5

File tree

10 files changed

+131
-7
lines changed

10 files changed

+131
-7
lines changed

llvm/include/llvm/CodeGen/TargetFrameLowering.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,13 +281,21 @@ class TargetFrameLowering {
281281
return getFrameIndexReference(MF, FI, FrameReg);
282282
}
283283

284+
/// Returns the callee-saved registers as computed by determineCalleeSaves
285+
/// in the BitVector \p SavedRegs.
286+
virtual void getCalleeSaves(const MachineFunction &MF,
287+
BitVector &SavedRegs) const;
288+
284289
/// This method determines which of the registers reported by
285290
/// TargetRegisterInfo::getCalleeSavedRegs() should actually get saved.
286291
/// The default implementation checks populates the \p SavedRegs bitset with
287292
/// all registers which are modified in the function, targets may override
288293
/// this function to save additional registers.
289294
/// This method also sets up the register scavenger ensuring there is a free
290295
/// register or a frameindex available.
296+
/// This method should not be called by any passes outside of PEI, because
297+
/// it may change state passed in by \p MF and \p RS. The preferred
298+
/// interface outside PEI is getCalleeSaves.
291299
virtual void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
292300
RegScavenger *RS = nullptr) const;
293301

llvm/lib/CodeGen/LiveDebugValues.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1409,8 +1409,7 @@ bool LiveDebugValues::runOnMachineFunction(MachineFunction &MF) {
14091409
TRI = MF.getSubtarget().getRegisterInfo();
14101410
TII = MF.getSubtarget().getInstrInfo();
14111411
TFI = MF.getSubtarget().getFrameLowering();
1412-
TFI->determineCalleeSaves(MF, CalleeSavedRegs,
1413-
std::make_unique<RegScavenger>().get());
1412+
TFI->getCalleeSaves(MF, CalleeSavedRegs);
14141413
LS.initialize(MF);
14151414

14161415
bool Changed = ExtendRanges(MF);

llvm/lib/CodeGen/RegUsageInfoCollector.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class RegUsageInfoCollector : public MachineFunctionPass {
5656

5757
bool runOnMachineFunction(MachineFunction &MF) override;
5858

59-
// Call determineCalleeSaves and then also set the bits for subregs and
59+
// Call getCalleeSaves and then also set the bits for subregs and
6060
// fully saved superregs.
6161
static void computeCalleeSavedRegs(BitVector &SavedRegs, MachineFunction &MF);
6262

@@ -199,7 +199,7 @@ computeCalleeSavedRegs(BitVector &SavedRegs, MachineFunction &MF) {
199199

200200
// Target will return the set of registers that it saves/restores as needed.
201201
SavedRegs.clear();
202-
TFI.determineCalleeSaves(MF, SavedRegs);
202+
TFI.getCalleeSaves(MF, SavedRegs);
203203
if (SavedRegs.none())
204204
return;
205205

llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,19 @@ bool TargetFrameLowering::needsFrameIndexResolution(
5959
return MF.getFrameInfo().hasStackObjects();
6060
}
6161

62+
void TargetFrameLowering::getCalleeSaves(const MachineFunction &MF,
63+
BitVector &CalleeSaves) const {
64+
const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();
65+
CalleeSaves.resize(TRI.getNumRegs());
66+
67+
const MachineFrameInfo &MFI = MF.getFrameInfo();
68+
if (!MFI.isCalleeSavedInfoValid())
69+
return;
70+
71+
for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo())
72+
CalleeSaves.set(Info.getReg());
73+
}
74+
6275
void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF,
6376
BitVector &SavedRegs,
6477
RegScavenger *RS) const {
@@ -127,4 +140,4 @@ int TargetFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const {
127140
unsigned TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF)
128141
const {
129142
llvm_unreachable("getInitialCFARegister() not implemented!");
130-
}
143+
}

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2225,6 +2225,10 @@ void AArch64FrameLowering::determineCalleeSaves(MachineFunction &MF,
22252225
<< EstimatedStackSize + AlignedCSStackSize
22262226
<< " bytes.\n");
22272227

2228+
assert((!MFI.isCalleeSavedInfoValid() ||
2229+
AFI->getCalleeSavedStackSize() == AlignedCSStackSize) &&
2230+
"Should not invalidate callee saved info");
2231+
22282232
// Round up to register pair alignment to avoid additional SP adjustment
22292233
// instructions.
22302234
AFI->setCalleeSavedStackSize(AlignedCSStackSize);

llvm/lib/Target/ARM/ARMFrameLowering.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2128,10 +2128,16 @@ void ARMFrameLowering::determineCalleeSaves(MachineFunction &MF,
21282128
AFI->setLRIsSpilledForFarJump(true);
21292129
}
21302130
AFI->setLRIsSpilled(SavedRegs.test(ARM::LR));
2131+
}
2132+
2133+
void ARMFrameLowering::getCalleeSaves(const MachineFunction &MF,
2134+
BitVector &SavedRegs) const {
2135+
TargetFrameLowering::getCalleeSaves(MF, SavedRegs);
21312136

21322137
// If we have the "returned" parameter attribute which guarantees that we
21332138
// return the value which was passed in r0 unmodified (e.g. C++ 'structors),
21342139
// record that fact for IPRA.
2140+
const ARMFunctionInfo *AFI = MF.getInfo<ARMFunctionInfo>();
21352141
if (AFI->getPreservesR0())
21362142
SavedRegs.set(ARM::R0);
21372143
}

llvm/lib/Target/ARM/ARMFrameLowering.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ class ARMFrameLowering : public TargetFrameLowering {
5353
int ResolveFrameIndexReference(const MachineFunction &MF, int FI,
5454
unsigned &FrameReg, int SPAdj) const;
5555

56+
void getCalleeSaves(const MachineFunction &MF,
57+
BitVector &SavedRegs) const override;
5658
void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
5759
RegScavenger *RS) const override;
5860

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
# RUN: llc -start-before=prologepilog -filetype=obj -o %t %s
2+
# RUN: llvm-dwarfdump --name=obj1 %t | FileCheck %s --check-prefix=CHECKDWARF1
3+
# RUN: llvm-dwarfdump --name=obj2 %t | FileCheck %s --check-prefix=CHECKDWARF2
4+
# RUN: llvm-objdump --disassemble %t | FileCheck %s --check-prefix=CHECKASM
5+
#
6+
# Test that the location for obj1 and obj2 in the debug information is
7+
# the same as the location used by load instructions.
8+
#
9+
# CHECKDWARF1: DW_AT_location (DW_OP_fbreg -1)
10+
# CHECKDWARF2: DW_AT_location (DW_OP_fbreg -2)
11+
# CHECKASM: ldurb w0, [x29, #-1]
12+
# CHECKASM: ldurb w1, [x29, #-2]
13+
--- |
14+
; ModuleID = 'wrong-callee-save-size-after-livedebugvariables.c'
15+
source_filename = "wrong-callee-save-size-after-livedebugvariables.c"
16+
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
17+
target triple = "aarch64-unknown-linux-gnu"
18+
19+
; Function Attrs: noinline nounwind optnone
20+
define dso_local i8 @foo() #0 !dbg !7 {
21+
entry:
22+
%obj1 = alloca i8, align 1
23+
%obj2 = alloca i8, align 1
24+
%obj3 = alloca [238 x i8], align 1
25+
ret i8 undef, !dbg !24
26+
}
27+
28+
declare dso_local i8 @bar(i8, i8, i8*) #0
29+
30+
attributes #0 = { noinline nounwind optnone "frame-pointer"="all" }
31+
32+
!llvm.dbg.cu = !{!0}
33+
!llvm.module.flags = !{!3, !4, !5}
34+
!llvm.ident = !{!6}
35+
36+
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 10.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
37+
!1 = !DIFile(filename: "wrong-callee-save-size-after-livedebugvariables.c", directory: "")
38+
!2 = !{}
39+
!3 = !{i32 2, !"Dwarf Version", i32 4}
40+
!4 = !{i32 2, !"Debug Info Version", i32 3}
41+
!5 = !{i32 1, !"wchar_size", i32 4}
42+
!6 = !{!"clang version 10.0.0"}
43+
!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
44+
!8 = !DISubroutineType(types: !9)
45+
!9 = !{!10}
46+
!10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char)
47+
!11 = !DILocalVariable(name: "obj1", scope: !7, file: !1, line: 4, type: !10)
48+
!12 = !DILocation(line: 4, column: 8, scope: !7)
49+
!13 = !DILocalVariable(name: "obj2", scope: !7, file: !1, line: 5, type: !10)
50+
!14 = !DILocation(line: 5, column: 8, scope: !7)
51+
!15 = !DILocalVariable(name: "obj3", scope: !7, file: !1, line: 6, type: !16)
52+
!16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 1904, elements: !17)
53+
!17 = !{!18}
54+
!18 = !DISubrange(count: 238)
55+
!19 = !DILocation(line: 6, column: 8, scope: !7)
56+
!20 = !DILocation(line: 7, column: 14, scope: !7)
57+
!21 = !DILocation(line: 7, column: 20, scope: !7)
58+
!22 = !DILocation(line: 7, column: 27, scope: !7)
59+
!23 = !DILocation(line: 7, column: 10, scope: !7)
60+
!24 = !DILocation(line: 7, column: 3, scope: !7)
61+
62+
...
63+
---
64+
name: foo
65+
tracksRegLiveness: true
66+
frameInfo:
67+
hasCalls: true
68+
fixedStack: []
69+
stack:
70+
- { id: 0, name: obj1, type: default, offset: 0, size: 1, alignment: 1,
71+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
72+
local-offset: -1, debug-info-variable: '!11', debug-info-expression: '!DIExpression()',
73+
debug-info-location: '!12' }
74+
- { id: 1, name: obj2, type: default, offset: 0, size: 1, alignment: 1,
75+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
76+
local-offset: -2, debug-info-variable: '!13', debug-info-expression: '!DIExpression()',
77+
debug-info-location: '!14' }
78+
- { id: 2, name: obj3, type: default, offset: 0, size: 238, alignment: 1,
79+
stack-id: default, callee-saved-register: '', callee-saved-restored: true,
80+
local-offset: -240, debug-info-variable: '!15', debug-info-expression: '!DIExpression()',
81+
debug-info-location: '!19' }
82+
body: |
83+
bb.1.entry:
84+
renamable $x2 = ADDXri %stack.2.obj3, 0, 0
85+
renamable $w0 = LDRBBui %stack.0.obj1, 0, debug-location !20 :: (load 1 from %ir.obj1)
86+
renamable $w1 = LDRBBui %stack.1.obj2, 0, debug-location !21 :: (load 1 from %ir.obj2)
87+
ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp, debug-location !23
88+
BL @bar, csr_aarch64_aapcs, implicit-def $lr, implicit $sp, implicit killed $w0, implicit killed $w1, implicit killed $x2, implicit-def $w0, debug-location !23
89+
ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp, debug-location !23
90+
RET_ReallyLR implicit killed $w0, debug-location !24
91+
92+
...

llvm/test/DebugInfo/MIR/Mips/live-debug-values-reg-copy.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# RUN: llc -run-pass=livedebugvalues %s -o - | FileCheck %s
1+
# RUN: llc -start-before=prologepilog -stop-after=livedebugvalues %s -o - | FileCheck %s
22
#
33
# This test tests tracking variables value transferring from one register to another.
44
# This example is altered additionally in order to test transferring from one float register

llvm/test/DebugInfo/MIR/X86/live-debug-values-reg-copy.mir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# RUN: llc -run-pass=livedebugvalues %s -o - | FileCheck %s
1+
# RUN: llc -start-before=prologepilog -stop-after=livedebugvalues %s -o - | FileCheck %s
22
#
33
# This test tests tracking variables value transferring from one register to another.
44
# This example is altered additionally in order to test transferring from one float register

0 commit comments

Comments
 (0)