MLIR: lib/Analysis/AliasAnalysis/LocalAliasAnalysis.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
10
25 #include "llvm/Support/Casting.h"
26 #include
27 #include
28 #include
29
30 using namespace mlir;
31
32
33
34
35
36
37
39
40
44
45
46
47
48
51 unsigned inputIndex,
52 unsigned maxDepth,
55
56
57
58
59 auto getOperandIndexIfPred =
62 branch.getSuccessorRegions(pred, successors);
64 if (successor.getSuccessor() != region)
65 continue;
66
67 ValueRange inputs = successor.getSuccessorInputs();
68 if (inputs.empty()) {
69 output.push_back(inputValue);
70 break;
71 }
72 unsigned firstInputIndex, lastInputIndex;
73 if (region) {
74 firstInputIndex = cast(inputs[0]).getArgNumber();
75 lastInputIndex = cast(inputs.back()).getArgNumber();
76 } else {
77 firstInputIndex = cast(inputs[0]).getResultNumber();
78 lastInputIndex = cast(inputs.back()).getResultNumber();
79 }
80 if (firstInputIndex > inputIndex || lastInputIndex < inputIndex) {
81 output.push_back(inputValue);
82 break;
83 }
84 return inputIndex - firstInputIndex;
85 }
86 return std::nullopt;
87 };
88
89
91 if (region)
92 branchPoint = region;
93
94 if (std::optional operandIndex =
97 branch.getEntrySuccessorOperands(branchPoint)[*operandIndex], maxDepth,
98 visited, output);
99 }
100
101 Operation *op = branch.getOperation();
103 if (std::optional operandIndex = getOperandIndexIfPred(region)) {
104 for (Block &block : region) {
105
106
107 if (auto term = dyn_cast(
108 block.getTerminator())) {
110 term.getSuccessorOperands(branchPoint)[*operandIndex], maxDepth,
111 visited, output);
112 } else if (block.getNumSuccessors()) {
113
114
115 output.push_back(inputValue);
116 return;
117 }
118 }
119 }
120 }
121 }
122
123
128
129
130 if (ViewLikeOpInterface view = dyn_cast(op))
132 visited, output);
133
134 if (auto branch = dyn_cast(op)) {
137 visited, output);
138 }
139
140 output.push_back(result);
141 }
142
143
144
150
151
153 for (auto it = block->pred_begin(), e = block->pred_end(); it != e; ++it) {
154 auto branch = dyn_cast((*it)->getTerminator());
155 if (!branch) {
156
157 output.push_back(arg);
158 return;
159 }
160
161
162 unsigned index = it.getSuccessorIndex();
163 Value operand = branch.getSuccessorOperands(index)[argNumber];
164 if (!operand) {
165
166 output.push_back(arg);
167 return;
168 }
170 }
171 return;
172 }
173
174
177 if (auto branch = dyn_cast(op)) {
179 maxDepth, visited, output);
180 }
181
182
183 output.push_back(arg);
184 }
185
186
190
191 if (!visited.insert(value).second)
192 return;
193 if (maxDepth == 0) {
194 output.push_back(value);
195 return;
196 }
197 --maxDepth;
198
199 if (BlockArgument arg = dyn_cast(value))
202 output);
203 }
204
205
210 output);
211 }
212
213
214
215
216
217
218
219
220
221
222
223 static LogicalResult
225 std::optionalMemoryEffects::EffectInstance &effect,
227
229 if (BlockArgument arg = dyn_cast(value))
231 else
232 op = cast(value).getOwner();
233 MemoryEffectOpInterface interface = dyn_cast(op);
234 if (!interface)
235 return failure();
236
237
239 return failure();
240
241
242
243
244 if (llvm::isaSideEffects::AutomaticAllocationScopeResource(
245 effect->getResource())) {
247 return success();
248 }
249
250
251
252
253
254 allocScopeOp = op->getParentOfType();
255 return success();
256 }
257
258
260 if (lhs == rhs)
262 Operation *lhsAllocScope = nullptr, *rhsAllocScope = nullptr;
263 std::optionalMemoryEffects::EffectInstance lhsAlloc, rhsAlloc;
264
265
268
269
270
273
274
275
276 return succeeded(getAllocEffectFor(rhs, rhsAlloc, rhsAllocScope))
279 }
280
282
283
284 return succeeded(getAllocEffectFor(lhs, lhsAlloc, lhsAllocScope))
287 }
288
289
290
291 bool lhsHasAlloc = succeeded(getAllocEffectFor(lhs, lhsAlloc, lhsAllocScope));
292 bool rhsHasAlloc = succeeded(getAllocEffectFor(rhs, rhsAlloc, rhsAllocScope));
293 if (lhsHasAlloc == rhsHasAlloc) {
294
295
297 }
298
299
300
301
302 if (rhsHasAlloc) {
303 std::swap(lhs, rhs);
304 lhsAlloc = rhsAlloc;
305 lhsAllocScope = rhsAllocScope;
306 }
307
308
309
310 if (lhsAllocScope) {
311
312
313
317 if (rhsParentOp == lhsAllocScope) {
318 BlockArgument rhsArg = dyn_cast(rhs);
321 }
322 }
323
324
325
327 }
328
329
331 if (lhs == rhs)
333
334
338
339
340
341 if (lhsValues.empty() || rhsValues.empty())
343
344
345 std::optional result;
346 for (Value lhsVal : lhsValues) {
347 for (Value rhsVal : rhsValues) {
349 result = result ? result->merge(nextResult) : nextResult;
350 }
351 }
352
353
354 return *result;
355 }
356
357
358
359
360
362
364
365
366
367
368
370 }
371
372
373 MemoryEffectOpInterface interface = dyn_cast(op);
374 if (!interface)
376
377
378
380 interface.getEffects(effects);
381
384 if (isa<MemoryEffects::Allocate, MemoryEffects::Free>(effect.getEffect()))
385 continue;
386
387
388
390 if (Value effectValue = effect.getValue())
391 aliasResult = alias(effectValue, location);
392
393
394 if (aliasResult.isNo())
395 continue;
396
397
398 if (isaMemoryEffects::Read(effect.getEffect())) {
400 } else {
401 assert(isaMemoryEffects::Write(effect.getEffect()));
403 }
405 break;
406 }
407 return result;
408 }
static LogicalResult getAllocEffectFor(Value value, std::optional< MemoryEffects::EffectInstance > &effect, Operation *&allocScopeOp)
Given a value, try to get an allocation effect attached to it.
static void collectUnderlyingAddressValues(Value value, unsigned maxDepth, DenseSet< Value > &visited, SmallVectorImpl< Value > &output)
Given a value, collect all of the underlying values being addressed.
static constexpr unsigned maxUnderlyingValueSearchDepth
The maximum depth that will be searched when trying to find an underlying value.
The possible results of an alias query.
bool isNo() const
Returns if this result indicates no possibility of aliasing.
@ MustAlias
The two locations precisely alias each other.
@ MayAlias
The two locations may or may not alias.
@ NoAlias
The two locations do not alias at all.
Attributes are known-constant values of operations.
This class represents an argument of a Block.
Block * getOwner() const
Returns the block that owns this argument.
unsigned getArgNumber() const
Returns the number of this argument.
Block represents an ordered list of Operations.
Region * getParent() const
Provide a 'getParent' method for ilist_node_with_parent methods.
pred_iterator pred_begin()
bool isEntryBlock()
Return if this block is the entry block in the parent region.
ModRefResult getModRef(Operation *op, Value location)
Return the modify-reference behavior of op on location.
virtual AliasResult aliasImpl(Value lhs, Value rhs)
Given the two values, return their aliasing behavior.
AliasResult alias(Value lhs, Value rhs)
Given two values, return their aliasing behavior.
The possible results of whether a memory access modifies or references a memory location.
bool isModAndRef() const
Returns if this result modifies and references memory.
ModRefResult merge(const ModRefResult &other)
Merge this ModRef result with other and return the result.
static ModRefResult getRef()
Return a new result that indicates that the memory access may reference the value stored in memory.
static ModRefResult getNoModRef()
Return a new result that indicates that the memory access neither references nor modifies the value s...
static ModRefResult getModAndRef()
Return a new result that indicates that the memory access may reference and may modify the value stor...
static ModRefResult getMod()
Return a new result that indicates that the memory access may modify the value stored in memory.
This is a value defined by a result of an operation.
Operation * getOwner() const
Returns the operation that owns this result.
unsigned getResultNumber() const
Returns the number of this result.
A trait of region holding operations that define a new scope for automatic allocations,...
This trait indicates that the memory effects of an operation includes the effects of operations neste...
Operation is the basic unit of execution within MLIR.
bool hasTrait()
Returns true if the operation was registered with a particular trait, e.g.
Operation * getParentOp()
Returns the closest surrounding operation that contains this operation or nullptr if this is a top-le...
OpTy getParentOfType()
Return the closest surrounding parent operation that is of type 'OpTy'.
Operation * getParentWithTrait()
Returns the closest surrounding parent operation with trait Trait.
MutableArrayRef< Region > getRegions()
Returns the regions held by this operation.
bool isProperAncestor(Operation *other)
Return true if this operation is a proper ancestor of the other operation.
This class represents a point being branched from in the methods of the RegionBranchOpInterface.
static constexpr RegionBranchPoint parent()
Returns an instance of RegionBranchPoint representing the parent operation.
This class represents a successor of a region.
This class contains a list of basic blocks and a link to the parent operation it is attached to.
Operation * getParentOp()
Return the parent operation this region is attached to.
This class represents a specific instance of an effect.
This class provides an abstraction over the different types of ranges over Values.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Block * getParentBlock()
Return the Block in which this Value is defined.
Region * getParentRegion()
Return the Region in which this Value is defined.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
The following effect indicates that the operation allocates from some resource.