[llvm] r309933 - [LiveDebugVariables] Use lexical scope to trim debug value live intervals

Robert Lougher via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 15 15:52:24 PDT 2017


Sorry for the delay, I've only just seen your reply...  If the lexical
scope is fragmented it will have more than one instruction range.  The
debug value intervals are checked against all of the ranges.  Any which
overlap the start or end of a range are trimmed to the start or end.  If a
DBG_VALUE starts outside of any range, but was live within the lexical
scope, it must overlap the start of one of the ranges - its trimmed live
interval would then start at the start of the range.

Rob.


On 7 August 2017 at 22:44, David Blaikie <dblaikie at gmail.com> wrote:

> Out of curiosity - how does this handle cases of fragmented lexical
> scopes? (& what if, say, the DBG_VALUE starts outside any of the fragments
> of the lexical scope, but is live within it?)
>
>
> On Thu, Aug 3, 2017 at 4:54 AM Robert Lougher via llvm-commits <
> llvm-commits at lists.llvm.org> wrote:
>
>> Author: rlougher
>> Date: Thu Aug  3 04:54:02 2017
>> New Revision: 309933
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=309933&view=rev
>> Log:
>> [LiveDebugVariables] Use lexical scope to trim debug value live intervals
>>
>> The debug value live intervals computed by Live Debug Variables may extend
>> beyond the range of the debug location's lexical scope. In this case,
>> splitting of an interval can result in an interval outside of the scope
>> being
>> created, causing extra unnecessary DBG_VALUEs to be emitted. To prevent
>> this,
>> trim the intervals to the lexical scope.
>>
>> This resolves PR33730.
>>
>> Reviewers: aprantl
>>
>> Differential Revision: https://reviews.llvm.org/D35953
>>
>> Added:
>>     llvm/trunk/test/DebugInfo/X86/live-debug-variables.ll
>> Modified:
>>     llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp
>>     llvm/trunk/test/DebugInfo/X86/dbg-value-dag-combine.ll
>>
>> Modified: llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/
>> CodeGen/LiveDebugVariables.cpp?rev=309933&r1=309932&r2=309933&view=diff
>> ============================================================
>> ==================
>> --- llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp (original)
>> +++ llvm/trunk/lib/CodeGen/LiveDebugVariables.cpp Thu Aug  3 04:54:02
>> 2017
>> @@ -21,7 +21,9 @@
>>
>>  #include "LiveDebugVariables.h"
>>  #include "llvm/ADT/IntervalMap.h"
>> +#include "llvm/ADT/SmallSet.h"
>>  #include "llvm/ADT/Statistic.h"
>> +#include "llvm/CodeGen/LexicalScopes.h"
>>  #include "llvm/CodeGen/LiveIntervalAnalysis.h"
>>  #include "llvm/CodeGen/MachineDominators.h"
>>  #include "llvm/CodeGen/MachineFunction.h"
>> @@ -101,6 +103,10 @@ class UserValue {
>>    /// Map of slot indices where this value is live.
>>    LocMap locInts;
>>
>> +  /// Set of interval start indexes that have been trimmed to the
>> +  /// lexical scope.
>> +  SmallSet<SlotIndex, 2> trimmedDefs;
>> +
>>    /// coalesceLocation - After LocNo was changed, check if it has become
>>    /// identical to another location, and coalesce them. This may cause
>> LocNo or
>>    /// a later location to be erased, but no earlier location will be
>> erased.
>> @@ -229,7 +235,7 @@ public:
>>    /// computeIntervals - Compute the live intervals of all locations
>> after
>>    /// collecting all their def points.
>>    void computeIntervals(MachineRegisterInfo &MRI, const
>> TargetRegisterInfo &TRI,
>> -                        LiveIntervals &LIS);
>> +                        LiveIntervals &LIS, LexicalScopes &LS);
>>
>>    /// splitRegister - Replace OldReg ranges with NewRegs ranges where
>> NewRegs is
>>    /// live. Returns true if any changes were made.
>> @@ -627,10 +633,9 @@ UserValue::addDefsFromCopies(LiveInterva
>>    }
>>  }
>>
>> -void
>> -UserValue::computeIntervals(MachineRegisterInfo &MRI,
>> -                            const TargetRegisterInfo &TRI,
>> -                            LiveIntervals &LIS) {
>> +void UserValue::computeIntervals(MachineRegisterInfo &MRI,
>> +                                 const TargetRegisterInfo &TRI,
>> +                                 LiveIntervals &LIS, LexicalScopes &LS) {
>>    SmallVector<std::pair<SlotIndex, unsigned>, 16> Defs;
>>
>>    // Collect all defs to be extended (Skipping undefs).
>> @@ -672,17 +677,88 @@ UserValue::computeIntervals(MachineRegis
>>      extendDef(Idx, LocNo, LR, VNI, nullptr, LIS);
>>    }
>>
>> -  // Finally, erase all the undefs.
>> +  // Erase all the undefs.
>>    for (LocMap::iterator I = locInts.begin(); I.valid();)
>>      if (I.value() == ~0u)
>>        I.erase();
>>      else
>>        ++I;
>> +
>> +  // The computed intervals may extend beyond the range of the debug
>> +  // location's lexical scope. In this case, splitting of an interval
>> +  // can result in an interval outside of the scope being created,
>> +  // causing extra unnecessary DBG_VALUEs to be emitted. To prevent
>> +  // this, trim the intervals to the lexical scope.
>> +
>> +  LexicalScope *Scope = LS.findLexicalScope(dl);
>> +  if (!Scope)
>> +    return;
>> +
>> +  SlotIndex PrevEnd;
>> +  LocMap::iterator I = locInts.begin();
>> +
>> +  // Iterate over the lexical scope ranges. Each time round the loop
>> +  // we check the intervals for overlap with the end of the previous
>> +  // range and the start of the next. The first range is handled as
>> +  // a special case where there is no PrevEnd.
>> +  for (const InsnRange &Range : Scope->getRanges()) {
>> +    SlotIndex RStart = LIS.getInstructionIndex(*Range.first);
>> +    SlotIndex REnd = LIS.getInstructionIndex(*Range.second);
>> +
>> +    // At the start of each iteration I has been advanced so that
>> +    // I.stop() >= PrevEnd. Check for overlap.
>> +    if (PrevEnd && I.start() < PrevEnd) {
>> +      SlotIndex IStop = I.stop();
>> +      unsigned LocNo = I.value();
>> +
>> +      // Stop overlaps previous end - trim the end of the interval to
>> +      // the scope range.
>> +      I.setStopUnchecked(PrevEnd);
>> +      ++I;
>> +
>> +      // If the interval also overlaps the start of the "next" (i.e.
>> +      // current) range create a new interval for the remainder (which
>> +      // may be further trimmed).
>> +      if (RStart < IStop)
>> +        I.insert(RStart, IStop, LocNo);
>> +    }
>> +
>> +    // Advance I so that I.stop() >= RStart, and check for overlap.
>> +    I.advanceTo(RStart);
>> +    if (!I.valid())
>> +      return;
>> +
>> +    if (I.start() < RStart) {
>> +      // Interval start overlaps range - trim to the scope range.
>> +      I.setStartUnchecked(RStart);
>> +      // Remember that this interval was trimmed.
>> +      trimmedDefs.insert(RStart);
>> +    }
>> +
>> +    // The end of a lexical scope range is the last instruction in the
>> +    // range. To convert to an interval we need the index of the
>> +    // instruction after it.
>> +    REnd = REnd.getNextIndex();
>> +
>> +    // Advance I to first interval outside current range.
>> +    I.advanceTo(REnd);
>> +    if (!I.valid())
>> +      return;
>> +
>> +    PrevEnd = REnd;
>> +  }
>> +
>> +  // Check for overlap with end of final range.
>> +  if (PrevEnd && I.start() < PrevEnd)
>> +    I.setStopUnchecked(PrevEnd);
>>  }
>>
>>  void LDVImpl::computeIntervals() {
>> +  LexicalScopes LS;
>> +  LS.initialize(*MF);
>> +
>>    for (unsigned i = 0, e = userValues.size(); i != e; ++i) {
>> -    userValues[i]->computeIntervals(MF->getRegInfo(), *TRI, *LIS);
>> +    userValues[i]->computeIntervals(MF->getRegInfo(), *TRI, *LIS, LS);
>>      userValues[i]->mapVirtRegs(this);
>>    }
>>  }
>> @@ -957,6 +1033,13 @@ void UserValue::emitDebugValues(VirtRegM
>>      SlotIndex Start = I.start();
>>      SlotIndex Stop = I.stop();
>>      unsigned LocNo = I.value();
>> +
>> +    // If the interval start was trimmed to the lexical scope insert the
>> +    // DBG_VALUE at the previous index (otherwise it appears after the
>> +    // first instruction in the range).
>> +    if (trimmedDefs.count(Start))
>> +      Start = Start.getPrevIndex();
>> +
>>      DEBUG(dbgs() << "\t[" << Start << ';' << Stop << "):" << LocNo);
>>      MachineFunction::iterator MBB = LIS.getMBBFromIndex(Start)->
>> getIterator();
>>      SlotIndex MBBEnd = LIS.getMBBEndIdx(&*MBB);
>>
>> Modified: llvm/trunk/test/DebugInfo/X86/dbg-value-dag-combine.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
>> DebugInfo/X86/dbg-value-dag-combine.ll?rev=309933&r1=
>> 309932&r2=309933&view=diff
>> ============================================================
>> ==================
>> --- llvm/trunk/test/DebugInfo/X86/dbg-value-dag-combine.ll (original)
>> +++ llvm/trunk/test/DebugInfo/X86/dbg-value-dag-combine.ll Thu Aug  3
>> 04:54:02 2017
>> @@ -5,10 +5,11 @@ target triple = "i686-apple-darwin"
>>
>>  ; There should be a DEBUG_VALUE for each call to llvm.dbg.value
>>
>> -; CHECK:  ##DEBUG_VALUE: __OpenCL_test_kernel:ip <-
>> -; CHECK:  ##DEBUG_VALUE: xxx <- 0
>> -; CHECK:  ##DEBUG_VALUE: gid <- %E{{..$}}
>> -; CHECK:  ##DEBUG_VALUE: idx <- %E{{..$}}
>> +; CHECK-LABEL: __OpenCL_test_kernel:
>> +; CHECK-DAG:  ##DEBUG_VALUE: __OpenCL_test_kernel:ip <-
>> +; CHECK-DAG:  ##DEBUG_VALUE: xxx <- 0
>> +; CHECK-DAG:  ##DEBUG_VALUE: gid <- %E{{..$}}
>> +; CHECK-DAG:  ##DEBUG_VALUE: idx <- %E{{..$}}
>>  ; CHECK-NOT:  ##DEBUG_VALUE:
>>
>>  declare <4 x i32> @__amdil_get_global_id_int()
>>
>> Added: llvm/trunk/test/DebugInfo/X86/live-debug-variables.ll
>> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/
>> DebugInfo/X86/live-debug-variables.ll?rev=309933&view=auto
>> ============================================================
>> ==================
>> --- llvm/trunk/test/DebugInfo/X86/live-debug-variables.ll (added)
>> +++ llvm/trunk/test/DebugInfo/X86/live-debug-variables.ll Thu Aug  3
>> 04:54:02 2017
>> @@ -0,0 +1,77 @@
>> +; RUN: llc -mtriple=x86_64-linux-gnu -filetype=obj -o - %s |
>> llvm-dwarfdump -debug-dump=loc - | FileCheck %s
>> +
>> +; The test inlines the function F four times, with each inlined variable
>> for
>> +; "i4" sharing the same virtual register. This means the live interval
>> of the
>> +; register spans all of the inlined callsites, extending beyond the
>> lexical
>> +; scope of each. Later during register allocation the live interval is
>> split
>> +; into multiple intervals. Check that this does not generate multiple
>> entries
>> +; within the debug location (see PR33730).
>> +;
>> +; Generated from:
>> +;
>> +; extern int foobar(int, int, int, int, int);
>> +;
>> +; int F(int i1, int i2, int i3, int i4, int i5) {
>> +;   return foobar(i1, i2, i3, i4, i5);
>> +; }
>> +;
>> +; int foo(int a, int b, int c, int d, int e) {
>> +;   return F(a,b,c,d,e) +
>> +;          F(a,b,c,d,e) +
>> +;          F(a,b,c,d,e) +
>> +;          F(a,b,c,d,e);
>> +; }
>> +
>> +; CHECK: Beginning address offset
>> +; CHECK-NOT: Beginning address offset
>> +
>> +declare i32 @foobar(i32, i32, i32, i32, i32)
>> +
>> +define i32 @foo(i32 %a, i32 %b, i32 %c, i32 %d, i32 %e) !dbg !25 {
>> +entry:
>> +  tail call void @llvm.dbg.value(metadata i32 %d, i64 0, metadata !15,
>> metadata !17) #3, !dbg !41
>> +  %call.i = tail call i32 @foobar(i32 %a, i32 %b, i32 %c, i32 %d, i32
>> %e) #3, !dbg !43
>> +  %call.i21 = tail call i32 @foobar(i32 %a, i32 %b, i32 %c, i32 %d, i32
>> %e) #3, !dbg !50
>> +  %add = add nsw i32 %call.i21, %call.i, !dbg !51
>> +  %call.i22 = tail call i32 @foobar(i32 %a, i32 %b, i32 %c, i32 %d, i32
>> %e) #3, !dbg !58
>> +  %add3 = add nsw i32 %add, %call.i22, !dbg !59
>> +  %call.i23 = tail call i32 @foobar(i32 %a, i32 %b, i32 %c, i32 %d, i32
>> %e) #3, !dbg !66
>> +  %add5 = add nsw i32 %add3, %call.i23, !dbg !67
>> +  ret i32 %add5, !dbg !68
>> +}
>> +
>> +declare void @llvm.dbg.value(metadata, i64, metadata, metadata)
>> +
>> +!llvm.dbg.cu = !{!0}
>> +!llvm.module.flags = !{!3, !4, !5}
>> +!llvm.ident = !{!6}
>> +
>> +!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer:
>> "clang version 6.0.0 (trunk 308976)", isOptimized: true, runtimeVersion: 0,
>> emissionKind: FullDebug, enums: !2)
>> +!1 = !DIFile(filename: "foo.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 = !{!"clang version 6.0.0 (trunk 308976)"}
>> +!7 = distinct !DISubprogram(name: "F", scope: !1, file: !1, line: 3,
>> type: !8, isLocal: false, isDefinition: true, scopeLine: 3, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, variables: !11)
>> +!8 = !DISubroutineType(types: !9)
>> +!9 = !{!10, !10, !10, !10, !10, !10}
>> +!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
>> +!11 = !{!15}
>> +!15 = !DILocalVariable(name: "i4", arg: 4, scope: !7, file: !1, line: 3,
>> type: !10)
>> +!17 = !DIExpression()
>> +!25 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 7,
>> type: !8, isLocal: false, isDefinition: true, scopeLine: 7, flags:
>> DIFlagPrototyped, isOptimized: true, unit: !0, variables: !26)
>> +!26 = !{}
>> +!38 = distinct !DILocation(line: 8, column: 10, scope: !25)
>> +!41 = !DILocation(line: 3, column: 35, scope: !7, inlinedAt: !38)
>> +!43 = !DILocation(line: 4, column: 10, scope: !7, inlinedAt: !38)
>> +!45 = distinct !DILocation(line: 9, column: 10, scope: !25)
>> +!50 = !DILocation(line: 4, column: 10, scope: !7, inlinedAt: !45)
>> +!51 = !DILocation(line: 8, column: 23, scope: !25)
>> +!53 = distinct !DILocation(line: 10, column: 10, scope: !25)
>> +!58 = !DILocation(line: 4, column: 10, scope: !7, inlinedAt: !53)
>> +!59 = !DILocation(line: 9, column: 23, scope: !25)
>> +!61 = distinct !DILocation(line: 11, column: 10, scope: !25)
>> +!66 = !DILocation(line: 4, column: 10, scope: !7, inlinedAt: !61)
>> +!67 = !DILocation(line: 10, column: 23, scope: !25)
>> +!68 = !DILocation(line: 8, column: 3, scope: !25)
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170815/8f52e06e/attachment.html>


More information about the llvm-commits mailing list