forked from OSchip/llvm-project
[mlir] Removed tight coupling of BufferPlacement pass to Alloc and Dealloc.
The current BufferPlacement implementation tries to find Alloc and Dealloc operations in order to move them. However, this is a tight coupling to standard-dialect ops which has been removed in this CL. Differential Revision: https://reviews.llvm.org/D78993
This commit is contained in:
parent
19f5da9c1d
commit
67b466deda
|
@ -187,13 +187,23 @@ public:
|
||||||
|
|
||||||
/// Finds all associated dealloc nodes for the alloc nodes using alias
|
/// Finds all associated dealloc nodes for the alloc nodes using alias
|
||||||
/// information.
|
/// information.
|
||||||
DeallocSetT findAssociatedDeallocs(AllocOp alloc) const {
|
DeallocSetT findAssociatedDeallocs(OpResult allocResult) const {
|
||||||
DeallocSetT result;
|
DeallocSetT result;
|
||||||
auto possibleValues = aliases.resolve(alloc);
|
auto possibleValues = aliases.resolve(allocResult);
|
||||||
for (Value alias : possibleValues)
|
for (Value alias : possibleValues)
|
||||||
for (Operation *user : alias.getUsers()) {
|
for (Operation *op : alias.getUsers()) {
|
||||||
if (isa<DeallocOp>(user))
|
// Check for an existing memory effect interface.
|
||||||
result.insert(user);
|
auto effectInstance = dyn_cast<MemoryEffectOpInterface>(op);
|
||||||
|
if (!effectInstance)
|
||||||
|
continue;
|
||||||
|
// Check whether the associated value will be freed using the current
|
||||||
|
// operation.
|
||||||
|
SmallVector<MemoryEffects::EffectInstance, 2> effects;
|
||||||
|
effectInstance.getEffectsOnValue(alias, effects);
|
||||||
|
if (llvm::any_of(effects, [=](MemoryEffects::EffectInstance &it) {
|
||||||
|
return isa<MemoryEffects::Free>(it.getEffect());
|
||||||
|
}))
|
||||||
|
result.insert(op);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -328,8 +338,6 @@ private:
|
||||||
|
|
||||||
/// The actual buffer placement pass that moves alloc and dealloc nodes into
|
/// The actual buffer placement pass that moves alloc and dealloc nodes into
|
||||||
/// the right positions. It uses the algorithm described at the top of the file.
|
/// the right positions. It uses the algorithm described at the top of the file.
|
||||||
// TODO: create a templated version that allows to match dialect-specific
|
|
||||||
// alloc/dealloc nodes and to insert dialect-specific dealloc node.
|
|
||||||
struct BufferPlacementPass
|
struct BufferPlacementPass
|
||||||
: mlir::PassWrapper<BufferPlacementPass, FunctionPass> {
|
: mlir::PassWrapper<BufferPlacementPass, FunctionPass> {
|
||||||
void runOnFunction() override {
|
void runOnFunction() override {
|
||||||
|
@ -337,42 +345,58 @@ struct BufferPlacementPass
|
||||||
auto &analysis = getAnalysis<BufferPlacementAnalysis>();
|
auto &analysis = getAnalysis<BufferPlacementAnalysis>();
|
||||||
|
|
||||||
// Compute an initial placement of all nodes.
|
// Compute an initial placement of all nodes.
|
||||||
llvm::SmallDenseMap<Value, BufferPlacementPositions, 16> placements;
|
llvm::SmallVector<std::pair<OpResult, BufferPlacementPositions>, 16>
|
||||||
getFunction().walk([&](AllocOp alloc) {
|
placements;
|
||||||
placements[alloc] = analysis.computeAllocAndDeallocPositions(
|
getFunction().walk([&](MemoryEffectOpInterface op) {
|
||||||
alloc.getOperation()->getResult(0));
|
// Try to find a single allocation result.
|
||||||
return WalkResult::advance();
|
SmallVector<MemoryEffects::EffectInstance, 2> effects;
|
||||||
|
op.getEffects(effects);
|
||||||
|
|
||||||
|
SmallVector<MemoryEffects::EffectInstance, 2> allocateResultEffects;
|
||||||
|
llvm::copy_if(effects, std::back_inserter(allocateResultEffects),
|
||||||
|
[=](MemoryEffects::EffectInstance &it) {
|
||||||
|
Value value = it.getValue();
|
||||||
|
return isa<MemoryEffects::Allocate>(it.getEffect()) &&
|
||||||
|
value && value.isa<OpResult>();
|
||||||
|
});
|
||||||
|
// If there is one result only, we will be able to move the allocation and
|
||||||
|
// (possibly existing) deallocation ops.
|
||||||
|
if (allocateResultEffects.size() == 1) {
|
||||||
|
// Insert allocation result.
|
||||||
|
auto allocResult = allocateResultEffects[0].getValue().cast<OpResult>();
|
||||||
|
placements.emplace_back(
|
||||||
|
allocResult, analysis.computeAllocAndDeallocPositions(allocResult));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Move alloc (and dealloc - if any) nodes into the right places
|
// Move alloc (and dealloc - if any) nodes into the right places and insert
|
||||||
// and insert dealloc nodes if necessary.
|
// dealloc nodes if necessary.
|
||||||
getFunction().walk([&](AllocOp alloc) {
|
for (auto &entry : placements) {
|
||||||
// Find already associated dealloc nodes.
|
// Find already associated dealloc nodes.
|
||||||
|
OpResult alloc = entry.first;
|
||||||
auto deallocs = analysis.findAssociatedDeallocs(alloc);
|
auto deallocs = analysis.findAssociatedDeallocs(alloc);
|
||||||
if (deallocs.size() > 1) {
|
if (deallocs.size() > 1) {
|
||||||
emitError(alloc.getLoc(),
|
emitError(alloc.getLoc(),
|
||||||
"Not supported number of associated dealloc operations");
|
"not supported number of associated dealloc operations");
|
||||||
return WalkResult::interrupt();
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move alloc node to the right place.
|
// Move alloc node to the right place.
|
||||||
BufferPlacementPositions &positions = placements[alloc];
|
BufferPlacementPositions &positions = entry.second;
|
||||||
Operation *allocOperation = alloc.getOperation();
|
Operation *allocOperation = alloc.getOwner();
|
||||||
allocOperation->moveBefore(positions.getAllocPosition());
|
allocOperation->moveBefore(positions.getAllocPosition());
|
||||||
|
|
||||||
// If there is an existing dealloc, move it to the right place.
|
// If there is an existing dealloc, move it to the right place.
|
||||||
|
Operation *nextOp = positions.getDeallocPosition()->getNextNode();
|
||||||
|
assert(nextOp && "Invalid Dealloc operation position");
|
||||||
if (deallocs.size()) {
|
if (deallocs.size()) {
|
||||||
Operation *nextOp = positions.getDeallocPosition()->getNextNode();
|
|
||||||
assert(nextOp && "Invalid Dealloc operation position");
|
|
||||||
(*deallocs.begin())->moveBefore(nextOp);
|
(*deallocs.begin())->moveBefore(nextOp);
|
||||||
} else {
|
} else {
|
||||||
// If there is no dealloc node, insert one in the right place.
|
// If there is no dealloc node, insert one in the right place.
|
||||||
OpBuilder builder(alloc);
|
OpBuilder builder(nextOp);
|
||||||
builder.setInsertionPointAfter(positions.getDeallocPosition());
|
|
||||||
builder.create<DeallocOp>(allocOperation->getLoc(), alloc);
|
builder.create<DeallocOp>(allocOperation->getLoc(), alloc);
|
||||||
}
|
}
|
||||||
return WalkResult::advance();
|
}
|
||||||
});
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue