<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - FoldBranchToCommonDest in SimplifyCFG can invalidate dbg.value operands"
href="https://bugs.llvm.org/show_bug.cgi?id=45667">45667</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>FoldBranchToCommonDest in SimplifyCFG can invalidate dbg.value operands
</td>
</tr>
<tr>
<th>Product</th>
<td>libraries
</td>
</tr>
<tr>
<th>Version</th>
<td>trunk
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>enhancement
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>Transformation Utilities
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>ricky@rzhou.org
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org
</td>
</tr></table>
<p>
<div>
<pre>Reproduction case:
Compiling the following program (<a href="https://godbolt.org/z/y2nzqR">https://godbolt.org/z/y2nzqR</a>):
```
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:
<a href="https://github.com/llvm/llvm-project/blob/master/llvm/lib/Transforms/Utils/Local.cpp#L385">https://github.com/llvm/llvm-project/blob/master/llvm/lib/Transforms/Utils/Local.cpp#L385</a>
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,
<a href="https://github.com/llvm-mirror/llvm/blob/master/lib/Transforms/Utils/SimplifyCFG.cpp#L2731-L2749">https://github.com/llvm-mirror/llvm/blob/master/lib/Transforms/Utils/SimplifyCFG.cpp#L2731-L2749</a>
appears to clone some instructions into a different basic block.
<a href="https://github.com/llvm-mirror/llvm/blob/master/lib/Transforms/Utils/SimplifyCFG.cpp#L2868-L2870">https://github.com/llvm-mirror/llvm/blob/master/lib/Transforms/Utils/SimplifyCFG.cpp#L2868-L2870</a>
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.</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>