OSDN Git Service

Subzero: Be more strict about i1 calculations.
authorJim Stichnoth <stichnot@chromium.org>
Mon, 8 Sep 2014 18:19:21 +0000 (11:19 -0700)
committerJim Stichnoth <stichnot@chromium.org>
Mon, 8 Sep 2014 18:19:21 +0000 (11:19 -0700)
One issue is that the test_arith cross test defined functions on i1 but never actually invoked them.

Another issue is that the lowering was using 8-bit registers for i1 values, but was being sloppy about leaving stuff in the upper 7 bits, and then using all 8 bits for tests.

This takes the approach of explicitly masking the result whenever it's possible for the result to exceed one bit, such as trunc, fptosi, fptoui.

Another possibility might be to allow the upper 7 bits to stay sloppy, and explicitly only test the lower bit.

Additionally, some "CHECK: ret" lines were removed, since they aren't actually needed after the change to use CHECK-LABEL, and they are affected by an llvm-dump bug (which is fixed in LLVM 3.6).

BUG= none
R=jvoung@chromium.org

Review URL: https://codereview.chromium.org/547033002

crosstest/test_arith_main.cpp
src/IceGlobalContext.cpp
src/IceTargetLoweringX8632.cpp
tests_lit/llvm2ice_tests/64bit.pnacl.ll
tests_lit/llvm2ice_tests/sext_zext_i1.ll [deleted file]
tests_lit/llvm2ice_tests/test_i1.ll [new file with mode: 0644]

index 84bc6b7..16b2c5e 100644 (file)
@@ -347,6 +347,7 @@ int main(int argc, char **argv) {
   size_t Passes = 0;
   size_t Failures = 0;
 
+  testsInt<bool, bool>(TotalTests, Passes, Failures);
   testsInt<uint8_t, myint8_t>(TotalTests, Passes, Failures);
   testsInt<uint16_t, int16_t>(TotalTests, Passes, Failures);
   testsInt<uint32_t, int32_t>(TotalTests, Passes, Failures);
index 5f9b620..f398255 100644 (file)
@@ -290,6 +290,8 @@ IceString GlobalContext::mangleName(const IceString &Name) const {
 GlobalContext::~GlobalContext() {}
 
 Constant *GlobalContext::getConstantInt(Type Ty, uint64_t ConstantInt64) {
+  if (Ty == IceType_i1)
+    ConstantInt64 &= UINT64_C(1);
   return ConstPool->Integers.getOrAdd(this, Ty, ConstantInt64);
 }
 
index 6fced4d..756508e 100644 (file)
@@ -1947,7 +1947,7 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
       if (Src0RM->getType() == IceType_i32) {
         _mov(T_Lo, Src0RM);
       } else if (Src0RM->getType() == IceType_i1) {
-        _mov(T_Lo, Src0RM);
+        _movzx(T_Lo, Src0RM);
         _shl(T_Lo, Shift);
         _sar(T_Lo, Shift);
       } else {
@@ -1956,7 +1956,9 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
       _mov(DestLo, T_Lo);
       Variable *T_Hi = NULL;
       _mov(T_Hi, T_Lo);
-      _sar(T_Hi, Shift);
+      if (Src0RM->getType() != IceType_i1)
+        // For i1, the sar instruction is already done above.
+        _sar(T_Hi, Shift);
       _mov(DestHi, T_Hi);
     } else if (Src0RM->getType() == IceType_i1) {
       // t1 = src
@@ -1965,8 +1967,15 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
       // dst = t1
       size_t DestBits = X86_CHAR_BIT * typeWidthInBytes(Dest->getType());
       Constant *ShiftAmount = Ctx->getConstantInt(IceType_i32, DestBits - 1);
-      Variable *T = NULL;
-      _mov(T, Src0RM);
+      Variable *T = makeReg(Dest->getType());
+      if (typeWidthInBytes(Dest->getType()) <=
+          typeWidthInBytes(Src0RM->getType())) {
+        _mov(T, Src0RM);
+      } else {
+        // Widen the source using movsx or movzx.  (It doesn't matter
+        // which one, since the following shl/sar overwrite the bits.)
+        _movzx(T, Src0RM);
+      }
       _shl(T, ShiftAmount);
       _sar(T, ShiftAmount);
       _mov(Dest, T);
@@ -1996,13 +2005,13 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
       Variable *Tmp = makeReg(DestLo->getType());
       if (Src0RM->getType() == IceType_i32) {
         _mov(Tmp, Src0RM);
-      } else if (Src0RM->getType() == IceType_i1) {
-        Constant *One = Ctx->getConstantInt(IceType_i32, 1);
-        _mov(Tmp, Src0RM);
-        _and(Tmp, One);
       } else {
         _movzx(Tmp, Src0RM);
       }
+      if (Src0RM->getType() == IceType_i1) {
+        Constant *One = Ctx->getConstantInt(IceType_i32, 1);
+        _and(Tmp, One);
+      }
       _mov(DestLo, Tmp);
       _mov(DestHi, Zero);
     } else if (Src0RM->getType() == IceType_i1) {
@@ -2038,6 +2047,8 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
       // t1 = trunc Src0RM; Dest = t1
       Variable *T = NULL;
       _mov(T, Src0RM);
+      if (Dest->getType() == IceType_i1)
+        _and(T, Ctx->getConstantInt(IceType_i1, 1));
       _mov(Dest, T);
     }
     break;
@@ -2081,6 +2092,8 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
       Variable *T_2 = makeReg(Dest->getType());
       _cvtt(T_1, Src0RM);
       _mov(T_2, T_1); // T_1 and T_2 may have different integer types
+      if (Dest->getType() == IceType_i1)
+        _and(T_2, Ctx->getConstantInt(IceType_i1, 1));
       _mov(Dest, T_2);
       T_2->setPreferredRegister(T_1, true);
     }
@@ -2116,6 +2129,8 @@ void TargetX8632::lowerCast(const InstCast *Inst) {
       Variable *T_2 = makeReg(Dest->getType());
       _cvtt(T_1, Src0RM);
       _mov(T_2, T_1); // T_1 and T_2 may have different integer types
+      if (Dest->getType() == IceType_i1)
+        _and(T_2, Ctx->getConstantInt(IceType_i1, 1));
       _mov(Dest, T_2);
       T_2->setPreferredRegister(T_1, true);
     }
index c4005c9..d8c6e6b 100644 (file)
@@ -127,12 +127,10 @@ entry:
 ; CHECK-LABEL: return64BitArg
 ; CHECK: mov     {{.*}}, dword ptr [esp + 4]
 ; CHECK: mov     {{.*}}, dword ptr [esp + 8]
-; CHECK: ret
 ;
 ; OPTM1-LABEL: return64BitArg
 ; OPTM1: mov     {{.*}}, dword ptr [esp + 4]
 ; OPTM1: mov     {{.*}}, dword ptr [esp + 8]
-; OPTM1: ret
 
 define internal i64 @return64BitConst() {
 entry:
@@ -141,12 +139,10 @@ entry:
 ; CHECK-LABEL: return64BitConst
 ; CHECK: mov     eax, 305419896
 ; CHECK: mov     edx, 3735928559
-; CHECK: ret
 ;
 ; OPTM1-LABEL: return64BitConst
 ; OPTM1: mov     eax, 305419896
 ; OPTM1: mov     edx, 3735928559
-; OPTM1: ret
 
 define internal i64 @add64BitSigned(i64 %a, i64 %b) {
 entry:
@@ -156,12 +152,10 @@ entry:
 ; CHECK-LABEL: add64BitSigned
 ; CHECK: add
 ; CHECK: adc
-; CHECK: ret
 ;
 ; OPTM1-LABEL: add64BitSigned
 ; OPTM1: add
 ; OPTM1: adc
-; OPTM1: ret
 
 define internal i64 @add64BitUnsigned(i64 %a, i64 %b) {
 entry:
@@ -171,12 +165,10 @@ entry:
 ; CHECK-LABEL: add64BitUnsigned
 ; CHECK: add
 ; CHECK: adc
-; CHECK: ret
 ;
 ; OPTM1-LABEL: add64BitUnsigned
 ; OPTM1: add
 ; OPTM1: adc
-; OPTM1: ret
 
 define internal i64 @sub64BitSigned(i64 %a, i64 %b) {
 entry:
@@ -186,12 +178,10 @@ entry:
 ; CHECK-LABEL: sub64BitSigned
 ; CHECK: sub
 ; CHECK: sbb
-; CHECK: ret
 ;
 ; OPTM1-LABEL: sub64BitSigned
 ; OPTM1: sub
 ; OPTM1: sbb
-; OPTM1: ret
 
 define internal i64 @sub64BitUnsigned(i64 %a, i64 %b) {
 entry:
@@ -201,12 +191,10 @@ entry:
 ; CHECK-LABEL: sub64BitUnsigned
 ; CHECK: sub
 ; CHECK: sbb
-; CHECK: ret
 ;
 ; OPTM1-LABEL: sub64BitUnsigned
 ; OPTM1: sub
 ; OPTM1: sbb
-; OPTM1: ret
 
 define internal i64 @mul64BitSigned(i64 %a, i64 %b) {
 entry:
@@ -219,7 +207,6 @@ entry:
 ; CHECK: mul
 ; CHECK: add
 ; CHECK: add
-; CHECK: ret
 ;
 ; OPTM1-LABEL: mul64BitSigned
 ; OPTM1: imul
@@ -227,7 +214,6 @@ entry:
 ; OPTM1: mul
 ; OPTM1: add
 ; OPTM1: add
-; OPTM1: ret
 
 define internal i64 @mul64BitUnsigned(i64 %a, i64 %b) {
 entry:
@@ -240,7 +226,6 @@ entry:
 ; CHECK: mul
 ; CHECK: add
 ; CHECK: add
-; CHECK: ret
 ;
 ; OPTM1-LABEL: mul64BitUnsigned
 ; OPTM1: imul
@@ -248,7 +233,6 @@ entry:
 ; OPTM1: mul
 ; OPTM1: add
 ; OPTM1: add
-; OPTM1: ret
 
 define internal i64 @div64BitSigned(i64 %a, i64 %b) {
 entry:
@@ -259,11 +243,9 @@ entry:
 ; CALLTARGETS-LABEL: div64BitSigned
 ; CHECK: call    -4
 ; CALLTARGETS: call __divdi3
-; CHECK: ret
 
 ; OPTM1-LABEL: div64BitSigned
 ; OPTM1: call    -4
-; OPTM1: ret
 
 define internal i64 @div64BitSignedConst(i64 %a) {
 entry:
@@ -276,13 +258,11 @@ entry:
 ; CHECK: mov     dword ptr [esp + 8],  1942892530
 ; CHECK: call    -4
 ; CALLTARGETS: call __divdi3
-; CHECK: ret
 ;
 ; OPTM1-LABEL: div64BitSignedConst
 ; OPTM1: mov     dword ptr [esp + 12], 2874
 ; OPTM1: mov     dword ptr [esp + 8],  1942892530
 ; OPTM1: call    -4
-; OPTM1: ret
 
 define internal i64 @div64BitUnsigned(i64 %a, i64 %b) {
 entry:
@@ -293,11 +273,9 @@ entry:
 ; CALLTARGETS-LABEL: div64BitUnsigned
 ; CHECK: call    -4
 ; CALLTARGETS: call __udivdi3
-; CHECK: ret
 ;
 ; OPTM1-LABEL: div64BitUnsigned
 ; OPTM1: call    -4
-; OPTM1: ret
 
 define internal i64 @rem64BitSigned(i64 %a, i64 %b) {
 entry:
@@ -308,11 +286,9 @@ entry:
 ; CALLTARGETS-LABEL: rem64BitSigned
 ; CHECK: call    -4
 ; CALLTARGETS: call __moddi3
-; CHECK: ret
 ;
 ; OPTM1-LABEL: rem64BitSigned
 ; OPTM1: call    -4
-; OPTM1: ret
 
 define internal i64 @rem64BitUnsigned(i64 %a, i64 %b) {
 entry:
@@ -323,11 +299,9 @@ entry:
 ; CALLTARGETS-LABEL: rem64BitUnsigned
 ; CHECK: call    -4
 ; CALLTARGETS: call __umoddi3
-; CHECK: ret
 ;
 ; OPTM1-LABEL: rem64BitUnsigned
 ; OPTM1: call    -4
-; OPTM1: ret
 
 define internal i64 @shl64BitSigned(i64 %a, i64 %b) {
 entry:
@@ -484,11 +458,9 @@ entry:
 }
 ; CHECK-LABEL: trunc64To32Signed
 ; CHECK: mov     eax, dword ptr [esp + 4]
-; CHECK-NEXT: ret
 ;
 ; OPTM1-LABEL: trunc64To32Signed
 ; OPTM1: mov     eax, dword ptr [esp +
-; OPTM1: ret
 
 define internal i32 @trunc64To16Signed(i64 %a) {
 entry:
@@ -499,12 +471,10 @@ entry:
 ; CHECK-LABEL: trunc64To16Signed
 ; CHECK:      mov     eax, dword ptr [esp + 4]
 ; CHECK-NEXT: movsx  eax, ax
-; CHECK-NEXT: ret
 ;
 ; OPTM1-LABEL: trunc64To16Signed
 ; OPTM1:      mov     eax, dword ptr [esp +
 ; OPTM1: movsx  eax,
-; OPTM1: ret
 
 define internal i32 @trunc64To8Signed(i64 %a) {
 entry:
@@ -515,12 +485,10 @@ entry:
 ; CHECK-LABEL: trunc64To8Signed
 ; CHECK:      mov     eax, dword ptr [esp + 4]
 ; CHECK-NEXT: movsx  eax, al
-; CHECK-NEXT: ret
 ;
 ; OPTM1-LABEL: trunc64To8Signed
 ; OPTM1:      mov     eax, dword ptr [esp +
 ; OPTM1: movsx  eax,
-; OPTM1: ret
 
 define internal i32 @trunc64To32SignedConst() {
 entry:
@@ -554,11 +522,9 @@ entry:
 }
 ; CHECK-LABEL: trunc64To32Unsigned
 ; CHECK: mov     eax, dword ptr [esp + 4]
-; CHECK-NEXT: ret
 ;
 ; OPTM1-LABEL: trunc64To32Unsigned
 ; OPTM1: mov     eax, dword ptr [esp +
-; OPTM1: ret
 
 define internal i32 @trunc64To16Unsigned(i64 %a) {
 entry:
@@ -569,12 +535,10 @@ entry:
 ; CHECK-LABEL: trunc64To16Unsigned
 ; CHECK:      mov     eax, dword ptr [esp + 4]
 ; CHECK-NEXT: movzx  eax, ax
-; CHECK-NEXT: ret
 ;
 ; OPTM1-LABEL: trunc64To16Unsigned
 ; OPTM1:      mov     eax, dword ptr [esp +
 ; OPTM1: movzx  eax,
-; OPTM1: ret
 
 define internal i32 @trunc64To8Unsigned(i64 %a) {
 entry:
@@ -585,12 +549,10 @@ entry:
 ; CHECK-LABEL: trunc64To8Unsigned
 ; CHECK:      mov     eax, dword ptr [esp + 4]
 ; CHECK-NEXT: movzx  eax, al
-; CHECK-NEXT: ret
 ;
 ; OPTM1-LABEL: trunc64To8Unsigned
 ; OPTM1: mov    eax, dword ptr [esp +
 ; OPTM1: movzx  eax,
-; OPTM1: ret
 
 define internal i32 @trunc64To1(i64 %a) {
 entry:
@@ -602,12 +564,12 @@ entry:
 ; CHECK-LABEL: trunc64To1
 ; CHECK:      mov     eax, dword ptr [esp + 4]
 ; CHECK:      and     eax, 1
-; CHECK-NEXT: ret
+; CHECK:      and     eax, 1
 ;
 ; OPTM1-LABEL: trunc64To1
 ; OPTM1:      mov     eax, dword ptr [esp +
 ; OPTM1:      and     eax, 1
-; OPTM1: ret
+; OPTM1:      and     eax, 1
 
 define internal i64 @sext32To64(i32 %a) {
 entry:
@@ -660,13 +622,11 @@ entry:
 ; CHECK: mov
 ; CHECK: shl {{.*}}, 31
 ; CHECK: sar {{.*}}, 31
-; CHECK: sar {{.*}}, 31
 ;
 ; OPTM1-LABEL: sext1To64
 ; OPTM1: mov
 ; OPTM1: shl {{.*}}, 31
 ; OPTM1: sar {{.*}}, 31
-; OPTM1: sar {{.*}}, 31
 
 define internal i64 @zext32To64(i32 %a) {
 entry:
diff --git a/tests_lit/llvm2ice_tests/sext_zext_i1.ll b/tests_lit/llvm2ice_tests/sext_zext_i1.ll
deleted file mode 100644 (file)
index e616e98..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-; Test sext and zext instructions with i1 source operands.
-
-; RUN: %llvm2ice -O2 --verbose none %s \
-; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
-; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
-; RUN: %llvm2ice -Om1 --verbose none %s \
-; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
-; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
-; RUN: %llvm2ice --verbose none %s | FileCheck --check-prefix=ERRORS %s
-; RUN: %llvm2iceinsts %s | %szdiff %s | FileCheck --check-prefix=DUMP %s
-; RUN: %llvm2iceinsts --pnacl %s | %szdiff %s \
-; RUN:                           | FileCheck --check-prefix=DUMP %s
-
-define internal i8 @sext1To8(i32 %a) {
-entry:
-  %a.arg_trunc = trunc i32 %a to i1
-  %conv = sext i1 %a.arg_trunc to i8
-  ret i8 %conv
-}
-; CHECK-LABEL: sext1To8
-; CHECK: mov
-; CHECK: shl {{.*}}, 7
-; CHECK: sar {{.*}}, 7
-
-define internal i16 @sext1To16(i32 %a) {
-entry:
-  %a.arg_trunc = trunc i32 %a to i1
-  %conv = sext i1 %a.arg_trunc to i16
-  ret i16 %conv
-}
-; CHECK-LABEL: sext1To16
-; CHECK: mov
-; CHECK: shl {{.*}}, 15
-; CHECK: sar {{.*}}, 15
-
-define internal i32 @sext1To32(i32 %a) {
-entry:
-  %a.arg_trunc = trunc i32 %a to i1
-  %conv = sext i1 %a.arg_trunc to i32
-  ret i32 %conv
-}
-; CHECK-LABEL: sext1To32
-; CHECK: mov
-; CHECK: shl {{.*}}, 31
-; CHECK: sar {{.*}}, 31
-
-define internal i64 @sext1To64(i32 %a) {
-entry:
-  %a.arg_trunc = trunc i32 %a to i1
-  %conv = sext i1 %a.arg_trunc to i64
-  ret i64 %conv
-}
-; CHECK-LABEL: sext1To64
-; CHECK: mov
-; CHECK: shl {{.*}}, 31
-; CHECK: sar {{.*}}, 31
-; CHECK: sar {{.*}}, 31
-
-define internal i8 @zext1To8(i32 %a) {
-entry:
-  %a.arg_trunc = trunc i32 %a to i1
-  %conv = zext i1 %a.arg_trunc to i8
-  ret i8 %conv
-}
-; CHECK-LABEL: zext1To8
-; CHECK: and {{.*}}, 1
-
-define internal i16 @zext1To16(i32 %a) {
-entry:
-  %a.arg_trunc = trunc i32 %a to i1
-  %conv = zext i1 %a.arg_trunc to i16
-  ret i16 %conv
-}
-; CHECK-LABEL: zext1To16
-; CHECK: and {{.*}}, 1
-
-define internal i32 @zext1To32(i32 %a) {
-entry:
-  %a.arg_trunc = trunc i32 %a to i1
-  %conv = zext i1 %a.arg_trunc to i32
-  ret i32 %conv
-}
-; CHECK-LABEL: zext1To32
-; CHECK: and {{.*}}, 1
-
-define internal i64 @zext1To64(i32 %a) {
-entry:
-  %a.arg_trunc = trunc i32 %a to i1
-  %conv = zext i1 %a.arg_trunc to i64
-  ret i64 %conv
-}
-; CHECK-LABEL: zext1To64
-; CHECK: and {{.*}}, 1
-
-; ERRORS-NOT: ICE translation error
-; DUMP-NOT: SZ
diff --git a/tests_lit/llvm2ice_tests/test_i1.ll b/tests_lit/llvm2ice_tests/test_i1.ll
new file mode 100644 (file)
index 0000000..6d623cc
--- /dev/null
@@ -0,0 +1,184 @@
+; Tests various aspects of i1 related lowering.
+
+; RUN: %llvm2ice -O2 --verbose none %s \
+; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
+; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
+; RUN: %llvm2ice -Om1 --verbose none %s \
+; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
+; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
+; RUN: %llvm2ice --verbose none %s | FileCheck --check-prefix=ERRORS %s
+; RUN: %llvm2iceinsts %s | %szdiff %s | FileCheck --check-prefix=DUMP %s
+; RUN: %llvm2iceinsts --pnacl %s | %szdiff %s \
+; RUN:                           | FileCheck --check-prefix=DUMP %s
+
+; Test that xor with true uses immediate 1, not -1.
+define internal i32 @testXorTrue(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result_i1 = xor i1 %arg_i1, true
+  %result = zext i1 %result_i1 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testXorTrue
+; CHECK: xor {{.*}}, 1
+
+; Test that trunc to i1 masks correctly.
+define internal i32 @testTrunc(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result = zext i1 %arg_i1 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testTrunc
+; CHECK: and {{.*}}, 1
+
+; Test zext to i8.
+define internal i32 @testZextI8(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result_i8 = zext i1 %arg_i1 to i8
+  %result = zext i8 %result_i8 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testZextI8
+; match the trunc instruction
+; CHECK: and {{.*}}, 1
+; match the zext i1 instruction
+; CHECK: movzx
+; CHECK: and {{.*}}, 1
+
+; Test zext to i16.
+define internal i32 @testZextI16(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result_i16 = zext i1 %arg_i1 to i16
+  %result = zext i16 %result_i16 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testZextI16
+; match the trunc instruction
+; CHECK: and {{.*}}, 1
+; match the zext i1 instruction
+; CHECK: movzx
+; CHECK: and {{.*}}, 1
+
+; Test zext to i32.
+define internal i32 @testZextI32(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result_i32 = zext i1 %arg_i1 to i32
+  ret i32 %result_i32
+}
+; CHECK-LABEL: testZextI32
+; match the trunc instruction
+; CHECK: and {{.*}}, 1
+; match the zext i1 instruction
+; CHECK: movzx
+; CHECK: and {{.*}}, 1
+
+; Test zext to i64.
+define internal i64 @testZextI64(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result_i64 = zext i1 %arg_i1 to i64
+  ret i64 %result_i64
+}
+; CHECK-LABEL: testZextI64
+; match the trunc instruction
+; CHECK: and {{.*}}, 1
+; match the zext i1 instruction
+; CHECK: movzx
+; CHECK: and {{.*}}, 1
+; CHECK: mov {{.*}}, 0
+
+; Test sext to i8.
+define internal i32 @testSextI8(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result_i8 = sext i1 %arg_i1 to i8
+  %result = sext i8 %result_i8 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testSextI8
+; match the trunc instruction
+; CHECK: and {{.*}}, 1
+; match the sext i1 instruction
+; CHECK: shl [[REG:.*]], 7
+; CHECK-NEXT: sar [[REG]], 7
+
+; Test sext to i16.
+define internal i32 @testSextI16(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result_i16 = sext i1 %arg_i1 to i16
+  %result = sext i16 %result_i16 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testSextI16
+; match the trunc instruction
+; CHECK: and {{.*}}, 1
+; match the sext i1 instruction
+; CHECK: movzx [[REG:.*]],
+; CHECK-NEXT: shl [[REG]], 15
+; CHECK-NEXT: sar [[REG]], 15
+
+; Test sext to i32.
+define internal i32 @testSextI32(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result_i32 = sext i1 %arg_i1 to i32
+  ret i32 %result_i32
+}
+; CHECK-LABEL: testSextI32
+; match the trunc instruction
+; CHECK: and {{.*}}, 1
+; match the sext i1 instruction
+; CHECK: movzx [[REG:.*]],
+; CHECK-NEXT: shl [[REG]], 31
+; CHECK-NEXT: sar [[REG]], 31
+
+; Test sext to i64.
+define internal i64 @testSextI64(i32 %arg) {
+entry:
+  %arg_i1 = trunc i32 %arg to i1
+  %result_i64 = sext i1 %arg_i1 to i64
+  ret i64 %result_i64
+}
+; CHECK-LABEL: testSextI64
+; match the trunc instruction
+; CHECK: and {{.*}}, 1
+; match the sext i1 instruction
+; CHECK: movzx [[REG:.*]],
+; CHECK-NEXT: shl [[REG]], 31
+; CHECK-NEXT: sar [[REG]], 31
+
+; Test fptosi float to i1.
+define internal i32 @testFptosiFloat(float %arg) {
+entry:
+  %arg_i1 = fptosi float %arg to i1
+  %result = sext i1 %arg_i1 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testFptosiFloat
+; CHECK: cvttss2si
+; CHECK: and {{.*}}, 1
+; CHECK: movzx [[REG:.*]],
+; CHECK-NEXT: shl [[REG]], 31
+; CHECK-NEXT: sar [[REG]], 31
+
+; Test fptosi double to i1.
+define internal i32 @testFptosiDouble(double %arg) {
+entry:
+  %arg_i1 = fptosi double %arg to i1
+  %result = sext i1 %arg_i1 to i32
+  ret i32 %result
+}
+; CHECK-LABEL: testFptosiDouble
+; CHECK: cvttsd2si
+; CHECK: and {{.*}}, 1
+; CHECK: movzx [[REG:.*]],
+; CHECK-NEXT: shl [[REG]], 31
+; CHECK-NEXT: sar [[REG]], 31
+
+; ERRORS-NOT: ICE translation error
+; DUMP-NOT: SZ