<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 - [WebAssembly] WebAssemblyOptimizeLiveIntervals does not split DBG_VALUEs"
   href="https://bugs.llvm.org/show_bug.cgi?id=50359">50359</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[WebAssembly] WebAssemblyOptimizeLiveIntervals does not split DBG_VALUEs
          </td>
        </tr>

        <tr>
          <th>Product</th>
          <td>libraries
          </td>
        </tr>

        <tr>
          <th>Version</th>
          <td>trunk
          </td>
        </tr>

        <tr>
          <th>Hardware</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>OS</th>
          <td>All
          </td>
        </tr>

        <tr>
          <th>Status</th>
          <td>NEW
          </td>
        </tr>

        <tr>
          <th>Severity</th>
          <td>normal
          </td>
        </tr>

        <tr>
          <th>Priority</th>
          <td>P
          </td>
        </tr>

        <tr>
          <th>Component</th>
          <td>Backend: WebAssembly
          </td>
        </tr>

        <tr>
          <th>Assignee</th>
          <td>unassignedbugs@nondot.org
          </td>
        </tr>

        <tr>
          <th>Reporter</th>
          <td>aheejin@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>aardappel@gmail.com, dschuff@google.com, llvm-bugs@lists.llvm.org, ydelendik@mozilla.com
          </td>
        </tr></table>
      <p>
        <div>
        <pre>WebAssemblyOptimizeLiveIntervals pass splits register live intervals by
splitting a single register having multiple defs into multiple registers. But
it does not handle splitting of corresponding DBG_VALUE instructions. For
example:


test.ll:
```
target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"                          
target triple = "wasm32-unknown-unknown"                                        

define i32 @test(i32* %arg0, i32* %arg1) {                                      
entry:                                                                          
  %tmp0 = load i32, i32* %arg0                                                  
  %tmp1 = load i32, i32* %arg1                                                  
  %tmp2 = add i32 %tmp0, %tmp1                                                  
  call void @llvm.dbg.value(metadata i32 %tmp0, metadata !6, metadata
!DIExpression()), !dbg !8
  ret i32 %tmp2                                                                 
}                                                                               

declare void @llvm.dbg.value(metadata, metadata, metadata)                      

!llvm.module.flags = !{!0}                                                      
!llvm.dbg.cu = !{!1}                                                            

!0 = !{i32 2, !"Debug Info Version", i32 3}                                     
!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang
version 3.9.0 (trunk 266005) (llvm/trunk 266105)", isOptimized: false,
runtimeVersion: 0, emissionKind: FullDebug, enums: !3)
!2 = !DIFile(filename: "test.c", directory: "/")                                
!3 = !{}                                                                        
!4 = distinct !DISubprogram(name: "test", scope: !2, file: !2, line: 10, type:
!5, isLocal: false, isDefinition: true, scopeLine: 11, flags: DIFlagPrototyped,
isOptimized: true, unit: !1, retainedNodes: !3)
!5 = !DISubroutineType(types: !3)                                               
!6 = !DILocalVariable(name: "var", scope: !4, file: !2, line: 15, type: !7)     
!7 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)    
!8 = !DILocation(line: 15, column: 6, scope: !4) 
```

Run:
$ llc -print-after-all test.ll

Right before WebAssemblyOptimizeLiveIntervals, the function is:
```
Function Live Ins: $arguments                                                   

bb.0.entry:
  liveins: $arguments
  %2:i32 = ARGUMENT_i32 0, implicit $arguments
  %0:i32 = ARGUMENT_i32 1, implicit $arguments
  dead %4:i32 = IMPLICIT_DEF
  dead %3:i32 = IMPLICIT_DEF
  dead %1:i32 = IMPLICIT_DEF
  %1:i32 = LOAD_I32_A32 2, 0, %0:i32, implicit-def dead $arguments :: (load 4
from %ir.arg1)
  %3:i32 = LOAD_I32_A32 2, 0, %2:i32, implicit-def dead $arguments :: (load 4
from %ir.arg0)
  %4:i32 = ADD_I32 %3:i32, %1:i32, implicit-def dead $arguments
  DBG_VALUE %3:i32, $noreg, !"var", !DIExpression(), debug-location !8;
test.c:15:6 line no:15
  RETURN %4:i32, implicit-def dead $arguments
```
(Here IMPLICIT_DEFs were added by WebAssemblyPrepareForLiveIntervals pass)
Note that the DBG_VALUE is referring to %3, the result of LOAD_I32_A32.


WebAssemblyOptimizeLiveIntervals pass currently consists of two parts. First
part splits live ranges, and the second part removes unnecessary IMPLICIT_DEF
instructions added by WebAssemblyPrepareForLiveIntervals pass.

After the first part (splitting live ranges), this becomes:
```
Function Live Ins: $arguments                                                   

bb.0.entry:                                                                     
  liveins: $arguments
  %2:i32 = ARGUMENT_i32 0, implicit $arguments
  %0:i32 = ARGUMENT_i32 1, implicit $arguments
  dead %4:i32 = IMPLICIT_DEF
  dead %3:i32 = IMPLICIT_DEF
  dead %1:i32 = IMPLICIT_DEF
  %5:i32 = LOAD_I32_A32 2, 0, %0:i32, implicit-def dead $arguments :: (load 4
from %ir.arg1)
  %6:i32 = LOAD_I32_A32 2, 0, %2:i32, implicit-def dead $arguments :: (load 4
from %ir.arg0)
  %7:i32 = ADD_I32 %6:i32, %5:i32, implicit-def dead $arguments
  DBG_VALUE %3:i32, $noreg, !"var", !DIExpression(), debug-location !8;
test.c:15:6 line no:15
  RETURN %7:i32, implicit-def dead $arguments
```
Now %3 is split into %3 and %6, each of which has a single def. Here
DBG_VALUE's operand needs to change from %3 to %6 as well but it doesn't, which
is a bug.

After the second part (removing unnecessary IMPLICIT_DEFs), this becomes:
```
Function Live Ins: $arguments                                                   

bb.0.entry:
  liveins: $arguments
  %2:i32 = ARGUMENT_i32 0, implicit $arguments
%0:i32 = ARGUMENT_i32 1, implicit $arguments
  %5:i32 = LOAD_I32_A32 2, 0, %0:i32, implicit-def dead $arguments :: (load 4
from %ir.arg1)
  %6:i32 = LOAD_I32_A32 2, 0, %2:i32, implicit-def dead $arguments :: (load 4
from %ir.arg0)
  %7:i32 = ADD_I32 %6:i32, %5:i32, implicit-def dead $arguments       
  DBG_VALUE %3:i32, $noreg, !"var", !DIExpression(), debug-location !8;
test.c:15:6 line no:15
  RETURN %7:i32, implicit-def dead $arguments
```
Now IMPLICIT_DEFs are removed and the DBG_VALUE's operand %3 does not even have
a def.

---

Note that this bug is not related to generation and removal of IMPLICIT_DEFs;
they happen to appear in this example, and the bug is that when we split live
ranges, we don't handle their corresponding DBG_VALUE instructions.</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>