[llvm-bugs] [Bug 45667] New: FoldBranchToCommonDest in SimplifyCFG can invalidate dbg.value operands

via llvm-bugs llvm-bugs at lists.llvm.org
Fri Apr 24 23:39:59 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=45667

            Bug ID: 45667
           Summary: FoldBranchToCommonDest in SimplifyCFG can invalidate
                    dbg.value operands
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Transformation Utilities
          Assignee: unassignedbugs at nondot.org
          Reporter: ricky at rzhou.org
                CC: llvm-bugs at lists.llvm.org

Reproduction case:

Compiling the following program (https://godbolt.org/z/y2nzqR):

```
int main(int argc, char** argv) {
  bool a = false;
  bool b = false;
  bool c = false;
  [&a, &b, &c] { b = true; }();

  if (a || b || c) {
    __builtin_debugtrap();
  }

  return 0;
}
```

with

```
clang++ -O1 -g -fno-exceptions -o test test.cc
```

produces incorrect DWARF debugging information for the "b" variable. This can
be seen by running the program in lldb and printing "b" at the breakpoint:

```
$ lldb ~/test
(lldb) target create ".../test"
Current executable set to '.../test' (x86_64).
(lldb) r
Process 90101 launched: '.../test' (x86_64)
Process 90101 stopped
* thread #1, name = 'test', stop reason = signal SIGTRAP
    frame #0: 0x000000000040115a test`main(argc=<unavailable>,
argv=<unavailable>) at test.cc:12:1
   9      }
   10
   11     return 0;
-> 12   }
(lldb) p b
(bool) $0 = false
```

The LLVM IR at the goldbolt link shows the issue. When "a", "b", and "c" are
initialized to 0, the original dbg.declare for these variables is replaced with
a dbg.value:

```
...
  call void @llvm.dbg.value(metadata i8 0, metadata !18, metadata
!DIExpression()), !dbg !22
  store i8 0, i8* %a, align 1, !dbg !24, !tbaa !25
  call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %b) #3, !dbg !29
  call void @llvm.dbg.value(metadata i8 0, metadata !20, metadata
!DIExpression()), !dbg !22
  store i8 0, i8* %b, align 1, !dbg !30, !tbaa !25
  call void @llvm.lifetime.start.p0i8(i64 1, i8* nonnull %c) #3, !dbg !31
  call void @llvm.dbg.value(metadata i8 0, metadata !21, metadata
!DIExpression()), !dbg !22
  store i8 0, i8* %c, align 1, !dbg !32, !tbaa !25
... call to lambda ...
  %4 = load i8, i8* %a, align 1, !dbg !36, !tbaa !25, !range !38
  call void @llvm.dbg.value(metadata i8 %4, metadata !18, metadata
!DIExpression()), !dbg !22
  %5 = load i8, i8* %b, align 1, !dbg !39
  %6 = or i8 %5, %4, !dbg !40
  %7 = load i8, i8* %c, align 1, !dbg !41
  %8 = or i8 %6, %7, !dbg !40
...

```

when "a" is loaded after calling the lambda, we emit an updated dbg.value for
it. However, "b" and "c" do not get one.

I into where this breaks by compiling with `-mllvm -print-after-all -mllvm
-print-before-all`, and found that there were valid-looking dbg.value
intrinsics the loads of "b" and "c" a "Simplify the CFG" phase invalidated
them, replacing them with a call like this:

```
  !2 = !{}
...
  call void @llvm.dbg.value(metadata !2, metadata !20, metadata
!DIExpression()), !dbg !30
```

Then an "Early CSE w/ MemorySSA" phase discards these intrinsics entirely, as
they fail this test:
https://github.com/llvm/llvm-project/blob/master/llvm/lib/Transforms/Utils/Local.cpp#L385

The transformation producing the invalidated dbg.value appears to be
SimplifyCFG rewriting:

```
if (a)
  if (b)
    if (c) ...
```

to

```
if (a || b || c) ...
```

Looking at the code that does this,

https://github.com/llvm-mirror/llvm/blob/master/lib/Transforms/Utils/SimplifyCFG.cpp#L2731-L2749

appears to clone some instructions into a different basic block.

https://github.com/llvm-mirror/llvm/blob/master/lib/Transforms/Utils/SimplifyCFG.cpp#L2868-L2870

then clones dbg intrinsics over, but does not update their operands to point to
the appropriate cloned values.

The following patch fixes up the dbg.value operands for me and causes
correct-looking debug info to be generated:

```
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index be5a375a2cf..73db4728ef3 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -2898,9 +2898,14 @@ bool llvm::FoldBranchToCommonDest(BranchInst *BI,
MemorySSAUpdater *MSSAU,
     // could replace PBI's branch probabilities with BI's.

     // Copy any debug value intrinsics into the end of PredBlock.
-    for (Instruction &I : *BB)
-      if (isa<DbgInfoIntrinsic>(I))
-        I.clone()->insertBefore(PBI);
+    for (Instruction &I : *BB) {
+      if (isa<DbgInfoIntrinsic>(I)) {
+        Instruction *NewI = I.clone();
+        RemapInstruction(NewI, VMap,
+                         RF_NoModuleLevelChanges | RF_IgnoreMissingLocals);
+        NewI->insertBefore(PBI);
+      }
+    }

     return true;
   }
```

Note that even with this patch, the generated DWARF information is not ideal.
"b" becomes "optimized out" at the breakpoint, even though it is on the stack.
It seems that replacing dbg.declare with dbg.value was counterproductive in
this case.

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20200425/325b3a9c/attachment-0001.html>


More information about the llvm-bugs mailing list