diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index aa18c7e73ad5f..66e2b6c72cce4 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -5390,35 +5390,6 @@ Instruction *InstCombinerImpl::foldICmpEquality(ICmpInst &I) { return new ICmpInst(Pred, A, Builder.CreateTrunc(B, A->getType())); } - // Test if 2 values have different or same signbits: - // (X u>> BitWidth - 1) == zext (Y s> -1) --> (X ^ Y) < 0 - // (X u>> BitWidth - 1) != zext (Y s> -1) --> (X ^ Y) > -1 - // (X s>> BitWidth - 1) == sext (Y s> -1) --> (X ^ Y) < 0 - // (X s>> BitWidth - 1) != sext (Y s> -1) --> (X ^ Y) > -1 - Instruction *ExtI; - if (match(Op1, m_CombineAnd(m_Instruction(ExtI), m_ZExtOrSExt(m_Value(A)))) && - (Op0->hasOneUse() || Op1->hasOneUse())) { - unsigned OpWidth = Op0->getType()->getScalarSizeInBits(); - Instruction *ShiftI; - Value *X, *Y; - ICmpInst::Predicate Pred2; - if (match(Op0, m_CombineAnd(m_Instruction(ShiftI), - m_Shr(m_Value(X), - m_SpecificIntAllowUndef(OpWidth - 1)))) && - match(A, m_ICmp(Pred2, m_Value(Y), m_AllOnes())) && - Pred2 == ICmpInst::ICMP_SGT && X->getType() == Y->getType()) { - unsigned ExtOpc = ExtI->getOpcode(); - unsigned ShiftOpc = ShiftI->getOpcode(); - if ((ExtOpc == Instruction::ZExt && ShiftOpc == Instruction::LShr) || - (ExtOpc == Instruction::SExt && ShiftOpc == Instruction::AShr)) { - Value *Xor = Builder.CreateXor(X, Y, "xor.signbits"); - Value *R = (Pred == ICmpInst::ICMP_EQ) ? Builder.CreateIsNeg(Xor) - : Builder.CreateIsNotNeg(Xor); - return replaceInstUsesWith(I, R); - } - } - } - // (A >> C) == (B >> C) --> (A^B) u< (1 << C) // For lshr and ashr pairs. const APInt *AP1, *AP2; @@ -7194,6 +7165,33 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) { if (Instruction *R = processUMulZExtIdiom(I, Op1, Op0, *this)) return R; } + + Value *X, *Y; + // Signbit test folds + // Fold (X u>> BitWidth - 1 Pred ZExt(i1)) --> X s< 0 Pred i1 + // Fold (X s>> BitWidth - 1 Pred SExt(i1)) --> X s< 0 Pred i1 + Instruction *ExtI; + if ((I.isUnsigned() || I.isEquality()) && + match(Op1, + m_CombineAnd(m_Instruction(ExtI), m_ZExtOrSExt(m_Value(Y)))) && + Y->getType()->getScalarSizeInBits() == 1 && + (Op0->hasOneUse() || Op1->hasOneUse())) { + unsigned OpWidth = Op0->getType()->getScalarSizeInBits(); + Instruction *ShiftI; + if (match(Op0, m_CombineAnd(m_Instruction(ShiftI), + m_Shr(m_Value(X), m_SpecificIntAllowUndef( + OpWidth - 1))))) { + unsigned ExtOpc = ExtI->getOpcode(); + unsigned ShiftOpc = ShiftI->getOpcode(); + if ((ExtOpc == Instruction::ZExt && ShiftOpc == Instruction::LShr) || + (ExtOpc == Instruction::SExt && ShiftOpc == Instruction::AShr)) { + Value *SLTZero = + Builder.CreateICmpSLT(X, Constant::getNullValue(X->getType())); + Value *Cmp = Builder.CreateICmp(Pred, SLTZero, Y, I.getName()); + return replaceInstUsesWith(I, Cmp); + } + } + } } if (Instruction *Res = foldICmpEquality(I)) diff --git a/llvm/test/Transforms/InstCombine/icmp-shr.ll b/llvm/test/Transforms/InstCombine/icmp-shr.ll index f4dfa2edfa177..1067897420705 100644 --- a/llvm/test/Transforms/InstCombine/icmp-shr.ll +++ b/llvm/test/Transforms/InstCombine/icmp-shr.ll @@ -1302,9 +1302,9 @@ define i1 @lshr_neg_sgt_zero(i8 %x) { define i1 @exactly_one_set_signbit(i8 %x, i8 %y) { ; CHECK-LABEL: @exactly_one_set_signbit( -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[XOR_SIGNBITS]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TMP2]] ; %xsign = lshr i8 %x, 7 %ypos = icmp sgt i8 %y, -1 @@ -1317,9 +1317,9 @@ define i1 @exactly_one_set_signbit_use1(i8 %x, i8 %y) { ; CHECK-LABEL: @exactly_one_set_signbit_use1( ; CHECK-NEXT: [[XSIGN:%.*]] = lshr i8 [[X:%.*]], 7 ; CHECK-NEXT: call void @use(i8 [[XSIGN]]) -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[XOR_SIGNBITS]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TMP2]] ; %xsign = lshr i8 %x, 7 call void @use(i8 %xsign) @@ -1331,9 +1331,9 @@ define i1 @exactly_one_set_signbit_use1(i8 %x, i8 %y) { define <2 x i1> @same_signbit(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @same_signbit( -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i8> [[XOR_SIGNBITS]], -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R1:%.*]] = icmp sgt <2 x i8> [[TMP1]], +; CHECK-NEXT: ret <2 x i1> [[R1]] ; %xsign = lshr <2 x i8> %x, %ypos = icmp sgt <2 x i8> %y, @@ -1347,9 +1347,9 @@ define i1 @same_signbit_use2(i8 %x, i8 %y) { ; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YPOSZ:%.*]] = zext i1 [[YPOS]] to i8 ; CHECK-NEXT: call void @use(i8 [[YPOSZ]]) -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor i8 [[X:%.*]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[XOR_SIGNBITS]], -1 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], [[Y]] +; CHECK-NEXT: [[R1:%.*]] = icmp sgt i8 [[TMP1]], -1 +; CHECK-NEXT: ret i1 [[R1]] ; %xsign = lshr i8 %x, 7 %ypos = icmp sgt i8 %y, -1 @@ -1382,9 +1382,10 @@ define i1 @same_signbit_use3(i8 %x, i8 %y) { define <2 x i1> @same_signbit_poison_elts(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @same_signbit_poison_elts( -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i8> [[XOR_SIGNBITS]], -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt <2 x i8> [[Y:%.*]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[R1:%.*]] = xor <2 x i1> [[TMP1]], [[YPOS]] +; CHECK-NEXT: ret <2 x i1> [[R1]] ; %xsign = lshr <2 x i8> %x, %ypos = icmp sgt <2 x i8> %y, @@ -1397,11 +1398,10 @@ define <2 x i1> @same_signbit_poison_elts(<2 x i8> %x, <2 x i8> %y) { define i1 @same_signbit_wrong_type(i8 %x, i32 %y) { ; CHECK-LABEL: @same_signbit_wrong_type( -; CHECK-NEXT: [[XSIGN:%.*]] = lshr i8 [[X:%.*]], 7 ; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt i32 [[Y:%.*]], -1 -; CHECK-NEXT: [[YPOSZ:%.*]] = zext i1 [[YPOS]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[XSIGN]], [[YPOSZ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0 +; CHECK-NEXT: [[R1:%.*]] = xor i1 [[TMP1]], [[YPOS]] +; CHECK-NEXT: ret i1 [[R1]] ; %xsign = lshr i8 %x, 7 %ypos = icmp sgt i32 %y, -1 @@ -1450,11 +1450,9 @@ define i1 @exactly_one_set_signbit_wrong_shr(i8 %x, i8 %y) { define i1 @exactly_one_set_signbit_wrong_pred(i8 %x, i8 %y) { ; CHECK-LABEL: @exactly_one_set_signbit_wrong_pred( -; CHECK-NEXT: [[XSIGN:%.*]] = lshr i8 [[X:%.*]], 7 -; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt i8 [[Y:%.*]], -1 -; CHECK-NEXT: [[YPOSZ:%.*]] = zext i1 [[YPOS]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[XSIGN]], [[YPOSZ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[Y:%.*]], [[X:%.*]] +; CHECK-NEXT: [[R1:%.*]] = icmp slt i8 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[R1]] ; %xsign = lshr i8 %x, 7 %ypos = icmp sgt i8 %y, -1 @@ -1465,9 +1463,9 @@ define i1 @exactly_one_set_signbit_wrong_pred(i8 %x, i8 %y) { define i1 @exactly_one_set_signbit_signed(i8 %x, i8 %y) { ; CHECK-LABEL: @exactly_one_set_signbit_signed( -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[XOR_SIGNBITS]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TMP2]] ; %xsign = ashr i8 %x, 7 %ypos = icmp sgt i8 %y, -1 @@ -1480,9 +1478,9 @@ define i1 @exactly_one_set_signbit_use1_signed(i8 %x, i8 %y) { ; CHECK-LABEL: @exactly_one_set_signbit_use1_signed( ; CHECK-NEXT: [[XSIGN:%.*]] = ashr i8 [[X:%.*]], 7 ; CHECK-NEXT: call void @use(i8 [[XSIGN]]) -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[XOR_SIGNBITS]], 0 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X]], [[Y:%.*]] +; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i8 [[TMP1]], 0 +; CHECK-NEXT: ret i1 [[TMP2]] ; %xsign = ashr i8 %x, 7 call void @use(i8 %xsign) @@ -1494,9 +1492,9 @@ define i1 @exactly_one_set_signbit_use1_signed(i8 %x, i8 %y) { define <2 x i1> @same_signbit_signed(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @same_signbit_signed( -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i8> [[XOR_SIGNBITS]], -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R1:%.*]] = icmp sgt <2 x i8> [[TMP1]], +; CHECK-NEXT: ret <2 x i1> [[R1]] ; %xsign = ashr <2 x i8> %x, %ypos = icmp sgt <2 x i8> %y, @@ -1510,9 +1508,9 @@ define i1 @same_signbit_use2_signed(i8 %x, i8 %y) { ; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt i8 [[Y:%.*]], -1 ; CHECK-NEXT: [[YPOSZ:%.*]] = sext i1 [[YPOS]] to i8 ; CHECK-NEXT: call void @use(i8 [[YPOSZ]]) -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor i8 [[X:%.*]], [[Y]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[XOR_SIGNBITS]], -1 -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[X:%.*]], [[Y]] +; CHECK-NEXT: [[R1:%.*]] = icmp sgt i8 [[TMP1]], -1 +; CHECK-NEXT: ret i1 [[R1]] ; %xsign = ashr i8 %x, 7 %ypos = icmp sgt i8 %y, -1 @@ -1545,9 +1543,10 @@ define i1 @same_signbit_use3_signed(i8 %x, i8 %y) { define <2 x i1> @same_signbit_poison_elts_signed(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @same_signbit_poison_elts_signed( -; CHECK-NEXT: [[XOR_SIGNBITS:%.*]] = xor <2 x i8> [[X:%.*]], [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = icmp sgt <2 x i8> [[XOR_SIGNBITS]], -; CHECK-NEXT: ret <2 x i1> [[R]] +; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt <2 x i8> [[Y:%.*]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <2 x i8> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[R1:%.*]] = xor <2 x i1> [[TMP1]], [[YPOS]] +; CHECK-NEXT: ret <2 x i1> [[R1]] ; %xsign = ashr <2 x i8> %x, %ypos = icmp sgt <2 x i8> %y, @@ -1560,11 +1559,10 @@ define <2 x i1> @same_signbit_poison_elts_signed(<2 x i8> %x, <2 x i8> %y) { define i1 @same_signbit_wrong_type_signed(i8 %x, i32 %y) { ; CHECK-LABEL: @same_signbit_wrong_type_signed( -; CHECK-NEXT: [[XSIGN:%.*]] = ashr i8 [[X:%.*]], 7 ; CHECK-NEXT: [[YPOS:%.*]] = icmp sgt i32 [[Y:%.*]], -1 -; CHECK-NEXT: [[YPOSZ:%.*]] = sext i1 [[YPOS]] to i8 -; CHECK-NEXT: [[R:%.*]] = icmp ne i8 [[XSIGN]], [[YPOSZ]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i8 [[X:%.*]], 0 +; CHECK-NEXT: [[R1:%.*]] = xor i1 [[TMP1]], [[YPOS]] +; CHECK-NEXT: ret i1 [[R1]] ; %xsign = ashr i8 %x, 7 %ypos = icmp sgt i32 %y, -1 @@ -1589,3 +1587,80 @@ define i1 @exactly_one_set_signbit_wrong_shamt_signed(i8 %x, i8 %y) { %r = icmp eq i8 %xsign, %yposz ret i1 %r } + +define i1 @slt_zero_ult_i1(i32 %a, i1 %b) { +; CHECK-LABEL: @slt_zero_ult_i1( +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[A:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[B:%.*]], true +; CHECK-NEXT: [[CMP21:%.*]] = and i1 [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret i1 [[CMP21]] +; + %conv = zext i1 %b to i32 + %cmp1 = lshr i32 %a, 31 + %cmp2 = icmp ult i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_ult_i1_fail1(i32 %a, i1 %b) { +; CHECK-LABEL: @slt_zero_ult_i1_fail1( +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[B:%.*]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = lshr i32 [[A:%.*]], 30 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[CMP1]], [[CONV]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %conv = zext i1 %b to i32 + %cmp1 = lshr i32 %a, 30 + %cmp2 = icmp ult i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_ult_i1_fail2(i32 %a, i1 %b) { +; CHECK-LABEL: @slt_zero_ult_i1_fail2( +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[B:%.*]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = ashr i32 [[A:%.*]], 31 +; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i32 [[CMP1]], [[CONV]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %conv = zext i1 %b to i32 + %cmp1 = ashr i32 %a, 31 + %cmp2 = icmp ult i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_slt_i1_fail(i32 %a, i1 %b) { +; CHECK-LABEL: @slt_zero_slt_i1_fail( +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[A:%.*]], 0 +; CHECK-NEXT: [[TMP2:%.*]] = xor i1 [[B:%.*]], true +; CHECK-NEXT: [[CMP21:%.*]] = and i1 [[TMP1]], [[TMP2]] +; CHECK-NEXT: ret i1 [[CMP21]] +; + %conv = zext i1 %b to i32 + %cmp1 = lshr i32 %a, 31 + %cmp2 = icmp slt i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_eq_i1_signed(i32 %a, i1 %b) { +; CHECK-LABEL: @slt_zero_eq_i1_signed( +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A:%.*]], -1 +; CHECK-NEXT: [[CMP21:%.*]] = xor i1 [[TMP1]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[CMP21]] +; + %conv = sext i1 %b to i32 + %cmp1 = ashr i32 %a, 31 + %cmp2 = icmp eq i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_eq_i1_fail_signed(i32 %a, i1 %b) { +; CHECK-LABEL: @slt_zero_eq_i1_fail_signed( +; CHECK-NEXT: [[CONV:%.*]] = sext i1 [[B:%.*]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = lshr i32 [[A:%.*]], 31 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[CMP1]], [[CONV]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %conv = sext i1 %b to i32 + %cmp1 = lshr i32 %a, 31 + %cmp2 = icmp eq i32 %conv, %cmp1 + ret i1 %cmp2 +} diff --git a/llvm/test/Transforms/InstCombine/icmp-xor-signbit.ll b/llvm/test/Transforms/InstCombine/icmp-xor-signbit.ll index 29a18ebbdd94e..d08dca225328f 100644 --- a/llvm/test/Transforms/InstCombine/icmp-xor-signbit.ll +++ b/llvm/test/Transforms/InstCombine/icmp-xor-signbit.ll @@ -217,3 +217,107 @@ define <2 x i1> @negative_simplify_splat(<4 x i8> %x) { ret <2 x i1> %c } +define i1 @slt_zero_eq_i1(i32 %a, i1 %b) { +; CHECK-LABEL: @slt_zero_eq_i1( +; CHECK-NEXT: [[TMP1:%.*]] = icmp sgt i32 [[A:%.*]], -1 +; CHECK-NEXT: [[CMP21:%.*]] = xor i1 [[TMP1]], [[B:%.*]] +; CHECK-NEXT: ret i1 [[CMP21]] +; + %conv = zext i1 %b to i32 + %cmp1 = lshr i32 %a, 31 + %cmp2 = icmp eq i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_eq_i1_fail(i32 %a, i1 %b) { +; CHECK-LABEL: @slt_zero_eq_i1_fail( +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[B:%.*]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = ashr i32 [[A:%.*]], 31 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[CMP1]], [[CONV]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %conv = zext i1 %b to i32 + %cmp1 = ashr i32 %a, 31 + %cmp2 = icmp eq i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_eq_ne_0(i32 %a) { +; CHECK-LABEL: @slt_zero_eq_ne_0( +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[A:%.*]], 1 +; CHECK-NEXT: ret i1 [[TMP1]] +; + %cmp = icmp ne i32 %a, 0 + %conv = zext i1 %cmp to i32 + %cmp1 = lshr i32 %a, 31 + %cmp2 = icmp eq i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_ne_ne_0(i32 %a) { +; CHECK-LABEL: @slt_zero_ne_ne_0( +; CHECK-NEXT: [[CMP21:%.*]] = icmp sgt i32 [[A:%.*]], 0 +; CHECK-NEXT: ret i1 [[CMP21]] +; + %cmp = icmp ne i32 %a, 0 + %conv = zext i1 %cmp to i32 + %cmp1 = lshr i32 %a, 31 + %cmp2 = icmp ne i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define <4 x i1> @slt_zero_eq_ne_0_vec(<4 x i32> %a) { +; CHECK-LABEL: @slt_zero_eq_ne_0_vec( +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt <4 x i32> [[A:%.*]], +; CHECK-NEXT: ret <4 x i1> [[TMP1]] +; + %cmp = icmp ne <4 x i32> %a, zeroinitializer + %conv = zext <4 x i1> %cmp to <4 x i32> + %cmp1 = lshr <4 x i32> %a, + %cmp2 = icmp eq <4 x i32> %conv, %cmp1 + ret <4 x i1> %cmp2 +} + +define i1 @slt_zero_ne_ne_b(i32 %a, i32 %b) { +; CHECK-LABEL: @slt_zero_ne_ne_b( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], [[B:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i32 [[A]], 0 +; CHECK-NEXT: [[CMP21:%.*]] = xor i1 [[TMP1]], [[CMP]] +; CHECK-NEXT: ret i1 [[CMP21]] +; + %cmp = icmp ne i32 %a, %b + %conv = zext i1 %cmp to i32 + %cmp1 = lshr i32 %a, 31 + %cmp2 = icmp ne i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_eq_ne_0_fail1(i32 %a) { +; CHECK-LABEL: @slt_zero_eq_ne_0_fail1( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = ashr i32 [[A]], 31 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[CMP1]], [[CONV]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %cmp = icmp ne i32 %a, 0 + %conv = zext i1 %cmp to i32 + %cmp1 = ashr i32 %a, 31 + %cmp2 = icmp eq i32 %conv, %cmp1 + ret i1 %cmp2 +} + +define i1 @slt_zero_eq_ne_0_fail2(i32 %a) { +; CHECK-LABEL: @slt_zero_eq_ne_0_fail2( +; CHECK-NEXT: [[CMP:%.*]] = icmp ne i32 [[A:%.*]], 0 +; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 +; CHECK-NEXT: [[CMP1:%.*]] = lshr i32 [[A]], 30 +; CHECK-NEXT: [[CMP2:%.*]] = icmp eq i32 [[CMP1]], [[CONV]] +; CHECK-NEXT: ret i1 [[CMP2]] +; + %cmp = icmp ne i32 %a, 0 + %conv = zext i1 %cmp to i32 + %cmp1 = lshr i32 %a, 30 + %cmp2 = icmp eq i32 %conv, %cmp1 + ret i1 %cmp2 +}