Skip to content

Commit 81cdd35

Browse files
committed
[ValueTracking] Add support for xor/disjoint or in isKnownNonZero
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 llvm#87706
1 parent 2646790 commit 81cdd35

File tree

2 files changed

+29
-25
lines changed

2 files changed

+29
-25
lines changed

llvm/lib/Analysis/ValueTracking.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3207,20 +3207,33 @@ getInvertibleOperands(const Operator *Op1,
32073207
return std::nullopt;
32083208
}
32093209

3210-
/// Return true if V2 == V1 + X, where X is known non-zero.
3211-
static bool isAddOfNonZero(const Value *V1, const Value *V2, unsigned Depth,
3212-
const SimplifyQuery &Q) {
3210+
/// Return true if V1 == (binop V2, X), where X is known non-zero.
3211+
/// Only handle a small subset of binops where (binop V2, X) with non-zero X
3212+
/// implies V2 != V1.
3213+
static bool isModifyingBinopOfNonZero(const Value *V1, const Value *V2,
3214+
unsigned Depth, const SimplifyQuery &Q) {
32133215
const BinaryOperator *BO = dyn_cast<BinaryOperator>(V1);
3214-
if (!BO || BO->getOpcode() != Instruction::Add)
3216+
if (!BO)
32153217
return false;
3216-
Value *Op = nullptr;
3217-
if (V2 == BO->getOperand(0))
3218-
Op = BO->getOperand(1);
3219-
else if (V2 == BO->getOperand(1))
3220-
Op = BO->getOperand(0);
3221-
else
3222-
return false;
3223-
return isKnownNonZero(Op, Depth + 1, Q);
3218+
switch (BO->getOpcode()) {
3219+
default:
3220+
break;
3221+
case Instruction::Or:
3222+
if (!cast<PossiblyDisjointInst>(V1)->isDisjoint())
3223+
break;
3224+
[[fallthrough]];
3225+
case Instruction::Xor:
3226+
case Instruction::Add:
3227+
Value *Op = nullptr;
3228+
if (V2 == BO->getOperand(0))
3229+
Op = BO->getOperand(1);
3230+
else if (V2 == BO->getOperand(1))
3231+
Op = BO->getOperand(0);
3232+
else
3233+
return false;
3234+
return isKnownNonZero(Op, Depth + 1, Q);
3235+
}
3236+
return false;
32243237
}
32253238

32263239
/// 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,
33803393
};
33813394
}
33823395

3383-
if (isAddOfNonZero(V1, V2, Depth, Q) || isAddOfNonZero(V2, V1, Depth, Q))
3396+
if (isModifyingBinopOfNonZero(V1, V2, Depth, Q) ||
3397+
isModifyingBinopOfNonZero(V2, V1, Depth, Q))
33843398
return true;
33853399

33863400
if (isNonEqualMul(V1, V2, Depth, Q) || isNonEqualMul(V2, V1, Depth, Q))

llvm/test/Transforms/InstSimplify/icmp.ll

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -359,12 +359,7 @@ define i1 @non_eq_xor_common_op_fail(i8 %x, i8 %y, i8 %ww, i8 %a) {
359359

360360
define i1 @non_eq_disjoint_or(i8 %x, i8 %yy, i8 %w) {
361361
; CHECK-LABEL: @non_eq_disjoint_or(
362-
; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1
363-
; CHECK-NEXT: [[LHS:%.*]] = add i8 [[X:%.*]], [[W:%.*]]
364-
; CHECK-NEXT: [[VAL:%.*]] = or disjoint i8 [[Y]], [[W]]
365-
; CHECK-NEXT: [[RHS:%.*]] = add i8 [[X]], [[VAL]]
366-
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[LHS]], [[RHS]]
367-
; CHECK-NEXT: ret i1 [[R]]
362+
; CHECK-NEXT: ret i1 false
368363
;
369364
%y = add nuw i8 %yy, 1
370365
%lhs = add i8 %x, %w
@@ -393,12 +388,7 @@ define i1 @non_eq_or_fail(i8 %x, i8 %yy, i8 %w) {
393388

394389
define i1 @non_eq_xor(i8 %x, i8 %yy, i8 %w) {
395390
; CHECK-LABEL: @non_eq_xor(
396-
; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1
397-
; CHECK-NEXT: [[LHS:%.*]] = add i8 [[X:%.*]], [[W:%.*]]
398-
; CHECK-NEXT: [[VAL:%.*]] = xor i8 [[Y]], [[W]]
399-
; CHECK-NEXT: [[RHS:%.*]] = add i8 [[X]], [[VAL]]
400-
; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[LHS]], [[RHS]]
401-
; CHECK-NEXT: ret i1 [[R]]
391+
; CHECK-NEXT: ret i1 false
402392
;
403393
%y = add nuw i8 %yy, 1
404394
%lhs = add i8 %x, %w

0 commit comments

Comments
 (0)