AssumeBundleQueries.h 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- AssumeBundleQueries.h - utilities to query assume bundles *- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file contain tools to query into assume bundles. assume bundles can be
  15. // built using utilities from Transform/Utils/AssumeBundleBuilder.h
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_ANALYSIS_ASSUMEBUNDLEQUERIES_H
  19. #define LLVM_ANALYSIS_ASSUMEBUNDLEQUERIES_H
  20. #include "llvm/ADT/DenseMap.h"
  21. #include "llvm/IR/IntrinsicInst.h"
  22. namespace llvm {
  23. class AssumptionCache;
  24. class DominatorTree;
  25. class Instruction;
  26. class Value;
  27. /// Index of elements in the operand bundle.
  28. /// If the element exist it is guaranteed to be what is specified in this enum
  29. /// but it may not exist.
  30. enum AssumeBundleArg {
  31. ABA_WasOn = 0,
  32. ABA_Argument = 1,
  33. };
  34. /// Query the operand bundle of an llvm.assume to find a single attribute of
  35. /// the specified kind applied on a specified Value.
  36. ///
  37. /// This has a non-constant complexity. It should only be used when a single
  38. /// attribute is going to be queried.
  39. ///
  40. /// Return true iff the queried attribute was found.
  41. /// If ArgVal is set. the argument will be stored to ArgVal.
  42. bool hasAttributeInAssume(AssumeInst &Assume, Value *IsOn, StringRef AttrName,
  43. uint64_t *ArgVal = nullptr);
  44. inline bool hasAttributeInAssume(AssumeInst &Assume, Value *IsOn,
  45. Attribute::AttrKind Kind,
  46. uint64_t *ArgVal = nullptr) {
  47. return hasAttributeInAssume(Assume, IsOn,
  48. Attribute::getNameFromAttrKind(Kind), ArgVal);
  49. }
  50. template<> struct DenseMapInfo<Attribute::AttrKind> {
  51. static Attribute::AttrKind getEmptyKey() {
  52. return Attribute::EmptyKey;
  53. }
  54. static Attribute::AttrKind getTombstoneKey() {
  55. return Attribute::TombstoneKey;
  56. }
  57. static unsigned getHashValue(Attribute::AttrKind AK) {
  58. return hash_combine(AK);
  59. }
  60. static bool isEqual(Attribute::AttrKind LHS, Attribute::AttrKind RHS) {
  61. return LHS == RHS;
  62. }
  63. };
  64. /// The map Key contains the Value on for which the attribute is valid and
  65. /// the Attribute that is valid for that value.
  66. /// If the Attribute is not on any value, the Value is nullptr.
  67. using RetainedKnowledgeKey = std::pair<Value *, Attribute::AttrKind>;
  68. struct MinMax {
  69. uint64_t Min;
  70. uint64_t Max;
  71. };
  72. /// A mapping from intrinsics (=`llvm.assume` calls) to a value range
  73. /// (=knowledge) that is encoded in them. How the value range is interpreted
  74. /// depends on the RetainedKnowledgeKey that was used to get this out of the
  75. /// RetainedKnowledgeMap.
  76. using Assume2KnowledgeMap = DenseMap<AssumeInst *, MinMax>;
  77. using RetainedKnowledgeMap =
  78. DenseMap<RetainedKnowledgeKey, Assume2KnowledgeMap>;
  79. /// Insert into the map all the informations contained in the operand bundles of
  80. /// the llvm.assume. This should be used instead of hasAttributeInAssume when
  81. /// many queries are going to be made on the same llvm.assume.
  82. /// String attributes are not inserted in the map.
  83. /// If the IR changes the map will be outdated.
  84. void fillMapFromAssume(AssumeInst &Assume, RetainedKnowledgeMap &Result);
  85. /// Represent one information held inside an operand bundle of an llvm.assume.
  86. /// AttrKind is the property that holds.
  87. /// WasOn if not null is that Value for which AttrKind holds.
  88. /// ArgValue is optionally an argument of the attribute.
  89. /// For example if we know that %P has an alignment of at least four:
  90. /// - AttrKind will be Attribute::Alignment.
  91. /// - WasOn will be %P.
  92. /// - ArgValue will be 4.
  93. struct RetainedKnowledge {
  94. Attribute::AttrKind AttrKind = Attribute::None;
  95. uint64_t ArgValue = 0;
  96. Value *WasOn = nullptr;
  97. bool operator==(RetainedKnowledge Other) const {
  98. return AttrKind == Other.AttrKind && WasOn == Other.WasOn &&
  99. ArgValue == Other.ArgValue;
  100. }
  101. bool operator!=(RetainedKnowledge Other) const { return !(*this == Other); }
  102. /// This is only intended for use in std::min/std::max between attribute that
  103. /// only differ in ArgValue.
  104. bool operator<(RetainedKnowledge Other) const {
  105. assert(((AttrKind == Other.AttrKind && WasOn == Other.WasOn) ||
  106. AttrKind == Attribute::None || Other.AttrKind == Attribute::None) &&
  107. "This is only intend for use in min/max to select the best for "
  108. "RetainedKnowledge that is otherwise equal");
  109. return ArgValue < Other.ArgValue;
  110. }
  111. operator bool() const { return AttrKind != Attribute::None; }
  112. static RetainedKnowledge none() { return RetainedKnowledge{}; }
  113. };
  114. /// Retreive the information help by Assume on the operand at index Idx.
  115. /// Assume should be an llvm.assume and Idx should be in the operand bundle.
  116. RetainedKnowledge getKnowledgeFromOperandInAssume(AssumeInst &Assume,
  117. unsigned Idx);
  118. /// Retreive the information help by the Use U of an llvm.assume. the use should
  119. /// be in the operand bundle.
  120. inline RetainedKnowledge getKnowledgeFromUseInAssume(const Use *U) {
  121. return getKnowledgeFromOperandInAssume(*cast<AssumeInst>(U->getUser()),
  122. U->getOperandNo());
  123. }
  124. /// Tag in operand bundle indicating that this bundle should be ignored.
  125. constexpr StringRef IgnoreBundleTag = "ignore";
  126. /// Return true iff the operand bundles of the provided llvm.assume doesn't
  127. /// contain any valuable information. This is true when:
  128. /// - The operand bundle is empty
  129. /// - The operand bundle only contains information about dropped values or
  130. /// constant folded values.
  131. ///
  132. /// the argument to the call of llvm.assume may still be useful even if the
  133. /// function returned true.
  134. bool isAssumeWithEmptyBundle(AssumeInst &Assume);
  135. /// Return a valid Knowledge associated to the Use U if its Attribute kind is
  136. /// in AttrKinds.
  137. RetainedKnowledge getKnowledgeFromUse(const Use *U,
  138. ArrayRef<Attribute::AttrKind> AttrKinds);
  139. /// Return a valid Knowledge associated to the Value V if its Attribute kind is
  140. /// in AttrKinds and it matches the Filter.
  141. RetainedKnowledge getKnowledgeForValue(
  142. const Value *V, ArrayRef<Attribute::AttrKind> AttrKinds,
  143. AssumptionCache *AC = nullptr,
  144. function_ref<bool(RetainedKnowledge, Instruction *,
  145. const CallBase::BundleOpInfo *)>
  146. Filter = [](auto...) { return true; });
  147. /// Return a valid Knowledge associated to the Value V if its Attribute kind is
  148. /// in AttrKinds and the knowledge is suitable to be used in the context of
  149. /// CtxI.
  150. RetainedKnowledge getKnowledgeValidInContext(
  151. const Value *V, ArrayRef<Attribute::AttrKind> AttrKinds,
  152. const Instruction *CtxI, const DominatorTree *DT = nullptr,
  153. AssumptionCache *AC = nullptr);
  154. /// This extracts the Knowledge from an element of an operand bundle.
  155. /// This is mostly for use in the assume builder.
  156. RetainedKnowledge getKnowledgeFromBundle(AssumeInst &Assume,
  157. const CallBase::BundleOpInfo &BOI);
  158. } // namespace llvm
  159. #endif
  160. #ifdef __GNUC__
  161. #pragma GCC diagnostic pop
  162. #endif