[llvm-bugs] [Bug 40172] New: [WebAssembly] Incorrect FastISel of icmp + zext due to missing masking

via llvm-bugs llvm-bugs at lists.llvm.org
Fri Dec 28 04:12:57 PST 2018


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

            Bug ID: 40172
           Summary: [WebAssembly] Incorrect FastISel of icmp + zext due to
                    missing masking
           Product: libraries
           Version: trunk
          Hardware: PC
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P
         Component: Backend: WebAssembly
          Assignee: unassignedbugs at nondot.org
          Reporter: nikita.ppv at gmail.com
                CC: llvm-bugs at lists.llvm.org

Originally reported at: https://github.com/rust-lang/rust/issues/57152

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
https://github.com/llvm-mirror/llvm/blob/78dfeb7de614170c9deebe990c9f0f5aa838d5b6/lib/Target/WebAssembly/WebAssemblyFastISel.cpp#L448
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.

-- 
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/20181228/6c5a95b5/attachment-0001.html>


More information about the llvm-bugs mailing list