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);
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);
}
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 {
_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
// 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);
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) {
// 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;
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);
}
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);
}
; 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:
; 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:
; 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:
; 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:
; 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:
; 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:
; CHECK: mul
; CHECK: add
; CHECK: add
-; CHECK: ret
;
; OPTM1-LABEL: mul64BitSigned
; OPTM1: imul
; OPTM1: mul
; OPTM1: add
; OPTM1: add
-; OPTM1: ret
define internal i64 @mul64BitUnsigned(i64 %a, i64 %b) {
entry:
; CHECK: mul
; CHECK: add
; CHECK: add
-; CHECK: ret
;
; OPTM1-LABEL: mul64BitUnsigned
; OPTM1: imul
; OPTM1: mul
; OPTM1: add
; OPTM1: add
-; OPTM1: ret
define internal i64 @div64BitSigned(i64 %a, i64 %b) {
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:
; 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:
; 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:
; 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:
; 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:
}
; 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:
; 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:
; 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:
}
; 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:
; 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:
; 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:
; 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:
; 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:
+++ /dev/null
-; 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
--- /dev/null
+; 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