[llvm] goldsteinn/or xor non eq (PR #87706)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 4 13:40:21 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
@llvm/pr-subscribers-llvm-analysis
Author: None (goldsteinn)
<details>
<summary>Changes</summary>
- **[ValueTracking] Add tests for `xor`/`disjoint or` in `isKnownNonZero`; NFC**
- **[ValueTracking] Add support for `xor`/`disjoint or` in `isKnownNonZero`**
---
Full diff: https://github.com/llvm/llvm-project/pull/87706.diff
2 Files Affected:
- (modified) llvm/lib/Analysis/ValueTracking.cpp (+27-13)
- (modified) llvm/test/Transforms/InstSimplify/icmp.ll (+60-1)
``````````diff
diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index 5ad4da43bca7db..a4b1352b8cea1e 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -3092,20 +3092,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
@@ -3265,7 +3278,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 3109768bdfe005..2e6d4a4b981a2e 100644
--- a/llvm/test/Transforms/InstSimplify/icmp.ll
+++ b/llvm/test/Transforms/InstSimplify/icmp.ll
@@ -270,7 +270,7 @@ define i1 @load_ptr(ptr %p) {
define i1 @load_ptr_null_valid(ptr %p) null_pointer_is_valid {
; CHECK-LABEL: @load_ptr_null_valid(
-; CHECK-NEXT: [[LOAD_P:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable !0
+; CHECK-NEXT: [[LOAD_P:%.*]] = load ptr, ptr [[P:%.*]], align 8, !dereferenceable [[META0:![0-9]+]]
; CHECK-NEXT: [[R:%.*]] = icmp ne ptr [[LOAD_P]], null
; CHECK-NEXT: ret i1 [[R]]
;
@@ -278,3 +278,62 @@ define i1 @load_ptr_null_valid(ptr %p) null_pointer_is_valid {
%r = icmp ne ptr %load_p, null
ret i1 %r
}
+
+
+define i1 @non_eq_disjoint_or(i8 %x, i8 %yy, i8 %w) {
+; CHECK-LABEL: @non_eq_disjoint_or(
+; CHECK-NEXT: ret i1 false
+;
+ %y = add nuw i8 %yy, 1
+ %lhs = add i8 %x, %w
+ %val = or disjoint i8 %y, %w
+ %rhs = add i8 %x, %val
+ %r = icmp eq i8 %lhs, %rhs
+ ret i1 %r
+}
+
+define i1 @non_eq_or_fail(i8 %x, i8 %yy, i8 %w) {
+; CHECK-LABEL: @non_eq_or_fail(
+; CHECK-NEXT: [[Y:%.*]] = add nuw i8 [[YY:%.*]], 1
+; CHECK-NEXT: [[LHS:%.*]] = add i8 [[X:%.*]], [[W:%.*]]
+; CHECK-NEXT: [[VAL:%.*]] = or i8 [[Y]], [[W]]
+; CHECK-NEXT: [[RHS:%.*]] = add i8 [[X]], [[VAL]]
+; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[LHS]], [[RHS]]
+; CHECK-NEXT: ret i1 [[R]]
+;
+ %y = add nuw i8 %yy, 1
+ %lhs = add i8 %x, %w
+ %val = or i8 %y, %w
+ %rhs = add i8 %x, %val
+ %r = icmp eq i8 %lhs, %rhs
+ ret i1 %r
+}
+
+define i1 @non_eq_xor(i8 %x, i8 %yy, i8 %w) {
+; CHECK-LABEL: @non_eq_xor(
+; CHECK-NEXT: ret i1 false
+;
+ %y = add nuw i8 %yy, 1
+ %lhs = add i8 %x, %w
+ %val = xor i8 %y, %w
+ %rhs = add i8 %x, %val
+ %r = icmp eq i8 %lhs, %rhs
+ ret i1 %r
+}
+
+define i1 @non_eq_xor_fail(i8 %x, i8 %yy, i8 %w) {
+; CHECK-LABEL: @non_eq_xor_fail(
+; CHECK-NEXT: [[Y:%.*]] = add nsw 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]]
+;
+ %y = add nsw i8 %yy, 1
+ %lhs = add i8 %x, %w
+ %val = xor i8 %y, %w
+ %rhs = add i8 %x, %val
+ %r = icmp eq i8 %lhs, %rhs
+ ret i1 %r
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/87706
More information about the llvm-commits
mailing list