[llvm] [Analysis][ValueTracking] Unify most of the tracking between AssumptionCache and DomConditionCache (PR #83161)

via llvm-commits llvm-commits at lists.llvm.org
Fri Mar 1 10:52:11 PST 2024


https://github.com/goldsteinn updated https://github.com/llvm/llvm-project/pull/83161

>From 6c53b960a16174a89b2458a5765ff370e48ec121 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Mon, 26 Feb 2024 15:54:04 -0600
Subject: [PATCH 1/3] [Analysis] Move `DomConditionCache::findAffectedValues`
 to a new file; NFC

---
 .../llvm/Analysis/ConditionCacheUtil.h        | 83 +++++++++++++++++++
 llvm/lib/Analysis/DomConditionCache.cpp       | 67 +--------------
 2 files changed, 86 insertions(+), 64 deletions(-)
 create mode 100644 llvm/include/llvm/Analysis/ConditionCacheUtil.h

diff --git a/llvm/include/llvm/Analysis/ConditionCacheUtil.h b/llvm/include/llvm/Analysis/ConditionCacheUtil.h
new file mode 100644
index 00000000000000..e3e2e98088f30c
--- /dev/null
+++ b/llvm/include/llvm/Analysis/ConditionCacheUtil.h
@@ -0,0 +1,83 @@
+#ifndef LLVM_ANALYSIS_CONDITIONCACHEUTIL_H
+#define LLVM_ANALYSIS_CONDITIONCACHEUTIL_H
+
+#include "llvm/IR/PatternMatch.h"
+#include <functional>
+
+namespace llvm {
+
+static void
+addValueAffectedByCondition(Value *V,
+                            function_ref<void(Value *)> InsertAffected) {
+  using namespace llvm::PatternMatch;
+  assert(V != nullptr);
+  if (isa<Argument>(V) || isa<GlobalValue>(V)) {
+    InsertAffected(V);
+  } else if (auto *I = dyn_cast<Instruction>(V)) {
+    InsertAffected(V);
+
+    // Peek through unary operators to find the source of the condition.
+    Value *Op;
+    if (match(I, m_PtrToInt(m_Value(Op)))) {
+      if (isa<Instruction>(Op) || isa<Argument>(Op))
+        InsertAffected(Op);
+    }
+  }
+}
+
+static void
+findValuesAffectedByCondition(Value *Cond, bool IsAssume,
+                              function_ref<void(Value *)> InsertAffected) {
+  using namespace llvm::PatternMatch;
+  auto AddAffected = [&InsertAffected](Value *V) {
+    addValueAffectedByCondition(V, InsertAffected);
+  };
+
+  assert(!IsAssume);
+  SmallVector<Value *, 8> Worklist;
+  SmallPtrSet<Value *, 8> Visited;
+  Worklist.push_back(Cond);
+  while (!Worklist.empty()) {
+    Value *V = Worklist.pop_back_val();
+    if (!Visited.insert(V).second)
+      continue;
+
+    CmpInst::Predicate Pred;
+    Value *A, *B;
+    if (match(V, m_LogicalOp(m_Value(A), m_Value(B)))) {
+      Worklist.push_back(A);
+      Worklist.push_back(B);
+    } else if (match(V, m_ICmp(Pred, m_Value(A), m_Constant()))) {
+      AddAffected(A);
+
+      if (ICmpInst::isEquality(Pred)) {
+        Value *X;
+        // (X & C) or (X | C) or (X ^ C).
+        // (X << C) or (X >>_s C) or (X >>_u C).
+        if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
+            match(A, m_Shift(m_Value(X), m_ConstantInt())))
+          AddAffected(X);
+      } else {
+        Value *X;
+        // Handle (A + C1) u< C2, which is the canonical form of
+        // A > C3 && A < C4.
+        if (match(A, m_Add(m_Value(X), m_ConstantInt())))
+          AddAffected(X);
+        // Handle icmp slt/sgt (bitcast X to int), 0/-1, which is supported by
+        // computeKnownFPClass().
+        if ((Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGT) &&
+            match(A, m_ElementWiseBitCast(m_Value(X))))
+          InsertAffected(X);
+      }
+    } else if (match(Cond, m_CombineOr(m_FCmp(Pred, m_Value(A), m_Constant()),
+                                       m_Intrinsic<Intrinsic::is_fpclass>(
+                                           m_Value(A), m_Constant())))) {
+      // Handle patterns that computeKnownFPClass() support.
+      AddAffected(A);
+    }
+  }
+}
+
+} // namespace llvm
+
+#endif // LLVM_ANALYSIS_CONDITIONCACHEUTIL_H
diff --git a/llvm/lib/Analysis/DomConditionCache.cpp b/llvm/lib/Analysis/DomConditionCache.cpp
index da05e02b4b57f7..0cfee2c894bc86 100644
--- a/llvm/lib/Analysis/DomConditionCache.cpp
+++ b/llvm/lib/Analysis/DomConditionCache.cpp
@@ -7,75 +7,14 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Analysis/DomConditionCache.h"
-#include "llvm/IR/PatternMatch.h"
+#include "llvm/Analysis/ConditionCacheUtil.h"
 
 using namespace llvm;
-using namespace llvm::PatternMatch;
 
-// TODO: This code is very similar to findAffectedValues() in
-// AssumptionCache, but currently specialized to just the patterns that
-// computeKnownBits() supports, and without the notion of result elem indices
-// that are AC specific. Deduplicate this code once we have a clearer picture
-// of how much they can be shared.
 static void findAffectedValues(Value *Cond,
                                SmallVectorImpl<Value *> &Affected) {
-  auto AddAffected = [&Affected](Value *V) {
-    if (isa<Argument>(V) || isa<GlobalValue>(V)) {
-      Affected.push_back(V);
-    } else if (auto *I = dyn_cast<Instruction>(V)) {
-      Affected.push_back(I);
-
-      // Peek through unary operators to find the source of the condition.
-      Value *Op;
-      if (match(I, m_PtrToInt(m_Value(Op)))) {
-        if (isa<Instruction>(Op) || isa<Argument>(Op))
-          Affected.push_back(Op);
-      }
-    }
-  };
-
-  SmallVector<Value *, 8> Worklist;
-  SmallPtrSet<Value *, 8> Visited;
-  Worklist.push_back(Cond);
-  while (!Worklist.empty()) {
-    Value *V = Worklist.pop_back_val();
-    if (!Visited.insert(V).second)
-      continue;
-
-    CmpInst::Predicate Pred;
-    Value *A, *B;
-    if (match(V, m_LogicalOp(m_Value(A), m_Value(B)))) {
-      Worklist.push_back(A);
-      Worklist.push_back(B);
-    } else if (match(V, m_ICmp(Pred, m_Value(A), m_Constant()))) {
-      AddAffected(A);
-
-      if (ICmpInst::isEquality(Pred)) {
-        Value *X;
-        // (X & C) or (X | C) or (X ^ C).
-        // (X << C) or (X >>_s C) or (X >>_u C).
-        if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
-            match(A, m_Shift(m_Value(X), m_ConstantInt())))
-          AddAffected(X);
-      } else {
-        Value *X;
-        // Handle (A + C1) u< C2, which is the canonical form of
-        // A > C3 && A < C4.
-        if (match(A, m_Add(m_Value(X), m_ConstantInt())))
-          AddAffected(X);
-        // Handle icmp slt/sgt (bitcast X to int), 0/-1, which is supported by
-        // computeKnownFPClass().
-        if ((Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGT) &&
-            match(A, m_ElementWiseBitCast(m_Value(X))))
-          Affected.push_back(X);
-      }
-    } else if (match(Cond, m_CombineOr(m_FCmp(Pred, m_Value(A), m_Constant()),
-                                       m_Intrinsic<Intrinsic::is_fpclass>(
-                                           m_Value(A), m_Constant())))) {
-      // Handle patterns that computeKnownFPClass() support.
-      AddAffected(A);
-    }
-  }
+  auto InsertAffected = [&Affected](Value *V) { Affected.push_back(V); };
+  findValuesAffectedByCondition(Cond, /*IsAssume*/ false, InsertAffected);
 }
 
 void DomConditionCache::registerBranch(BranchInst *BI) {

>From 28e6568d83c7e7cfdb1679ca9adc655c86b15608 Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Mon, 26 Feb 2024 16:19:48 -0600
Subject: [PATCH 2/3] [Analysis] Share `findAffectedValues` between
 DomConditionCache and AssumptionCache; NFC

---
 .../llvm/Analysis/ConditionCacheUtil.h        | 83 +++++++++++++------
 llvm/lib/Analysis/AssumptionCache.cpp         | 77 ++++-------------
 2 files changed, 72 insertions(+), 88 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ConditionCacheUtil.h b/llvm/include/llvm/Analysis/ConditionCacheUtil.h
index e3e2e98088f30c..e827cdda4cb226 100644
--- a/llvm/include/llvm/Analysis/ConditionCacheUtil.h
+++ b/llvm/include/llvm/Analysis/ConditionCacheUtil.h
@@ -33,7 +33,6 @@ findValuesAffectedByCondition(Value *Cond, bool IsAssume,
     addValueAffectedByCondition(V, InsertAffected);
   };
 
-  assert(!IsAssume);
   SmallVector<Value *, 8> Worklist;
   SmallPtrSet<Value *, 8> Visited;
   Worklist.push_back(Cond);
@@ -43,35 +42,67 @@ findValuesAffectedByCondition(Value *Cond, bool IsAssume,
       continue;
 
     CmpInst::Predicate Pred;
-    Value *A, *B;
-    if (match(V, m_LogicalOp(m_Value(A), m_Value(B)))) {
+    Value *A, *B, *X;
+
+    if (IsAssume)
+      AddAffected(V);
+
+    if (IsAssume && match(V, m_Not(m_Value(X))))
+      AddAffected(X);
+    if (!IsAssume && match(V, m_LogicalOp(m_Value(A), m_Value(B)))) {
       Worklist.push_back(A);
       Worklist.push_back(B);
-    } else if (match(V, m_ICmp(Pred, m_Value(A), m_Constant()))) {
-      AddAffected(A);
+    } else if (match(V, m_Cmp(Pred, m_Value(A), m_Value(B))) &&
+               (IsAssume || isa<ICmpInst>(V))) {
+      if (IsAssume || match(B, m_Constant())) {
+        AddAffected(A);
+        if (IsAssume)
+          AddAffected(B);
+
+        if (IsAssume ? (Pred == ICmpInst::ICMP_EQ)
+                     : ICmpInst::isEquality(Pred)) {
+          if (match(B, m_ConstantInt())) {
+            // (X & C) or (X | C) or (X ^ C).
+            // (X << C) or (X >>_s C) or (X >>_u C).
+            if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
+                match(A, m_Shift(m_Value(X), m_ConstantInt())))
+              AddAffected(X);
+          }
+        } else {
+          if (Pred == ICmpInst::ICMP_NE)
+            if (match(A, m_And(m_Value(X), m_Power2())) && match(B, m_Zero()))
+              AddAffected(X);
+
+          if (!IsAssume || Pred == ICmpInst::ICMP_ULT) {
+            // Handle (A + C1) u< C2, which is the canonical form of
+            // A > C3 && A < C4.
+            if (match(A, m_Add(m_Value(X), m_ConstantInt())) &&
+                match(B, m_ConstantInt()))
+              AddAffected(X);
+          }
+          if (!IsAssume) {
+            // Handle icmp slt/sgt (bitcast X to int), 0/-1, which is supported
+            // by computeKnownFPClass().
+            if ((Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGT) &&
+                match(A, m_ElementWiseBitCast(m_Value(X))))
+              InsertAffected(X);
+          }
 
-      if (ICmpInst::isEquality(Pred)) {
-        Value *X;
-        // (X & C) or (X | C) or (X ^ C).
-        // (X << C) or (X >>_s C) or (X >>_u C).
-        if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
-            match(A, m_Shift(m_Value(X), m_ConstantInt())))
-          AddAffected(X);
-      } else {
-        Value *X;
-        // Handle (A + C1) u< C2, which is the canonical form of
-        // A > C3 && A < C4.
-        if (match(A, m_Add(m_Value(X), m_ConstantInt())))
-          AddAffected(X);
-        // Handle icmp slt/sgt (bitcast X to int), 0/-1, which is supported by
-        // computeKnownFPClass().
-        if ((Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGT) &&
-            match(A, m_ElementWiseBitCast(m_Value(X))))
-          InsertAffected(X);
+          if (IsAssume && CmpInst::isFPPredicate(Pred)) {
+            // fcmp fneg(x), y
+            // fcmp fabs(x), y
+            // fcmp fneg(fabs(x)), y
+            if (match(A, m_FNeg(m_Value(A))))
+              AddAffected(A);
+            if (match(A, m_FAbs(m_Value(A))))
+              AddAffected(A);
+          }
+        }
       }
-    } else if (match(Cond, m_CombineOr(m_FCmp(Pred, m_Value(A), m_Constant()),
-                                       m_Intrinsic<Intrinsic::is_fpclass>(
-                                           m_Value(A), m_Constant())))) {
+    } else if ((!IsAssume &&
+                match(Cond, m_FCmp(Pred, m_Value(A), m_Constant()))) ||
+               match(Cond, m_Intrinsic<Intrinsic::is_fpclass>(m_Value(A),
+                                                              m_Value(B)))) {
       // Handle patterns that computeKnownFPClass() support.
       AddAffected(A);
     }
diff --git a/llvm/lib/Analysis/AssumptionCache.cpp b/llvm/lib/Analysis/AssumptionCache.cpp
index 1b7277df0e0cd0..1fbb81f6a173e8 100644
--- a/llvm/lib/Analysis/AssumptionCache.cpp
+++ b/llvm/lib/Analysis/AssumptionCache.cpp
@@ -16,6 +16,7 @@
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/Analysis/AssumeBundleQueries.h"
+#include "llvm/Analysis/ConditionCacheUtil.h"
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/IR/BasicBlock.h"
@@ -61,85 +62,37 @@ findAffectedValues(CallBase *CI, TargetTransformInfo *TTI,
   // Note: This code must be kept in-sync with the code in
   // computeKnownBitsFromAssume in ValueTracking.
 
-  auto AddAffected = [&Affected](Value *V, unsigned Idx =
-                                               AssumptionCache::ExprResultIdx) {
-    if (isa<Argument>(V) || isa<GlobalValue>(V)) {
-      Affected.push_back({V, Idx});
-    } else if (auto *I = dyn_cast<Instruction>(V)) {
-      Affected.push_back({I, Idx});
-
-      // Peek through unary operators to find the source of the condition.
-      Value *Op;
-      if (match(I, m_PtrToInt(m_Value(Op)))) {
-        if (isa<Instruction>(Op) || isa<Argument>(Op))
-          Affected.push_back({Op, Idx});
-      }
-    }
+  auto InsertAffected = [&Affected](Value *V) {
+    Affected.push_back({V, AssumptionCache::ExprResultIdx});
   };
 
   for (unsigned Idx = 0; Idx != CI->getNumOperandBundles(); Idx++) {
+    auto AddAffectedBundleVal = [&Affected](Value *V, unsigned Idx) {
+      if (isa<Argument>(V) || isa<GlobalValue>(V) || isa<Instruction>(V)) {
+        Affected.push_back({V, Idx});
+      }
+    };
     OperandBundleUse Bundle = CI->getOperandBundleAt(Idx);
     if (Bundle.getTagName() == "separate_storage") {
       assert(Bundle.Inputs.size() == 2 &&
              "separate_storage must have two args");
-      AddAffected(getUnderlyingObject(Bundle.Inputs[0]), Idx);
-      AddAffected(getUnderlyingObject(Bundle.Inputs[1]), Idx);
+      AddAffectedBundleVal(getUnderlyingObject(Bundle.Inputs[0]), Idx);
+      AddAffectedBundleVal(getUnderlyingObject(Bundle.Inputs[1]), Idx);
     } else if (Bundle.Inputs.size() > ABA_WasOn &&
                Bundle.getTagName() != IgnoreBundleTag)
-      AddAffected(Bundle.Inputs[ABA_WasOn], Idx);
+      AddAffectedBundleVal(Bundle.Inputs[ABA_WasOn], Idx);
   }
 
-  Value *Cond = CI->getArgOperand(0), *A, *B;
-  AddAffected(Cond);
-  if (match(Cond, m_Not(m_Value(A))))
-    AddAffected(A);
-
-  CmpInst::Predicate Pred;
-  if (match(Cond, m_Cmp(Pred, m_Value(A), m_Value(B)))) {
-    AddAffected(A);
-    AddAffected(B);
-
-    if (Pred == ICmpInst::ICMP_EQ) {
-      if (match(B, m_ConstantInt())) {
-        Value *X;
-        // (X & C) or (X | C) or (X ^ C).
-        // (X << C) or (X >>_s C) or (X >>_u C).
-        if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
-            match(A, m_Shift(m_Value(X), m_ConstantInt())))
-          AddAffected(X);
-      }
-    } else if (Pred == ICmpInst::ICMP_NE) {
-      Value *X;
-      // Handle (X & pow2 != 0).
-      if (match(A, m_And(m_Value(X), m_Power2())) && match(B, m_Zero()))
-        AddAffected(X);
-    } else if (Pred == ICmpInst::ICMP_ULT) {
-      Value *X;
-      // Handle (A + C1) u< C2, which is the canonical form of A > C3 && A < C4,
-      // and recognized by LVI at least.
-      if (match(A, m_Add(m_Value(X), m_ConstantInt())) &&
-          match(B, m_ConstantInt()))
-        AddAffected(X);
-    } else if (CmpInst::isFPPredicate(Pred)) {
-      // fcmp fneg(x), y
-      // fcmp fabs(x), y
-      // fcmp fneg(fabs(x)), y
-      if (match(A, m_FNeg(m_Value(A))))
-        AddAffected(A);
-      if (match(A, m_FAbs(m_Value(A))))
-        AddAffected(A);
-    }
-  } else if (match(Cond, m_Intrinsic<Intrinsic::is_fpclass>(m_Value(A),
-                                                            m_Value(B)))) {
-    AddAffected(A);
-  }
+  Value *Cond = CI->getArgOperand(0);
+  findValuesAffectedByCondition(Cond, /*IsAssume*/ true, InsertAffected);
 
   if (TTI) {
     const Value *Ptr;
     unsigned AS;
     std::tie(Ptr, AS) = TTI->getPredicatedAddrSpace(Cond);
     if (Ptr)
-      AddAffected(const_cast<Value *>(Ptr->stripInBoundsOffsets()));
+      addValueAffectedByCondition(
+          const_cast<Value *>(Ptr->stripInBoundsOffsets()), InsertAffected);
   }
 }
 

>From d95e97609b15dc13a2d20dc9edb0257b742af86b Mon Sep 17 00:00:00 2001
From: Noah Goldstein <goldstein.w.n at gmail.com>
Date: Mon, 26 Feb 2024 16:30:39 -0600
Subject: [PATCH 3/3] [Analysis] Unify most of the tracking between
 AssumptionCache and DomConditionCache

This helps cover some missing cases in both and hopefully serves as
creating an easier framework for extending general condition based
analysis.
---
 .../llvm/Analysis/ConditionCacheUtil.h        | 129 ++++++++++--------
 .../ValueTracking/numsignbits-from-assume.ll  |   2 +-
 .../InstCombine/fpclass-from-dom-cond.ll      |   5 +-
 3 files changed, 77 insertions(+), 59 deletions(-)

diff --git a/llvm/include/llvm/Analysis/ConditionCacheUtil.h b/llvm/include/llvm/Analysis/ConditionCacheUtil.h
index e827cdda4cb226..fa856083b13ebb 100644
--- a/llvm/include/llvm/Analysis/ConditionCacheUtil.h
+++ b/llvm/include/llvm/Analysis/ConditionCacheUtil.h
@@ -1,6 +1,20 @@
+//===- llvm/Analysis/ConditionCacheUtil.h -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Shared by DomConditionCache and AssumptionCache. Holds common operation of
+// finding values potentially affected by an assumed/branched on condition.
+//
+//===----------------------------------------------------------------------===//
+
 #ifndef LLVM_ANALYSIS_CONDITIONCACHEUTIL_H
 #define LLVM_ANALYSIS_CONDITIONCACHEUTIL_H
 
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/PatternMatch.h"
 #include <functional>
 
@@ -33,6 +47,14 @@ findValuesAffectedByCondition(Value *Cond, bool IsAssume,
     addValueAffectedByCondition(V, InsertAffected);
   };
 
+  auto AddCmpOperands = [&AddAffected, IsAssume](Value *LHS, Value *RHS) {
+    if (IsAssume) {
+      AddAffected(LHS);
+      AddAffected(RHS);
+    } else if (match(RHS, m_Constant()))
+      AddAffected(LHS);
+  };
+
   SmallVector<Value *, 8> Worklist;
   SmallPtrSet<Value *, 8> Visited;
   Worklist.push_back(Cond);
@@ -44,65 +66,62 @@ findValuesAffectedByCondition(Value *Cond, bool IsAssume,
     CmpInst::Predicate Pred;
     Value *A, *B, *X;
 
-    if (IsAssume)
+    if (IsAssume) {
       AddAffected(V);
+      if (match(V, m_Not(m_Value(X))))
+        AddAffected(X);
+    }
 
-    if (IsAssume && match(V, m_Not(m_Value(X))))
-      AddAffected(X);
-    if (!IsAssume && match(V, m_LogicalOp(m_Value(A), m_Value(B)))) {
-      Worklist.push_back(A);
-      Worklist.push_back(B);
-    } else if (match(V, m_Cmp(Pred, m_Value(A), m_Value(B))) &&
-               (IsAssume || isa<ICmpInst>(V))) {
-      if (IsAssume || match(B, m_Constant())) {
-        AddAffected(A);
-        if (IsAssume)
-          AddAffected(B);
-
-        if (IsAssume ? (Pred == ICmpInst::ICMP_EQ)
-                     : ICmpInst::isEquality(Pred)) {
-          if (match(B, m_ConstantInt())) {
-            // (X & C) or (X | C) or (X ^ C).
-            // (X << C) or (X >>_s C) or (X >>_u C).
-            if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
-                match(A, m_Shift(m_Value(X), m_ConstantInt())))
-              AddAffected(X);
-          }
-        } else {
-          if (Pred == ICmpInst::ICMP_NE)
-            if (match(A, m_And(m_Value(X), m_Power2())) && match(B, m_Zero()))
-              AddAffected(X);
-
-          if (!IsAssume || Pred == ICmpInst::ICMP_ULT) {
-            // Handle (A + C1) u< C2, which is the canonical form of
-            // A > C3 && A < C4.
-            if (match(A, m_Add(m_Value(X), m_ConstantInt())) &&
-                match(B, m_ConstantInt()))
-              AddAffected(X);
-          }
-          if (!IsAssume) {
-            // Handle icmp slt/sgt (bitcast X to int), 0/-1, which is supported
-            // by computeKnownFPClass().
-            if ((Pred == ICmpInst::ICMP_SLT || Pred == ICmpInst::ICMP_SGT) &&
-                match(A, m_ElementWiseBitCast(m_Value(X))))
-              InsertAffected(X);
-          }
-
-          if (IsAssume && CmpInst::isFPPredicate(Pred)) {
-            // fcmp fneg(x), y
-            // fcmp fabs(x), y
-            // fcmp fneg(fabs(x)), y
-            if (match(A, m_FNeg(m_Value(A))))
-              AddAffected(A);
-            if (match(A, m_FAbs(m_Value(A))))
-              AddAffected(A);
-          }
+    if (match(V, m_LogicalOp(m_Value(A), m_Value(B)))) {
+      // assume(A && B) is split to -> assume(A); assume(B);
+      // assume(!(A || B)) is split to -> assume(!A); assume(!B);
+      // Finally, assume(A || B) / assume(!(A && B)) generally don't provide
+      // enough information to be worth handling (intersection of information as
+      // opposed to union).
+      if (!IsAssume) {
+        Worklist.push_back(A);
+        Worklist.push_back(B);
+      }
+    } else if (match(V, m_ICmp(Pred, m_Value(A), m_Value(B)))) {
+      AddCmpOperands(A, B);
+
+      if (ICmpInst::isEquality(Pred)) {
+        if (match(B, m_ConstantInt())) {
+          // (X & C) or (X | C) or (X ^ C).
+          // (X << C) or (X >>_s C) or (X >>_u C).
+          if (match(A, m_BitwiseLogic(m_Value(X), m_ConstantInt())) ||
+              match(A, m_Shift(m_Value(X), m_ConstantInt())))
+            AddAffected(X);
+        }
+      } else {
+        // Handle (A + C1) u< C2, which is the canonical form of
+        // A > C3 && A < C4.
+        if (match(A, m_Add(m_Value(X), m_ConstantInt())) &&
+            match(B, m_ConstantInt()))
+          AddAffected(X);
+
+        // Handle icmp slt/sgt (bitcast X to int), 0/-1, which is supported
+        // by computeKnownFPClass().
+        if (match(A, m_ElementWiseBitCast(m_Value(X)))) {
+          if (Pred == ICmpInst::ICMP_SLT && match(B, m_Zero()))
+            InsertAffected(X);
+          else if (Pred == ICmpInst::ICMP_SGT && match(B, m_AllOnes()))
+            InsertAffected(X);
         }
       }
-    } else if ((!IsAssume &&
-                match(Cond, m_FCmp(Pred, m_Value(A), m_Constant()))) ||
-               match(Cond, m_Intrinsic<Intrinsic::is_fpclass>(m_Value(A),
-                                                              m_Value(B)))) {
+    } else if (match(Cond, m_FCmp(Pred, m_Value(A), m_Value(B)))) {
+      AddCmpOperands(A, B);
+
+      // fcmp fneg(x), y
+      // fcmp fabs(x), y
+      // fcmp fneg(fabs(x)), y
+      if (match(A, m_FNeg(m_Value(A))))
+        AddAffected(A);
+      if (match(A, m_FAbs(m_Value(A))))
+        AddAffected(A);
+
+    } else if (match(V, m_Intrinsic<Intrinsic::is_fpclass>(m_Value(A),
+                                                           m_Value()))) {
       // Handle patterns that computeKnownFPClass() support.
       AddAffected(A);
     }
diff --git a/llvm/test/Analysis/ValueTracking/numsignbits-from-assume.ll b/llvm/test/Analysis/ValueTracking/numsignbits-from-assume.ll
index 00c66eeb599572..95ac98532da621 100644
--- a/llvm/test/Analysis/ValueTracking/numsignbits-from-assume.ll
+++ b/llvm/test/Analysis/ValueTracking/numsignbits-from-assume.ll
@@ -51,7 +51,7 @@ define i32 @computeNumSignBits_sub1(i32 %in) {
 
 define i32 @computeNumSignBits_sub2(i32 %in) {
 ; CHECK-LABEL: @computeNumSignBits_sub2(
-; CHECK-NEXT:    [[SUB:%.*]] = add i32 [[IN:%.*]], -1
+; CHECK-NEXT:    [[SUB:%.*]] = add nsw i32 [[IN:%.*]], -1
 ; CHECK-NEXT:    [[COND:%.*]] = icmp ult i32 [[SUB]], 43
 ; CHECK-NEXT:    call void @llvm.assume(i1 [[COND]])
 ; CHECK-NEXT:    [[SH:%.*]] = shl nuw nsw i32 [[SUB]], 3
diff --git a/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll b/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll
index d40cd7fd503ecc..d6706d76056eea 100644
--- a/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll
+++ b/llvm/test/Transforms/InstCombine/fpclass-from-dom-cond.ll
@@ -185,10 +185,9 @@ define i1 @test8(float %x) {
 ; CHECK-NEXT:    [[COND:%.*]] = fcmp oeq float [[ABS]], 0x7FF0000000000000
 ; CHECK-NEXT:    br i1 [[COND]], label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
 ; CHECK:       if.then:
-; CHECK-NEXT:    [[RET1:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 575)
-; CHECK-NEXT:    ret i1 [[RET1]]
+; CHECK-NEXT:    ret i1 true
 ; CHECK:       if.else:
-; CHECK-NEXT:    [[RET2:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 575)
+; CHECK-NEXT:    [[RET2:%.*]] = call i1 @llvm.is.fpclass.f32(float [[X]], i32 59)
 ; CHECK-NEXT:    ret i1 [[RET2]]
 ;
   %abs = call float @llvm.fabs.f32(float %x)



More information about the llvm-commits mailing list