[PATCH] D142427: [ValueTracking] Add logic for tracking lowbit of (and/xor/or X, (add/sub X, Odd))

Noah Goldstein via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 29 14:09:30 PST 2023


goldstein.w.n updated this revision to Diff 493146.
goldstein.w.n added a comment.

Rebase after splitting


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D142427/new/

https://reviews.llvm.org/D142427

Files:
  llvm/lib/Analysis/ValueTracking.cpp
  llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll


Index: llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll
===================================================================
--- llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll
+++ llvm/test/Analysis/ValueTracking/knownbits-and-or-xor-lowbit.ll
@@ -25,10 +25,7 @@
 
 define i32 @cmp_ne_0_sub_xor_eval(i32 %x, i32 %C) {
 ; CHECK-LABEL: @cmp_ne_0_sub_xor_eval(
-; CHECK-NEXT:    [[Y:%.*]] = add i32 [[X:%.*]], 1
-; CHECK-NEXT:    [[Z:%.*]] = xor i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[B:%.*]] = and i32 [[Z]], 1
-; CHECK-NEXT:    ret i32 [[B]]
+; CHECK-NEXT:    ret i32 1
 ;
   %C1 = or i32 %C, 13
   %y = sub i32 %x, %C1
@@ -50,10 +47,7 @@
 
 define i32 @cmp_ne_0_sub_or_eval(i32 %x, i32 %C) {
 ; CHECK-LABEL: @cmp_ne_0_sub_or_eval(
-; CHECK-NEXT:    [[Y:%.*]] = add i32 [[X:%.*]], 1
-; CHECK-NEXT:    [[Z:%.*]] = or i32 [[Y]], [[X]]
-; CHECK-NEXT:    [[B:%.*]] = and i32 [[Z]], 1
-; CHECK-NEXT:    ret i32 [[B]]
+; CHECK-NEXT:    ret i32 1
 ;
   %C1 = or i32 %C, 5
   %y = sub i32 %x, %C1
Index: llvm/lib/Analysis/ValueTracking.cpp
===================================================================
--- llvm/lib/Analysis/ValueTracking.cpp
+++ llvm/lib/Analysis/ValueTracking.cpp
@@ -1110,16 +1110,23 @@
   }
 
   // and(x, add (x, -1)) is a common idiom that always clears the low bit;
+  // xor/or(x, add (x, -1)) is an idiom that will always set the low bit.
   // here we handle the more general case of adding any odd number by
-  // matching the form and(x, add(x, y)) where y is odd.
+  // matching the form and/xor/or(x, add(x, y)) where y is odd.
   // TODO: This could be generalized to clearing any bit set in y where the
   // following bit is known to be unset in y.
-  if (IsAnd && !KnownOut.Zero[0] && !KnownOut.One[0] &&
-      match(I, m_c_BinOp(m_Value(X), m_c_Add(m_Deferred(X), m_Value(Y))))) {
+  if (!KnownOut.Zero[0] && !KnownOut.One[0] &&
+      (match(I, m_c_BinOp(m_Value(X), m_c_Add(m_Deferred(X), m_Value(Y)))) ||
+       match(I, m_c_BinOp(m_Value(X), m_Sub(m_Deferred(X), m_Value(Y)))) ||
+       match(I, m_c_BinOp(m_Value(X), m_Sub(m_Value(Y), m_Deferred(X)))))) {
     KnownBits KnownY(BitWidth);
     computeKnownBits(Y, DemandedElts, KnownY, Depth + 1, Q);
-    if (KnownY.countMinTrailingOnes() > 0)
-      KnownOut.Zero.setBit(0);
+    if (KnownY.countMinTrailingOnes() > 0) {
+      if (IsAnd)
+        KnownOut.Zero.setBit(0);
+      else
+        KnownOut.One.setBit(0);
+    }
   }
   return KnownOut;
 }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D142427.493146.patch
Type: text/x-patch
Size: 2474 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230129/6062dfcf/attachment.bin>


More information about the llvm-commits mailing list