Skip to content

Commit

Permalink
[ValueTracking] Add support for xor/disjoint or in isKnownNonZero
Browse files Browse the repository at this point in the history
Handles cases like `X ^ Y == X` / `X disjoint| Y == X`.

Both of these cases have identical logic to the existing `add` case,
so just converting the `add` code to a more general helper.

Proofs: https://alive2.llvm.org/ce/z/Htm7pe

Closes #87706
  • Loading branch information
goldsteinn committed Apr 10, 2024
1 parent 2646790 commit 81cdd35
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 25 deletions.
40 changes: 27 additions & 13 deletions llvm/lib/Analysis/ValueTracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<BinaryOperator>(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<PossiblyDisjointInst>(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
Expand Down Expand Up @@ -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))
Expand Down
14 changes: 2 additions & 12 deletions llvm/test/Transforms/InstSimplify/icmp.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 81cdd35

Please sign in to comment.