[AffineStoreForward] factor out applyAffineStoreForward() method; [SimplifyMemrefAccess] factor out applySimplifyMemrefAccess() method
This commit is contained in:
parent
07d77f7193
commit
9f31dd663d
|
@ -33,6 +33,10 @@ bool applyLoopPipelining(AffineForOp loop, OpBuilder &builder);
|
||||||
|
|
||||||
bool applyArrayPartition(FuncOp func, OpBuilder &builder);
|
bool applyArrayPartition(FuncOp func, OpBuilder &builder);
|
||||||
|
|
||||||
|
bool applyAffineStoreForward(FuncOp func, OpBuilder &builder);
|
||||||
|
|
||||||
|
bool applySimplifyMemrefAccess(FuncOp func);
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// Optimization Pass Entries
|
// Optimization Pass Entries
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -19,6 +19,23 @@ using namespace scalehls;
|
||||||
// The difference between this pass and built-in memref-dataflow-opt is this
|
// The difference between this pass and built-in memref-dataflow-opt is this
|
||||||
// pass support to forward the StoreOps that are conditionally executed.
|
// pass support to forward the StoreOps that are conditionally executed.
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
struct AffineStoreForward : public AffineStoreForwardBase<AffineStoreForward> {
|
||||||
|
void runOnOperation() override {
|
||||||
|
// Only supports single block functions at the moment.
|
||||||
|
FuncOp func = getOperation();
|
||||||
|
auto builder = OpBuilder(func);
|
||||||
|
|
||||||
|
if (!llvm::hasSingleElement(func)) {
|
||||||
|
markAllAnalysesPreserved();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
applyAffineStoreForward(func, builder);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
// The store to load forwarding relies on three conditions:
|
// The store to load forwarding relies on three conditions:
|
||||||
//
|
//
|
||||||
|
@ -52,29 +69,30 @@ namespace {
|
||||||
// currently only eliminates the stores only if no other loads/uses (other
|
// currently only eliminates the stores only if no other loads/uses (other
|
||||||
// than dealloc) remain.
|
// than dealloc) remain.
|
||||||
//
|
//
|
||||||
struct AffineStoreForward : public AffineStoreForwardBase<AffineStoreForward> {
|
class AffineStoreForwardImpl {
|
||||||
void runOnOperation() override;
|
public:
|
||||||
|
explicit AffineStoreForwardImpl(SmallPtrSet<Value, 4> &memrefsToErase,
|
||||||
|
DominanceInfo *domInfo,
|
||||||
|
PostDominanceInfo *postDomInfo,
|
||||||
|
OpBuilder &builder)
|
||||||
|
: memrefsToErase(memrefsToErase), domInfo(domInfo),
|
||||||
|
postDomInfo(postDomInfo), builder(builder) {}
|
||||||
|
|
||||||
void forwardStoreToLoad(AffineReadOpInterface loadOp);
|
void forwardStoreToLoad(AffineReadOpInterface loadOp);
|
||||||
|
|
||||||
// A list of memref's that are potentially dead / could be eliminated.
|
// A list of memref's that are potentially dead / could be eliminated.
|
||||||
SmallPtrSet<Value, 4> memrefsToErase;
|
SmallPtrSet<Value, 4> &memrefsToErase;
|
||||||
|
|
||||||
DominanceInfo *domInfo = nullptr;
|
DominanceInfo *domInfo = nullptr;
|
||||||
PostDominanceInfo *postDomInfo = nullptr;
|
PostDominanceInfo *postDomInfo = nullptr;
|
||||||
|
|
||||||
|
OpBuilder &builder;
|
||||||
};
|
};
|
||||||
|
} // namespace
|
||||||
} // end anonymous namespace
|
|
||||||
|
|
||||||
/// Creates a pass to perform optimizations relying on memref dataflow such as
|
|
||||||
/// store to load forwarding, elimination of dead stores, and dead allocs.
|
|
||||||
std::unique_ptr<Pass> scalehls::createAffineStoreForwardPass() {
|
|
||||||
return std::make_unique<AffineStoreForward>();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a straightforward implementation not optimized for speed. Optimize
|
// This is a straightforward implementation not optimized for speed. Optimize
|
||||||
// if needed.
|
// if needed.
|
||||||
void AffineStoreForward::forwardStoreToLoad(AffineReadOpInterface loadOp) {
|
void AffineStoreForwardImpl::forwardStoreToLoad(AffineReadOpInterface loadOp) {
|
||||||
// First pass over the use list to get the minimum number of surrounding
|
// First pass over the use list to get the minimum number of surrounding
|
||||||
// loops common between the load op and the store op, with min taken across
|
// loops common between the load op and the store op, with min taken across
|
||||||
// all store ops.
|
// all store ops.
|
||||||
|
@ -188,7 +206,6 @@ void AffineStoreForward::forwardStoreToLoad(AffineReadOpInterface loadOp) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Create a new if operation before the loadOp.
|
// Create a new if operation before the loadOp.
|
||||||
OpBuilder builder(loadOp);
|
|
||||||
builder.setInsertionPointAfter(loadOp);
|
builder.setInsertionPointAfter(loadOp);
|
||||||
auto newIfOp = builder.create<mlir::AffineIfOp>(
|
auto newIfOp = builder.create<mlir::AffineIfOp>(
|
||||||
loadOp.getLoc(), loadOp.getValue().getType(), ifOp.getIntegerSet(),
|
loadOp.getLoc(), loadOp.getValue().getType(), ifOp.getIntegerSet(),
|
||||||
|
@ -214,21 +231,21 @@ void AffineStoreForward::forwardStoreToLoad(AffineReadOpInterface loadOp) {
|
||||||
memrefsToErase.insert(loadOp.getMemRef());
|
memrefsToErase.insert(loadOp.getMemRef());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AffineStoreForward::runOnOperation() {
|
bool scalehls::applyAffineStoreForward(FuncOp func, OpBuilder &builder) {
|
||||||
// Only supports single block functions at the moment.
|
SmallPtrSet<Value, 4> memrefsToErase;
|
||||||
FuncOp f = getOperation();
|
|
||||||
if (!llvm::hasSingleElement(f)) {
|
|
||||||
markAllAnalysesPreserved();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
domInfo = &getAnalysis<DominanceInfo>();
|
|
||||||
postDomInfo = &getAnalysis<PostDominanceInfo>();
|
|
||||||
|
|
||||||
memrefsToErase.clear();
|
memrefsToErase.clear();
|
||||||
|
|
||||||
|
auto domInfo = DominanceInfo(func);
|
||||||
|
auto postDomInfo = PostDominanceInfo(func);
|
||||||
|
|
||||||
|
// Instantiate the pass implementation.
|
||||||
|
auto implement =
|
||||||
|
AffineStoreForwardImpl(memrefsToErase, &domInfo, &postDomInfo, builder);
|
||||||
|
|
||||||
// Walk all load's and perform store to load forwarding.
|
// Walk all load's and perform store to load forwarding.
|
||||||
f.walk([&](AffineReadOpInterface loadOp) { forwardStoreToLoad(loadOp); });
|
func.walk([&](AffineReadOpInterface loadOp) {
|
||||||
|
implement.forwardStoreToLoad(loadOp);
|
||||||
|
});
|
||||||
|
|
||||||
// Check if the store fwd'ed memrefs are now left with only stores and can
|
// Check if the store fwd'ed memrefs are now left with only stores and can
|
||||||
// thus be completely deleted. Note: the canonicalize pass should be able
|
// thus be completely deleted. Note: the canonicalize pass should be able
|
||||||
|
@ -250,4 +267,12 @@ void AffineStoreForward::runOnOperation() {
|
||||||
user->erase();
|
user->erase();
|
||||||
defOp->erase();
|
defOp->erase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a pass to perform optimizations relying on memref dataflow such as
|
||||||
|
/// store to load forwarding, elimination of dead stores, and dead allocs.
|
||||||
|
std::unique_ptr<Pass> scalehls::createAffineStoreForwardPass() {
|
||||||
|
return std::make_unique<AffineStoreForward>();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,11 @@ using namespace scalehls;
|
||||||
namespace {
|
namespace {
|
||||||
struct SimplifyMemrefAccess
|
struct SimplifyMemrefAccess
|
||||||
: public SimplifyMemrefAccessBase<SimplifyMemrefAccess> {
|
: public SimplifyMemrefAccessBase<SimplifyMemrefAccess> {
|
||||||
void runOnOperation() override;
|
void runOnOperation() override { applySimplifyMemrefAccess(getOperation()); }
|
||||||
};
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
} // end anonymous namespace
|
bool scalehls::applySimplifyMemrefAccess(FuncOp func) {
|
||||||
|
|
||||||
void SimplifyMemrefAccess::runOnOperation() {
|
|
||||||
auto func = getOperation();
|
|
||||||
|
|
||||||
// Collect all load and store operations in the function block.
|
// Collect all load and store operations in the function block.
|
||||||
MemAccessesMap map;
|
MemAccessesMap map;
|
||||||
getMemAccessesMap(func.front(), map);
|
getMemAccessesMap(func.front(), map);
|
||||||
|
@ -115,6 +112,8 @@ void SimplifyMemrefAccess::runOnOperation() {
|
||||||
opIndex++;
|
opIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Pass> scalehls::createSimplifyMemrefAccessPass() {
|
std::unique_ptr<Pass> scalehls::createSimplifyMemrefAccessPass() {
|
||||||
|
|
Loading…
Reference in New Issue