@@ -187,13 +187,23 @@ class BufferPlacementAnalysis {
187
187
188
188
// / Finds all associated dealloc nodes for the alloc nodes using alias
189
189
// / information.
190
- DeallocSetT findAssociatedDeallocs (AllocOp alloc ) const {
190
+ DeallocSetT findAssociatedDeallocs (OpResult allocResult ) const {
191
191
DeallocSetT result;
192
- auto possibleValues = aliases.resolve (alloc );
192
+ auto possibleValues = aliases.resolve (allocResult );
193
193
for (Value alias : possibleValues)
194
- for (Operation *user : alias.getUsers ()) {
195
- if (isa<DeallocOp>(user))
196
- result.insert (user);
194
+ for (Operation *op : alias.getUsers ()) {
195
+ // Check for an existing memory effect interface.
196
+ auto effectInstance = dyn_cast<MemoryEffectOpInterface>(op);
197
+ if (!effectInstance)
198
+ continue ;
199
+ // Check whether the associated value will be freed using the current
200
+ // operation.
201
+ SmallVector<MemoryEffects::EffectInstance, 2 > effects;
202
+ effectInstance.getEffectsOnValue (alias, effects);
203
+ if (llvm::any_of (effects, [=](MemoryEffects::EffectInstance &it) {
204
+ return isa<MemoryEffects::Free>(it.getEffect ());
205
+ }))
206
+ result.insert (op);
197
207
}
198
208
return result;
199
209
}
@@ -328,51 +338,65 @@ class BufferPlacementAnalysis {
328
338
329
339
// / The actual buffer placement pass that moves alloc and dealloc nodes into
330
340
// / the right positions. It uses the algorithm described at the top of the file.
331
- // TODO: create a templated version that allows to match dialect-specific
332
- // alloc/dealloc nodes and to insert dialect-specific dealloc node.
333
341
struct BufferPlacementPass
334
342
: mlir::PassWrapper<BufferPlacementPass, FunctionPass> {
335
343
void runOnFunction () override {
336
344
// Get required analysis information first.
337
345
auto &analysis = getAnalysis<BufferPlacementAnalysis>();
338
346
339
347
// Compute an initial placement of all nodes.
340
- llvm::SmallDenseMap<Value, BufferPlacementPositions, 16 > placements;
341
- getFunction ().walk ([&](AllocOp alloc) {
342
- placements[alloc] = analysis.computeAllocAndDeallocPositions (
343
- alloc.getOperation ()->getResult (0 ));
344
- return WalkResult::advance ();
348
+ llvm::SmallVector<std::pair<OpResult, BufferPlacementPositions>, 16 >
349
+ placements;
350
+ getFunction ().walk ([&](MemoryEffectOpInterface op) {
351
+ // Try to find a single allocation result.
352
+ SmallVector<MemoryEffects::EffectInstance, 2 > effects;
353
+ op.getEffects (effects);
354
+
355
+ SmallVector<MemoryEffects::EffectInstance, 2 > allocateResultEffects;
356
+ llvm::copy_if (effects, std::back_inserter (allocateResultEffects),
357
+ [=](MemoryEffects::EffectInstance &it) {
358
+ Value value = it.getValue ();
359
+ return isa<MemoryEffects::Allocate>(it.getEffect ()) &&
360
+ value && value.isa <OpResult>();
361
+ });
362
+ // If there is one result only, we will be able to move the allocation and
363
+ // (possibly existing) deallocation ops.
364
+ if (allocateResultEffects.size () == 1 ) {
365
+ // Insert allocation result.
366
+ auto allocResult = allocateResultEffects[0 ].getValue ().cast <OpResult>();
367
+ placements.emplace_back (
368
+ allocResult, analysis.computeAllocAndDeallocPositions (allocResult));
369
+ }
345
370
});
346
371
347
- // Move alloc (and dealloc - if any) nodes into the right places
348
- // and insert dealloc nodes if necessary.
349
- getFunction (). walk ([&](AllocOp alloc ) {
372
+ // Move alloc (and dealloc - if any) nodes into the right places and insert
373
+ // dealloc nodes if necessary.
374
+ for ( auto &entry : placements ) {
350
375
// Find already associated dealloc nodes.
376
+ OpResult alloc = entry.first ;
351
377
auto deallocs = analysis.findAssociatedDeallocs (alloc);
352
378
if (deallocs.size () > 1 ) {
353
379
emitError (alloc.getLoc (),
354
- " Not supported number of associated dealloc operations" );
355
- return WalkResult::interrupt () ;
380
+ " not supported number of associated dealloc operations" );
381
+ return ;
356
382
}
357
383
358
384
// Move alloc node to the right place.
359
- BufferPlacementPositions &positions = placements[alloc] ;
360
- Operation *allocOperation = alloc.getOperation ();
385
+ BufferPlacementPositions &positions = entry. second ;
386
+ Operation *allocOperation = alloc.getOwner ();
361
387
allocOperation->moveBefore (positions.getAllocPosition ());
362
388
363
389
// If there is an existing dealloc, move it to the right place.
390
+ Operation *nextOp = positions.getDeallocPosition ()->getNextNode ();
391
+ assert (nextOp && " Invalid Dealloc operation position" );
364
392
if (deallocs.size ()) {
365
- Operation *nextOp = positions.getDeallocPosition ()->getNextNode ();
366
- assert (nextOp && " Invalid Dealloc operation position" );
367
393
(*deallocs.begin ())->moveBefore (nextOp);
368
394
} else {
369
395
// If there is no dealloc node, insert one in the right place.
370
- OpBuilder builder (alloc);
371
- builder.setInsertionPointAfter (positions.getDeallocPosition ());
396
+ OpBuilder builder (nextOp);
372
397
builder.create <DeallocOp>(allocOperation->getLoc (), alloc);
373
398
}
374
- return WalkResult::advance ();
375
- });
399
+ }
376
400
};
377
401
};
378
402
0 commit comments