<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] Incorrect FastISel of icmp + zext due to missing masking"
   href="https://bugs.llvm.org/show_bug.cgi?id=40172">40172</a>
          </td>
        </tr>

        <tr>
          <th>Summary</th>
          <td>[WebAssembly] Incorrect FastISel of icmp + zext due to missing masking
          </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>Backend: WebAssembly
          </td>
        </tr>

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

        <tr>
          <th>Reporter</th>
          <td>nikita.ppv@gmail.com
          </td>
        </tr>

        <tr>
          <th>CC</th>
          <td>llvm-bugs@lists.llvm.org
          </td>
        </tr></table>
      <p>
        <div>
        <pre>Originally reported at: <a href="https://github.com/rust-lang/rust/issues/57152">https://github.com/rust-lang/rust/issues/57152</a>

For LLVM IR:

define void @test(i8 %byte) {
  %t = alloca { i8, i8 }, align 1
  %x4 = and i8 %byte, 1
  %x5 = icmp eq i8 %x4, 1
  %x6 = and i8 %byte, 2
  %x7 = icmp eq i8 %x6, 2
  %x8 = bitcast { i8, i8 }* %t to i8*
  %x9 = zext i1 %x5 to i8
  store i8 %x9, i8* %x8, align 1
  %x10 = getelementptr inbounds { i8, i8 }, { i8, i8 }* %t, i32 0, i32 1
  %x11 = zext i1 %x7 to i8
  store i8 %x11, i8* %x10, align 1
  ret void
}

An llc -O0 -mtriple=wasm32 -debug trace shows:

bb.0 (%ir-block.0):
  liveins: $arguments
  %0:i32 = ARGUMENT_i32 0, implicit $arguments
  %10:i32 = CONST_I32 2, implicit-def $arguments
  %5:i32 = COPY %0:i32
  %14:i32 = CONST_I32 2, implicit-def dead $arguments
  %7:i32 = AND_I32 %0:i32, killed %14:i32, implicit-def dead $arguments
  %8:i32 = CONST_I32 255, implicit-def $arguments
  %9:i32 = AND_I32 %7:i32, %8:i32, implicit-def $arguments
  %11:i32 = CONST_I32 255, implicit-def $arguments
  %12:i32 = AND_I32 %10:i32, %11:i32, implicit-def $arguments
  %13:i32 = EQ_I32 %9:i32, %12:i32, implicit-def $arguments
  %6:i32 = COPY %5:i32
  STORE8_I32 0, 0, %stack.0.t, %6:i32, implicit-def $arguments :: (store 1 into
%ir.x8)
  %3:i32 = COPY %13:i32
  STORE8_I32 0, 1, %stack.0.t, %3:i32, implicit-def $arguments :: (store 1 into
%ir.x10)
  RETURN_VOID implicit-def $arguments

The first STORE8_I32 stores %6, which is a COPY of %5 which is a copy of %0, so
it stores the argument directly, rather than the argument masked with 1.

Looking at debug output, we can see that the first icmp generates this
SelectionDAG fragment:

    t2: i32,ch = CopyFromReg t0, Register:i32 %0
  t3: i8 = truncate t2
          t5: i8 = and t3, Constant:i8<1>
        t7: i1 = setcc t5, Constant:i8<1>, seteq:ch
      t8: i32 = any_extend t7
    t10: ch = CopyToReg t0, Register:i32 %5, t8

Which then (correctly) combines down to:

  t2: i32,ch = CopyFromReg t0, Register:i32 %0
    t10: ch = CopyToReg t0, Register:i32 %5, t2

That is, the masking has been removed *on the assumption that only the lowest
bit is significant*. Note that the any_extend above has been generated as part
of a copy to a virtual export register.

However, FastISel for WebAssembly has a reverse assumption in
<a href="https://github.com/llvm-mirror/llvm/blob/78dfeb7de614170c9deebe990c9f0f5aa838d5b6/lib/Target/WebAssembly/WebAssemblyFastISel.cpp#L448">https://github.com/llvm-mirror/llvm/blob/78dfeb7de614170c9deebe990c9f0f5aa838d5b6/lib/Target/WebAssembly/WebAssemblyFastISel.cpp#L448</a>
that the result of an icmp will always be 0 or 1.

I'm not totally sure what the right way to fix this is. The conservative fix
would be to remove the specialized code for (zext (icmp)) from wasm FastISel,
but probably there's a better way to do this.</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>