[llvm] 81cdd35 - [ValueTracking] Add support for `xor`/`disjoint or` in `isKnownNonZero`

Noah Goldstein via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 10 11:14:07 PDT 2024


Author: Noah Goldstein
Date: 2024-04-10T13:13:43-05:00
New Revision: 81cdd35c0c8db22bfdd1f06cb2118d17fd99fc07

URL: https://github.com/llvm/llvm-project/commit/81cdd35c0c8db22bfdd1f06cb2118d17fd99fc07
DIFF: https://github.com/llvm/llvm-project/commit/81cdd35c0c8db22bfdd1f06cb2118d17fd99fc07.diff

LOG: [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 #87706

Added: 
    

Modified: 
    llvm/lib/Analysis/ValueTracking.cpp
    llvm/test/Transforms/InstSimplify/icmp.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp
index f3ea73b2f0ec4d..3a10de72a27562 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<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
@@ -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 530dc16144eba9..c94922197096f2 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


        


More information about the llvm-commits mailing list