[llvm-bugs] [Bug 40010] New: [DebugInfo at O2] Register Coalescing makes variable assignments appear too early

via llvm-bugs llvm-bugs at lists.llvm.org
Thu Dec 13 09:51:19 PST 2018


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

            Bug ID: 40010
           Summary: [DebugInfo at O2] Register Coalescing makes variable
                    assignments appear too early
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: Linux
            Status: CONFIRMED
          Keywords: wrong-debug
          Severity: normal
          Priority: P
         Component: Scalar Optimizations
          Assignee: unassignedbugs at nondot.org
          Reporter: jeremy.morse.llvm at gmail.com
                CC: chackz0x12 at gmail.com, dblaikie at gmail.com,
                    greg.bedwell at sony.com,
                    international.phantom at gmail.com,
                    llvm-bugs at lists.llvm.org, paul.robinson at am.sony.com
            Blocks: 38754

With trunk r348754 and the code below, the register coalescing pass combines
the "foo" and "bar" SSA variables into one virtual register, but points the
corresponding DBG_VALUE at the wrong value. Command line is "llc
-start-after=codegenprepare -stop-after=simple-register-coalescing", and the
heavily contrived code:

-------->8--------
declare void @llvm.dbg.value(metadata, metadata, metadata)

define i32 @test(i32* %pin) {
entry:
  br label %start

start:
  %foo = phi i32 [0, %entry], [%bar, %start]
  %baz = load i32, i32* %pin, align 1
  %qux = xor i32 %baz, 1234
  %bar = add i32 %qux, %foo
  call void @llvm.dbg.value(metadata i32 %foo, metadata !1, metadata
!DIExpression()), !dbg !6
  %cmp = icmp ugt i32 %bar, 1000000
  br i1 %cmp, label %leave, label %start

leave:
  ret i32 %bar
}

!llvm.module.flags = !{!4}
!llvm.dbg.cu = !{!2}
!1 = !DILocalVariable(name: "bees", scope: !5, type: null)
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer:
"beards", isOptimized: true, runtimeVersion: 4, emissionKind: FullDebug)
!3 = !DIFile(filename: "bees.cpp", directory: "")
!4 = !{i32 2, !"Debug Info Version", i32 3}
!5 = distinct !DISubprogram(name: "nope", scope: !2, file: !3, line: 1, unit:
!2)
!6 = !DILocation(line: 0, scope: !5)
--------8<--------

The loop here is loading some integers, xoring and accumulating them, then
breaking out after a large value is reached. %foo is the phi for the
accumulator, and %bar the value for the next iteration. The dbg.value points a
DILocalVariable at %foo half way through the loop body.

Register coalescing correctly spots that %foo and %bar can share the same
register (being the accumulator), and combines them, transforming this X86:

-------->8--------
%0:gr32 = COPY %7:gr32
%8:gr32 = MOV32rm %2:gr64, 1, $noreg, 0, $noreg :: (load 4 from %ir.pin, align
1)
%5:gr32 = COPY %8:gr32
%5:gr32 = XOR32rr %5:gr32(tied-def 0), %4:gr32, implicit-def dead $eflags
%1:gr32 = COPY %0:gr32
%1:gr32 = ADD32rr %1:gr32(tied-def 0), %5:gr32, implicit-def dead $eflags
DBG_VALUE %0:gr32, $noreg, !"bees", !DIExpression(), debug-location !5;
bees.cpp:0 line no:0
CMP32ri %1:gr32, 1000001, implicit-def $eflags
%7:gr32 = COPY %1:gr32
JB_1 %bb.1, implicit killed $eflags
JMP_1 %bb.2
--------8<--------

Into:

-------->8--------
%5:gr32 = MOV32rm %2, 1, $noreg, 0, $noreg :: (load 4 from %ir.pin...)
%5:gr32 = XOR32rr %5, %4, implicit-def dead $eflags
%7:gr32 = ADD32rr %7, %5, implicit-def dead $eflags
DBG_VALUE %7, $noreg, !3, !DIExpression(), debug-location !5
CMP32ri %7, 1000001, implicit-def $eflags
JB_1 %bb.1, implicit killed $eflags
JMP_1 %bb.2
--------8<--------

Note that the DBG_VALUE now points at what was %bar, the next accumulator value
of the loop, where previously it referred to the current value in %foo. A
developer would expect the DBG_VALUE to have the value of %foo for the
remainder of the loop, but due to this transform, they get the value of %bar.

The coalescing is a totally valid optimisation but leads to the value of %foo
being dead for the second half of the loop body. IMHO the correct action of
register coalescing would have been to mark the DBG_VALUE as undef: once %0 and
%7 are coalesced and %7 modified, there's no way to recover the original
valuation of %0.

While this is currently observable from vanilla trunk with the given command
line, codegenprepare messes with the location of the dbg.value, so this isn't a
fault that one would observe from a frontend I believe.

Given that the two registers have to be connected by a COPY, this isn't going
to lead to a completely unexpected value appearing to the debugger in a
variable. However, making values appear before their time is reporting a false
state to the developer.


Referenced Bugs:

https://bugs.llvm.org/show_bug.cgi?id=38754
[Bug 38754] [DebugInfo at O2][Dexter] Illegal value appears in variable when
conditional blocks folded
-- 
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/20181213/c0d6b3ae/attachment-0001.html>


More information about the llvm-bugs mailing list