LLVM 17.0.0git
AssumeBundleQueries.cpp
Go to the documentation of this file.
1//===- AssumeBundleQueries.cpp - tool to query assume bundles ---*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "llvm/ADT/Statistic.h"
13#include "llvm/IR/Instruction.h"
18
19#define DEBUG_TYPE "assume-queries"
20
21using namespace llvm;
22using namespace llvm::PatternMatch;
23
24STATISTIC(NumAssumeQueries, "Number of Queries into an assume assume bundles");
26 NumUsefullAssumeQueries,
27 "Number of Queries into an assume assume bundles that were satisfied");
28
29DEBUG_COUNTER(AssumeQueryCounter, "assume-queries-counter",
30 "Controls which assumes gets created");
31
32static bool bundleHasArgument(const CallBase::BundleOpInfo &BOI, unsigned Idx) {
33 return BOI.End - BOI.Begin > Idx;
34}
35
37 const CallBase::BundleOpInfo &BOI,
38 unsigned Idx) {
39 assert(bundleHasArgument(BOI, Idx) && "index out of range");
40 return (Assume.op_begin() + BOI.Begin + Idx)->get();
41}
42
44 StringRef AttrName, uint64_t *ArgVal) {
46 "this attribute doesn't exist");
47 assert((ArgVal == nullptr || Attribute::isIntAttrKind(
49 "requested value for an attribute that has no argument");
50 if (Assume.bundle_op_infos().empty())
51 return false;
52
53 for (auto &BOI : Assume.bundle_op_infos()) {
54 if (BOI.Tag->getKey() != AttrName)
55 continue;
56 if (IsOn && (BOI.End - BOI.Begin <= ABA_WasOn ||
57 IsOn != getValueFromBundleOpInfo(Assume, BOI, ABA_WasOn)))
58 continue;
59 if (ArgVal) {
60 assert(BOI.End - BOI.Begin > ABA_Argument);
61 *ArgVal =
62 cast<ConstantInt>(getValueFromBundleOpInfo(Assume, BOI, ABA_Argument))
63 ->getZExtValue();
64 }
65 return true;
66 }
67 return false;
68}
69
71 for (auto &Bundles : Assume.bundle_op_infos()) {
72 std::pair<Value *, Attribute::AttrKind> Key{
73 nullptr, Attribute::getAttrKindFromName(Bundles.Tag->getKey())};
74 if (bundleHasArgument(Bundles, ABA_WasOn))
75 Key.first = getValueFromBundleOpInfo(Assume, Bundles, ABA_WasOn);
76
77 if (Key.first == nullptr && Key.second == Attribute::None)
78 continue;
79 if (!bundleHasArgument(Bundles, ABA_Argument)) {
80 Result[Key][&Assume] = {0, 0};
81 continue;
82 }
83 auto *CI = dyn_cast<ConstantInt>(
84 getValueFromBundleOpInfo(Assume, Bundles, ABA_Argument));
85 if (!CI)
86 continue;
87 uint64_t Val = CI->getZExtValue();
88 auto Lookup = Result.find(Key);
89 if (Lookup == Result.end() || !Lookup->second.count(&Assume)) {
90 Result[Key][&Assume] = {Val, Val};
91 continue;
92 }
93 Lookup->second[&Assume].Min = std::min(Val, Lookup->second[&Assume].Min);
94 Lookup->second[&Assume].Max = std::max(Val, Lookup->second[&Assume].Max);
95 }
96}
97
100 const CallBase::BundleOpInfo &BOI) {
101 RetainedKnowledge Result;
102 Result.AttrKind = Attribute::getAttrKindFromName(BOI.Tag->getKey());
104 Result.WasOn = getValueFromBundleOpInfo(Assume, BOI, ABA_WasOn);
105 auto GetArgOr1 = [&](unsigned Idx) -> uint64_t {
106 if (auto *ConstInt = dyn_cast<ConstantInt>(
108 return ConstInt->getZExtValue();
109 return 1;
110 };
111 if (BOI.End - BOI.Begin > ABA_Argument)
112 Result.ArgValue = GetArgOr1(0);
113 if (Result.AttrKind == Attribute::Alignment)
114 if (BOI.End - BOI.Begin > ABA_Argument + 1)
115 Result.ArgValue = MinAlign(Result.ArgValue, GetArgOr1(1));
116 return Result;
117}
118
120 unsigned Idx) {
122 return getKnowledgeFromBundle(Assume, BOI);
123}
124
126 return none_of(Assume.bundle_op_infos(),
127 [](const CallBase::BundleOpInfo &BOI) {
128 return BOI.Tag->getKey() != IgnoreBundleTag;
129 });
130}
131
133 if (!match(U->getUser(),
134 m_Intrinsic<Intrinsic::assume>(m_Unless(m_Specific(U->get())))))
135 return nullptr;
136 auto *Intr = cast<IntrinsicInst>(U->getUser());
137 return &Intr->getBundleOpInfoForOperand(U->getOperandNo());
138}
139
144 if (!Bundle)
147 getKnowledgeFromBundle(*cast<AssumeInst>(U->getUser()), *Bundle);
148 if (llvm::is_contained(AttrKinds, RK.AttrKind))
149 return RK;
151}
152
156 AssumptionCache *AC,
158 const CallBase::BundleOpInfo *)>
159 Filter) {
160 NumAssumeQueries++;
161 if (!DebugCounter::shouldExecute(AssumeQueryCounter))
163 if (AC) {
164 for (AssumptionCache::ResultElem &Elem : AC->assumptionsFor(V)) {
165 auto *II = dyn_cast_or_null<AssumeInst>(Elem.Assume);
166 if (!II || Elem.Index == AssumptionCache::ExprResultIdx)
167 continue;
169 *II, II->bundle_op_info_begin()[Elem.Index])) {
170 if (V != RK.WasOn)
171 continue;
172 if (is_contained(AttrKinds, RK.AttrKind) &&
173 Filter(RK, II, &II->bundle_op_info_begin()[Elem.Index])) {
174 NumUsefullAssumeQueries++;
175 return RK;
176 }
177 }
178 }
180 }
181 for (const auto &U : V->uses()) {
183 if (!Bundle)
184 continue;
185 if (RetainedKnowledge RK =
186 getKnowledgeFromBundle(*cast<AssumeInst>(U.getUser()), *Bundle))
187 if (is_contained(AttrKinds, RK.AttrKind) &&
188 Filter(RK, cast<Instruction>(U.getUser()), Bundle)) {
189 NumUsefullAssumeQueries++;
190 return RK;
191 }
192 }
194}
195
197 const Value *V, ArrayRef<Attribute::AttrKind> AttrKinds,
198 const Instruction *CtxI, const DominatorTree *DT, AssumptionCache *AC) {
199 return getKnowledgeForValue(V, AttrKinds, AC,
200 [&](auto, Instruction *I, auto) {
201 return isValidAssumeForContext(I, CtxI, DT);
202 });
203}
unsigned Intr
static CallInst::BundleOpInfo * getBundleFromUse(const Use *U)
static Value * getValueFromBundleOpInfo(AssumeInst &Assume, const CallBase::BundleOpInfo &BOI, unsigned Idx)
static bool bundleHasArgument(const CallBase::BundleOpInfo &BOI, unsigned Idx)
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file provides an implementation of debug counters.
#define DEBUG_COUNTER(VARNAME, COUNTERNAME, DESC)
Definition: DebugCounter.h:182
#define I(x, y, z)
Definition: MD5.cpp:58
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
This represents the llvm.assume intrinsic.
A cache of @llvm.assume calls within a function.
MutableArrayRef< ResultElem > assumptionsFor(const Value *V)
Access the list of assumptions which affect this value.
static Attribute::AttrKind getAttrKindFromName(StringRef AttrName)
Definition: Attributes.cpp:233
static bool isExistingAttribute(StringRef Name)
Return true if the provided string matches the IR name of an attribute.
Definition: Attributes.cpp:256
@ None
No attributes have been set.
Definition: Attributes.h:88
static bool isIntAttrKind(AttrKind Kind)
Definition: Attributes.h:102
BundleOpInfo & getBundleOpInfoForOperand(unsigned OpIdx)
Return the BundleOpInfo for the operand at index OpIdx.
iterator_range< bundle_op_iterator > bundle_op_infos()
Return the range [bundle_op_info_begin, bundle_op_info_end).
Definition: InstrTypes.h:2230
static bool shouldExecute(unsigned CounterName)
Definition: DebugCounter.h:72
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:166
StringRef getKey() const
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
op_iterator op_begin()
Definition: User.h:234
LLVM Value Representation.
Definition: Value.h:74
iterator_range< use_iterator > uses()
Definition: Value.h:376
An efficient, type-erasing, non-owning reference to a callable.
bool match(Val *V, const Pattern &P)
Definition: PatternMatch.h:49
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
Definition: PatternMatch.h:772
match_unless< Ty > m_Unless(const Ty &M)
Match if the inner matcher does NOT match.
Definition: PatternMatch.h:182
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
RetainedKnowledge getKnowledgeFromOperandInAssume(AssumeInst &Assume, unsigned Idx)
Retreive the information help by Assume on the operand at index Idx.
RetainedKnowledge getKnowledgeValidInContext(const Value *V, ArrayRef< Attribute::AttrKind > AttrKinds, const Instruction *CtxI, const DominatorTree *DT=nullptr, AssumptionCache *AC=nullptr)
Return a valid Knowledge associated to the Value V if its Attribute kind is in AttrKinds and the know...
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 it match...
RetainedKnowledge getKnowledgeFromBundle(AssumeInst &Assume, const CallBase::BundleOpInfo &BOI)
This extracts the Knowledge from an element of an operand bundle.
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1749
RetainedKnowledge getKnowledgeFromUse(const Use *U, ArrayRef< Attribute::AttrKind > AttrKinds)
Return a valid Knowledge associated to the Use U if its Attribute kind is in AttrKinds.
constexpr uint64_t MinAlign(uint64_t A, uint64_t B)
A and B are either alignments or offsets.
Definition: MathExtras.h:426
bool hasAttributeInAssume(AssumeInst &Assume, Value *IsOn, StringRef AttrName, uint64_t *ArgVal=nullptr)
Query the operand bundle of an llvm.assume to find a single attribute of the specified kind applied o...
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
Definition: STLExtras.h:1869
void fillMapFromAssume(AssumeInst &Assume, RetainedKnowledgeMap &Result)
Insert into the map all the informations contained in the operand bundles of the llvm....
bool isValidAssumeForContext(const Instruction *I, const Instruction *CxtI, const DominatorTree *DT=nullptr)
Return true if it is valid to use the assumptions provided by an assume intrinsic,...
bool isAssumeWithEmptyBundle(AssumeInst &Assume)
Return true iff the operand bundles of the provided llvm.assume doesn't contain any valuable informat...
Used to keep track of an operand bundle.
Definition: InstrTypes.h:2121
StringMapEntry< uint32_t > * Tag
The operand bundle tag, interned by LLVMContextImpl::getOrInsertBundleTag.
Definition: InstrTypes.h:2124
uint32_t End
The index in the Use& vector where operands for this operand bundle ends.
Definition: InstrTypes.h:2132
uint32_t Begin
The index in the Use& vector where operands for this operand bundle starts.
Definition: InstrTypes.h:2128
Represent one information held inside an operand bundle of an llvm.assume.
Attribute::AttrKind AttrKind
static RetainedKnowledge none()