diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -4557,7 +4557,7 @@ return nullptr; } -static Instruction *foldICmpAndXX(ICmpInst &I, const SimplifyQuery &Q, +static Instruction *foldICmpAndXX(ICmpInst &I, const SimplifyQuery &, InstCombinerImpl &IC) { Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1), *A; // Normalize and operand as operand 0. @@ -4594,6 +4594,49 @@ Constant::getNullValue(Op1->getType())); } + if (ICmpInst::isEquality(Pred) || ICmpInst::getSignedPredicate(Pred) != Pred) + return nullptr; + + auto IsTrue = [](std::optional OptBool) { + return OptBool.has_value() && OptBool.value(); + }; + + auto IsFalse = [](std::optional OptBool) { + return OptBool.has_value() && !OptBool.value(); + }; + + auto KnownSignY = IC.getKnownSign(A, &I); + + // (X & NegY) spred X --> (icmp (X & NegY) upred X + if (IsTrue(KnownSignY)) + return new ICmpInst(ICmpInst::getUnsignedPredicate(Pred), Op0, Op1); + + if (Pred != ICmpInst::ICMP_SLE && Pred != ICmpInst::ICMP_SGT) + return nullptr; + + if (IsFalse(KnownSignY)) { + // (X & PosY) s<= X --> X s>= 0 + if (Pred == ICmpInst::ICMP_SLE) + return new ICmpInst(ICmpInst::ICMP_SGE, Op1, + Constant::getNullValue(Op1->getType())); + // (X & PosY) s> X --> X s< 0 + if (Pred == ICmpInst::ICMP_SGT) + return new ICmpInst(ICmpInst::ICMP_SLT, Op1, + Constant::getNullValue(Op1->getType())); + } + + if (IsTrue(IC.getKnownSign(Op1, &I))) { + // (NegX & Y) s> NegX --> Y s>= 0 + if (Pred == ICmpInst::ICMP_SGT) + return new ICmpInst(ICmpInst::ICMP_SGE, A, + Constant::getNullValue(A->getType())); + + // (NegX & Y) s<= NegX --> Y s< 0 + if (Pred == ICmpInst::ICMP_SLE) + return new ICmpInst(ICmpInst::ICMP_SLT, A, + Constant::getNullValue(A->getType())); + } + return nullptr; } diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sge-to-icmp-sle.ll @@ -98,8 +98,7 @@ define i1 @c0() { ; CHECK-LABEL: @c0( ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() -; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X]], 3 -; CHECK-NEXT: [[RET:%.*]] = icmp sge i8 [[X]], [[TMP0]] +; CHECK-NEXT: [[RET:%.*]] = icmp sgt i8 [[X]], -1 ; CHECK-NEXT: ret i1 [[RET]] ; %x = call i8 @gen8() diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sgt-to-icmp-sgt.ll @@ -125,8 +125,7 @@ define i1 @c0(i8 %x) { ; CHECK-LABEL: @c0( -; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3 -; CHECK-NEXT: [[RET:%.*]] = icmp sgt i8 [[TMP0]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %tmp0 = and i8 %x, 3 diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-sle-to-icmp-sle.ll @@ -113,8 +113,7 @@ define i1 @c0(i8 %x) { ; CHECK-LABEL: @c0( -; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X:%.*]], 3 -; CHECK-NEXT: [[RET:%.*]] = icmp sle i8 [[TMP0]], [[X]] +; CHECK-NEXT: [[RET:%.*]] = icmp sgt i8 [[X:%.*]], -1 ; CHECK-NEXT: ret i1 [[RET]] ; %tmp0 = and i8 %x, 3 diff --git a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll --- a/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll +++ b/llvm/test/Transforms/InstCombine/canonicalize-constant-low-bit-mask-and-icmp-slt-to-icmp-sgt.ll @@ -108,8 +108,7 @@ define i1 @c0() { ; CHECK-LABEL: @c0( ; CHECK-NEXT: [[X:%.*]] = call i8 @gen8() -; CHECK-NEXT: [[TMP0:%.*]] = and i8 [[X]], 3 -; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], [[TMP0]] +; CHECK-NEXT: [[RET:%.*]] = icmp slt i8 [[X]], 0 ; CHECK-NEXT: ret i1 [[RET]] ; %x = call i8 @gen8() diff --git a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll --- a/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll +++ b/llvm/test/Transforms/InstCombine/icmp-and-lowbit-mask.ll @@ -577,9 +577,7 @@ define i1 @src_is_mask_const_slt(i8 %x_in) { ; CHECK-LABEL: @src_is_mask_const_slt( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], 7 -; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X]], [[AND]] +; CHECK-NEXT: [[R:%.*]] = icmp slt i8 [[X_IN:%.*]], 0 ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 @@ -602,9 +600,7 @@ define i1 @src_is_mask_const_sle(i8 %x_in) { ; CHECK-LABEL: @src_is_mask_const_sle( -; CHECK-NEXT: [[X:%.*]] = xor i8 [[X_IN:%.*]], 123 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], 31 -; CHECK-NEXT: [[R:%.*]] = icmp sle i8 [[AND]], [[X]] +; CHECK-NEXT: [[R:%.*]] = icmp sgt i8 [[X_IN:%.*]], -1 ; CHECK-NEXT: ret i1 [[R]] ; %x = xor i8 %x_in, 123 diff --git a/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll b/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll --- a/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll +++ b/llvm/test/Transforms/InstCombine/icmp-of-and-x.ll @@ -57,7 +57,7 @@ ; CHECK-NEXT: [[CY:%.*]] = icmp slt i8 [[Y:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[CY]]) ; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = icmp sge i8 [[AND]], [[X]] +; CHECK-NEXT: [[Z:%.*]] = icmp eq i8 [[AND]], [[X]] ; CHECK-NEXT: ret i1 [[Z]] ; %cy = icmp slt i8 %y, 0 @@ -73,7 +73,7 @@ ; CHECK-NEXT: br i1 [[CY]], label [[NEGY:%.*]], label [[POSY:%.*]] ; CHECK: negy: ; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = icmp slt i8 [[AND]], [[X]] +; CHECK-NEXT: [[Z:%.*]] = icmp ne i8 [[AND]], [[X]] ; CHECK-NEXT: ret i1 [[Z]] ; CHECK: posy: ; CHECK-NEXT: [[R:%.*]] = call i1 @barrier() @@ -115,10 +115,7 @@ define i1 @icmp_sle_x_negy(i8 %x, i8 %yy) { ; CHECK-LABEL: @icmp_sle_x_negy( -; CHECK-NEXT: [[Y:%.*]] = or i8 [[YY:%.*]], -128 -; CHECK-NEXT: [[AND:%.*]] = and i8 [[Y]], [[X:%.*]] -; CHECK-NEXT: [[Z:%.*]] = icmp sle i8 [[AND]], [[X]] -; CHECK-NEXT: ret i1 [[Z]] +; CHECK-NEXT: ret i1 true ; %y = or i8 %yy, 128 %and = and i8 %y, %x @@ -128,10 +125,7 @@ define <2 x i1> @icmp_sgt_x_negy(<2 x i8> %x, <2 x i8> %yy) { ; CHECK-LABEL: @icmp_sgt_x_negy( -; CHECK-NEXT: [[Y:%.*]] = or <2 x i8> [[YY:%.*]], -; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y]], [[X:%.*]] -; CHECK-NEXT: [[Z:%.*]] = icmp sgt <2 x i8> [[AND]], [[X]] -; CHECK-NEXT: ret <2 x i1> [[Z]] +; CHECK-NEXT: ret <2 x i1> zeroinitializer ; %y = or <2 x i8> %yy, %and = and <2 x i8> %y, %x @@ -154,9 +148,7 @@ define <2 x i1> @icmp_sle_x_posy(<2 x i8> %x, <2 x i8> %yy) { ; CHECK-LABEL: @icmp_sle_x_posy( -; CHECK-NEXT: [[Y:%.*]] = and <2 x i8> [[YY:%.*]], -; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[Y]], [[X:%.*]] -; CHECK-NEXT: [[Z:%.*]] = icmp sle <2 x i8> [[AND]], [[X]] +; CHECK-NEXT: [[Z:%.*]] = icmp sgt <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i1> [[Z]] ; %y = and <2 x i8> %yy, @@ -182,8 +174,7 @@ ; CHECK-LABEL: @icmp_sgt_x_posy( ; CHECK-NEXT: [[CY:%.*]] = icmp sgt i8 [[Y:%.*]], -1 ; CHECK-NEXT: call void @llvm.assume(i1 [[CY]]) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X:%.*]], [[Y]] -; CHECK-NEXT: [[Z:%.*]] = icmp sgt i8 [[AND]], [[X]] +; CHECK-NEXT: [[Z:%.*]] = icmp slt i8 [[X:%.*]], 0 ; CHECK-NEXT: ret i1 [[Z]] ; %cy = icmp sge i8 %y, 0 @@ -195,9 +186,7 @@ define <2 x i1> @icmp_sgt_negx_y(<2 x i8> %xx, <2 x i8> %y) { ; CHECK-LABEL: @icmp_sgt_negx_y( -; CHECK-NEXT: [[X:%.*]] = or <2 x i8> [[XX:%.*]], -; CHECK-NEXT: [[AND:%.*]] = and <2 x i8> [[X]], [[Y:%.*]] -; CHECK-NEXT: [[Z:%.*]] = icmp sgt <2 x i8> [[AND]], [[X]] +; CHECK-NEXT: [[Z:%.*]] = icmp sgt <2 x i8> [[Y:%.*]], ; CHECK-NEXT: ret <2 x i1> [[Z]] ; %x = or <2 x i8> %xx, @@ -210,8 +199,7 @@ ; CHECK-LABEL: @icmp_sle_negx_y( ; CHECK-NEXT: [[CX:%.*]] = icmp slt i8 [[X:%.*]], 0 ; CHECK-NEXT: call void @llvm.assume(i1 [[CX]]) -; CHECK-NEXT: [[AND:%.*]] = and i8 [[X]], [[Y:%.*]] -; CHECK-NEXT: [[Z:%.*]] = icmp sle i8 [[AND]], [[X]] +; CHECK-NEXT: [[Z:%.*]] = icmp slt i8 [[Y:%.*]], 0 ; CHECK-NEXT: ret i1 [[Z]] ; %cx = icmp slt i8 %x, 0