[PATCH] D80691: Proposed fix for PR46114
Qirun Zhang via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri May 29 16:57:29 PDT 2020
helloqirun marked an inline comment as done.
helloqirun added a comment.
In D80691#2062323 <https://reviews.llvm.org/D80691#2062323>, @Orlando wrote:
> I think that this patch reduces variable coverage by undefing dbg.values which
> it cannot salvage that would otherwise be RAUWd.
>
> I'd expect your call to salvageDebugInfoOrMarkUndef to insert an 'undef'
> dbg.value for 'l_52' for your original reproducer because you cannot salvage a
> load operation. When I build with this patch locally, that is what I get. lldb
> (and gdb) tells me that the value for 'l_52' has been optimized out.
>
> With your patch applied, using your original reproducer:
>
> $ cat test.c
> int a = 1;
> short b;
> char c;
> int main() {
> int d = a, l_52 = 0;
> b = (l_52 = a) - c; // qirun0
> if (d) {
> int e=1;
> }
> }
>
> $ clang-with-your-patch -O3 -g test.c
> $ lldb a.out
> ...
> (lldb) s
> Process 21970 stopped
> * thread #1, name = 'a.out', stop reason = step in
> frame #0: 0x0000000000400486 a.out`main at test.c:6:20
> 3 char c;
> 4 int main() {
> 5 int d = a, l_52 = 0;
> -> 6 b = (l_52 = a) - c; // qirun0
> 7 if (d) {
> 8 int e=1;
> 9 }
> (lldb) p l_52
> error: Couldn't materialize: couldn't get the value of variable l_52: no location, value may have been optimized out
>
>
> My lldb is built at 9b56cc9361a471a3ce57da4c98f60e377cc43026 <https://reviews.llvm.org/rG9b56cc9361a471a3ce57da4c98f60e377cc43026> (1st April 2020),
> and clang 709c52b9553 <https://reviews.llvm.org/rG709c52b9553f4ba83ab901a873392f8a7f2c56a5> (18th May 2020). What do you see in lldb when you build
> your original reproducer with this patch?
>
> > There are cases where EarlyCSE needs to remove the first (the following case). The instruction `%0 = load i32, i32* @a, align 4` can be the product of both EarlyCSE DCE (the following case) and EarlyCSE CSE LOAD (the case in the original PR).
>
> My understanding is that DCE and CSE do not have equal implications for
> debug-info. DCE means the value is going away because it isn't used. In this
> case we should salvage any debug users (i.e. dbg.values using the value),
> because the value will no longer exist. For CSE the value still exists
> somewhere, so we instead want to update debug users to use the value which we
> are keeping. This is what the line `Inst.replaceAllUsesWith(Op);` is doing
> without your patch. However, with your patch applied, the salvage call replaces
> the dbg.values with a constant if it can salvage, or undef if it cannot. This
> means that the replaceAllUsesWith (RAUW) cannot update the debug users.
>
> > Thanks! Yes, if we want to have two dbg.value in the IR, it works fine. That's precisely what was before e5f07080b8a <https://reviews.llvm.org/rGe5f07080b8ac73dd573e81a186925a122ab8a39d>, i.e., the final IR will contain
> >
> > call void @llvm.dbg.value(metadata i32 0, metadata !22, metadata !DIExpression()), !dbg !31
> > call void @llvm.dbg.value(metadata i32 %0, metadata !22, metadata !DIExpression()), !dbg !31
> > and lldb can print the correct value of 0.
>
> I wouldn't expect this to result in you seeing a value of '0' in the debugger.
Indeed it shows a 0, as I mentioned in the summary. See the following.
$ clang -v
clang version 10.0.0 (https://github.com/llvm/llvm-project.git 632deb6bd04022945468faef2dcaa8c9fdf1b0fd)
$ clang -g -O3 abc.c
$ cat abc.ll
; ModuleID = 'abc.c'
source_filename = "abc.c"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
@a = dso_local local_unnamed_addr global i32 1, align 4, !dbg !0
@c = common dso_local local_unnamed_addr global i8 0, align 1, !dbg !9
@b = common dso_local local_unnamed_addr global i16 0, align 2, !dbg !6
; Function Attrs: nofree norecurse nounwind uwtable
define dso_local i32 @main() local_unnamed_addr #0 !dbg !17 {
entry:
%0 = load i32, i32* @a, align 4, !dbg !26, !tbaa !27
call void @llvm.dbg.value(metadata i32 %0, metadata !21, metadata !DIExpression()), !dbg !31
call void @llvm.dbg.value(metadata i32 0, metadata !22, metadata !DIExpression()), !dbg !31
call void @llvm.dbg.value(metadata i32 %0, metadata !22, metadata !DIExpression()), !dbg !31
%1 = load i8, i8* @c, align 1, !dbg !32, !tbaa !33
%conv = sext i8 %1 to i32, !dbg !32
$ lldb-trunk -s cmds -b a.out
(lldb) target create "a.out"
(lldb) b 6
Breakpoint 1: where = a.out`main + 6 at abc.c:6:20, address = 0x0000000000400486
(lldb) r
Process 13524 stopped
* thread #1, name = 'a.out', stop reason = breakpoint 1.1
frame #0: 0x0000000000400486 a.out`main at abc.c:6:20
3 char c;
4 int main() {
5 int d = a, l_52 = 0;
-> 6 b = (l_52 = a) - c; // qirun0
7 if (d) {
8 int e=1;
9 }
Process 13524 launched: '/home/absozero/bisect/fix/a.out' (x86_64)
(lldb) p l_52
(int) $0 = 0
$ llvm-dwarfdump a.out -name l_52
a.out: file format ELF64-x86-64
0x00000097: DW_TAG_variable
DW_AT_location (0x00000000:
[0x0000000000400486, 0x0000000000400499): DW_OP_consts +0, DW_OP_stack_value)
DW_AT_name ("l_52")
DW_AT_decl_file ("/home/absozero/bisect/fix/abc.c")
DW_AT_decl_line (5)
DW_AT_type (0x0000003f "int")
That's precisely the motivation behind my patch. I don't know an immediate way in earlyCSE to remove the second `dbg.value`. The backward scan in `RemoveRedundantDbgInstrs` will always eliminate the first `dbg.value`.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D80691/new/
https://reviews.llvm.org/D80691
More information about the llvm-commits
mailing list