mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
[DebugInfo] Handle stack slot offsets for spilled sub-registers in LDV
Summary: Extend LDV so that stack slot offsets for spilled sub-registers are added to the emitted debug locations. This is accomplished by querying InstrInfo::getStackSlotRange(). With this change, LDV will add a DW_OP_plus_uconst operation to the expression if a sub-register is spilled. Later on, PEI will add an offset operation for the stack slot, meaning that we will get expressions of the forms: * {DW_OP_constu #fp-offset, DW_OP_minus, DW_OP_plus_uconst #subreg-offset} * {DW_OP_plus_const #fp-offset, DW_OP_minus, DW_OP_plus_uconst #subreg-offset} The two offset operations should ideally be merged. Reviewers: rnk, aprantl, stoklund Reviewed By: aprantl Subscribers: dblaikie, bjope, nemanjai, JDevlieghere, llvm-commits Tags: #debug-info Differential Revision: https://reviews.llvm.org/D51612 llvm-svn: 341659
This commit is contained in:
parent
7ea14c2d15
commit
565aeb86aa
@ -135,6 +135,10 @@ private:
|
||||
/// LocMap - Map of where a user value is live, and its location.
|
||||
using LocMap = IntervalMap<SlotIndex, DbgValueLocation, 4>;
|
||||
|
||||
/// SpillOffsetMap - Map of stack slot offsets for spilled locations.
|
||||
/// Non-spilled locations are not added to the map.
|
||||
using SpillOffsetMap = DenseMap<unsigned, unsigned>;
|
||||
|
||||
namespace {
|
||||
|
||||
class LDVImpl;
|
||||
@ -168,8 +172,8 @@ class UserValue {
|
||||
|
||||
/// insertDebugValue - Insert a DBG_VALUE into MBB at Idx for LocNo.
|
||||
void insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
|
||||
SlotIndex StopIdx,
|
||||
DbgValueLocation Loc, bool Spilled, LiveIntervals &LIS,
|
||||
SlotIndex StopIdx, DbgValueLocation Loc, bool Spilled,
|
||||
unsigned SpillOffset, LiveIntervals &LIS,
|
||||
const TargetInstrInfo &TII,
|
||||
const TargetRegisterInfo &TRI);
|
||||
|
||||
@ -311,15 +315,18 @@ public:
|
||||
LiveIntervals &LIS);
|
||||
|
||||
/// rewriteLocations - Rewrite virtual register locations according to the
|
||||
/// provided virtual register map. Record which locations were spilled.
|
||||
void rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
|
||||
BitVector &SpilledLocations);
|
||||
/// provided virtual register map. Record the stack slot offsets for the
|
||||
/// locations that were spilled.
|
||||
void rewriteLocations(VirtRegMap &VRM, const MachineFunction &MF,
|
||||
const TargetInstrInfo &TII,
|
||||
const TargetRegisterInfo &TRI,
|
||||
SpillOffsetMap &SpillOffsets);
|
||||
|
||||
/// emitDebugValues - Recreate DBG_VALUE instruction from data structures.
|
||||
void emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
|
||||
const TargetInstrInfo &TII,
|
||||
const TargetRegisterInfo &TRI,
|
||||
const BitVector &SpilledLocations);
|
||||
const SpillOffsetMap &SpillOffsets);
|
||||
|
||||
/// getDebugLoc - Return DebugLoc of this UserValue.
|
||||
DebugLoc getDebugLoc() { return dl;}
|
||||
@ -1052,8 +1059,10 @@ splitRegister(unsigned OldReg, ArrayRef<unsigned> NewRegs, LiveIntervals &LIS) {
|
||||
static_cast<LDVImpl*>(pImpl)->splitRegister(OldReg, NewRegs);
|
||||
}
|
||||
|
||||
void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
|
||||
BitVector &SpilledLocations) {
|
||||
void UserValue::rewriteLocations(VirtRegMap &VRM, const MachineFunction &MF,
|
||||
const TargetInstrInfo &TII,
|
||||
const TargetRegisterInfo &TRI,
|
||||
SpillOffsetMap &SpillOffsets) {
|
||||
// Build a set of new locations with new numbers so we can coalesce our
|
||||
// IntervalMap if two vreg intervals collapse to the same physical location.
|
||||
// Use MapVector instead of SetVector because MapVector::insert returns the
|
||||
@ -1062,10 +1071,11 @@ void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
|
||||
// FIXME: This will be problematic if we ever support direct and indirect
|
||||
// frame index locations, i.e. expressing both variables in memory and
|
||||
// 'int x, *px = &x'. The "spilled" bit must become part of the location.
|
||||
MapVector<MachineOperand, bool> NewLocations;
|
||||
MapVector<MachineOperand, std::pair<bool, unsigned>> NewLocations;
|
||||
SmallVector<unsigned, 4> LocNoMap(locations.size());
|
||||
for (unsigned I = 0, E = locations.size(); I != E; ++I) {
|
||||
bool Spilled = false;
|
||||
unsigned SpillOffset = 0;
|
||||
MachineOperand Loc = locations[I];
|
||||
// Only virtual registers are rewritten.
|
||||
if (Loc.isReg() && Loc.getReg() &&
|
||||
@ -1078,7 +1088,16 @@ void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
|
||||
// non-existent sub-register, and %noreg is exactly what we want.
|
||||
Loc.substPhysReg(VRM.getPhys(VirtReg), TRI);
|
||||
} else if (VRM.getStackSlot(VirtReg) != VirtRegMap::NO_STACK_SLOT) {
|
||||
// FIXME: Translate SubIdx to a stackslot offset.
|
||||
// Retrieve the stack slot offset.
|
||||
unsigned SpillSize;
|
||||
const MachineRegisterInfo &MRI = MF.getRegInfo();
|
||||
const TargetRegisterClass *TRC = MRI.getRegClass(VirtReg);
|
||||
bool Success = TII.getStackSlotRange(TRC, Loc.getSubReg(), SpillSize,
|
||||
SpillOffset, MF);
|
||||
|
||||
// FIXME: Invalidate the location if the offset couldn't be calculated.
|
||||
(void)Success;
|
||||
|
||||
Loc = MachineOperand::CreateFI(VRM.getStackSlot(VirtReg));
|
||||
Spilled = true;
|
||||
} else {
|
||||
@ -1089,20 +1108,22 @@ void UserValue::rewriteLocations(VirtRegMap &VRM, const TargetRegisterInfo &TRI,
|
||||
|
||||
// Insert this location if it doesn't already exist and record a mapping
|
||||
// from the old number to the new number.
|
||||
auto InsertResult = NewLocations.insert({Loc, Spilled});
|
||||
auto InsertResult = NewLocations.insert({Loc, {Spilled, SpillOffset}});
|
||||
unsigned NewLocNo = std::distance(NewLocations.begin(), InsertResult.first);
|
||||
LocNoMap[I] = NewLocNo;
|
||||
}
|
||||
|
||||
// Rewrite the locations and record which ones were spill slots.
|
||||
// Rewrite the locations and record the stack slot offsets for spills.
|
||||
locations.clear();
|
||||
SpilledLocations.clear();
|
||||
SpilledLocations.resize(NewLocations.size());
|
||||
SpillOffsets.clear();
|
||||
for (auto &Pair : NewLocations) {
|
||||
bool Spilled;
|
||||
unsigned SpillOffset;
|
||||
std::tie(Spilled, SpillOffset) = Pair.second;
|
||||
locations.push_back(Pair.first);
|
||||
if (Pair.second) {
|
||||
if (Spilled) {
|
||||
unsigned NewLocNo = std::distance(&*NewLocations.begin(), &Pair);
|
||||
SpilledLocations.set(NewLocNo);
|
||||
SpillOffsets[NewLocNo] = SpillOffset;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1171,10 +1192,9 @@ findNextInsertLocation(MachineBasicBlock *MBB,
|
||||
}
|
||||
|
||||
void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
|
||||
SlotIndex StopIdx,
|
||||
DbgValueLocation Loc, bool Spilled,
|
||||
LiveIntervals &LIS,
|
||||
const TargetInstrInfo &TII,
|
||||
SlotIndex StopIdx, DbgValueLocation Loc,
|
||||
bool Spilled, unsigned SpillOffset,
|
||||
LiveIntervals &LIS, const TargetInstrInfo &TII,
|
||||
const TargetRegisterInfo &TRI) {
|
||||
SlotIndex MBBEndIdx = LIS.getMBBEndIdx(&*MBB);
|
||||
// Only search within the current MBB.
|
||||
@ -1197,12 +1217,14 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
|
||||
|
||||
// If the location was spilled, the new DBG_VALUE will be indirect. If the
|
||||
// original DBG_VALUE was indirect, we need to add DW_OP_deref to indicate
|
||||
// that the original virtual register was a pointer.
|
||||
// that the original virtual register was a pointer. Also, add the stack slot
|
||||
// offset for the spilled register to the expression.
|
||||
const DIExpression *Expr = Expression;
|
||||
bool IsIndirect = Loc.wasIndirect();
|
||||
if (Spilled) {
|
||||
if (IsIndirect)
|
||||
Expr = DIExpression::prepend(Expr, DIExpression::WithDeref);
|
||||
auto Deref = IsIndirect ? DIExpression::WithDeref : DIExpression::NoDeref;
|
||||
Expr =
|
||||
DIExpression::prepend(Expr, DIExpression::NoDeref, SpillOffset, Deref);
|
||||
IsIndirect = true;
|
||||
}
|
||||
|
||||
@ -1221,14 +1243,17 @@ void UserValue::insertDebugValue(MachineBasicBlock *MBB, SlotIndex StartIdx,
|
||||
void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
|
||||
const TargetInstrInfo &TII,
|
||||
const TargetRegisterInfo &TRI,
|
||||
const BitVector &SpilledLocations) {
|
||||
const SpillOffsetMap &SpillOffsets) {
|
||||
MachineFunction::iterator MFEnd = VRM->getMachineFunction().end();
|
||||
|
||||
for (LocMap::const_iterator I = locInts.begin(); I.valid();) {
|
||||
SlotIndex Start = I.start();
|
||||
SlotIndex Stop = I.stop();
|
||||
DbgValueLocation Loc = I.value();
|
||||
bool Spilled = !Loc.isUndef() ? SpilledLocations.test(Loc.locNo()) : false;
|
||||
auto SpillIt =
|
||||
!Loc.isUndef() ? SpillOffsets.find(Loc.locNo()) : SpillOffsets.end();
|
||||
bool Spilled = SpillIt != SpillOffsets.end();
|
||||
unsigned SpillOffset = Spilled ? SpillIt->second : 0;
|
||||
|
||||
// If the interval start was trimmed to the lexical scope insert the
|
||||
// DBG_VALUE at the previous index (otherwise it appears after the
|
||||
@ -1241,7 +1266,8 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
|
||||
SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);
|
||||
|
||||
LLVM_DEBUG(dbgs() << ' ' << printMBBReference(*MBB) << '-' << MBBEnd);
|
||||
insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, LIS, TII, TRI);
|
||||
insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, SpillOffset, LIS, TII,
|
||||
TRI);
|
||||
// This interval may span multiple basic blocks.
|
||||
// Insert a DBG_VALUE into each one.
|
||||
while (Stop > MBBEnd) {
|
||||
@ -1251,7 +1277,8 @@ void UserValue::emitDebugValues(VirtRegMap *VRM, LiveIntervals &LIS,
|
||||
break;
|
||||
MBBEnd = LIS.getMBBEndIdx(&*MBB);
|
||||
LLVM_DEBUG(dbgs() << ' ' << printMBBReference(*MBB) << '-' << MBBEnd);
|
||||
insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, LIS, TII, TRI);
|
||||
insertDebugValue(&*MBB, Start, Stop, Loc, Spilled, SpillOffset, LIS, TII,
|
||||
TRI);
|
||||
}
|
||||
LLVM_DEBUG(dbgs() << '\n');
|
||||
if (MBB == MFEnd)
|
||||
@ -1266,11 +1293,11 @@ void LDVImpl::emitDebugValues(VirtRegMap *VRM) {
|
||||
if (!MF)
|
||||
return;
|
||||
const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo();
|
||||
BitVector SpilledLocations;
|
||||
SpillOffsetMap SpillOffsets;
|
||||
for (unsigned i = 0, e = userValues.size(); i != e; ++i) {
|
||||
LLVM_DEBUG(userValues[i]->print(dbgs(), TRI));
|
||||
userValues[i]->rewriteLocations(*VRM, *TRI, SpilledLocations);
|
||||
userValues[i]->emitDebugValues(VRM, *LIS, *TII, *TRI, SpilledLocations);
|
||||
userValues[i]->rewriteLocations(*VRM, *MF, *TII, *TRI, SpillOffsets);
|
||||
userValues[i]->emitDebugValues(VRM, *LIS, *TII, *TRI, SpillOffsets);
|
||||
}
|
||||
EmitDone = true;
|
||||
}
|
||||
|
81
test/DebugInfo/PowerPC/live-debug-vars-subreg-offset.ll
Normal file
81
test/DebugInfo/PowerPC/live-debug-vars-subreg-offset.ll
Normal file
@ -0,0 +1,81 @@
|
||||
; RUN: llc -O3 -stop-after virtregrewriter %s -o - | FileCheck %s
|
||||
|
||||
target datalayout = "E-m:e-i64:64-n32:64"
|
||||
target triple = "ppc64"
|
||||
|
||||
; Verify that live-debug-variables includes the stack slot offset
|
||||
; for the sub-register in the debug expression for `spilled'.
|
||||
|
||||
; This reproducer was generated from the following C file:
|
||||
;
|
||||
; extern int foo(void);
|
||||
; extern void bar(int);
|
||||
;
|
||||
; int main() {
|
||||
; int spilled = foo();
|
||||
;
|
||||
; // Clobber all GPRs.
|
||||
; __asm volatile ("" : : : "0", "1", "2", "3", "4", "5", "6", "7",
|
||||
; "8", "9", "10", "11", "12", "13", "14", "15",
|
||||
; "16", "17", "18", "19", "20", "21", "22", "23",
|
||||
; "24", "25", "26", "27", "28", "29", "30", "31");
|
||||
;
|
||||
; for(;;)
|
||||
; bar(spilled);
|
||||
;
|
||||
; return 0;
|
||||
; }
|
||||
;
|
||||
; compiled using:
|
||||
;
|
||||
; clang --target=ppc64 -O3 -g -S -emit-llvm
|
||||
|
||||
; CHECK: ![[VAR:.*]] = !DILocalVariable(name: "spilled"
|
||||
|
||||
; CHECK: STD $x3, 0, %stack.0
|
||||
; CHECK-NEXT: DBG_VALUE %stack.0, 0, ![[VAR]], !DIExpression(DW_OP_plus_uconst, 4)
|
||||
|
||||
; Function Attrs: noreturn nounwind
|
||||
define signext i32 @main() local_unnamed_addr #0 !dbg !8 {
|
||||
entry:
|
||||
%call = tail call signext i32 @foo() #2, !dbg !14
|
||||
call void @llvm.dbg.value(metadata i32 %call, metadata !13, metadata !DIExpression()), !dbg !14
|
||||
tail call void asm sideeffect "", "~{r0},~{r1},~{r2},~{r3},~{r4},~{r5},~{r6},~{r7},~{r8},~{r9},~{r10},~{r11},~{r12},~{r13},~{r14},~{r15},~{r16},~{r17},~{r18},~{r19},~{r20},~{r21},~{r22},~{r23},~{r24},~{r25},~{r26},~{r27},~{r28},~{r29},~{r30},~{r31}"() #2, !dbg !14, !srcloc !15
|
||||
br label %for.cond, !dbg !14
|
||||
|
||||
for.cond: ; preds = %for.cond, %entry
|
||||
tail call void @bar(i32 signext %call) #2, !dbg !14
|
||||
br label %for.cond, !dbg !14
|
||||
}
|
||||
|
||||
declare signext i32 @foo() local_unnamed_addr
|
||||
|
||||
declare void @bar(i32 signext) local_unnamed_addr
|
||||
|
||||
; Function Attrs: nounwind readnone speculatable
|
||||
declare void @llvm.dbg.value(metadata, metadata, metadata) #1
|
||||
|
||||
attributes #0 = { noreturn nounwind }
|
||||
attributes #1 = { nounwind readnone speculatable }
|
||||
attributes #2 = { nounwind }
|
||||
|
||||
!llvm.dbg.cu = !{!0}
|
||||
!llvm.module.flags = !{!3, !4, !5, !6}
|
||||
!llvm.ident = !{!7}
|
||||
|
||||
!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 8.0.0", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
|
||||
!1 = !DIFile(filename: "live-debug-vars-subreg-offset.c", directory: "/")
|
||||
!2 = !{}
|
||||
!3 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!4 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!5 = !{i32 1, !"wchar_size", i32 4}
|
||||
!6 = !{i32 7, !"PIC Level", i32 2}
|
||||
!7 = !{!"clang version 8.0.0"}
|
||||
!8 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 4, type: !9, isLocal: false, isDefinition: true, scopeLine: 4, isOptimized: true, unit: !0, retainedNodes: !12)
|
||||
!9 = !DISubroutineType(types: !10)
|
||||
!10 = !{!11}
|
||||
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
!12 = !{!13}
|
||||
!13 = !DILocalVariable(name: "spilled", scope: !8, file: !1, line: 5, type: !11)
|
||||
!14 = !DILocation(line: 5, column: 17, scope: !8)
|
||||
!15 = !{i32 125}
|
Loading…
Reference in New Issue
Block a user