diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2938,7 +2938,7 @@ // (icmp ne A, 0) | (icmp ne B, 0) --> (icmp ne (A|B), 0) // (icmp eq A, 0) & (icmp eq B, 0) --> (icmp eq (A|B), 0) - // TODO: Remove this when foldLogOpOfMaskedICmps can handle undefs. + // TODO: Remove this and below when foldLogOpOfMaskedICmps can handle undefs. if (!IsLogical && PredL == (IsAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE) && PredL == PredR && match(LHS1, m_ZeroInt()) && match(RHS1, m_ZeroInt()) && LHS0->getType() == RHS0->getType()) { @@ -2947,6 +2947,16 @@ Constant::getNullValue(NewOr->getType())); } + // (icmp ne A, -1) | (icmp ne B, -1) --> (icmp ne (A&B), -1) + // (icmp eq A, -1) & (icmp eq B, -1) --> (icmp eq (A&B), -1) + if (!IsLogical && PredL == (IsAnd ? ICmpInst::ICMP_EQ : ICmpInst::ICMP_NE) && + PredL == PredR && match(LHS1, m_AllOnes()) && match(RHS1, m_AllOnes()) && + LHS0->getType() == RHS0->getType()) { + Value *NewAnd = Builder.CreateAnd(LHS0, RHS0); + return Builder.CreateICmp(PredL, NewAnd, + Constant::getAllOnesValue(LHS0->getType())); + } + // This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2). if (!LHSC || !RHSC) return nullptr; diff --git a/llvm/test/Transforms/InstCombine/and-or-icmps.ll b/llvm/test/Transforms/InstCombine/and-or-icmps.ll --- a/llvm/test/Transforms/InstCombine/and-or-icmps.ll +++ b/llvm/test/Transforms/InstCombine/and-or-icmps.ll @@ -2497,9 +2497,8 @@ define <2 x i1> @icmp_eq_m1_and_eq_m1(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @icmp_eq_m1_and_eq_m1( -; CHECK-NEXT: [[RX:%.*]] = icmp eq <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RY:%.*]] = icmp eq <2 x i8> [[Y:%.*]], -; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[RX]], [[RY]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[TMP1]], ; CHECK-NEXT: ret <2 x i1> [[R]] ; %rx = icmp eq <2 x i8> %x, @@ -2510,9 +2509,8 @@ define <2 x i1> @icmp_eq_m1_and_eq_undef_m1(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @icmp_eq_m1_and_eq_undef_m1( -; CHECK-NEXT: [[RX:%.*]] = icmp eq <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RY:%.*]] = icmp eq <2 x i8> [[Y:%.*]], -; CHECK-NEXT: [[R:%.*]] = and <2 x i1> [[RX]], [[RY]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp eq <2 x i8> [[TMP1]], ; CHECK-NEXT: ret <2 x i1> [[R]] ; %rx = icmp eq <2 x i8> %x, @@ -2561,9 +2559,8 @@ define <2 x i1> @icmp_ne_m1_or_ne_m1(<2 x i8> %x, <2 x i8> %y) { ; CHECK-LABEL: @icmp_ne_m1_or_ne_m1( -; CHECK-NEXT: [[RX:%.*]] = icmp ne <2 x i8> [[X:%.*]], -; CHECK-NEXT: [[RY:%.*]] = icmp ne <2 x i8> [[Y:%.*]], -; CHECK-NEXT: [[R:%.*]] = or <2 x i1> [[RX]], [[RY]] +; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i8> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i8> [[TMP1]], ; CHECK-NEXT: ret <2 x i1> [[R]] ; %rx = icmp ne <2 x i8> %x, diff --git a/llvm/test/Transforms/PhaseOrdering/pr62311.ll b/llvm/test/Transforms/PhaseOrdering/pr62311.ll --- a/llvm/test/Transforms/PhaseOrdering/pr62311.ll +++ b/llvm/test/Transforms/PhaseOrdering/pr62311.ll @@ -19,31 +19,9 @@ define noundef zeroext i1 @allones(<8 x i64> noundef %x) { ; CHECK-LABEL: @allones( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[VECEXT:%.*]] = extractelement <8 x i64> [[X:%.*]], i64 0 -; CHECK-NEXT: [[VECEXT1:%.*]] = extractelement <8 x i64> [[X]], i64 1 -; CHECK-NEXT: [[TMP0:%.*]] = and i64 [[VECEXT]], [[VECEXT1]] -; CHECK-NEXT: [[OR_COND:%.*]] = icmp eq i64 [[TMP0]], -1 -; CHECK-NEXT: [[VECEXT4:%.*]] = extractelement <8 x i64> [[X]], i64 2 -; CHECK-NEXT: [[VECEXT7:%.*]] = extractelement <8 x i64> [[X]], i64 3 -; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[VECEXT4]], [[VECEXT7]] -; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i64 [[TMP1]], -1 -; CHECK-NEXT: [[OR_COND21:%.*]] = and i1 [[OR_COND]], [[TMP2]] -; CHECK-NEXT: [[VECEXT10:%.*]] = extractelement <8 x i64> [[X]], i64 4 -; CHECK-NEXT: [[VECEXT13:%.*]] = extractelement <8 x i64> [[X]], i64 5 -; CHECK-NEXT: [[TMP3:%.*]] = and i64 [[VECEXT10]], [[VECEXT13]] -; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[TMP3]], -1 -; CHECK-NEXT: [[OR_COND23:%.*]] = and i1 [[TMP4]], [[OR_COND21]] -; CHECK-NEXT: [[VECEXT16:%.*]] = extractelement <8 x i64> [[X]], i64 6 -; CHECK-NEXT: [[CMP17:%.*]] = icmp eq i64 [[VECEXT16]], -1 -; CHECK-NEXT: [[OR_COND24:%.*]] = and i1 [[CMP17]], [[OR_COND23]] -; CHECK-NEXT: br i1 [[OR_COND24]], label [[LAND_RHS:%.*]], label [[LAND_END:%.*]] -; CHECK: land.rhs: -; CHECK-NEXT: [[VECEXT18:%.*]] = extractelement <8 x i64> [[X]], i64 7 -; CHECK-NEXT: [[CMP19:%.*]] = icmp eq i64 [[VECEXT18]], -1 -; CHECK-NEXT: br label [[LAND_END]] -; CHECK: land.end: -; CHECK-NEXT: [[TMP5:%.*]] = phi i1 [ false, [[ENTRY:%.*]] ], [ [[CMP19]], [[LAND_RHS]] ] -; CHECK-NEXT: ret i1 [[TMP5]] +; CHECK-NEXT: [[TMP0:%.*]] = tail call i64 @llvm.vector.reduce.and.v8i64(<8 x i64> [[X:%.*]]) +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], -1 +; CHECK-NEXT: ret i1 [[TMP1]] ; entry: %vecext = extractelement <8 x i64> %x, i32 0