llvm.org GIT mirror llvm / b951e50
Consider regmasks when computing register-based DBG_VALUE live ranges Now register parameters that aren't saved to the stack or CSRs are considered dead after the first call. Previously the debugger would show whatever was in the register. Fixes PR26589 Reviewers: aprantl Differential Revision: http://reviews.llvm.org/D17211 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@264429 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 years ago
9 changed file(s) with 194 addition(s) and 42 deletion(s). Raw diff Collapse all Expand all
1414 #include "llvm/IR/DebugInfo.h"
1515 #include "llvm/Support/Debug.h"
1616 #include "llvm/Support/raw_ostream.h"
17 #include "llvm/Target/TargetLowering.h"
1718 #include "llvm/Target/TargetRegisterInfo.h"
19 #include "llvm/Target/TargetSubtargetInfo.h"
1820 #include
1921 #include
2022 using namespace llvm;
119121 if (I == RegVars.end())
120122 return;
121123 clobberRegisterUses(RegVars, I, HistMap, ClobberingInstr);
122 }
123
124 // \brief Collect all registers clobbered by @MI and apply the functor
125 // @Func to their RegNo.
126 // @Func should be a functor with a void(unsigned) signature. We're
127 // not using std::function here for performance reasons. It has a
128 // small but measurable impact. By using a functor instead of a
129 // std::set& here, we can avoid the overhead of constructing
130 // temporaries in calculateDbgValueHistory, which has a significant
131 // performance impact.
132 template
133 static void applyToClobberedRegisters(const MachineInstr &MI,
134 const TargetRegisterInfo *TRI,
135 Callable Func) {
136 for (const MachineOperand &MO : MI.operands()) {
137 if (!MO.isReg() || !MO.isDef() || !MO.getReg())
138 continue;
139 for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid(); ++AI)
140 Func(*AI);
141 }
142124 }
143125
144126 // \brief Returns the first instruction in @MBB which corresponds to
172154 auto FirstEpilogueInst = getFirstEpilogueInst(MBB);
173155
174156 for (const auto &MI : MBB) {
157 // Avoid looking at prologue or epilogue instructions.
175158 if (&MI == FirstEpilogueInst)
176159 break;
177 if (!MI.getFlag(MachineInstr::FrameSetup))
178 applyToClobberedRegisters(MI, TRI, [&](unsigned r) { Regs.set(r); });
160 if (MI.getFlag(MachineInstr::FrameSetup))
161 continue;
162
163 // Look for register defs and register masks. Register masks are
164 // typically on calls and they clobber everything not in the mask.
165 for (const MachineOperand &MO : MI.operands()) {
166 if (MO.isReg() && MO.isDef() && MO.getReg()) {
167 for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
168 ++AI)
169 Regs.set(*AI);
170 } else if (MO.isRegMask()) {
171 Regs.setBitsNotInMask(MO.getRegMask());
172 }
173 }
179174 }
180175 }
181176 }
186181 BitVector ChangingRegs(TRI->getNumRegs());
187182 collectChangingRegs(MF, TRI, ChangingRegs);
188183
184 const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
185 unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
189186 RegDescribedVarsMap RegVars;
190187 for (const auto &MBB : *MF) {
191188 for (const auto &MI : MBB) {
192189 if (!MI.isDebugValue()) {
193190 // Not a DBG_VALUE instruction. It may clobber registers which describe
194191 // some variables.
195 applyToClobberedRegisters(MI, TRI, [&](unsigned RegNo) {
196 if (ChangingRegs.test(RegNo))
197 clobberRegisterUses(RegVars, RegNo, Result, MI);
198 });
192 for (const MachineOperand &MO : MI.operands()) {
193 if (MO.isReg() && MO.isDef() && MO.getReg()) {
194 // If this is a register def operand, it may end a debug value
195 // range.
196 for (MCRegAliasIterator AI(MO.getReg(), TRI, true); AI.isValid();
197 ++AI)
198 if (ChangingRegs.test(*AI))
199 clobberRegisterUses(RegVars, *AI, Result, MI);
200 } else if (MO.isRegMask()) {
201 // If this is a register mask operand, clobber all debug values in
202 // non-CSRs.
203 for (int I = ChangingRegs.find_first(); I != -1;
204 I = ChangingRegs.find_next(I)) {
205 // Don't consider SP to be clobbered by register masks.
206 if (unsigned(I) != SP && TRI->isPhysicalRegister(I) &&
207 MO.clobbersPhysReg(I)) {
208 clobberRegisterUses(RegVars, I, Result, MI);
209 }
210 }
211 }
212 }
199213 continue;
200214 }
201215
2929 #include "llvm/Support/Debug.h"
3030 #include "llvm/Support/raw_ostream.h"
3131 #include "llvm/Target/TargetInstrInfo.h"
32 #include "llvm/Target/TargetLowering.h"
3233 #include "llvm/Target/TargetRegisterInfo.h"
3334 #include "llvm/Target/TargetSubtargetInfo.h"
3435 #include
207208 /// A definition of a register may mark the end of a range.
208209 void LiveDebugValues::transferRegisterDef(MachineInstr &MI,
209210 VarLocList &OpenRanges) {
211 MachineFunction *MF = MI.getParent()->getParent();
212 const TargetLowering *TLI = MF->getSubtarget().getTargetLowering();
213 unsigned SP = TLI->getStackPointerRegisterToSaveRestore();
210214 for (const MachineOperand &MO : MI.operands()) {
211 if (!(MO.isReg() && MO.isDef() && MO.getReg() &&
212 TRI->isPhysicalRegister(MO.getReg())))
213 continue;
214 // Remove ranges of all aliased registers.
215 for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI)
215 if (MO.isReg() && MO.isDef() && MO.getReg() &&
216 TRI->isPhysicalRegister(MO.getReg())) {
217 // Remove ranges of all aliased registers.
218 for (MCRegAliasIterator RAI(MO.getReg(), TRI, true); RAI.isValid(); ++RAI)
219 OpenRanges.erase(std::remove_if(OpenRanges.begin(), OpenRanges.end(),
220 [&](const VarLoc &V) {
221 return (*RAI ==
222 isDescribedByReg(*V.MI));
223 }),
224 OpenRanges.end());
225 } else if (MO.isRegMask()) {
226 // Remove ranges of all clobbered registers. Register masks don't usually
227 // list SP as preserved. While the debug info may be off for an
228 // instruction or two around callee-cleanup calls, transferring the
229 // DEBUG_VALUE across the call is still a better user experience.
216230 OpenRanges.erase(std::remove_if(OpenRanges.begin(), OpenRanges.end(),
217231 [&](const VarLoc &V) {
218 return (*RAI ==
219 isDescribedByReg(*V.MI));
232 unsigned Reg = isDescribedByReg(*V.MI);
233 return Reg && Reg != SP &&
234 MO.clobbersPhysReg(Reg);
220235 }),
221236 OpenRanges.end());
237 }
222238 }
223239 }
224240
3232 # DBG_VALUE for variable "n" is extended into BB#5 from its predecessors BB#3
3333 # and BB#4.
3434 # CHECK: bb.5.if.end.7:
35 # CHECK: DBG_VALUE debug-use %rsi, debug-use _, !13, !20, debug-location !22
36 # CHECK-NEXT: DBG_VALUE debug-use %ebx, debug-use _, !14, !20, debug-location !33
35 # CHECK: DBG_VALUE debug-use %ebx, debug-use _, !14, !20, debug-location !33
3736
3837
3938 --- |
1515 ; Test that we only emit register-indirect locations for the array array.
1616 ; rdar://problem/14874886
1717 ;
18 ; CHECK: ##DEBUG_VALUE: main:array <- [%R{{.*}}+0]
19 ; CHECK: ##DEBUG_VALUE: main:array <- [%R{{.*}}+0]
20 ; CHECK: ##DEBUG_VALUE: main:array <- [%R{{.*}}+0]
18 ; FIXME: If we described this location as RSP-relative instead of RDI-relative
19 ; the live range would be larger.
20 ; CHECK: ##DEBUG_VALUE: main:array <- [%RDI+0]
2121 ; CHECK-NOT: ##DEBUG_VALUE: main:array <- %R{{.*}}
2222 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
2323 target triple = "x86_64-apple-macosx10.9.0"
1313 ; CHECK: DBG_VALUE 23, 0, ![[X]],
1414 ; CHECK: DBG_VALUE debug-use %rdi, debug-use _, ![[X]]
1515 ; CHECK: bb.1.if.then:
16 ; CHECK: DBG_VALUE debug-use %rdi, debug-use _, ![[X]],
16 ; CHECK: DBG_VALUE 43, 0, ![[X]],
1717 ; CHECK: bb.2.if.end:
1818 ; CHECK-NOT: DBG_VALUE 23, 0, ![[X]],
1919 ; CHECK: RETQ %eax
0 ; RUN: llc < %s | FileCheck %s --check-prefix=ASM
1 ; RUN: llc < %s -filetype=obj | llvm-dwarfdump - | FileCheck %s --check-prefix=DWARF
2
3 ; Values in registers should be clobbered by calls, which use a regmask instead
4 ; of individual register def operands.
5
6 ; ASM: main: # @main
7 ; ASM: #DEBUG_VALUE: main:argc <- %ECX
8 ; ASM: movl $1, x(%rip)
9 ; ASM: callq clobber
10 ; ASM-NEXT: [[argc_range_end:.Ltmp[0-9]+]]:
11 ; Previously LiveDebugValues would claim argc was still in ECX after the call.
12 ; ASM-NOT: #DEBUG_VALUE: main:argc
13
14 ; argc is the first debug location.
15 ; ASM: .Ldebug_loc1:
16 ; ASM-NEXT: .quad .Lfunc_begin0-.Lfunc_begin0
17 ; ASM-NEXT: .quad [[argc_range_end]]-.Lfunc_begin0
18 ; ASM-NEXT: .short 3 # Loc expr size
19 ; ASM-NEXT: .byte 82 # super-register DW_OP_reg2
20 ; ASM-NEXT: .byte 147 # DW_OP_piece
21 ; ASM-NEXT: .byte 4 # 4
22
23 ; argc is the first formal parameter.
24 ; DWARF: .debug_info contents:
25 ; DWARF: DW_TAG_formal_parameter
26 ; DWARF-NEXT: DW_AT_location [DW_FORM_sec_offset] ([[argc_loc_offset:0x.*]])
27 ; DWARF-NEXT: DW_AT_name [DW_FORM_strp] {{.*}} "argc"
28
29 ; DWARF: .debug_loc contents:
30 ; DWARF: [[argc_loc_offset]]: Beginning address offset: 0x0000000000000000
31 ; DWARF-NEXT: Ending address offset: 0x0000000000000013
32 ; DWARF-NEXT: Location description: 52 93 04
33
34 ; ModuleID = 't.cpp'
35 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
36 target triple = "x86_64-pc-windows-msvc18.0.0"
37
38 @x = common global i32 0, align 4
39
40 ; Function Attrs: nounwind uwtable
41 define i32 @main(i32 %argc, i8** nocapture readnone %argv) #0 !dbg !4 {
42 entry:
43 tail call void @llvm.dbg.value(metadata i8** %argv, i64 0, metadata !12, metadata !21), !dbg !22
44 tail call void @llvm.dbg.value(metadata i32 %argc, i64 0, metadata !13, metadata !21), !dbg !23
45 store volatile i32 1, i32* @x, align 4, !dbg !24, !tbaa !25
46 tail call void @clobber() #3, !dbg !29
47 store volatile i32 2, i32* @x, align 4, !dbg !30, !tbaa !25
48 %0 = load volatile i32, i32* @x, align 4, !dbg !31, !tbaa !25
49 %tobool = icmp eq i32 %0, 0, !dbg !31
50 br i1 %tobool, label %if.else, label %if.then, !dbg !33
51
52 if.then: ; preds = %entry
53 store volatile i32 3, i32* @x, align 4, !dbg !34, !tbaa !25
54 br label %if.end, !dbg !36
55
56 if.else: ; preds = %entry
57 store volatile i32 4, i32* @x, align 4, !dbg !37, !tbaa !25
58 br label %if.end
59
60 if.end: ; preds = %if.else, %if.then
61 ret i32 0, !dbg !39
62 }
63
64 declare void @clobber()
65
66 ; Function Attrs: nounwind readnone
67 declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #2
68
69 attributes #0 = { nounwind uwtable }
70 attributes #2 = { nounwind readnone }
71 attributes #3 = { nounwind }
72
73 !llvm.dbg.cu = !{!0}
74 !llvm.module.flags = !{!17, !18, !19}
75 !llvm.ident = !{!20}
76
77 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (trunk 260617) (llvm/trunk 260619)", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3, globals: !14)
78 !1 = !DIFile(filename: "t.cpp", directory: "D:\5Csrc\5Cllvm\5Cbuild")
79 !2 = !{}
80 !3 = !{!4}
81 !4 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 4, type: !5, isLocal: false, isDefinition: true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: true, variables: !11)
82 !5 = !DISubroutineType(types: !6)
83 !6 = !{!7, !7, !8}
84 !7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
85 !8 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !9, size: 64, align: 64)
86 !9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, align: 64)
87 !10 = !DIBasicType(name: "char", size: 8, align: 8, encoding: DW_ATE_signed_char)
88 !11 = !{!12, !13}
89 !12 = !DILocalVariable(name: "argv", arg: 2, scope: !4, file: !1, line: 4, type: !8)
90 !13 = !DILocalVariable(name: "argc", arg: 1, scope: !4, file: !1, line: 4, type: !7)
91 !14 = !{!15}
92 !15 = !DIGlobalVariable(name: "x", scope: !0, file: !1, line: 1, type: !16, isLocal: false, isDefinition: true, variable: i32* @x)
93 !16 = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: !7)
94 !17 = !{i32 2, !"Dwarf Version", i32 4}
95 !18 = !{i32 2, !"Debug Info Version", i32 3}
96 !19 = !{i32 1, !"PIC Level", i32 2}
97 !20 = !{!"clang version 3.9.0 (trunk 260617) (llvm/trunk 260619)"}
98 !21 = !DIExpression()
99 !22 = !DILocation(line: 4, column: 27, scope: !4)
100 !23 = !DILocation(line: 4, column: 14, scope: !4)
101 !24 = !DILocation(line: 5, column: 5, scope: !4)
102 !25 = !{!26, !26, i64 0}
103 !26 = !{!"int", !27, i64 0}
104 !27 = !{!"omnipotent char", !28, i64 0}
105 !28 = !{!"Simple C/C++ TBAA"}
106 !29 = !DILocation(line: 6, column: 3, scope: !4)
107 !30 = !DILocation(line: 7, column: 5, scope: !4)
108 !31 = !DILocation(line: 8, column: 7, scope: !32)
109 !32 = distinct !DILexicalBlock(scope: !4, file: !1, line: 8, column: 7)
110 !33 = !DILocation(line: 8, column: 7, scope: !4)
111 !34 = !DILocation(line: 9, column: 7, scope: !35)
112 !35 = distinct !DILexicalBlock(scope: !32, file: !1, line: 8, column: 10)
113 !36 = !DILocation(line: 10, column: 3, scope: !35)
114 !37 = !DILocation(line: 11, column: 7, scope: !38)
115 !38 = distinct !DILexicalBlock(scope: !32, file: !1, line: 10, column: 10)
116 !39 = !DILocation(line: 13, column: 1, scope: !4)
1414 ; CHECK: #DEBUG_VALUE: bar:y <- [%RDI+0]
1515 ; CHECK: movq %rdi, [[OFFSET:[0-9]+]](%rsp)
1616 ; CHECK-NEXT: [[START_LABEL:.Ltmp[0-9]+]]
17 ; CHECK-NEXT: #DEBUG_VALUE: bar:y <- [complex expression]
1718 ; This location should be valid until the end of the function.
19
20 ; CHECK: movq %rbp, %rsp
21 ; CHECK-NEXT: [[END_LABEL:.Ltmp[0-9]+]]:
1822
1923 ; CHECK: .Ldebug_loc{{[0-9]+}}:
2024 ; We expect two location ranges for the variable.
2630
2731 ; Then it's addressed via %rsp:
2832 ; CHECK: .quad [[START_LABEL]]-.Lfunc_begin0
29 ; CHECK-NEXT: .Lfunc_end0-.Lfunc_begin0
33 ; CHECK-NEXT: .quad [[END_LABEL]]-.Lfunc_begin0
3034 ; CHECK: DW_OP_breg7
3135 ; CHECK-NEXT: [[OFFSET]]
3236 ; CHECK: DW_OP_deref
3030 ; and BB#4.
3131 ; CHECK: .LBB0_5:
3232 ; CHECK-NEXT: #DEBUG_VALUE: main:n <- %EBX
33 ; CHECK-NEXT: #DEBUG_VALUE: main:argv <- %RSI
33 ; Other register values have been clobbered.
34 ; CHECK-NOT: #DEBUG_VALUE:
35 ; CHECK: movl %ecx, m(%rip)
3436
3537 ; ModuleID = 'LiveDebugValues.c'
3638 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
1313 ; Location of "range" string is spilled from %rdx to stack and is
1414 ; addressed via %rbp.
1515 ; CHECK: movq %rdx, {{[-0-9]+}}(%rbp)
16 ; CHECK-NEXT: [[START_LABEL:.Ltmp[0-9]+]]
16 ; CHECK-NEXT: [[START_LABEL:.Ltmp[0-9]+]]:
1717 ; This location should be valid until the end of the function.
1818
1919 ; Verify that we have proper range in debug_loc section: