[NFC] Split Knowledge retention and place it more appropriatly

Summary:
Splitting Knowledge retention into Queries in Analysis and Builder into Transform/Utils
allows Queries and Transform/Utils to use Analysis.

Reviewers: jdoerfert, sstefan1

Reviewed By: jdoerfert

Subscribers: mgorny, hiraditya, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D77171
diff --git a/llvm/include/llvm/IR/KnowledgeRetention.h b/llvm/include/llvm/Analysis/AssumeBundleQueries.h
similarity index 84%
rename from llvm/include/llvm/IR/KnowledgeRetention.h
rename to llvm/include/llvm/Analysis/AssumeBundleQueries.h
index 0942d79..c2083e9 100644
--- a/llvm/include/llvm/IR/KnowledgeRetention.h
+++ b/llvm/include/llvm/Analysis/AssumeBundleQueries.h
@@ -1,4 +1,4 @@
-//===- KnowledgeRetention.h - utilities to preserve informations *- C++ -*-===//
+//===- AssumeBundleQueries.h - utilities to query assume bundles *- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,19 +6,16 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This file contain tools to preserve informations. They should be used before
-// performing a transformation that may move and delete instructions as those
-// transformation may destroy or worsen information that can be derived from the
-// IR.
+// This file contain tools to query into assume bundles. assume bundles can be
+// built using utilities from Transform/Utils/AssumeBundleBuilder.h
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef LLVM_TRANSFORMS_UTILS_ASSUMEBUILDER_H
-#define LLVM_TRANSFORMS_UTILS_ASSUMEBUILDER_H
+#ifndef LLVM_TRANSFORMS_UTILS_ASSUMEBUNDLEQUERIES_H
+#define LLVM_TRANSFORMS_UTILS_ASSUMEBUNDLEQUERIES_H
 
 #include "llvm/IR/Attributes.h"
-#include "llvm/IR/Instruction.h"
-#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/ADT/DenseMap.h"
 
 namespace llvm {
@@ -35,6 +32,14 @@
 /// contained in the instruction I.
 void salvageKnowledge(Instruction *I);
 
+/// Index of elements in the operand bundle.
+/// If the element exist it is guaranteed to be what is specified in this enum
+/// but it may not exist.
+enum AssumeBundleArg {
+  ABA_WasOn = 0,
+  ABA_Argument = 1,
+};
+
 /// It is possible to have multiple Value for the argument of an attribute in
 /// the same llvm.assume on the same llvm::Value. This is rare but need to be
 /// dealt with.
@@ -135,16 +140,6 @@
 /// function returned true.
 bool isAssumeWithEmptyBundle(CallInst &Assume);
 
-//===----------------------------------------------------------------------===//
-// Utilities for testing
-//===----------------------------------------------------------------------===//
-
-/// This pass will try to build an llvm.assume for every instruction in the
-/// function. Its main purpose is testing.
-struct AssumeBuilderPass : public PassInfoMixin<AssumeBuilderPass> {
-  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
-};
-
 } // namespace llvm
 
 #endif
diff --git a/llvm/include/llvm/Transforms/IPO/Attributor.h b/llvm/include/llvm/Transforms/IPO/Attributor.h
index 3b0dad0..b0c7db2 100644
--- a/llvm/include/llvm/Transforms/IPO/Attributor.h
+++ b/llvm/include/llvm/Transforms/IPO/Attributor.h
@@ -101,6 +101,7 @@
 #include "llvm/ADT/SCCIterator.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/AssumeBundleQueries.h"
 #include "llvm/Analysis/CGSCCPassManager.h"
 #include "llvm/Analysis/CallGraph.h"
 #include "llvm/Analysis/InlineCost.h"
@@ -110,7 +111,6 @@
 #include "llvm/Analysis/TargetTransformInfo.h"
 #include "llvm/IR/CallSite.h"
 #include "llvm/IR/ConstantRange.h"
-#include "llvm/IR/KnowledgeRetention.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/Transforms/Utils/CallGraphUpdater.h"
diff --git a/llvm/include/llvm/Transforms/Utils/AssumeBundleBuilder.h b/llvm/include/llvm/Transforms/Utils/AssumeBundleBuilder.h
new file mode 100644
index 0000000..50f8919
--- /dev/null
+++ b/llvm/include/llvm/Transforms/Utils/AssumeBundleBuilder.h
@@ -0,0 +1,45 @@
+//===- AssumeBundleBuilder.h - utils to build assume bundles ----*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contain tools to preserve informations. They should be used before
+// performing a transformation that may move and delete instructions as those
+// transformation may destroy or worsen information that can be derived from the
+// IR.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TRANSFORMS_UTILS_ASSUMEBUNDLEBUILDER_H
+#define LLVM_TRANSFORMS_UTILS_ASSUMEBUNDLEBUILDER_H
+
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/PassManager.h"
+
+namespace llvm {
+class IntrinsicInst;
+
+/// Build a call to llvm.assume to preserve informations that can be derived
+/// from the given instruction.
+/// If no information derived from \p I, this call returns null.
+/// The returned instruction is not inserted anywhere.
+IntrinsicInst *buildAssumeFromInst(Instruction *I);
+
+/// Calls BuildAssumeFromInst and if the resulting llvm.assume is valid insert
+/// if before I. This is usually what need to be done to salvage the knowledge
+/// contained in the instruction I.
+void salvageKnowledge(Instruction *I);
+
+/// This pass will try to build an llvm.assume for every instruction in the
+/// function. Its main purpose is testing.
+struct AssumeBuilderPass : public PassInfoMixin<AssumeBuilderPass> {
+  PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/llvm/include/llvm/module.modulemap b/llvm/include/llvm/module.modulemap
index ff05f62..1709ee6e 100644
--- a/llvm/include/llvm/module.modulemap
+++ b/llvm/include/llvm/module.modulemap
@@ -272,7 +272,6 @@
   module IR_PatternMatch { header "IR/PatternMatch.h" export * }
   module IR_SafepointIRVerifier { header "IR/SafepointIRVerifier.h" export * }
   module IR_Statepoint { header "IR/Statepoint.h" export * }
-  module IR_KnowledgeRetention { header "IR/KnowledgeRetention.h" export * }
 
   export *
 }
diff --git a/llvm/lib/Analysis/AssumeBundleQueries.cpp b/llvm/lib/Analysis/AssumeBundleQueries.cpp
new file mode 100644
index 0000000..5521ac9
--- /dev/null
+++ b/llvm/lib/Analysis/AssumeBundleQueries.cpp
@@ -0,0 +1,120 @@
+//===- AssumeBundleQueries.cpp - tool to query assume bundles ---*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/AssumeBundleQueries.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/IntrinsicInst.h"
+
+using namespace llvm;
+
+static bool bundleHasArgument(const CallBase::BundleOpInfo &BOI, unsigned Idx) {
+  return BOI.End - BOI.Begin > Idx;
+}
+
+static Value *getValueFromBundleOpInfo(IntrinsicInst &Assume,
+                                       const CallBase::BundleOpInfo &BOI,
+                                       unsigned Idx) {
+  assert(bundleHasArgument(BOI, Idx) && "index out of range");
+  return (Assume.op_begin() + BOI.Begin + Idx)->get();
+}
+
+bool llvm::hasAttributeInAssume(CallInst &AssumeCI, Value *IsOn,
+                                StringRef AttrName, uint64_t *ArgVal,
+                                AssumeQuery AQR) {
+  assert(isa<IntrinsicInst>(AssumeCI) &&
+         "this function is intended to be used on llvm.assume");
+  IntrinsicInst &Assume = cast<IntrinsicInst>(AssumeCI);
+  assert(Assume.getIntrinsicID() == Intrinsic::assume &&
+         "this function is intended to be used on llvm.assume");
+  assert(Attribute::isExistingAttribute(AttrName) &&
+         "this attribute doesn't exist");
+  assert((ArgVal == nullptr || Attribute::doesAttrKindHaveArgument(
+                                   Attribute::getAttrKindFromName(AttrName))) &&
+         "requested value for an attribute that has no argument");
+  if (Assume.bundle_op_infos().empty())
+    return false;
+
+  auto Loop = [&](auto &&Range) {
+    for (auto &BOI : Range) {
+      if (BOI.Tag->getKey() != AttrName)
+        continue;
+      if (IsOn && (BOI.End - BOI.Begin <= ABA_WasOn ||
+                   IsOn != getValueFromBundleOpInfo(Assume, BOI, ABA_WasOn)))
+        continue;
+      if (ArgVal) {
+        assert(BOI.End - BOI.Begin > ABA_Argument);
+        *ArgVal = cast<ConstantInt>(
+                      getValueFromBundleOpInfo(Assume, BOI, ABA_Argument))
+                      ->getZExtValue();
+      }
+      return true;
+    }
+    return false;
+  };
+
+  if (AQR == AssumeQuery::Lowest)
+    return Loop(Assume.bundle_op_infos());
+  return Loop(reverse(Assume.bundle_op_infos()));
+}
+
+void llvm::fillMapFromAssume(CallInst &AssumeCI, RetainedKnowledgeMap &Result) {
+  IntrinsicInst &Assume = cast<IntrinsicInst>(AssumeCI);
+  assert(Assume.getIntrinsicID() == Intrinsic::assume &&
+         "this function is intended to be used on llvm.assume");
+  for (auto &Bundles : Assume.bundle_op_infos()) {
+    std::pair<Value *, Attribute::AttrKind> Key{
+        nullptr, Attribute::getAttrKindFromName(Bundles.Tag->getKey())};
+    if (bundleHasArgument(Bundles, ABA_WasOn))
+      Key.first = getValueFromBundleOpInfo(Assume, Bundles, ABA_WasOn);
+
+    if (Key.first == nullptr && Key.second == Attribute::None)
+      continue;
+    if (!bundleHasArgument(Bundles, ABA_Argument)) {
+      Result[Key][&Assume] = {0, 0};
+      continue;
+    }
+    unsigned Val = cast<ConstantInt>(
+                       getValueFromBundleOpInfo(Assume, Bundles, ABA_Argument))
+                       ->getZExtValue();
+    auto Lookup = Result.find(Key);
+    if (Lookup == Result.end() || !Lookup->second.count(&Assume)) {
+      Result[Key][&Assume] = {Val, Val};
+      continue;
+    }
+    Lookup->second[&Assume].Min = std::min(Val, Lookup->second[&Assume].Min);
+    Lookup->second[&Assume].Max = std::max(Val, Lookup->second[&Assume].Max);
+  }
+}
+
+RetainedKnowledge llvm::getKnowledgeFromOperandInAssume(CallInst &AssumeCI,
+                                                        unsigned Idx) {
+  IntrinsicInst &Assume = cast<IntrinsicInst>(AssumeCI);
+  assert(Assume.getIntrinsicID() == Intrinsic::assume &&
+         "this function is intended to be used on llvm.assume");
+  CallBase::BundleOpInfo BOI = Assume.getBundleOpInfoForOperand(Idx);
+  RetainedKnowledge Result;
+  Result.AttrKind = Attribute::getAttrKindFromName(BOI.Tag->getKey());
+  Result.WasOn = getValueFromBundleOpInfo(Assume, BOI, ABA_WasOn);
+  if (BOI.End - BOI.Begin > ABA_Argument)
+    Result.ArgValue =
+        cast<ConstantInt>(getValueFromBundleOpInfo(Assume, BOI, ABA_Argument))
+            ->getZExtValue();
+
+  return Result;
+}
+
+bool llvm::isAssumeWithEmptyBundle(CallInst &CI) {
+  IntrinsicInst &Assume = cast<IntrinsicInst>(CI);
+  assert(Assume.getIntrinsicID() == Intrinsic::assume &&
+         "this function is intended to be used on llvm.assume");
+  return none_of(Assume.bundle_op_infos(),
+                 [](const CallBase::BundleOpInfo &BOI) {
+                   return BOI.Tag->getKey() != "ignore";
+                 });
+}
diff --git a/llvm/lib/Analysis/CMakeLists.txt b/llvm/lib/Analysis/CMakeLists.txt
index 969049f..8a658aa 100644
--- a/llvm/lib/Analysis/CMakeLists.txt
+++ b/llvm/lib/Analysis/CMakeLists.txt
@@ -4,6 +4,7 @@
   AliasAnalysisSummary.cpp
   AliasSetTracker.cpp
   Analysis.cpp
+  AssumeBundleQueries.cpp
   AssumptionCache.cpp
   BasicAliasAnalysis.cpp
   BlockFrequencyInfo.cpp
diff --git a/llvm/lib/IR/CMakeLists.txt b/llvm/lib/IR/CMakeLists.txt
index 14207bc..8fcc10f 100644
--- a/llvm/lib/IR/CMakeLists.txt
+++ b/llvm/lib/IR/CMakeLists.txt
@@ -28,7 +28,6 @@
   Instruction.cpp
   Instructions.cpp
   IntrinsicInst.cpp
-  KnowledgeRetention.cpp
   LLVMContext.cpp
   LLVMContextImpl.cpp
   LLVMRemarkStreamer.cpp
diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp
index 57c510b..c56c3586 100644
--- a/llvm/lib/Passes/PassBuilder.cpp
+++ b/llvm/lib/Passes/PassBuilder.cpp
@@ -59,7 +59,6 @@
 #include "llvm/CodeGen/UnreachableBlockElim.h"
 #include "llvm/IR/Dominators.h"
 #include "llvm/IR/IRPrintingPasses.h"
-#include "llvm/IR/KnowledgeRetention.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/SafepointIRVerifier.h"
 #include "llvm/IR/Verifier.h"
@@ -176,6 +175,7 @@
 #include "llvm/Transforms/Scalar/TailRecursionElimination.h"
 #include "llvm/Transforms/Scalar/WarnMissedTransforms.h"
 #include "llvm/Transforms/Utils/AddDiscriminators.h"
+#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
 #include "llvm/Transforms/Utils/BreakCriticalEdges.h"
 #include "llvm/Transforms/Utils/CanonicalizeAliases.h"
 #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 4ad0f8d..4dbe517 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -22,6 +22,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/AssumeBundleQueries.h"
 #include "llvm/Analysis/AssumptionCache.h"
 #include "llvm/Analysis/InstructionSimplify.h"
 #include "llvm/Analysis/Loads.h"
@@ -48,7 +49,6 @@
 #include "llvm/IR/IntrinsicsNVPTX.h"
 #include "llvm/IR/IntrinsicsAMDGPU.h"
 #include "llvm/IR/IntrinsicsPowerPC.h"
-#include "llvm/IR/KnowledgeRetention.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/PatternMatch.h"
diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index 05fea8c..fb9db56 100644
--- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -38,7 +38,6 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
-#include "llvm/IR/KnowledgeRetention.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/PassManager.h"
 #include "llvm/IR/PatternMatch.h"
@@ -55,6 +54,7 @@
 #include "llvm/Support/RecyclingAllocator.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Scalar.h"
+#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
 #include "llvm/Transforms/Utils/GuardUtils.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include <cassert>
diff --git a/llvm/lib/IR/KnowledgeRetention.cpp b/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp
similarity index 61%
rename from llvm/lib/IR/KnowledgeRetention.cpp
rename to llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp
index 3de899a..cd677f7 100644
--- a/llvm/lib/IR/KnowledgeRetention.cpp
+++ b/llvm/lib/Transforms/Utils/AssumeBundleBuilder.cpp
@@ -1,4 +1,4 @@
-//===- KnowledgeRetention.h - utilities to preserve informations *- C++ -*-===//
+//===- AssumeBundleBuilder.cpp - tools to preserve informations -*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/IR/KnowledgeRetention.h"
+#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
+#include "llvm/Analysis/AssumeBundleQueries.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/InstIterator.h"
@@ -65,14 +66,6 @@
 
 namespace {
 
-/// Index of elements in the operand bundle.
-/// If the element exist it is guaranteed to be what is specified in this enum
-/// but it may not exist.
-enum BundleOpInfoElem {
-  BOIE_WasOn = 0,
-  BOIE_Argument = 1,
-};
-
 /// Deterministically compare OperandBundleDef.
 /// The ordering is:
 /// - by the attribute's name aka operand bundle tag, (doesn't change)
@@ -85,13 +78,13 @@
   auto getTuple = [](const OperandBundleDef &Op) {
     return std::make_tuple(
         Op.getTag(),
-        Op.input_size() <= BOIE_Argument
+        Op.input_size() <= ABA_Argument
             ? 0
-            : cast<ConstantInt>(*(Op.input_begin() + BOIE_Argument))
+            : cast<ConstantInt>(*(Op.input_begin() + ABA_Argument))
                   ->getZExtValue(),
-         Op.input_size() <= BOIE_WasOn
+        Op.input_size() <= ABA_WasOn
             ? StringRef("")
-            : (*(Op.input_begin() + BOIE_WasOn))->getName());
+            : (*(Op.input_begin() + ABA_WasOn))->getName());
   };
   return getTuple(LHS) < getTuple(RHS);
 }
@@ -234,113 +227,6 @@
     Intr->insertBefore(I);
 }
 
-static bool bundleHasArgument(const CallBase::BundleOpInfo &BOI,
-                               unsigned Idx) {
-  return BOI.End - BOI.Begin > Idx;
-}
-
-static Value *getValueFromBundleOpInfo(IntrinsicInst &Assume,
-                                const CallBase::BundleOpInfo &BOI,
-                                unsigned Idx) {
-  assert(bundleHasArgument(BOI, Idx) && "index out of range");
-  return (Assume.op_begin() + BOI.Begin + Idx)->get();
-}
-
-bool llvm::hasAttributeInAssume(CallInst &AssumeCI, Value *IsOn,
-                                StringRef AttrName, uint64_t *ArgVal,
-                                AssumeQuery AQR) {
-  assert(isa<IntrinsicInst>(AssumeCI) &&
-         "this function is intended to be used on llvm.assume");
-  IntrinsicInst &Assume = cast<IntrinsicInst>(AssumeCI);
-  assert(Assume.getIntrinsicID() == Intrinsic::assume &&
-         "this function is intended to be used on llvm.assume");
-  assert(Attribute::isExistingAttribute(AttrName) &&
-         "this attribute doesn't exist");
-  assert((ArgVal == nullptr || Attribute::doesAttrKindHaveArgument(
-                                   Attribute::getAttrKindFromName(AttrName))) &&
-         "requested value for an attribute that has no argument");
-  if (Assume.bundle_op_infos().empty())
-    return false;
-
-  auto Loop = [&](auto &&Range) {
-    for (auto &BOI : Range) {
-      if (BOI.Tag->getKey() != AttrName)
-        continue;
-      if (IsOn && (BOI.End - BOI.Begin <= BOIE_WasOn ||
-                   IsOn != getValueFromBundleOpInfo(Assume, BOI, BOIE_WasOn)))
-        continue;
-      if (ArgVal) {
-        assert(BOI.End - BOI.Begin > BOIE_Argument);
-        *ArgVal = cast<ConstantInt>(
-                      getValueFromBundleOpInfo(Assume, BOI, BOIE_Argument))
-                      ->getZExtValue();
-      }
-      return true;
-    }
-    return false;
-  };
-
-  if (AQR == AssumeQuery::Lowest)
-    return Loop(Assume.bundle_op_infos());
-  return Loop(reverse(Assume.bundle_op_infos()));
-}
-
-void llvm::fillMapFromAssume(CallInst &AssumeCI, RetainedKnowledgeMap &Result) {
-  IntrinsicInst &Assume = cast<IntrinsicInst>(AssumeCI);
-  assert(Assume.getIntrinsicID() == Intrinsic::assume &&
-         "this function is intended to be used on llvm.assume");
-  for (auto &Bundles : Assume.bundle_op_infos()) {
-    std::pair<Value *, Attribute::AttrKind> Key{
-        nullptr, Attribute::getAttrKindFromName(Bundles.Tag->getKey())};
-    if (bundleHasArgument(Bundles, BOIE_WasOn))
-      Key.first = getValueFromBundleOpInfo(Assume, Bundles, BOIE_WasOn);
-
-    if (Key.first == nullptr && Key.second == Attribute::None)
-      continue;
-    if (!bundleHasArgument(Bundles, BOIE_Argument)) {
-      Result[Key][&Assume] = {0, 0};
-      continue;
-    }
-    unsigned Val = cast<ConstantInt>(
-                       getValueFromBundleOpInfo(Assume, Bundles, BOIE_Argument))
-                       ->getZExtValue();
-    auto Lookup = Result.find(Key);
-    if (Lookup == Result.end() || !Lookup->second.count(&Assume)) {
-      Result[Key][&Assume] = {Val, Val};
-      continue;
-    }
-    Lookup->second[&Assume].Min = std::min(Val, Lookup->second[&Assume].Min);
-    Lookup->second[&Assume].Max = std::max(Val, Lookup->second[&Assume].Max);
-  }
-}
-
-RetainedKnowledge llvm::getKnowledgeFromOperandInAssume(CallInst &AssumeCI,
-                                                        unsigned Idx) {
-  IntrinsicInst &Assume = cast<IntrinsicInst>(AssumeCI);
-  assert(Assume.getIntrinsicID() == Intrinsic::assume &&
-         "this function is intended to be used on llvm.assume");
-  CallBase::BundleOpInfo BOI = Assume.getBundleOpInfoForOperand(Idx);
-  RetainedKnowledge Result;
-  Result.AttrKind = Attribute::getAttrKindFromName(BOI.Tag->getKey());
-  Result.WasOn = getValueFromBundleOpInfo(Assume, BOI, BOIE_WasOn);
-  if (BOI.End - BOI.Begin > BOIE_Argument)
-    Result.ArgValue =
-        cast<ConstantInt>(getValueFromBundleOpInfo(Assume, BOI, BOIE_Argument))
-            ->getZExtValue();
-
-  return Result;
-}
-
-bool llvm::isAssumeWithEmptyBundle(CallInst &CI) {
-  IntrinsicInst &Assume = cast<IntrinsicInst>(CI);
-  assert(Assume.getIntrinsicID() == Intrinsic::assume &&
-         "this function is intended to be used on llvm.assume");
-  return none_of(Assume.bundle_op_infos(),
-                 [](const CallBase::BundleOpInfo &BOI) {
-                   return BOI.Tag->getKey() != "ignore";
-                 });
-}
-
 PreservedAnalyses AssumeBuilderPass::run(Function &F,
                                          FunctionAnalysisManager &AM) {
   for (Instruction &I : instructions(F))
diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt
index 30a157f..7d9fcb5 100644
--- a/llvm/lib/Transforms/Utils/CMakeLists.txt
+++ b/llvm/lib/Transforms/Utils/CMakeLists.txt
@@ -1,7 +1,8 @@
 add_llvm_component_library(LLVMTransformUtils
+  AddDiscriminators.cpp
   AMDGPUEmitPrintf.cpp
   ASanStackFrameLayout.cpp
-  AddDiscriminators.cpp
+  AssumeBundleBuilder.cpp
   BasicBlockUtils.cpp
   BreakCriticalEdges.cpp
   BuildLibCalls.cpp
diff --git a/llvm/lib/Transforms/Utils/InlineFunction.cpp b/llvm/lib/Transforms/Utils/InlineFunction.cpp
index b8b3d18..065b49d 100644
--- a/llvm/lib/Transforms/Utils/InlineFunction.cpp
+++ b/llvm/lib/Transforms/Utils/InlineFunction.cpp
@@ -50,7 +50,6 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
-#include "llvm/IR/KnowledgeRetention.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Metadata.h"
@@ -61,6 +60,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
 #include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/ValueMapper.h"
 #include <algorithm>
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 8cccadd..e3c9a3b 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -25,6 +25,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Analysis/AssumeBundleQueries.h"
 #include "llvm/Analysis/ConstantFolding.h"
 #include "llvm/Analysis/DomTreeUpdater.h"
 #include "llvm/Analysis/EHPersonalities.h"
@@ -59,7 +60,6 @@
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/IntrinsicInst.h"
 #include "llvm/IR/Intrinsics.h"
-#include "llvm/IR/KnowledgeRetention.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/MDBuilder.h"
 #include "llvm/IR/Metadata.h"
diff --git a/llvm/test/IR/assume-builder.ll b/llvm/test/Transforms/Util/assume-builder.ll
similarity index 100%
rename from llvm/test/IR/assume-builder.ll
rename to llvm/test/Transforms/Util/assume-builder.ll
diff --git a/llvm/unittests/IR/KnowledgeRetentionTest.cpp b/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp
similarity index 98%
rename from llvm/unittests/IR/KnowledgeRetentionTest.cpp
rename to llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp
index 2c923aa..f6f4849 100644
--- a/llvm/unittests/IR/KnowledgeRetentionTest.cpp
+++ b/llvm/unittests/Analysis/AssumeBundleQueriesTest.cpp
@@ -1,4 +1,4 @@
-//===- KnowledgeRetention.h - utilities to preserve informations *- C++ -*-===//
+//===- AssumeBundleQueriesTest.cpp ------------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/IR/KnowledgeRetention.h"
+#include "llvm/Analysis/AssumeBundleQueries.h"
 #include "llvm/AsmParser/Parser.h"
 #include "llvm/IR/CallSite.h"
 #include "llvm/IR/LLVMContext.h"
@@ -14,6 +14,7 @@
 #include "llvm/Support/Regex.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Transforms/Utils/AssumeBundleBuilder.h"
 #include "gtest/gtest.h"
 #include <random>
 
diff --git a/llvm/unittests/Analysis/CMakeLists.txt b/llvm/unittests/Analysis/CMakeLists.txt
index 6fabd94..254b289 100644
--- a/llvm/unittests/Analysis/CMakeLists.txt
+++ b/llvm/unittests/Analysis/CMakeLists.txt
@@ -9,6 +9,7 @@
 add_llvm_unittest(AnalysisTests
   AliasAnalysisTest.cpp
   AliasSetTrackerTest.cpp
+  AssumeBundleQueriesTest.cpp
   BasicAliasAnalysisTest.cpp
   BlockFrequencyInfoTest.cpp
   BranchProbabilityInfoTest.cpp
diff --git a/llvm/unittests/IR/CMakeLists.txt b/llvm/unittests/IR/CMakeLists.txt
index 05df08d..d0068517 100644
--- a/llvm/unittests/IR/CMakeLists.txt
+++ b/llvm/unittests/IR/CMakeLists.txt
@@ -24,7 +24,6 @@
   IRBuilderTest.cpp
   InstructionsTest.cpp
   IntrinsicsTest.cpp
-  KnowledgeRetentionTest.cpp
   LegacyPassManagerTest.cpp
   MDBuilderTest.cpp
   ManglerTest.cpp