AssumeBundleQueries.h 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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_TRANSFORMS_UTILS_ASSUMEBUNDLEQUERIES_H
  19. #define LLVM_TRANSFORMS_UTILS_ASSUMEBUNDLEQUERIES_H
  20. #include "llvm/IR/Attributes.h"
  21. #include "llvm/IR/Instructions.h"
  22. #include "llvm/ADT/DenseMap.h"
  23. namespace llvm {
  24. class IntrinsicInst;
  25. class AssumptionCache;
  26. class DominatorTree;
  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(CallInst &AssumeCI, Value *IsOn, StringRef AttrName,
  43. uint64_t *ArgVal = nullptr);
  44. inline bool hasAttributeInAssume(CallInst &AssumeCI, Value *IsOn,
  45. Attribute::AttrKind Kind,
  46. uint64_t *ArgVal = nullptr) {
  47. return hasAttributeInAssume(AssumeCI, 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. unsigned Min;
  70. unsigned 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<IntrinsicInst *, 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(CallInst &AssumeCI, 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. unsigned 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. operator bool() const { return AttrKind != Attribute::None; }
  103. static RetainedKnowledge none() { return RetainedKnowledge{}; }
  104. };
  105. /// Retreive the information help by Assume on the operand at index Idx.
  106. /// Assume should be an llvm.assume and Idx should be in the operand bundle.
  107. RetainedKnowledge getKnowledgeFromOperandInAssume(CallInst &Assume,
  108. unsigned Idx);
  109. /// Retreive the information help by the Use U of an llvm.assume. the use should
  110. /// be in the operand bundle.
  111. inline RetainedKnowledge getKnowledgeFromUseInAssume(const Use *U) {
  112. return getKnowledgeFromOperandInAssume(*cast<CallInst>(U->getUser()),
  113. U->getOperandNo());
  114. }
  115. /// Tag in operand bundle indicating that this bundle should be ignored.
  116. constexpr StringRef IgnoreBundleTag = "ignore";
  117. /// Return true iff the operand bundles of the provided llvm.assume doesn't
  118. /// contain any valuable information. This is true when:
  119. /// - The operand bundle is empty
  120. /// - The operand bundle only contains information about dropped values or
  121. /// constant folded values.
  122. ///
  123. /// the argument to the call of llvm.assume may still be useful even if the
  124. /// function returned true.
  125. bool isAssumeWithEmptyBundle(CallInst &Assume);
  126. /// Return a valid Knowledge associated to the Use U if its Attribute kind is
  127. /// in AttrKinds.
  128. RetainedKnowledge getKnowledgeFromUse(const Use *U,
  129. ArrayRef<Attribute::AttrKind> AttrKinds);
  130. /// Return a valid Knowledge associated to the Value V if its Attribute kind is
  131. /// in AttrKinds and it matches the Filter.
  132. RetainedKnowledge getKnowledgeForValue(
  133. const Value *V, ArrayRef<Attribute::AttrKind> AttrKinds,
  134. AssumptionCache *AC = nullptr,
  135. function_ref<bool(RetainedKnowledge, Instruction *,
  136. const CallBase::BundleOpInfo *)>
  137. Filter = [](auto...) { return true; });
  138. /// Return a valid Knowledge associated to the Value V if its Attribute kind is
  139. /// in AttrKinds and the knowledge is suitable to be used in the context of
  140. /// CtxI.
  141. RetainedKnowledge getKnowledgeValidInContext(
  142. const Value *V, ArrayRef<Attribute::AttrKind> AttrKinds,
  143. const Instruction *CtxI, const DominatorTree *DT = nullptr,
  144. AssumptionCache *AC = nullptr);
  145. /// This extracts the Knowledge from an element of an operand bundle.
  146. /// This is mostly for use in the assume builder.
  147. RetainedKnowledge getKnowledgeFromBundle(CallInst &Assume,
  148. const CallBase::BundleOpInfo &BOI);
  149. } // namespace llvm
  150. #endif
  151. #ifdef __GNUC__
  152. #pragma GCC diagnostic pop
  153. #endif