[llvm] r370877 - [DebugInfo] LiveDebugValues: locations with different exprs should not be merged

Jeremy Morse via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 4 04:09:05 PDT 2019


Author: jmorse
Date: Wed Sep  4 04:09:05 2019
New Revision: 370877

URL: http://llvm.org/viewvc/llvm-project?rev=370877&view=rev
Log:
[DebugInfo] LiveDebugValues: locations with different exprs should not be merged

When comparing variable locations, LiveDebugValues currently considers only
the machine location, ignoring any DIExpression applied to it. This is a
problem because that DIExpression can do pretty much anything to the machine
location, for example dereferencing it.

This patch adds DIExpressions to that comparison; now variables based on the
same register/memory-location but with different expressions will compare
differently, and be dropped if we attempt to merge them between blocks. This
reduces variable coverage-range a little, but only because we were producing
broken locations.

Differential Revision: https://reviews.llvm.org/D66942

Added:
    llvm/trunk/test/DebugInfo/X86/live-debug-values-expr-conflict.ll
Modified:
    llvm/trunk/lib/CodeGen/LiveDebugValues.cpp

Modified: llvm/trunk/lib/CodeGen/LiveDebugValues.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/LiveDebugValues.cpp?rev=370877&r1=370876&r2=370877&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/LiveDebugValues.cpp (original)
+++ llvm/trunk/lib/CodeGen/LiveDebugValues.cpp Wed Sep  4 04:09:05 2019
@@ -189,8 +189,16 @@ private:
       }
     };
 
+    /// Identity of the variable at this location.
     const DebugVariable Var;
-    const MachineInstr &MI; ///< Only used for cloning a new DBG_VALUE.
+
+    /// The expression applied to this location.
+    const DIExpression *Expr;
+
+    /// DBG_VALUE to clone var/expr information from if this location
+    /// is moved.
+    const MachineInstr &MI;
+
     mutable UserValueScopes UVS;
     enum VarLocKind {
       InvalidKind = 0,
@@ -212,8 +220,9 @@ private:
     } Loc;
 
     VarLoc(const MachineInstr &MI, LexicalScopes &LS,
-          VarLocKind K = InvalidKind)
-        : Var(MI), MI(MI), UVS(MI.getDebugLoc(), LS){
+           VarLocKind K = InvalidKind)
+        : Var(MI), Expr(MI.getDebugExpression()), MI(MI),
+          UVS(MI.getDebugLoc(), LS) {
       static_assert((sizeof(Loc) == sizeof(uint64_t)),
                     "hash does not cover all members of Loc");
       assert(MI.isDebugValue() && "not a DBG_VALUE");
@@ -238,7 +247,8 @@ private:
     /// The constructor for spill locations.
     VarLoc(const MachineInstr &MI, unsigned SpillBase, int SpillOffset,
            LexicalScopes &LS, const MachineInstr &OrigMI)
-        : Var(MI), MI(OrigMI), UVS(MI.getDebugLoc(), LS) {
+        : Var(MI), Expr(MI.getDebugExpression()), MI(OrigMI),
+          UVS(MI.getDebugLoc(), LS) {
       assert(MI.isDebugValue() && "not a DBG_VALUE");
       assert(MI.getNumOperands() == 4 && "malformed DBG_VALUE");
       Kind = SpillLocKind;
@@ -266,13 +276,13 @@ private:
 
     bool operator==(const VarLoc &Other) const {
       return Kind == Other.Kind && Var == Other.Var &&
-             Loc.Hash == Other.Loc.Hash;
+             Loc.Hash == Other.Loc.Hash && Expr == Other.Expr;
     }
 
     /// This operator guarantees that VarLocs are sorted by Variable first.
     bool operator<(const VarLoc &Other) const {
-      return std::tie(Var, Kind, Loc.Hash) <
-             std::tie(Other.Var, Other.Kind, Other.Loc.Hash);
+      return std::tie(Var, Kind, Loc.Hash, Expr) <
+             std::tie(Other.Var, Other.Kind, Other.Loc.Hash, Other.Expr);
     }
   };
 

Added: llvm/trunk/test/DebugInfo/X86/live-debug-values-expr-conflict.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/DebugInfo/X86/live-debug-values-expr-conflict.ll?rev=370877&view=auto
==============================================================================
--- llvm/trunk/test/DebugInfo/X86/live-debug-values-expr-conflict.ll (added)
+++ llvm/trunk/test/DebugInfo/X86/live-debug-values-expr-conflict.ll Wed Sep  4 04:09:05 2019
@@ -0,0 +1,75 @@
+; RUN: llc %s -mtriple=x86_64-unknown-unknown -o - -stop-after=livedebugvalues | FileCheck %s
+;
+; In the C below, 'baz' is re-assigned with a value that gets salvaged, making
+; it's dbg.value base itself on 'bar', but with a complex expression.
+; LiveDebugValues should recognize that these are different locations, and not
+; propagate a location for 'baz' into the return block.
+;
+; void escape1(int bees);
+; void escape2(int bees);
+; 
+; int foo(int bar) {
+;   int baz = bar;
+;   if (baz == 12) {
+;     escape1(bar);
+;   } else {
+;     baz += 1;
+;     escape2(bar);
+;   }
+; 
+;   return bar;
+; }
+;
+; We should get a plain DBG_VALUE in the entry block, a plain one then complex
+; one in the block two, and none in block three.
+; CHECK:       ![[BAZVAR:[0-9]+]] = !DILocalVariable(name: "baz",
+; CHECK-LABEL: bb.0.entry:
+; CHECK:       DBG_VALUE {{[0-9a-zA-Z$%_]*}}, $noreg, ![[BAZVAR]],
+; CHECK-SAME:     !DIExpression()
+; CHECK-LABEL: bb.1.if.then:
+; CHECK-LABEL: bb.2.if.else:
+; CHECK:       DBG_VALUE {{[0-9a-zA-Z$%_]*}}, $noreg, ![[BAZVAR]],
+; CHECK-SAME:     !DIExpression()
+; CHECK:       DBG_VALUE {{[0-9a-zA-Z$%_]*}}, $noreg, ![[BAZVAR]],
+; CHECK-SAME:     !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)
+; CHECK-LABEL: bb.3.if.end:
+; CHECK-NOT:   DBG_VALUE
+
+declare void @escape1(i32)
+declare void @escape2(i32)
+declare void @llvm.dbg.value(metadata, metadata, metadata)
+
+define i32 @foo(i32 returned %bar) !dbg !7 {
+entry:
+  call void @llvm.dbg.value(metadata i32 %bar, metadata !13, metadata !DIExpression()), !dbg !14
+  %cmp = icmp eq i32 %bar, 12, !dbg !14
+  br i1 %cmp, label %if.then, label %if.else, !dbg !14
+
+if.then:
+  tail call void @escape1(i32 12) #3, !dbg !14
+  br label %if.end, !dbg !14
+
+if.else:
+  call void @llvm.dbg.value(metadata i32 %bar, metadata !13, metadata !DIExpression(DW_OP_plus_uconst, 1, DW_OP_stack_value)), !dbg !14
+  tail call void @escape2(i32 %bar) #3, !dbg !14
+  br label %if.end
+
+if.end:
+  ret i32 %bar, !dbg !14
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!3, !4}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, nameTableKind: None)
+!1 = !DIFile(filename: "exprconflict.c", directory: "/home/jmorse")
+!2 = !{}
+!3 = !{i32 2, !"Dwarf Version", i32 4}
+!4 = !{i32 2, !"Debug Info Version", i32 3}
+!7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 5, type: !8, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11)
+!8 = !DISubroutineType(types: !9)
+!9 = !{!10, !10}
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !{!13}
+!13 = !DILocalVariable(name: "baz", scope: !7, file: !1, line: 6, type: !10)
+!14 = !DILocation(line: 1, scope: !7)




More information about the llvm-commits mailing list