From: Jim Stichnoth Date: Mon, 8 Sep 2014 18:19:21 +0000 (-0700) Subject: Subzero: Be more strict about i1 calculations. X-Git-Tag: android-x86-7.1-r1~148^2~1103 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=3ef786f3ae36599429990e4146941b4f793cb082;p=android-x86%2Fexternal-swiftshader.git Subzero: Be more strict about i1 calculations. 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 --- diff --git a/crosstest/test_arith_main.cpp b/crosstest/test_arith_main.cpp index 84bc6b72e..16b2c5e10 100644 --- a/crosstest/test_arith_main.cpp +++ b/crosstest/test_arith_main.cpp @@ -347,6 +347,7 @@ int main(int argc, char **argv) { size_t Passes = 0; size_t Failures = 0; + testsInt(TotalTests, Passes, Failures); testsInt(TotalTests, Passes, Failures); testsInt(TotalTests, Passes, Failures); testsInt(TotalTests, Passes, Failures); diff --git a/src/IceGlobalContext.cpp b/src/IceGlobalContext.cpp index 5f9b62012..f3982554b 100644 --- a/src/IceGlobalContext.cpp +++ b/src/IceGlobalContext.cpp @@ -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); } diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp index 6fced4d4a..756508ec4 100644 --- a/src/IceTargetLoweringX8632.cpp +++ b/src/IceTargetLoweringX8632.cpp @@ -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); } diff --git a/tests_lit/llvm2ice_tests/64bit.pnacl.ll b/tests_lit/llvm2ice_tests/64bit.pnacl.ll index c4005c918..d8c6e6bb3 100644 --- a/tests_lit/llvm2ice_tests/64bit.pnacl.ll +++ b/tests_lit/llvm2ice_tests/64bit.pnacl.ll @@ -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 index e616e98a8..000000000 --- a/tests_lit/llvm2ice_tests/sext_zext_i1.ll +++ /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 index 000000000..6d623cc68 --- /dev/null +++ b/tests_lit/llvm2ice_tests/test_i1.ll @@ -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