llvm.org GIT mirror llvm / 4548d29
[AArch64][DebugInfo] Do not recompute CalleeSavedStackSize (Take 2) Commit message from D66935: 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. This patch fixes the lldb unit tests in `functionalities/thread/concurrent_events/*` Changes after D66935: Ensures AArch64FunctionInfo::getCalleeSavedStackSize does not return the uninitialized CalleeSavedStackSize when running `llc` on a specific pass where the MIR code has already been expected to have gone through PEI. Instead, getCalleeSavedStackSize (when passed the MachineFrameInfo) will try to recalculate the CalleeSavedStackSize from the CalleeSavedInfo. In debug mode, the compiler will assert the recalculated size equals the cached size as calculated through a call to determineCalleeSaves. This fixes two tests: test/DebugInfo/AArch64/asan-stack-vars.mir test/DebugInfo/AArch64/compiler-gen-bbs-livedebugvalues.mir that otherwise fail when compiled using msan. Reviewed By: omjavaid, efriedma Tags: #llvm Differential Revision: https://reviews.llvm.org/D68783 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@375425 91177308-0d34-0410-b5e6-96231b3b80d8 Sander de Smalen 1 year, 1 month ago
10 changed file(s) with 182 addition(s) and 9 deletion(s). Raw diff Collapse all Expand all
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
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
14381438 TRI = MF.getSubtarget().getRegisterInfo();
14391439 TII = MF.getSubtarget().getInstrInfo();
14401440 TFI = MF.getSubtarget().getFrameLowering();
1441 TFI->determineCalleeSaves(MF, CalleeSavedRegs,
1442 std::make_unique().get());
1441 TFI->getCalleeSaves(MF, CalleeSavedRegs);
14431442 LS.initialize(MF);
14441443
14451444 bool Changed = ExtendRanges(MF);
5555
5656 bool runOnMachineFunction(MachineFunction &MF) override;
5757
58 // Call determineCalleeSaves and then also set the bits for subregs and
58 // Call getCalleeSaves and then also set the bits for subregs and
5959 // fully saved superregs.
6060 static void computeCalleeSavedRegs(BitVector &SavedRegs, MachineFunction &MF);
6161
198198
199199 // Target will return the set of registers that it saves/restores as needed.
200200 SavedRegs.clear();
201 TFI.determineCalleeSaves(MF, SavedRegs);
201 TFI.getCalleeSaves(MF, SavedRegs);
202202 if (SavedRegs.none())
203203 return;
204204
5757 bool TargetFrameLowering::needsFrameIndexResolution(
5858 const MachineFunction &MF) const {
5959 return MF.getFrameInfo().hasStackObjects();
60 }
61
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());
6073 }
6174
6275 void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF,
15871587 bool IsWin64 =
15881588 Subtarget.isCallingConvWin64(MF.getFunction().getCallingConv());
15891589 unsigned FixedObject = IsWin64 ? alignTo(AFI->getVarArgsGPRSize(), 16) : 0;
1590 unsigned FPAdjust = isTargetDarwin(MF) ? 16 : AFI->getCalleeSavedStackSize();
1590 unsigned FPAdjust = isTargetDarwin(MF)
1591 ? 16 : AFI->getCalleeSavedStackSize(MF.getFrameInfo());
15911592 return {ObjectOffset + FixedObject + FPAdjust, MVT::i8};
15921593 }
15931594
16291630 int FPOffset = getFPOffset(MF, ObjectOffset).getBytes();
16301631 int Offset = getStackOffset(MF, ObjectOffset).getBytes();
16311632 bool isCSR =
1632 !isFixed && ObjectOffset >= -((int)AFI->getCalleeSavedStackSize());
1633 !isFixed && ObjectOffset >= -((int)AFI->getCalleeSavedStackSize(MFI));
16331634
16341635 const StackOffset &SVEStackSize = getSVEStackSize(MF);
16351636
23032304 << EstimatedStackSize + AlignedCSStackSize
23042305 << " bytes.\n");
23052306
2307 assert((!MFI.isCalleeSavedInfoValid() ||
2308 AFI->getCalleeSavedStackSize() == AlignedCSStackSize) &&
2309 "Should not invalidate callee saved info");
2310
23062311 // Round up to register pair alignment to avoid additional SP adjustment
23072312 // instructions.
23082313 AFI->setCalleeSavedStackSize(AlignedCSStackSize);
5454
5555 /// Amount of stack frame size used for saving callee-saved registers.
5656 unsigned CalleeSavedStackSize;
57 bool HasCalleeSavedStackSize = false;
5758
5859 /// Number of TLS accesses using the special (combinable)
5960 /// _TLS_MODULE_BASE_ symbol.
166167 void setLocalStackSize(unsigned Size) { LocalStackSize = Size; }
167168 unsigned getLocalStackSize() const { return LocalStackSize; }
168169
169 void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; }
170 unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; }
170 void setCalleeSavedStackSize(unsigned Size) {
171 CalleeSavedStackSize = Size;
172 HasCalleeSavedStackSize = true;
173 }
174
175 // When CalleeSavedStackSize has not been set (for example when
176 // some MachineIR pass is run in isolation), then recalculate
177 // the CalleeSavedStackSize directly from the CalleeSavedInfo.
178 // Note: This information can only be recalculated after PEI
179 // has assigned offsets to the callee save objects.
180 unsigned getCalleeSavedStackSize(const MachineFrameInfo &MFI) const {
181 bool ValidateCalleeSavedStackSize = false;
182
183 #ifndef NDEBUG
184 // Make sure the calculated size derived from the CalleeSavedInfo
185 // equals the cached size that was calculated elsewhere (e.g. in
186 // determineCalleeSaves).
187 ValidateCalleeSavedStackSize = HasCalleeSavedStackSize;
188 #endif
189
190 if (!HasCalleeSavedStackSize || ValidateCalleeSavedStackSize) {
191 assert(MFI.isCalleeSavedInfoValid() && "CalleeSavedInfo not calculated");
192 if (MFI.getCalleeSavedInfo().empty())
193 return 0;
194
195 int64_t MinOffset = std::numeric_limits::max();
196 int64_t MaxOffset = std::numeric_limits::min();
197 for (const auto &Info : MFI.getCalleeSavedInfo()) {
198 int FrameIdx = Info.getFrameIdx();
199 int64_t Offset = MFI.getObjectOffset(FrameIdx);
200 int64_t ObjSize = MFI.getObjectSize(FrameIdx);
201 MinOffset = std::min(Offset, MinOffset);
202 MaxOffset = std::max(Offset + ObjSize, MaxOffset);
203 }
204
205 unsigned Size = alignTo(MaxOffset - MinOffset, 16);
206 assert((!HasCalleeSavedStackSize || getCalleeSavedStackSize() == Size) &&
207 "Invalid size calculated for callee saves");
208 return Size;
209 }
210
211 return getCalleeSavedStackSize();
212 }
213
214 unsigned getCalleeSavedStackSize() const {
215 assert(HasCalleeSavedStackSize &&
216 "CalleeSavedStackSize has not been calculated");
217 return CalleeSavedStackSize;
218 }
171219
172220 void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamicTLSAccesses; }
173221 unsigned getNumLocalDynamicTLSAccesses() const {
21272127 AFI->setLRIsSpilledForFarJump(true);
21282128 }
21292129 AFI->setLRIsSpilled(SavedRegs.test(ARM::LR));
2130 }
2131
2132 void ARMFrameLowering::getCalleeSaves(const MachineFunction &MF,
2133 BitVector &SavedRegs) const {
2134 TargetFrameLowering::getCalleeSaves(MF, SavedRegs);
21302135
21312136 // If we have the "returned" parameter attribute which guarantees that we
21322137 // return the value which was passed in r0 unmodified (e.g. C++ 'structors),
21332138 // record that fact for IPRA.
2139 const ARMFunctionInfo *AFI = MF.getInfo();
21342140 if (AFI->getPreservesR0())
21352141 SavedRegs.set(ARM::R0);
21362142 }
5252 int ResolveFrameIndexReference(const MachineFunction &MF, int FI,
5353 unsigned &FrameReg, int SPAdj) const;
5454
55 void getCalleeSaves(const MachineFunction &MF,
56 BitVector &SavedRegs) const override;
5557 void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs,
5658 RegScavenger *RS) const override;
5759
0 # RUN: llc -start-before=prologepilog -filetype=obj -o %t %s
1 # RUN: llvm-dwarfdump --name=obj1 %t | FileCheck %s --check-prefix=CHECKDWARF1
2 # RUN: llvm-dwarfdump --name=obj2 %t | FileCheck %s --check-prefix=CHECKDWARF2
3 # RUN: llvm-objdump --disassemble %t | FileCheck %s --check-prefix=CHECKASM
4 #
5 # Test that the location for obj1 and obj2 in the debug information is
6 # the same as the location used by load instructions.
7 #
8 # CHECKDWARF1: DW_AT_location (DW_OP_fbreg -1)
9 # CHECKDWARF2: DW_AT_location (DW_OP_fbreg -2)
10 # CHECKASM: ldurb w0, [x29, #-1]
11 # CHECKASM: ldurb w1, [x29, #-2]
12 --- |
13 ; ModuleID = 'wrong-callee-save-size-after-livedebugvariables.c'
14 source_filename = "wrong-callee-save-size-after-livedebugvariables.c"
15 target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
16 target triple = "aarch64-unknown-linux-gnu"
17
18 ; Function Attrs: noinline nounwind optnone
19 define dso_local i8 @foo() #0 !dbg !7 {
20 entry:
21 %obj1 = alloca i8, align 1
22 %obj2 = alloca i8, align 1
23 %obj3 = alloca [238 x i8], align 1
24 ret i8 undef, !dbg !24
25 }
26
27 declare dso_local i8 @bar(i8, i8, i8*) #0
28
29 attributes #0 = { noinline nounwind optnone "frame-pointer"="all" }
30
31 !llvm.dbg.cu = !{!0}
32 !llvm.module.flags = !{!3, !4, !5}
33 !llvm.ident = !{!6}
34
35 !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)
36 !1 = !DIFile(filename: "wrong-callee-save-size-after-livedebugvariables.c", directory: "")
37 !2 = !{}
38 !3 = !{i32 2, !"Dwarf Version", i32 4}
39 !4 = !{i32 2, !"Debug Info Version", i32 3}
40 !5 = !{i32 1, !"wchar_size", i32 4}
41 !6 = !{!"clang version 10.0.0"}
42 !7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 3, type: !8, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
43 !8 = !DISubroutineType(types: !9)
44 !9 = !{!10}
45 !10 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_unsigned_char)
46 !11 = !DILocalVariable(name: "obj1", scope: !7, file: !1, line: 4, type: !10)
47 !12 = !DILocation(line: 4, column: 8, scope: !7)
48 !13 = !DILocalVariable(name: "obj2", scope: !7, file: !1, line: 5, type: !10)
49 !14 = !DILocation(line: 5, column: 8, scope: !7)
50 !15 = !DILocalVariable(name: "obj3", scope: !7, file: !1, line: 6, type: !16)
51 !16 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 1904, elements: !17)
52 !17 = !{!18}
53 !18 = !DISubrange(count: 238)
54 !19 = !DILocation(line: 6, column: 8, scope: !7)
55 !20 = !DILocation(line: 7, column: 14, scope: !7)
56 !21 = !DILocation(line: 7, column: 20, scope: !7)
57 !22 = !DILocation(line: 7, column: 27, scope: !7)
58 !23 = !DILocation(line: 7, column: 10, scope: !7)
59 !24 = !DILocation(line: 7, column: 3, scope: !7)
60
61 ...
62 ---
63 name: foo
64 tracksRegLiveness: true
65 frameInfo:
66 hasCalls: true
67 fixedStack: []
68 stack:
69 - { id: 0, name: obj1, type: default, offset: 0, size: 1, alignment: 1,
70 stack-id: default, callee-saved-register: '', callee-saved-restored: true,
71 local-offset: -1, debug-info-variable: '!11', debug-info-expression: '!DIExpression()',
72 debug-info-location: '!12' }
73 - { id: 1, name: obj2, type: default, offset: 0, size: 1, alignment: 1,
74 stack-id: default, callee-saved-register: '', callee-saved-restored: true,
75 local-offset: -2, debug-info-variable: '!13', debug-info-expression: '!DIExpression()',
76 debug-info-location: '!14' }
77 - { id: 2, name: obj3, type: default, offset: 0, size: 238, alignment: 1,
78 stack-id: default, callee-saved-register: '', callee-saved-restored: true,
79 local-offset: -240, debug-info-variable: '!15', debug-info-expression: '!DIExpression()',
80 debug-info-location: '!19' }
81 body: |
82 bb.1.entry:
83 renamable $x2 = ADDXri %stack.2.obj3, 0, 0
84 renamable $w0 = LDRBBui %stack.0.obj1, 0, debug-location !20 :: (load 1 from %ir.obj1)
85 renamable $w1 = LDRBBui %stack.1.obj2, 0, debug-location !21 :: (load 1 from %ir.obj2)
86 ADJCALLSTACKDOWN 0, 0, implicit-def $sp, implicit $sp, debug-location !23
87 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
88 ADJCALLSTACKUP 0, 0, implicit-def $sp, implicit $sp, debug-location !23
89 RET_ReallyLR implicit killed $w0, debug-location !24
90
91 ...
None # RUN: llc -run-pass=livedebugvalues %s -o - | FileCheck %s
0 # RUN: llc -start-before=prologepilog -stop-after=livedebugvalues %s -o - | FileCheck %s
11 #
22 # This test tests tracking variables value transferring from one register to another.
33 # This example is altered additionally in order to test transferring from one float register