Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1713,24 +1713,25 @@ Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1); - // ( A << (X - 1) ) | ((A > 0) zext to iX) - // <=> A < 0 | A > 0 - // <=> (A != 0) zext to iX - Value *A; - ICmpInst::Predicate Pred; - - auto MatchOrZExtICmp = [&](Value *Op0, Value *Op1) -> bool { - return match(Op0, m_LShr(m_Value(A), m_SpecificInt(Op0->getType()->getScalarSizeInBits() - 1))) && - match(Op1, m_ZExt(m_ICmp(Pred, m_Specific(A), m_Zero()))); + // fold and/or(A << X - 1, zext(icmp)) (X is the scalar bits of the type of A) + // -> and/or(zext(A < 0), zext(icmp)) + // -> zext(and/or(A < 0, icmp)) + auto MatchBitwiseICmpZeroWithICmp = [&](Value *&Op0, Value *Op1) { + ICmpInst::Predicate Pred; + Value *A; + bool IsMatched = + match(Op0, m_LShr(m_Value(A), + m_SpecificInt(Op0->getType()->getScalarSizeInBits() - 1))) && + match(Op1, m_ZExt(m_ICmp(Pred, m_Value(), m_Value()))); + if (IsMatched) { + Op0 = Builder.CreateZExt( + Builder.CreateICmpSLT(A, Constant::getNullValue(A->getType())), + A->getType()); + } }; - if (LogicOpc == Instruction::Or && - (MatchOrZExtICmp(Op0, Op1) || MatchOrZExtICmp(Op1, Op0)) && - Pred == ICmpInst::ICMP_SGT) { - Value *Cmp = - Builder.CreateICmpNE(A, Constant::getNullValue(A->getType())); - return new ZExtInst(Cmp, A->getType()); - } + MatchBitwiseICmpZeroWithICmp(Op0, Op1); + MatchBitwiseICmpZeroWithICmp(Op1, Op0); CastInst *Cast0 = dyn_cast(Op0); if (!Cast0) Index: llvm/test/Transforms/InstCombine/and-or-icmps.ll =================================================================== --- llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -2571,8 +2571,8 @@ define i32 @icmp_slt_0_or_icmp_sgt_0_i32(i32 %x) { ; CHECK-LABEL: @icmp_slt_0_or_icmp_sgt_0_i32( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i32 [[X:%.*]], 0 -; CHECK-NEXT: [[E:%.*]] = zext i1 [[TMP1]] to i32 +; CHECK-NEXT: [[E1:%.*]] = icmp ne i32 [[X:%.*]], 0 +; CHECK-NEXT: [[E:%.*]] = zext i1 [[E1]] to i32 ; CHECK-NEXT: ret i32 [[E]] ; %A = icmp slt i32 %x, 0 @@ -2585,8 +2585,8 @@ define i64 @icmp_slt_0_or_icmp_sgt_0_i64(i64 %x) { ; CHECK-LABEL: @icmp_slt_0_or_icmp_sgt_0_i64( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ne i64 [[X:%.*]], 0 -; CHECK-NEXT: [[E:%.*]] = zext i1 [[TMP1]] to i64 +; CHECK-NEXT: [[E1:%.*]] = icmp ne i64 [[X:%.*]], 0 +; CHECK-NEXT: [[E:%.*]] = zext i1 [[E1]] to i64 ; CHECK-NEXT: ret i64 [[E]] ; %A = icmp slt i64 %x, 0 @@ -2655,8 +2655,8 @@ define <2 x i64> @icmp_slt_0_or_icmp_sgt_0_i64x2(<2 x i64> %x) { ; CHECK-LABEL: @icmp_slt_0_or_icmp_sgt_0_i64x2( -; CHECK-NEXT: [[TMP1:%.*]] = icmp ne <2 x i64> [[X:%.*]], zeroinitializer -; CHECK-NEXT: [[E:%.*]] = zext <2 x i1> [[TMP1]] to <2 x i64> +; CHECK-NEXT: [[E1:%.*]] = icmp ne <2 x i64> [[X:%.*]], zeroinitializer +; CHECK-NEXT: [[E:%.*]] = zext <2 x i1> [[E1]] to <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[E]] ; %A = icmp slt <2 x i64> %x, @@ -2668,10 +2668,8 @@ } define <2 x i64> @icmp_slt_0_or_icmp_sgt_0_i64x2_fail(<2 x i64> %x) { ; CHECK-LABEL: @icmp_slt_0_or_icmp_sgt_0_i64x2_fail( -; CHECK-NEXT: [[B:%.*]] = icmp sgt <2 x i64> [[X:%.*]], -; CHECK-NEXT: [[C:%.*]] = lshr <2 x i64> [[X]], -; CHECK-NEXT: [[D:%.*]] = zext <2 x i1> [[B]] to <2 x i64> -; CHECK-NEXT: [[E:%.*]] = or <2 x i64> [[C]], [[D]] +; CHECK-NEXT: [[E1:%.*]] = icmp ugt <2 x i64> [[X:%.*]], +; CHECK-NEXT: [[E:%.*]] = zext <2 x i1> [[E1]] to <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[E]] ; %B = icmp sgt <2 x i64> %x, @@ -2684,11 +2682,7 @@ define i32 @icmps_slt_0_and_icmp_sge_neg1_i32(i32 %x) { ; CHECK-LABEL: @icmps_slt_0_and_icmp_sge_neg1_i32( -; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -1 -; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 -; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 -; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 0 ; %A = icmp sgt i32 %x, -1 %B = zext i1 %A to i32 @@ -2699,11 +2693,7 @@ define i32 @icmps_slt_0_or_icmp_sge_neg1_i32(i32 %x) { ; CHECK-LABEL: @icmps_slt_0_or_icmp_sge_neg1_i32( -; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -2 -; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 -; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 -; CHECK-NEXT: [[D:%.*]] = or i32 [[C]], [[B]] -; CHECK-NEXT: ret i32 [[D]] +; CHECK-NEXT: ret i32 1 ; %A = icmp sge i32 %x, -1 %B = zext i1 %A to i32 @@ -2714,10 +2704,8 @@ define i64 @icmps_slt_0_and_icmp_sge_neg1_i64(i64 %x) { ; CHECK-LABEL: @icmps_slt_0_and_icmp_sge_neg1_i64( -; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -2 -; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 -; CHECK-NEXT: [[C:%.*]] = lshr i64 [[X]], 63 -; CHECK-NEXT: [[D:%.*]] = and i64 [[C]], [[B]] +; CHECK-NEXT: [[D1:%.*]] = icmp eq i64 [[X:%.*]], -1 +; CHECK-NEXT: [[D:%.*]] = zext i1 [[D1]] to i64 ; CHECK-NEXT: ret i64 [[D]] ; %A = icmp sge i64 %x, -1 @@ -2729,10 +2717,8 @@ define i64 @icmps_slt_0_and_icmp_sge_neg1_i64_fail0(i64 %x) { ; CHECK-LABEL: @icmps_slt_0_and_icmp_sge_neg1_i64_fail0( -; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -2 -; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 -; CHECK-NEXT: [[C:%.*]] = lshr i64 [[X]], 63 -; CHECK-NEXT: [[D:%.*]] = and i64 [[C]], [[B]] +; CHECK-NEXT: [[D1:%.*]] = icmp eq i64 [[X:%.*]], -1 +; CHECK-NEXT: [[D:%.*]] = zext i1 [[D1]] to i64 ; CHECK-NEXT: ret i64 [[D]] ; %A = icmp sge i64 %x, -1 @@ -2744,10 +2730,8 @@ define i64 @icmps_slt_0_and_icmp_sge_neg1_i64_fail1(i64 %x) { ; CHECK-LABEL: @icmps_slt_0_and_icmp_sge_neg1_i64_fail1( -; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -2 -; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 -; CHECK-NEXT: [[C1:%.*]] = lshr i64 [[X]], 63 -; CHECK-NEXT: [[D:%.*]] = and i64 [[C1]], [[B]] +; CHECK-NEXT: [[D2:%.*]] = icmp eq i64 [[X:%.*]], -1 +; CHECK-NEXT: [[D:%.*]] = zext i1 [[D2]] to i64 ; CHECK-NEXT: ret i64 [[D]] ; %A = icmp sge i64 %x, -1 @@ -2774,11 +2758,7 @@ define i64 @icmps_slt_0_and_icmp_sge_neg1_i64_fail3(i64 %x) { ; CHECK-LABEL: @icmps_slt_0_and_icmp_sge_neg1_i64_fail3( -; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -1 -; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 -; CHECK-NEXT: [[C:%.*]] = lshr i64 [[X]], 63 -; CHECK-NEXT: [[D:%.*]] = and i64 [[C]], [[B]] -; CHECK-NEXT: ret i64 [[D]] +; CHECK-NEXT: ret i64 0 ; %A = icmp sgt i64 %x, -1 %B = zext i1 %A to i64 @@ -2789,10 +2769,8 @@ define <2 x i32> @icmps_slt_0_and_icmp_sge_neg1_i32x2(<2 x i32> %x) { ; CHECK-LABEL: @icmps_slt_0_and_icmp_sge_neg1_i32x2( -; CHECK-NEXT: [[A:%.*]] = icmp sgt <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[B:%.*]] = zext <2 x i1> [[A]] to <2 x i32> -; CHECK-NEXT: [[C:%.*]] = lshr <2 x i32> [[X]], -; CHECK-NEXT: [[D:%.*]] = and <2 x i32> [[C]], [[B]] +; CHECK-NEXT: [[D1:%.*]] = icmp eq <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[D:%.*]] = zext <2 x i1> [[D1]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[D]] ; %A = icmp sge <2 x i32> %x, @@ -2804,10 +2782,8 @@ define <2 x i32> @icmps_slt_0_and_icmp_sge_neg2_i32x2(<2 x i32> %x) { ; CHECK-LABEL: @icmps_slt_0_and_icmp_sge_neg2_i32x2( -; CHECK-NEXT: [[A:%.*]] = icmp sgt <2 x i32> [[X:%.*]], -; CHECK-NEXT: [[B:%.*]] = zext <2 x i1> [[A]] to <2 x i32> -; CHECK-NEXT: [[C:%.*]] = lshr <2 x i32> [[X]], -; CHECK-NEXT: [[D:%.*]] = and <2 x i32> [[C]], [[B]] +; CHECK-NEXT: [[D1:%.*]] = icmp ugt <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[D:%.*]] = zext <2 x i1> [[D1]] to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[D]] ; %A = icmp sge <2 x i32> %x,