diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -3116,13 +3116,29 @@ if (Pred == ICmpInst::ICMP_UGE) return getTrue(ITy); - if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE) { + if (Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGE || + Pred == ICmpInst::ICMP_ULE || Pred == ICmpInst::ICMP_UGT) { KnownBits RHSKnown = computeKnownBits(RHS, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); KnownBits YKnown = computeKnownBits(Y, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); - if (RHSKnown.isNonNegative() && YKnown.isNegative()) - return Pred == ICmpInst::ICMP_SLT ? getTrue(ITy) : getFalse(ITy); - if (RHSKnown.isNegative() || YKnown.isNonNegative()) - return Pred == ICmpInst::ICMP_SLT ? getFalse(ITy) : getTrue(ITy); + + if (ICmpInst::isSigned(Pred)) { + if (RHSKnown.isNonNegative() && YKnown.isNegative()) + return Pred == ICmpInst::ICMP_SLT ? getTrue(ITy) : getFalse(ITy); + if (RHSKnown.isNegative() || YKnown.isNonNegative()) + return Pred == ICmpInst::ICMP_SLT ? getFalse(ITy) : getTrue(ITy); + + } + // Check if there are any bits in Y set that are not set in RHS. + // If this is the case the `(or X, Y)` cannot equal `X`. For ULE/UGT, the + // only case the equality is true/false is equality, so we can constant + // fold those cases. + // NB: Y.One & RHS.Zero is equivilent of ~Y & RHS != 0. + else if ((YKnown.One & RHSKnown.Zero) != 0) { + // We could also do EQ/NE here, but seems unnecessary as they are + // handled elsewhere so no reason to spend the extra time on + // computeKnownBits. + return ICmpInst::isTrueWhenEqual(Pred) ? getFalse(ITy) : getTrue(ITy); + } } } diff --git a/llvm/test/Transforms/InstSimplify/icmp-orx-x.ll b/llvm/test/Transforms/InstSimplify/icmp-orx-x.ll --- a/llvm/test/Transforms/InstSimplify/icmp-orx-x.ll +++ b/llvm/test/Transforms/InstSimplify/icmp-orx-x.ll @@ -3,11 +3,7 @@ define i1 @or_simplify_ule(i8 %y_in, i8 %rhs_in, i1 %c) { ; CHECK-LABEL: @or_simplify_ule( -; CHECK-NEXT: [[Y:%.*]] = or i8 [[Y_IN:%.*]], 1 -; CHECK-NEXT: [[RHS:%.*]] = and i8 [[RHS_IN:%.*]], -2 -; CHECK-NEXT: [[LBO:%.*]] = or i8 [[Y]], [[RHS]] -; CHECK-NEXT: [[R:%.*]] = icmp ule i8 [[LBO]], [[RHS]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %y = or i8 %y_in, 1 %rhs = and i8 %rhs_in, -2 @@ -18,11 +14,7 @@ define i1 @or_simplify_uge(i8 %y_in, i8 %rhs_in, i1 %c) { ; CHECK-LABEL: @or_simplify_uge( -; CHECK-NEXT: [[Y:%.*]] = or i8 [[Y_IN:%.*]], -127 -; CHECK-NEXT: [[RHS:%.*]] = and i8 [[RHS_IN:%.*]], 127 -; CHECK-NEXT: [[LBO:%.*]] = or i8 [[Y]], [[RHS]] -; CHECK-NEXT: [[R:%.*]] = icmp uge i8 [[RHS]], [[LBO]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %y = or i8 %y_in, 129 %rhs = and i8 %rhs_in, 127 @@ -48,11 +40,7 @@ define i1 @or_simplify_ugt(i8 %y_in, i8 %rhs_in) { ; CHECK-LABEL: @or_simplify_ugt( -; CHECK-NEXT: [[Y:%.*]] = or i8 [[Y_IN:%.*]], 1 -; CHECK-NEXT: [[RHS:%.*]] = and i8 [[RHS_IN:%.*]], -2 -; CHECK-NEXT: [[LBO:%.*]] = or i8 [[Y]], [[RHS]] -; CHECK-NEXT: [[R:%.*]] = icmp ugt i8 [[LBO]], [[RHS]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %y = or i8 %y_in, 1 %rhs = and i8 %rhs_in, -2 @@ -63,11 +51,7 @@ define i1 @or_simplify_ult(i8 %y_in, i8 %rhs_in) { ; CHECK-LABEL: @or_simplify_ult( -; CHECK-NEXT: [[Y:%.*]] = or i8 [[Y_IN:%.*]], 36 -; CHECK-NEXT: [[RHS:%.*]] = and i8 [[RHS_IN:%.*]], -5 -; CHECK-NEXT: [[LBO:%.*]] = or i8 [[Y]], [[RHS]] -; CHECK-NEXT: [[R:%.*]] = icmp ult i8 [[RHS]], [[LBO]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %y = or i8 %y_in, 36 %rhs = and i8 %rhs_in, -5 @@ -93,11 +77,7 @@ define i1 @pr64610(ptr %b) { ; CHECK-LABEL: @pr64610( -; CHECK-NEXT: [[V:%.*]] = load i1, ptr [[B:%.*]], align 2 -; CHECK-NEXT: [[S:%.*]] = select i1 [[V]], i32 74, i32 0 -; CHECK-NEXT: [[OR:%.*]] = or i32 [[S]], 1 -; CHECK-NEXT: [[R:%.*]] = icmp ugt i32 [[OR]], [[S]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 true ; %v = load i1, ptr %b, align 2 %s = select i1 %v, i32 74, i32 0