- //===- 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. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // This file contain tools to query into assume bundles. assume bundles can be 
- // built using utilities from Transform/Utils/AssumeBundleBuilder.h 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_ANALYSIS_ASSUMEBUNDLEQUERIES_H 
- #define LLVM_ANALYSIS_ASSUMEBUNDLEQUERIES_H 
-   
- #include "llvm/ADT/DenseMap.h" 
- #include "llvm/IR/IntrinsicInst.h" 
-   
- namespace llvm { 
- class AssumptionCache; 
- class DominatorTree; 
- class Instruction; 
- class Value; 
-   
- /// 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, 
- }; 
-   
- /// Query the operand bundle of an llvm.assume to find a single attribute of 
- /// the specified kind applied on a specified Value. 
- /// 
- /// This has a non-constant complexity. It should only be used when a single 
- /// attribute is going to be queried. 
- /// 
- /// Return true iff the queried attribute was found. 
- /// If ArgVal is set. the argument will be stored to ArgVal. 
- bool hasAttributeInAssume(AssumeInst &Assume, Value *IsOn, StringRef AttrName, 
-                           uint64_t *ArgVal = nullptr); 
- inline bool hasAttributeInAssume(AssumeInst &Assume, Value *IsOn, 
-                                  Attribute::AttrKind Kind, 
-                                  uint64_t *ArgVal = nullptr) { 
-   return hasAttributeInAssume(Assume, IsOn, 
-                               Attribute::getNameFromAttrKind(Kind), ArgVal); 
- } 
-   
- template<> struct DenseMapInfo<Attribute::AttrKind> { 
-   static Attribute::AttrKind getEmptyKey() { 
-     return Attribute::EmptyKey; 
-   } 
-   static Attribute::AttrKind getTombstoneKey() { 
-     return Attribute::TombstoneKey; 
-   } 
-   static unsigned getHashValue(Attribute::AttrKind AK) { 
-     return hash_combine(AK); 
-   } 
-   static bool isEqual(Attribute::AttrKind LHS, Attribute::AttrKind RHS) { 
-     return LHS == RHS; 
-   } 
- }; 
-   
- /// The map Key contains the Value on for which the attribute is valid and 
- /// the Attribute that is valid for that value. 
- /// If the Attribute is not on any value, the Value is nullptr. 
- using RetainedKnowledgeKey = std::pair<Value *, Attribute::AttrKind>; 
-   
- struct MinMax { 
-   uint64_t Min; 
-   uint64_t Max; 
- }; 
-   
- /// A mapping from intrinsics (=`llvm.assume` calls) to a value range 
- /// (=knowledge) that is encoded in them. How the value range is interpreted 
- /// depends on the RetainedKnowledgeKey that was used to get this out of the 
- /// RetainedKnowledgeMap. 
- using Assume2KnowledgeMap = DenseMap<AssumeInst *, MinMax>; 
-   
- using RetainedKnowledgeMap = 
-     DenseMap<RetainedKnowledgeKey, Assume2KnowledgeMap>; 
-   
- /// Insert into the map all the informations contained in the operand bundles of 
- /// the llvm.assume. This should be used instead of hasAttributeInAssume when 
- /// many queries are going to be made on the same llvm.assume. 
- /// String attributes are not inserted in the map. 
- /// If the IR changes the map will be outdated. 
- void fillMapFromAssume(AssumeInst &Assume, RetainedKnowledgeMap &Result); 
-   
- /// Represent one information held inside an operand bundle of an llvm.assume. 
- /// AttrKind is the property that holds. 
- /// WasOn if not null is that Value for which AttrKind holds. 
- /// ArgValue is optionally an argument of the attribute. 
- /// For example if we know that %P has an alignment of at least four: 
- ///  - AttrKind will be Attribute::Alignment. 
- ///  - WasOn will be %P. 
- ///  - ArgValue will be 4. 
- struct RetainedKnowledge { 
-   Attribute::AttrKind AttrKind = Attribute::None; 
-   uint64_t ArgValue = 0; 
-   Value *WasOn = nullptr; 
-   bool operator==(RetainedKnowledge Other) const { 
-     return AttrKind == Other.AttrKind && WasOn == Other.WasOn && 
-            ArgValue == Other.ArgValue; 
-   } 
-   bool operator!=(RetainedKnowledge Other) const { return !(*this == Other); } 
-   /// This is only intended for use in std::min/std::max between attribute that 
-   /// only differ in ArgValue. 
-   bool operator<(RetainedKnowledge Other) const { 
-     assert(((AttrKind == Other.AttrKind && WasOn == Other.WasOn) || 
-             AttrKind == Attribute::None || Other.AttrKind == Attribute::None) && 
-            "This is only intend for use in min/max to select the best for " 
-            "RetainedKnowledge that is otherwise equal"); 
-     return ArgValue < Other.ArgValue; 
-   } 
-   operator bool() const { return AttrKind != Attribute::None; } 
-   static RetainedKnowledge none() { return RetainedKnowledge{}; } 
- }; 
-   
- /// Retreive the information help by Assume on the operand at index Idx. 
- /// Assume should be an llvm.assume and Idx should be in the operand bundle. 
- RetainedKnowledge getKnowledgeFromOperandInAssume(AssumeInst &Assume, 
-                                                   unsigned Idx); 
-   
- /// Retreive the information help by the Use U of an llvm.assume. the use should 
- /// be in the operand bundle. 
- inline RetainedKnowledge getKnowledgeFromUseInAssume(const Use *U) { 
-   return getKnowledgeFromOperandInAssume(*cast<AssumeInst>(U->getUser()), 
-                                          U->getOperandNo()); 
- } 
-   
- /// Tag in operand bundle indicating that this bundle should be ignored. 
- constexpr StringRef IgnoreBundleTag = "ignore"; 
-   
- /// Return true iff the operand bundles of the provided llvm.assume doesn't 
- /// contain any valuable information. This is true when: 
- ///  - The operand bundle is empty 
- ///  - The operand bundle only contains information about dropped values or 
- ///    constant folded values. 
- /// 
- /// the argument to the call of llvm.assume may still be useful even if the 
- /// function returned true. 
- bool isAssumeWithEmptyBundle(AssumeInst &Assume); 
-   
- /// Return a valid Knowledge associated to the Use U if its Attribute kind is 
- /// in AttrKinds. 
- RetainedKnowledge getKnowledgeFromUse(const Use *U, 
-                                       ArrayRef<Attribute::AttrKind> AttrKinds); 
-   
- /// Return a valid Knowledge associated to the Value V if its Attribute kind is 
- /// in AttrKinds and it matches the Filter. 
- RetainedKnowledge getKnowledgeForValue( 
-     const Value *V, ArrayRef<Attribute::AttrKind> AttrKinds, 
-     AssumptionCache *AC = nullptr, 
-     function_ref<bool(RetainedKnowledge, Instruction *, 
-                             const CallBase::BundleOpInfo *)> 
-         Filter = [](auto...) { return true; }); 
-   
- /// Return a valid Knowledge associated to the Value V if its Attribute kind is 
- /// in AttrKinds and the knowledge is suitable to be used in the context of 
- /// CtxI. 
- RetainedKnowledge getKnowledgeValidInContext( 
-     const Value *V, ArrayRef<Attribute::AttrKind> AttrKinds, 
-     const Instruction *CtxI, const DominatorTree *DT = nullptr, 
-     AssumptionCache *AC = nullptr); 
-   
- /// This extracts the Knowledge from an element of an operand bundle. 
- /// This is mostly for use in the assume builder. 
- RetainedKnowledge getKnowledgeFromBundle(AssumeInst &Assume, 
-                                          const CallBase::BundleOpInfo &BOI); 
-   
- } // namespace llvm 
-   
- #endif 
-