[llvm] r336138 - [WebAssembly] Fix fast-isel optimization of branch conditions.

Dan Gohman via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 2 12:45:57 PDT 2018


Author: djg
Date: Mon Jul  2 12:45:57 2018
New Revision: 336138

URL: http://llvm.org/viewvc/llvm-project?rev=336138&view=rev
Log:
[WebAssembly] Fix fast-isel optimization of branch conditions.

LLVM doesn't guarantee anything about the high bits of a register holding
an i1 value at the IR level, so don't translate LLVM IR i1 values directly
into WebAssembly conditional branch operands. WebAssembly's conditional
branches do demand all 32 bits be valid.

Fixes PR38019.

Added:
    llvm/trunk/test/CodeGen/WebAssembly/fast-isel-br-i1.ll
Modified:
    llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp

Modified: llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp?rev=336138&r1=336137&r2=336138&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/WebAssemblyFastISel.cpp Mon Jul  2 12:45:57 2018
@@ -419,7 +419,7 @@ unsigned WebAssemblyFastISel::getRegForI
         return getRegForValue(ICmp->getOperand(0));
       }
 
-  if (BinaryOperator::isNot(V)) {
+  if (BinaryOperator::isNot(V) && V->getType()->isIntegerTy(32)) {
     Not = true;
     return getRegForValue(BinaryOperator::getNotArgument(V));
   }

Added: llvm/trunk/test/CodeGen/WebAssembly/fast-isel-br-i1.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WebAssembly/fast-isel-br-i1.ll?rev=336138&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/WebAssembly/fast-isel-br-i1.ll (added)
+++ llvm/trunk/test/CodeGen/WebAssembly/fast-isel-br-i1.ll Mon Jul  2 12:45:57 2018
@@ -0,0 +1,48 @@
+; RUN: llc < %s -fast-isel -asm-verbose=false | FileCheck %s
+
+target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
+target triple = "wasm32-unknown-unknown"
+
+; Fast-isel uses a 32-bit xor with -1 to negate i1 values, because it doesn't
+; make any guarantees about the contents of the high bits of a register holding
+; an i1 value. Test that when we do a `br_if` or `br_unless` with what what an
+; i1 value in LLVM IR, that we only test the low bit.
+
+; CHECK: i32.xor
+; CHECK: i32.const       $push[[L0:[0-9]+]]=, 1{{$}}
+; CHECK: i32.and         $push[[L1:[0-9]+]]=, $pop{{[0-9]+}}, $pop[[L0]]{{$}}
+; CHECK: br_if           0, $pop[[L1]]{{$}}
+
+; CHECK: i32.xor
+; CHECK: i32.const       $push[[L2:[0-9]+]]=, 1{{$}}
+; CHECK: i32.and         $push[[L3:[0-9]+]]=, $pop{{[0-9]+}}, $pop[[L2]]{{$}}
+; CHECK: br_if           0, $pop[[L3]]{{$}}
+
+define void @test() {
+start:
+  %0 = call i32 @return_one()
+  br label %bb1
+
+bb1:
+  %1 = icmp eq i32 %0, 1
+  %2 = xor i1 %1, true
+  br i1 %2, label %bb2, label %bb3
+
+bb2:
+  call void @panic()
+  unreachable
+
+bb3:
+  %3 = xor i1 %2, true
+  br i1 %3, label %bb4, label %bb5
+
+bb4:
+  call void @panic()
+  unreachable
+
+bb5:
+  ret void
+}
+
+declare i32 @return_one()
+declare void @panic()




More information about the llvm-commits mailing list