123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- #pragma once
- #ifdef __GNUC__
- #pragma GCC diagnostic push
- #pragma GCC diagnostic ignored "-Wunused-parameter"
- #endif
- //===- 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
- #ifdef __GNUC__
- #pragma GCC diagnostic pop
- #endif
|