Skip to content
This repository was archived by the owner on Apr 23, 2020. It is now read-only.

Commit ca18763

Browse files
committed
Re-land "[DebugInfo] Insert DW_OP_deref when spilling indirect DBG_VALUEs"
After r313775, it's easier to maintain a parallel BitVector of spilled locations indexed by location number. I wasn't able to build a good reduced test case for this iteration of the bug, but I added a more direct assertion that spilled values must use frame index locations. If this bug reappears, it won't only fire on the NEON vector code that we detected it on, but on medium-sized integer-only programs as well. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313786 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent e444299 commit ca18763

File tree

5 files changed

+380
-43
lines changed

5 files changed

+380
-43
lines changed

lib/CodeGen/LiveDebugVariables.cpp

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ class LDVImpl;
108108
/// held by the same virtual register. The equivalence class is the transitive
109109
/// closure of that relation.
110110
class UserValue {
111-
const MDNode *Variable; ///< The debug info variable we are part of.
112-
const MDNode *Expression; ///< Any complex address expression.
111+
const DILocalVariable *Variable; ///< The debug info variable we are part of.
112+
const DIExpression *Expression; ///< Any complex address expression.
113113
bool IsIndirect; ///< true if this is a register-indirect+offset value.
114114
DebugLoc dl; ///< The debug location for the variable. This is
115115
///< used by dwarf writer to find lexical scope.
@@ -127,8 +127,9 @@ class UserValue {
127127
SmallSet<SlotIndex, 2> trimmedDefs;
128128

129129
/// insertDebugValue - Insert a DBG_VALUE into MBB at Idx for LocNo.
130-
void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx, unsigned LocNo,
131-
LiveIntervals &LIS, const TargetInstrInfo &TII);
130+
void insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
131+
unsigned LocNo, bool Spilled, LiveIntervals &LIS,
132+
const TargetInstrInfo &TII);
132133

133134
/// splitLocation - Replace OldLocNo ranges with NewRegs ranges where NewRegs
134135
/// is live. Returns true if any changes were made.
@@ -137,8 +138,8 @@ class UserValue {
137138

138139
public:
139140
/// UserValue - Create a new UserValue.
140-
UserValue(const MDNode *var, const MDNode *expr, bool i, DebugLoc L,
141-
LocMap::Allocator &alloc)
141+
UserValue(const DILocalVariable *var, const DIExpression *expr, bool i,
142+
DebugLoc L, LocMap::Allocator &alloc)
142143
: Variable(var), Expression(expr), IsIndirect(i), dl(std::move(L)),
143144
leader(this), locInts(alloc) {}
144145

@@ -154,8 +155,8 @@ class UserValue {
154155
UserValue *getNext() const { return next; }
155156

156157
/// match - Does this UserValue match the parameters?
157-
bool match(const MDNode *Var, const MDNode *Expr, const DILocation *IA,
158-
bool indirect) const {
158+
bool match(const DILocalVariable *Var, const DIExpression *Expr,
159+
const DILocation *IA, bool indirect) const {
159160
return Var == Variable && Expr == Expression && dl->getInlinedAt() == IA &&
160161
indirect == IsIndirect;
161162
}
@@ -259,12 +260,14 @@ class UserValue {
259260
LiveIntervals &LIS);
260261

261262
/// rewriteLocations - Rewrite virtual register locations according to the
262-
/// provided virtual register map.
263-
void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI);
263+
/// provided virtual register map. Record which locations were spilled.
264+
void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
265+
BitVector &SpilledLocations);
264266

265267
/// emitDebugValues - Recreate DBG_VALUE instruction from data structures.
266-
void emitDebugValues(VirtRegMap *VRM,
267-
LiveIntervals &LIS, const TargetInstrInfo &TRI);
268+
void emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
269+
const TargetInstrInfo &TRI,
270+
const BitVector &SpilledLocations);
268271

269272
/// getDebugLoc - Return DebugLoc of this UserValue.
270273
DebugLoc getDebugLoc() { return dl;}
@@ -294,11 +297,11 @@ class LDVImpl {
294297
VRMap virtRegToEqClass;
295298

296299
/// Map user variable to eq class leader.
297-
using UVMap = DenseMap<const MDNode *, UserValue *>;
300+
using UVMap = DenseMap<const DILocalVariable *, UserValue *>;
298301
UVMap userVarMap;
299302

300303
/// getUserValue - Find or create a UserValue.
301-
UserValue *getUserValue(const MDNode *Var, const MDNode *Expr,
304+
UserValue *getUserValue(const DILocalVariable *Var, const DIExpression *Expr,
302305
bool IsIndirect, const DebugLoc &DL);
303306

304307
/// lookupVirtReg - Find the EC leader for VirtReg or null.
@@ -423,8 +426,9 @@ void UserValue::mapVirtRegs(LDVImpl *LDV) {
423426
LDV->mapVirtReg(locations[i].getReg(), this);
424427
}
425428

426-
UserValue *LDVImpl::getUserValue(const MDNode *Var, const MDNode *Expr,
427-
bool IsIndirect, const DebugLoc &DL) {
429+
UserValue *LDVImpl::getUserValue(const DILocalVariable *Var,
430+
const DIExpression *Expr, bool IsIndirect,
431+
const DebugLoc &DL) {
428432
UserValue *&Leader = userVarMap[Var];
429433
if (Leader) {
430434
UserValue *UV = Leader->getLeader();
@@ -463,11 +467,11 @@ bool LDVImpl::handleDebugValue(MachineInstr &MI, SlotIndex Idx) {
463467
}
464468

465469
// Get or create the UserValue for (variable,offset).
466-
bool IsIndirect = MI.isIndirectDebugValue();
470+
bool IsIndirect = MI.getOperand(1).isImm();
467471
if (IsIndirect)
468472
assert(MI.getOperand(1).getImm() == 0 && "DBG_VALUE with nonzero offset");
469-
const MDNode *Var = MI.getDebugVariable();
470-
const MDNode *Expr = MI.getDebugExpression();
473+
const DILocalVariable *Var = MI.getDebugVariable();
474+
const DIExpression *Expr = MI.getDebugExpression();
471475
//here.
472476
UserValue *UV = getUserValue(Var, Expr, IsIndirect, MI.getDebugLoc());
473477
UV->addDef(Idx, MI.getOperand(0));
@@ -940,15 +944,20 @@ splitRegister(unsigned OldReg, ArrayRef<unsigned> NewRegs, LiveIntervals &LIS) {
940944
static_cast<LDVImpl*>(pImpl)->splitRegister(OldReg, NewRegs);
941945
}
942946

943-
void UserValue::rewriteLocations(VirtRegMap &VRM,
944-
const TargetRegisterInfo &TRI) {
947+
void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
948+
BitVector &SpilledLocations) {
945949
// Build a set of new locations with new numbers so we can coalesce our
946950
// IntervalMap if two vreg intervals collapse to the same physical location.
947951
// Use MapVector instead of SetVector because MapVector::insert returns the
948-
// position of the previously or newly inserted element.
952+
// position of the previously or newly inserted element. The boolean value
953+
// tracks if the location was produced by a spill.
954+
// FIXME: This will be problematic if we ever support direct and indirect
955+
// frame index locations, i.e. expressing both variables in memory and
956+
// 'int x, *px = &x'. The "spilled" bit must become part of the location.
949957
MapVector<MachineOperand, bool> NewLocations;
950958
SmallVector<unsigned, 4> LocNoMap(locations.size());
951959
for (unsigned I = 0, E = locations.size(); I != E; ++I) {
960+
bool Spilled = false;
952961
MachineOperand Loc = locations[I];
953962
// Only virtual registers are rewritten.
954963
if (Loc.isReg() && Loc.getReg() &&
@@ -963,6 +972,7 @@ void UserValue::rewriteLocations(VirtRegMap &VRM,
963972
} else if (VRM.getStackSlot(VirtReg) != VirtRegMap::NO_STACK_SLOT) {
964973
// FIXME: Translate SubIdx to a stackslot offset.
965974
Loc = MachineOperand::CreateFI(VRM.getStackSlot(VirtReg));
975+
Spilled = true;
966976
} else {
967977
Loc.setReg(0);
968978
Loc.setSubReg(0);
@@ -971,14 +981,22 @@ void UserValue::rewriteLocations(VirtRegMap &VRM,
971981

972982
// Insert this location if it doesn't already exist and record a mapping
973983
// from the old number to the new number.
974-
auto InsertResult = NewLocations.insert({Loc, false});
975-
LocNoMap[I] = std::distance(NewLocations.begin(), InsertResult.first);
984+
auto InsertResult = NewLocations.insert({Loc, Spilled});
985+
unsigned NewLocNo = std::distance(NewLocations.begin(), InsertResult.first);
986+
LocNoMap[I] = NewLocNo;
976987
}
977988

978-
// Rewrite the locations.
989+
// Rewrite the locations and record which ones were spill slots.
979990
locations.clear();
980-
for (const auto &Pair : NewLocations)
991+
SpilledLocations.clear();
992+
SpilledLocations.resize(NewLocations.size());
993+
for (auto &Pair : NewLocations) {
981994
locations.push_back(Pair.first);
995+
if (Pair.second) {
996+
unsigned NewLocNo = std::distance(&*NewLocations.begin(), &Pair);
997+
SpilledLocations.set(NewLocNo);
998+
}
999+
}
9821000

9831001
// Update the interval map, but only coalesce left, since intervals to the
9841002
// right use the old location numbers. This should merge two contiguous
@@ -1016,7 +1034,7 @@ findInsertLocation(MachineBasicBlock *MBB, SlotIndex Idx,
10161034
}
10171035

10181036
void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
1019-
unsigned LocNo,
1037+
unsigned LocNo, bool Spilled,
10201038
LiveIntervals &LIS,
10211039
const TargetInstrInfo &TII) {
10221040
MachineBasicBlock::iterator I = findInsertLocation(MBB, Idx, LIS);
@@ -1026,25 +1044,38 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex Idx,
10261044
assert(cast<DILocalVariable>(Variable)
10271045
->isValidLocationForIntrinsic(getDebugLoc()) &&
10281046
"Expected inlined-at fields to agree");
1029-
if (Loc.isReg())
1030-
BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE),
1031-
IsIndirect, Loc.getReg(), Variable, Expression);
1047+
1048+
// If the location was spilled, the new DBG_VALUE will be indirect. If the
1049+
// original DBG_VALUE was indirect, we need to add DW_OP_deref to indicate
1050+
// that the original virtual register was a pointer.
1051+
bool NewIndirect = IsIndirect || Spilled;
1052+
const DIExpression *Expr = Expression;
1053+
if (Spilled && IsIndirect)
1054+
Expr = DIExpression::prepend(Expr, DIExpression::WithDeref);
1055+
1056+
assert((!Spilled || Loc.isFI()) &&
1057+
"a spilled location must be a frame index");
1058+
1059+
MachineInstrBuilder MIB =
1060+
BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE))
1061+
.add(Loc);
1062+
if (NewIndirect)
1063+
MIB.addImm(0U);
10321064
else
1033-
BuildMI(*MBB, I, getDebugLoc(), TII.get(TargetOpcode::DBG_VALUE))
1034-
.add(Loc)
1035-
.addImm(0U)
1036-
.addMetadata(Variable)
1037-
.addMetadata(Expression);
1065+
MIB.addReg(0U, RegState::Debug);
1066+
MIB.addMetadata(Variable).addMetadata(Expr);
10381067
}
10391068

10401069
void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
1041-
const TargetInstrInfo &TII) {
1070+
const TargetInstrInfo &TII,
1071+
const BitVector &SpilledLocations) {
10421072
MachineFunction::iterator MFEnd = VRM->getMachineFunction().end();
10431073

10441074
for (LocMap::const_iterator I = locInts.begin(); I.valid();) {
10451075
SlotIndex Start = I.start();
10461076
SlotIndex Stop = I.stop();
10471077
unsigned LocNo = I.value();
1078+
bool Spilled = LocNo != UndefLocNo ? SpilledLocations.test(LocNo) : false;
10481079

10491080
// If the interval start was trimmed to the lexical scope insert the
10501081
// DBG_VALUE at the previous index (otherwise it appears after the
@@ -1057,7 +1088,7 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
10571088
SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);
10581089

10591090
DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);
1060-
insertDebugValue(&*MBB, Start, LocNo, LIS, TII);
1091+
insertDebugValue(&*MBB, Start, LocNo, Spilled, LIS, TII);
10611092
// This interval may span multiple basic blocks.
10621093
// Insert a DBG_VALUE into each one.
10631094
while(Stop > MBBEnd) {
@@ -1067,7 +1098,7 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
10671098
break;
10681099
MBBEnd = LIS.getMBBEndIdx(&*MBB);
10691100
DEBUG(dbgs() << " BB#" << MBB->getNumber() << '-' << MBBEnd);
1070-
insertDebugValue(&*MBB, Start, LocNo, LIS, TII);
1101+
insertDebugValue(&*MBB, Start, LocNo, Spilled, LIS, TII);
10711102
}
10721103
DEBUG(dbgs() << '\n');
10731104
if (MBB == MFEnd)
@@ -1082,10 +1113,11 @@ void LDVImpl::emitDebugValues(VirtRegMap *VRM) {
10821113
if (!MF)
10831114
return;
10841115
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
1116+
BitVector SpilledLocations;
10851117
for (unsigned i = 0, e = userValues.size(); i != e; ++i) {
10861118
DEBUG(userValues[i]->print(dbgs(), TRI));
1087-
userValues[i]->rewriteLocations(*VRM, *TRI);
1088-
userValues[i]->emitDebugValues(VRM, *LIS, *TII);
1119+
userValues[i]->rewriteLocations(*VRM, *TRI, SpilledLocations);
1120+
userValues[i]->emitDebugValues(VRM, *LIS, *TII, SpilledLocations);
10891121
}
10901122
EmitDone = true;
10911123
}

test/DebugInfo/X86/bbjoin.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@
1111
; }
1212
; CHECK: ![[X:.*]] = !DILocalVariable(name: "x",
1313
; CHECK: bb.0.entry:
14-
; CHECK: DBG_VALUE 23, 0, ![[X]],
14+
; CHECK: DBG_VALUE 23, debug-use _, ![[X]],
1515
; CHECK: DBG_VALUE %rsp, 0, ![[X]], !DIExpression(DW_OP_plus_uconst, 4, DW_OP_deref),
1616
; CHECK: bb.1.if.then:
17-
; CHECK: DBG_VALUE 43, 0, ![[X]],
17+
; CHECK: DBG_VALUE 43, debug-use _, ![[X]],
1818
; CHECK: bb.2.if.end:
19-
; CHECK-NOT: DBG_VALUE 23, 0, ![[X]],
19+
; CHECK-NOT: DBG_VALUE 23, debug-use _, ![[X]],
2020
; CHECK: RETQ %eax
2121

2222
target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
; RUN: llc < %s | FileCheck %s
2+
; RUN: llc -O0 < %s | FileCheck %s
3+
4+
; Make sure we insert DW_OP_deref when spilling indirect DBG_VALUE instructions.
5+
6+
; C++ source:
7+
; #define FORCE_SPILL() \
8+
; __asm volatile("" : : : \
9+
; "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "r8", \
10+
; "r9", "r10", "r11", "r12", "r13", "r14", "r15")
11+
; struct string {
12+
; string();
13+
; string(int i);
14+
; ~string();
15+
; int i = 0;
16+
; };
17+
; string get_string() {
18+
; string result = 3;
19+
; FORCE_SPILL();
20+
; return result;
21+
; }
22+
23+
; CHECK-LABEL: _Z10get_stringv:
24+
; CHECK: #DEBUG_VALUE: get_string:result <- [%RDI+0]
25+
; CHECK: movq %rdi, [[OFFS:[0-9]+]](%rsp) # 8-byte Spill
26+
; CHECK: #DEBUG_VALUE: get_string:result <- [DW_OP_plus_uconst [[OFFS]], DW_OP_deref] [%RSP+0]
27+
; CHECK: callq _ZN6stringC1Ei
28+
; CHECK: #APP
29+
; CHECK: #NO_APP
30+
31+
; ModuleID = 't.cpp'
32+
source_filename = "t.cpp"
33+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
34+
target triple = "x86_64--linux"
35+
36+
%struct.string = type { i32 }
37+
38+
; Function Attrs: uwtable
39+
define void @_Z10get_stringv(%struct.string* noalias sret %agg.result) #0 !dbg !7 {
40+
entry:
41+
%nrvo = alloca i1, align 1
42+
store i1 false, i1* %nrvo, align 1, !dbg !24
43+
call void @llvm.dbg.declare(metadata %struct.string* %agg.result, metadata !23, metadata !DIExpression()), !dbg !25
44+
call void @_ZN6stringC1Ei(%struct.string* %agg.result, i32 3), !dbg !26
45+
call void asm sideeffect "", "~{rax},~{rbx},~{rcx},~{rdx},~{rsi},~{rdi},~{rbp},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{dirflag},~{fpsr},~{flags}"() #3, !dbg !27, !srcloc !28
46+
store i1 true, i1* %nrvo, align 1, !dbg !29
47+
%nrvo.val = load i1, i1* %nrvo, align 1, !dbg !30
48+
br i1 %nrvo.val, label %nrvo.skipdtor, label %nrvo.unused, !dbg !30
49+
50+
nrvo.unused: ; preds = %entry
51+
call void @_ZN6stringD1Ev(%struct.string* %agg.result), !dbg !30
52+
br label %nrvo.skipdtor, !dbg !30
53+
54+
nrvo.skipdtor: ; preds = %nrvo.unused, %entry
55+
ret void, !dbg !30
56+
}
57+
58+
; Function Attrs: nounwind readnone speculatable
59+
declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
60+
61+
declare void @_ZN6stringC1Ei(%struct.string*, i32) unnamed_addr
62+
63+
declare void @_ZN6stringD1Ev(%struct.string*) unnamed_addr
64+
65+
attributes #0 = { uwtable }
66+
attributes #1 = { nounwind readnone speculatable }
67+
attributes #3 = { nounwind }
68+
69+
!llvm.dbg.cu = !{!0}
70+
!llvm.module.flags = !{!3, !4, !5}
71+
!llvm.ident = !{!6}
72+
73+
!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 6.0.0 ", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
74+
!1 = !DIFile(filename: "t.cpp", directory: "C:\5Csrc\5Cllvm-project\5Cbuild")
75+
!2 = !{}
76+
!3 = !{i32 2, !"Dwarf Version", i32 4}
77+
!4 = !{i32 2, !"Debug Info Version", i32 3}
78+
!5 = !{i32 1, !"wchar_size", i32 4}
79+
!6 = !{!"clang version 6.0.0 "}
80+
!7 = distinct !DISubprogram(name: "get_string", linkageName: "_Z10get_stringv", scope: !1, file: !1, line: 13, type: !8, isLocal: false, isDefinition: true, scopeLine: 13, flags: DIFlagPrototyped, isOptimized: true, unit: !0, variables: !22)
81+
!8 = !DISubroutineType(types: !9)
82+
!9 = !{!10}
83+
!10 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "string", file: !1, line: 7, size: 32, elements: !11, identifier: "_ZTS6string")
84+
!11 = !{!12, !14, !18, !21}
85+
!12 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope: !10, file: !1, line: 11, baseType: !13, size: 32)
86+
!13 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
87+
!14 = !DISubprogram(name: "string", scope: !10, file: !1, line: 8, type: !15, isLocal: false, isDefinition: false, scopeLine: 8, flags: DIFlagPrototyped, isOptimized: true)
88+
!15 = !DISubroutineType(types: !16)
89+
!16 = !{null, !17}
90+
!17 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
91+
!18 = !DISubprogram(name: "string", scope: !10, file: !1, line: 9, type: !19, isLocal: false, isDefinition: false, scopeLine: 9, flags: DIFlagPrototyped, isOptimized: true)
92+
!19 = !DISubroutineType(types: !20)
93+
!20 = !{null, !17, !13}
94+
!21 = !DISubprogram(name: "~string", scope: !10, file: !1, line: 10, type: !15, isLocal: false, isDefinition: false, scopeLine: 10, flags: DIFlagPrototyped, isOptimized: true)
95+
!22 = !{!23}
96+
!23 = !DILocalVariable(name: "result", scope: !7, file: !1, line: 14, type: !10)
97+
!24 = !DILocation(line: 14, column: 3, scope: !7)
98+
!25 = !DILocation(line: 14, column: 10, scope: !7)
99+
!26 = !DILocation(line: 14, column: 19, scope: !7)
100+
!27 = !DILocation(line: 15, column: 3, scope: !7)
101+
!28 = !{i32 -2147471175}
102+
!29 = !DILocation(line: 16, column: 3, scope: !7)
103+
!30 = !DILocation(line: 17, column: 1, scope: !7)

0 commit comments

Comments
 (0)