diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 703065280096f..cbdab3e9c5fb9 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2650,6 +2650,12 @@ Instruction *InstCombinerImpl::visitAnd(BinaryOperator &I) { A->getType()->isIntOrIntVectorTy(1)) return SelectInst::Create(A, Constant::getNullValue(Ty), B); + // and(zext(A), B) -> A ? (B & 1) : 0 + if (match(&I, m_c_And(m_OneUse(m_ZExt(m_Value(A))), m_Value(B))) && + A->getType()->isIntOrIntVectorTy(1)) + return SelectInst::Create(A, Builder.CreateAnd(B, ConstantInt::get(Ty, 1)), + Constant::getNullValue(Ty)); + // (-1 + A) & B --> A ? 0 : B where A is 0/1. if (match(&I, m_c_And(m_OneUse(m_Add(m_ZExtOrSelf(m_Value(A)), m_AllOnes())), m_Value(B)))) { diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll index 065dbf261e131..881a9b7ff129d 100644 --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -2769,9 +2769,9 @@ define i64 @icmp_slt_0_and_icmp_sgt_neg1_i64(i64 %x) { define i64 @icmp_slt_0_and_icmp_sge_neg1_i64_fail(i64 %x) { ; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg1_i64_fail( ; CHECK-NEXT: [[A:%.*]] = icmp sgt i64 [[X:%.*]], -2 -; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i64 ; CHECK-NEXT: [[C:%.*]] = lshr i64 [[X]], 62 -; CHECK-NEXT: [[D:%.*]] = and i64 [[C]], [[B]] +; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[C]], 1 +; CHECK-NEXT: [[D:%.*]] = select i1 [[A]], i64 [[TMP1]], i64 0 ; CHECK-NEXT: ret i64 [[D]] ; %A = icmp sge i64 %x, -1 @@ -2871,9 +2871,8 @@ define i32 @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse1(i32 %x) { define i32 @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse2(i32 %x) { ; CHECK-LABEL: @icmp_slt_0_and_icmp_sge_neg2_i32_multiuse2( ; CHECK-NEXT: [[A:%.*]] = icmp sgt i32 [[X:%.*]], -3 -; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 ; CHECK-NEXT: [[C:%.*]] = lshr i32 [[X]], 31 -; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: [[D:%.*]] = select i1 [[A]], i32 [[C]], i32 0 ; CHECK-NEXT: call void @use32(i32 [[C]]) ; CHECK-NEXT: ret i32 [[D]] ; @@ -2923,10 +2922,9 @@ define i32 @icmp_slt_0_or_icmp_eq_100_i32_multiuse_fail1(i32 %x) { define i32 @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_multiuse_fail2(i32 %x, i32 %y) { ; CHECK-LABEL: @icmp_x_slt_0_and_icmp_y_ne_neg2_i32_multiuse_fail2( -; CHECK-NEXT: [[A:%.*]] = icmp ne i32 [[X:%.*]], -2 -; CHECK-NEXT: [[B:%.*]] = zext i1 [[A]] to i32 +; CHECK-NEXT: [[A_NOT:%.*]] = icmp eq i32 [[X:%.*]], -2 ; CHECK-NEXT: [[C:%.*]] = lshr i32 [[Y:%.*]], 31 -; CHECK-NEXT: [[D:%.*]] = and i32 [[C]], [[B]] +; CHECK-NEXT: [[D:%.*]] = select i1 [[A_NOT]], i32 0, i32 [[C]] ; CHECK-NEXT: call void @use32(i32 [[C]]) ; CHECK-NEXT: ret i32 [[D]] ; diff --git a/llvm/test/Transforms/InstCombine/and.ll b/llvm/test/Transforms/InstCombine/and.ll index 0ab404b28fa4d..90f027010e2ae 100644 --- a/llvm/test/Transforms/InstCombine/and.ll +++ b/llvm/test/Transforms/InstCombine/and.ll @@ -2443,8 +2443,8 @@ define i64 @test_and_or_constexpr_infloop() { define i32 @and_zext(i32 %a, i1 %b) { ; CHECK-LABEL: @and_zext( -; CHECK-NEXT: [[MASK:%.*]] = zext i1 [[B:%.*]] to i32 -; CHECK-NEXT: [[R:%.*]] = and i32 [[MASK]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 1 +; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i32 [[TMP1]], i32 0 ; CHECK-NEXT: ret i32 [[R]] ; %mask = zext i1 %b to i32 @@ -2454,8 +2454,8 @@ define i32 @and_zext(i32 %a, i1 %b) { define i32 @and_zext_commuted(i32 %a, i1 %b) { ; CHECK-LABEL: @and_zext_commuted( -; CHECK-NEXT: [[MASK:%.*]] = zext i1 [[B:%.*]] to i32 -; CHECK-NEXT: [[R:%.*]] = and i32 [[MASK]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[A:%.*]], 1 +; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], i32 [[TMP1]], i32 0 ; CHECK-NEXT: ret i32 [[R]] ; %mask = zext i1 %b to i32 @@ -2478,8 +2478,8 @@ define i32 @and_zext_multiuse(i32 %a, i1 %b) { define <2 x i32> @and_zext_vec(<2 x i32> %a, <2 x i1> %b) { ; CHECK-LABEL: @and_zext_vec( -; CHECK-NEXT: [[MASK:%.*]] = zext <2 x i1> [[B:%.*]] to <2 x i32> -; CHECK-NEXT: [[R:%.*]] = and <2 x i32> [[MASK]], [[A:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[A:%.*]], +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[B:%.*]], <2 x i32> [[TMP1]], <2 x i32> zeroinitializer ; CHECK-NEXT: ret <2 x i32> [[R]] ; %mask = zext <2 x i1> %b to <2 x i32> @@ -2490,10 +2490,7 @@ define <2 x i32> @and_zext_vec(<2 x i32> %a, <2 x i1> %b) { ; tests from PR66606 define i32 @and_zext_eq_even(i32 %a) { ; CHECK-LABEL: @and_zext_eq_even( -; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[A:%.*]], 2 -; CHECK-NEXT: [[NOT:%.*]] = zext i1 [[COND]] to i32 -; CHECK-NEXT: [[R:%.*]] = and i32 [[NOT]], [[A]] -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: ret i32 0 ; %cond = icmp eq i32 %a, 2 %not = zext i1 %cond to i32 @@ -2503,10 +2500,7 @@ define i32 @and_zext_eq_even(i32 %a) { define i32 @and_zext_eq_even_commuted(i32 %a) { ; CHECK-LABEL: @and_zext_eq_even_commuted( -; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[A:%.*]], 2 -; CHECK-NEXT: [[NOT:%.*]] = zext i1 [[COND]] to i32 -; CHECK-NEXT: [[R:%.*]] = and i32 [[NOT]], [[A]] -; CHECK-NEXT: ret i32 [[R]] +; CHECK-NEXT: ret i32 0 ; %cond = icmp eq i32 %a, 2 %not = zext i1 %cond to i32 @@ -2517,8 +2511,7 @@ define i32 @and_zext_eq_even_commuted(i32 %a) { define i32 @and_zext_eq_odd(i32 %a) { ; CHECK-LABEL: @and_zext_eq_odd( ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[A:%.*]], 3 -; CHECK-NEXT: [[NOT:%.*]] = zext i1 [[COND]] to i32 -; CHECK-NEXT: [[R:%.*]] = and i32 [[NOT]], [[A]] +; CHECK-NEXT: [[R:%.*]] = zext i1 [[COND]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %cond = icmp eq i32 %a, 3 @@ -2530,8 +2523,7 @@ define i32 @and_zext_eq_odd(i32 %a) { define i32 @and_zext_eq_odd_commuted(i32 %a) { ; CHECK-LABEL: @and_zext_eq_odd_commuted( ; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[A:%.*]], 3 -; CHECK-NEXT: [[NOT:%.*]] = zext i1 [[COND]] to i32 -; CHECK-NEXT: [[R:%.*]] = and i32 [[NOT]], [[A]] +; CHECK-NEXT: [[R:%.*]] = zext i1 [[COND]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %cond = icmp eq i32 %a, 3 @@ -2545,10 +2537,7 @@ define i32 @and_zext_eq_zero(i32 %A, i32 %C) { ; CHECK-LABEL: @and_zext_eq_zero( ; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i32 [[A:%.*]], 0 ; CHECK-NEXT: [[TMP2:%.*]] = zext i1 [[TMP1]] to i32 -; CHECK-NEXT: [[TMP3:%.*]] = lshr i32 [[A]], [[C:%.*]] -; CHECK-NEXT: [[TMP4:%.*]] = xor i32 [[TMP3]], -1 -; CHECK-NEXT: [[TMP5:%.*]] = and i32 [[TMP2]], [[TMP4]] -; CHECK-NEXT: ret i32 [[TMP5]] +; CHECK-NEXT: ret i32 [[TMP2]] ; %1 = icmp eq i32 %A, 0 %2 = zext i1 %1 to i32 diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index 666d85d6cc321..a5c05278f4232 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -4441,9 +4441,9 @@ define i1 @redundant_sign_bit_count_ugt_31_30(i32 %x) { define i1 @zext_bool_and_eq0(i1 %x, i8 %y) { ; CHECK-LABEL: @zext_bool_and_eq0( ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[Y:%.*]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0 -; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP3]], true +; CHECK-NEXT: [[R1:%.*]] = icmp eq i8 [[TMP1]], 0 +; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true +; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[R1]] ; CHECK-NEXT: ret i1 [[R]] ; %zx = zext i1 %x to i8 @@ -4454,9 +4454,10 @@ define i1 @zext_bool_and_eq0(i1 %x, i8 %y) { define <2 x i1> @zext_bool_and_eq0_commute(<2 x i1> %x, <2 x i8> %p) { ; CHECK-LABEL: @zext_bool_and_eq0_commute( -; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i8> [[P:%.*]] to <2 x i1> -; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i1> [[TMP1]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = xor <2 x i1> [[TMP2]], +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[P:%.*]], +; CHECK-NEXT: [[R1:%.*]] = icmp eq <2 x i8> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[NOT_X:%.*]] = xor <2 x i1> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[NOT_X]], <2 x i1> , <2 x i1> [[R1]] ; CHECK-NEXT: ret <2 x i1> [[R]] ; %y = mul <2 x i8> %p, %p ; thwart complexity-based canonicalization @@ -4469,8 +4470,8 @@ define <2 x i1> @zext_bool_and_eq0_commute(<2 x i1> %x, <2 x i8> %p) { define i1 @zext_bool_and_ne0(i1 %x, i8 %y) { ; CHECK-LABEL: @zext_bool_and_ne0( ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[Y:%.*]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0 -; CHECK-NEXT: [[R:%.*]] = and i1 [[TMP2]], [[X:%.*]] +; CHECK-NEXT: [[R1:%.*]] = icmp ne i8 [[TMP1]], 0 +; CHECK-NEXT: [[R:%.*]] = select i1 [[X:%.*]], i1 [[R1]], i1 false ; CHECK-NEXT: ret i1 [[R]] ; %zx = zext i1 %x to i8 @@ -4482,9 +4483,9 @@ define i1 @zext_bool_and_ne0(i1 %x, i8 %y) { define i1 @zext_bool_and_ne1(i1 %x, i8 %y) { ; CHECK-LABEL: @zext_bool_and_ne1( ; CHECK-NEXT: [[TMP1:%.*]] = and i8 [[Y:%.*]], 1 -; CHECK-NEXT: [[TMP2:%.*]] = icmp ne i8 [[TMP1]], 0 -; CHECK-NEXT: [[TMP3:%.*]] = and i1 [[TMP2]], [[X:%.*]] -; CHECK-NEXT: [[R:%.*]] = xor i1 [[TMP3]], true +; CHECK-NEXT: [[R1:%.*]] = icmp eq i8 [[TMP1]], 0 +; CHECK-NEXT: [[NOT_X:%.*]] = xor i1 [[X:%.*]], true +; CHECK-NEXT: [[R:%.*]] = select i1 [[NOT_X]], i1 true, i1 [[R1]] ; CHECK-NEXT: ret i1 [[R]] ; %zx = zext i1 %x to i8 @@ -4495,8 +4496,8 @@ define i1 @zext_bool_and_ne1(i1 %x, i8 %y) { define <2 x i1> @zext_bool_and_eq1(<2 x i1> %x, <2 x i8> %y) { ; CHECK-LABEL: @zext_bool_and_eq1( -; CHECK-NEXT: [[TMP1:%.*]] = trunc <2 x i8> [[Y:%.*]] to <2 x i1> -; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[TMP1]], [[X:%.*]] +; CHECK-NEXT: [[R1:%.*]] = trunc <2 x i8> [[Y:%.*]] to <2 x i1> +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[X:%.*]], <2 x i1> [[R1]], <2 x i1> zeroinitializer ; CHECK-NEXT: ret <2 x i1> [[R]] ; %zx = zext <2 x i1> %x to <2 x i8> @@ -4541,8 +4542,8 @@ define i1 @zext_bool_and_eq0_use(i1 %x, i64 %y) { define i1 @zext_bool_and_ne0_use(i1 %x, i64 %y) { ; CHECK-LABEL: @zext_bool_and_ne0_use( -; CHECK-NEXT: [[ZX:%.*]] = zext i1 [[X:%.*]] to i64 -; CHECK-NEXT: [[A:%.*]] = and i64 [[ZX]], [[Y:%.*]] +; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[Y:%.*]], 1 +; CHECK-NEXT: [[A:%.*]] = select i1 [[X:%.*]], i64 [[TMP1]], i64 0 ; CHECK-NEXT: call void @use_i64(i64 [[A]]) ; CHECK-NEXT: [[R:%.*]] = icmp ne i64 [[A]], 0 ; CHECK-NEXT: ret i1 [[R]] diff --git a/llvm/test/Transforms/InstCombine/narrow.ll b/llvm/test/Transforms/InstCombine/narrow.ll index 9e4670b51ad13..781974d33bf11 100644 --- a/llvm/test/Transforms/InstCombine/narrow.ll +++ b/llvm/test/Transforms/InstCombine/narrow.ll @@ -155,8 +155,7 @@ define i1 @searchArray2(i32 %hay, ptr %haystack) { ; CHECK-NEXT: [[IDX:%.*]] = getelementptr i32, ptr [[HAYSTACK:%.*]], i64 [[INDVAR]] ; CHECK-NEXT: [[LD:%.*]] = load i32, ptr [[IDX]], align 4 ; CHECK-NEXT: [[CMP1:%.*]] = icmp eq i32 [[LD]], [[HAY:%.*]] -; CHECK-NEXT: [[ZEXT:%.*]] = zext i1 [[CMP1]] to i8 -; CHECK-NEXT: [[AND]] = and i8 [[FOUND]], [[ZEXT]] +; CHECK-NEXT: [[AND]] = select i1 [[CMP1]], i8 [[FOUND]], i8 0 ; CHECK-NEXT: [[INDVAR_NEXT]] = add i64 [[INDVAR]], 1 ; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i64 [[INDVAR_NEXT]], 1000 ; CHECK-NEXT: br i1 [[EXITCOND]], label [[EXIT:%.*]], label [[LOOP]] diff --git a/llvm/test/Transforms/InstCombine/zext-or-icmp.ll b/llvm/test/Transforms/InstCombine/zext-or-icmp.ll index 74d0f2f21aec8..dcb8c081f154a 100644 --- a/llvm/test/Transforms/InstCombine/zext-or-icmp.ll +++ b/llvm/test/Transforms/InstCombine/zext-or-icmp.ll @@ -173,15 +173,15 @@ define i8 @PR49475_infloop(i32 %t0, i16 %insert, i64 %e, i8 %i162) { ; CHECK-NEXT: [[B:%.*]] = icmp eq i32 [[T0:%.*]], 0 ; CHECK-NEXT: [[B2:%.*]] = icmp eq i16 [[INSERT:%.*]], 0 ; CHECK-NEXT: [[T1:%.*]] = or i1 [[B]], [[B2]] -; CHECK-NEXT: [[EXT:%.*]] = zext i1 [[T1]] to i32 -; CHECK-NEXT: [[AND:%.*]] = and i32 [[EXT]], [[T0]] -; CHECK-NEXT: [[TMP1:%.*]] = or i32 [[AND]], 140 -; CHECK-NEXT: [[XOR1:%.*]] = zext i32 [[TMP1]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[T0]], 1 +; CHECK-NEXT: [[TMP2:%.*]] = or i32 [[TMP1]], 140 +; CHECK-NEXT: [[TMP3:%.*]] = zext i32 [[TMP2]] to i64 +; CHECK-NEXT: [[XOR1:%.*]] = select i1 [[T1]], i64 [[TMP3]], i64 140 ; CHECK-NEXT: [[CONV16:%.*]] = sext i8 [[I162:%.*]] to i64 ; CHECK-NEXT: [[SUB17:%.*]] = sub i64 [[CONV16]], [[E:%.*]] ; CHECK-NEXT: [[SEXT:%.*]] = shl i64 [[SUB17]], 32 ; CHECK-NEXT: [[CONV18:%.*]] = ashr exact i64 [[SEXT]], 32 -; CHECK-NEXT: [[CMP:%.*]] = icmp sle i64 [[CONV18]], [[XOR1]] +; CHECK-NEXT: [[CMP:%.*]] = icmp sge i64 [[XOR1]], [[CONV18]] ; CHECK-NEXT: [[CONV19:%.*]] = zext i1 [[CMP]] to i16 ; CHECK-NEXT: [[OR21:%.*]] = or i16 [[CONV19]], [[INSERT]] ; CHECK-NEXT: [[TOBOOL23_NOT:%.*]] = icmp eq i16 [[OR21]], 0