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

David Blaikie via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 7 14:44:45 PDT 2017


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/20170807/3342dc5c/attachment.html>


More information about the llvm-commits mailing list