diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index f3ea73b2f0ec4..3a10de72a2756 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -3207,20 +3207,33 @@ getInvertibleOperands(const Operator *Op1, return std::nullopt; } -/// Return true if V2 == V1 + X, where X is known non-zero. -static bool isAddOfNonZero(const Value *V1, const Value *V2, unsigned Depth, - const SimplifyQuery &Q) { +/// Return true if V1 == (binop V2, X), where X is known non-zero. +/// Only handle a small subset of binops where (binop V2, X) with non-zero X +/// implies V2 != V1. +static bool isModifyingBinopOfNonZero(const Value *V1, const Value *V2, + unsigned Depth, const SimplifyQuery &Q) { const BinaryOperator *BO = dyn_cast(V1); - if (!BO || BO->getOpcode() != Instruction::Add) + if (!BO) return false; - Value *Op = nullptr; - if (V2 == BO->getOperand(0)) - Op = BO->getOperand(1); - else if (V2 == BO->getOperand(1)) - Op = BO->getOperand(0); - else - return false; - return isKnownNonZero(Op, Depth + 1, Q); + switch (BO->getOpcode()) { + default: + break; + case Instruction::Or: + if (!cast(V1)->isDisjoint()) + break; + [[fallthrough]]; + case Instruction::Xor: + case Instruction::Add: + Value *Op = nullptr; + if (V2 == BO->getOperand(0)) + Op = BO->getOperand(1); + else if (V2 == BO->getOperand(1)) + Op = BO->getOperand(0); + else + return false; + return isKnownNonZero(Op, Depth + 1, Q); + } + return false; } /// Return true if V2 == V1 * C, where V1 is known non-zero, C is not 0/1 and @@ -3380,7 +3393,8 @@ static bool isKnownNonEqual(const Value *V1, const Value *V2, unsigned Depth, }; } - if (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q)) + if (isModifyingBinopOfNonZero(V1, V2, Depth, Q) || + isModifyingBinopOfNonZero(V2, V1, Depth, Q)) return true; if (isNonEqualMul(V1, V2, Depth, Q) || isNonEqualMul(V2, V1, Depth, Q)) diff --git a/llvm/test/Transforms/InstSimplify/icmp.ll b/llvm/test/Transforms/InstSimplify/icmp.ll index 530dc16144eba..c94922197096f 100644 --- a/llvm/test/Transforms/InstSimplify/icmp.ll +++ b/llvm/test/Transforms/InstSimplify/icmp.ll @@ -359,12 +359,7 @@ define i1 @non_eq_xor_common_op_fail(i8 %x, i8 %y, i8 %ww, i8 %a) { define i1 @non_eq_disjoint_or(i8 %x, i8 %yy, i8 %w) { ; CHECK-LABEL: @non_eq_disjoint_or( -; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1 -; CHECK-NEXT: [[LHS:%.*]] = add i8 [[X:%.*]], [[W:%.*]] -; CHECK-NEXT: [[VAL:%.*]] = or disjoint i8 [[Y]], [[W]] -; CHECK-NEXT: [[RHS:%.*]] = add i8 [[X]], [[VAL]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[LHS]], [[RHS]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %y = add nuw i8 %yy, 1 %lhs = add i8 %x, %w @@ -393,12 +388,7 @@ define i1 @non_eq_or_fail(i8 %x, i8 %yy, i8 %w) { define i1 @non_eq_xor(i8 %x, i8 %yy, i8 %w) { ; CHECK-LABEL: @non_eq_xor( -; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1 -; CHECK-NEXT: [[LHS:%.*]] = add i8 [[X:%.*]], [[W:%.*]] -; CHECK-NEXT: [[VAL:%.*]] = xor i8 [[Y]], [[W]] -; CHECK-NEXT: [[RHS:%.*]] = add i8 [[X]], [[VAL]] -; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[LHS]], [[RHS]] -; CHECK-NEXT: ret i1 [[R]] +; CHECK-NEXT: ret i1 false ; %y = add nuw i8 %yy, 1 %lhs = add i8 %x, %w