Subzero: Fix sext/zext lowering with i1 source operands. Also declare a few variables as Constant* instead of Operand* when they hold the result of Ctx->getConstantInt(), to be consistent with the rest of the code. BUG= none R=jvoung@chromium.org Review URL: https://codereview.chromium.org/541093002
diff --git a/src/IceTargetLoweringX8632.cpp b/src/IceTargetLoweringX8632.cpp index e23e5ad..7b97758 100644 --- a/src/IceTargetLoweringX8632.cpp +++ b/src/IceTargetLoweringX8632.cpp
@@ -1916,22 +1916,7 @@ // but we're unlikely to see something like that in the bitcode that // the optimizer wouldn't have already taken care of. Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); - if (Dest->getType() == IceType_i64) { - // t1=movsx src; t2=t1; t2=sar t2, 31; dst.lo=t1; dst.hi=t2 - Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); - Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); - Variable *T_Lo = makeReg(DestLo->getType()); - if (Src0RM->getType() == IceType_i32) - _mov(T_Lo, Src0RM); - else - _movsx(T_Lo, Src0RM); - _mov(DestLo, T_Lo); - Variable *T_Hi = NULL; - Constant *Shift = Ctx->getConstantInt(IceType_i32, 31); - _mov(T_Hi, T_Lo); - _sar(T_Hi, Shift); - _mov(DestHi, T_Hi); - } else if (isVectorType(Dest->getType())) { + if (isVectorType(Dest->getType())) { Type DestTy = Dest->getType(); if (DestTy == IceType_v16i8) { // onemask = materialize(1,1,...); dst = (src & onemask) > 0 @@ -1953,9 +1938,39 @@ _psra(T, ShiftConstant); _movp(Dest, T); } + } else if (Dest->getType() == IceType_i64) { + // t1=movsx src; t2=t1; t2=sar t2, 31; dst.lo=t1; dst.hi=t2 + Constant *Shift = Ctx->getConstantInt(IceType_i32, 31); + Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); + Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); + Variable *T_Lo = makeReg(DestLo->getType()); + if (Src0RM->getType() == IceType_i32) { + _mov(T_Lo, Src0RM); + } else if (Src0RM->getType() == IceType_i1) { + _mov(T_Lo, Src0RM); + _shl(T_Lo, Shift); + _sar(T_Lo, Shift); + } else { + _movsx(T_Lo, Src0RM); + } + _mov(DestLo, T_Lo); + Variable *T_Hi = NULL; + _mov(T_Hi, T_Lo); + _sar(T_Hi, Shift); + _mov(DestHi, T_Hi); + } else if (Src0RM->getType() == IceType_i1) { + // t1 = src + // shl t1, dst_bitwidth - 1 + // sar t1, dst_bitwidth - 1 + // 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); + _shl(T, ShiftAmount); + _sar(T, ShiftAmount); + _mov(Dest, T); } else { - // TODO: Sign-extend an i1 via "shl reg, 31; sar reg, 31", and - // also copy to the high operand of a 64-bit variable. // t1 = movsx src; dst = t1 Variable *T = makeReg(Dest->getType()); _movsx(T, Src0RM); @@ -1965,26 +1980,7 @@ } case InstCast::Zext: { Operand *Src0RM = legalize(Inst->getSrc(0), Legal_Reg | Legal_Mem); - if (Dest->getType() == IceType_i64) { - // t1=movzx src; dst.lo=t1; dst.hi=0 - Constant *Zero = Ctx->getConstantZero(IceType_i32); - Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); - Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); - Variable *Tmp = makeReg(DestLo->getType()); - if (Src0RM->getType() == IceType_i32) - _mov(Tmp, Src0RM); - else - _movzx(Tmp, Src0RM); - _mov(DestLo, Tmp); - _mov(DestHi, Zero); - } else if (Src0RM->getType() == IceType_i1) { - // t = Src0RM; t &= 1; Dest = t - Operand *One = Ctx->getConstantInt(IceType_i32, 1); - Variable *T = makeReg(IceType_i32); - _movzx(T, Src0RM); - _and(T, One); - _mov(Dest, T); - } else if (isVectorType(Dest->getType())) { + if (isVectorType(Dest->getType())) { // onemask = materialize(1,1,...); dest = onemask & src Type DestTy = Dest->getType(); Variable *OneMask = makeVectorOfOnes(DestTy); @@ -1992,6 +1988,30 @@ _movp(T, Src0RM); _pand(T, OneMask); _movp(Dest, T); + } else if (Dest->getType() == IceType_i64) { + // t1=movzx src; dst.lo=t1; dst.hi=0 + Constant *Zero = Ctx->getConstantZero(IceType_i32); + Variable *DestLo = llvm::cast<Variable>(loOperand(Dest)); + Variable *DestHi = llvm::cast<Variable>(hiOperand(Dest)); + 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); + } + _mov(DestLo, Tmp); + _mov(DestHi, Zero); + } else if (Src0RM->getType() == IceType_i1) { + // t = Src0RM; t &= 1; Dest = t + Constant *One = Ctx->getConstantInt(IceType_i32, 1); + Variable *T = makeReg(IceType_i32); + _movzx(T, Src0RM); + _and(T, One); + _mov(Dest, T); } else { // t1 = movzx src; dst = t1 Variable *T = makeReg(Dest->getType()); @@ -3920,7 +3940,7 @@ Src0 = legalize(Src0, Legal_Reg | Legal_Mem, true); for (SizeT I = 0; I < NumCases; ++I) { // TODO(stichnot): Correct lowering for IceType_i64. - Operand *Value = Ctx->getConstantInt(IceType_i32, Inst->getValue(I)); + Constant *Value = Ctx->getConstantInt(IceType_i32, Inst->getValue(I)); _cmp(Src0, Value); _br(InstX8632Br::Br_e, Inst->getLabel(I)); }
diff --git a/tests_lit/llvm2ice_tests/64bit.pnacl.ll b/tests_lit/llvm2ice_tests/64bit.pnacl.ll index c21063b..c4005c9 100644 --- a/tests_lit/llvm2ice_tests/64bit.pnacl.ll +++ b/tests_lit/llvm2ice_tests/64bit.pnacl.ll
@@ -650,6 +650,24 @@ ; OPTM1: movsx ; OPTM1: 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 +; +; OPTM1-LABEL: sext1To64 +; OPTM1: mov +; OPTM1: shl {{.*}}, 31 +; OPTM1: sar {{.*}}, 31 +; OPTM1: sar {{.*}}, 31 + define internal i64 @zext32To64(i32 %a) { entry: %conv = zext i32 %a to i64 @@ -698,11 +716,11 @@ ret i64 %conv } ; CHECK-LABEL: zext1To64 -; CHECK: movzx +; CHECK: and {{.*}}, 1 ; CHECK: mov {{.*}}, 0 ; ; OPTM1-LABEL: zext1To64 -; OPTM1: movzx +; OPTM1: and {{.*}}, 1 ; OPTM1: mov {{.*}}, 0 define internal void @icmpEq64(i64 %a, i64 %b, i64 %c, i64 %d) {
diff --git a/tests_lit/llvm2ice_tests/sext_zext_i1.ll b/tests_lit/llvm2ice_tests/sext_zext_i1.ll new file mode 100644 index 0000000..e616e98 --- /dev/null +++ b/tests_lit/llvm2ice_tests/sext_zext_i1.ll
@@ -0,0 +1,96 @@ +; 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