mirror of https://github.com/llvm/circt.git
[Transforms] Move generally applicable passes to transforms (#6087)
SSA maximization and merge block insertion are generally applicable transformations and so shouldn't be nested within CFToHandshake.
This commit is contained in:
parent
96ab076f32
commit
ac85f16f30
|
@ -17,6 +17,7 @@
|
|||
#include "circt/Dialect/Handshake/HandshakeOps.h"
|
||||
#include "circt/Dialect/Handshake/HandshakePasses.h"
|
||||
#include "circt/Support/BackedgeBuilder.h"
|
||||
#include "circt/Transforms/Passes.h"
|
||||
#include "mlir/Transforms/DialectConversion.h"
|
||||
|
||||
#include <memory>
|
||||
|
@ -28,63 +29,6 @@ class OperationPass;
|
|||
} // namespace mlir
|
||||
|
||||
namespace circt {
|
||||
|
||||
/// Strategy class to control the behavior of SSA maximization. The class
|
||||
/// exposes overridable filter functions to dynamically select which blocks,
|
||||
/// block arguments, operations, and operation results should be put into
|
||||
/// maximal SSA form. All filter functions should return true whenever the
|
||||
/// entity they operate on should be considered for SSA maximization. By
|
||||
/// default, all filter functions always return true.
|
||||
class SSAMaximizationStrategy {
|
||||
public:
|
||||
/// Determines whether a block should have the values it defines (i.e., block
|
||||
/// arguments and operation results within the block) SSA maximized.
|
||||
virtual bool maximizeBlock(Block *block);
|
||||
/// Determines whether a block argument should be SSA maximized.
|
||||
virtual bool maximizeArgument(BlockArgument arg);
|
||||
/// Determines whether an operation should have its results SSA maximized.
|
||||
virtual bool maximizeOp(Operation *op);
|
||||
/// Determines whether an operation's result should be SSA maximized.
|
||||
virtual bool maximizeResult(OpResult res);
|
||||
|
||||
virtual ~SSAMaximizationStrategy() = default;
|
||||
};
|
||||
|
||||
/// Converts a single value within a function into maximal SSA form. This
|
||||
/// removes any implicit dataflow of this specific value within the enclosing
|
||||
/// function. The function adds new block arguments wherever necessary to carry
|
||||
/// the value explicitly between blocks.
|
||||
/// Succeeds when it was possible to convert the value into maximal SSA form.
|
||||
LogicalResult maximizeSSA(Value value, PatternRewriter &rewriter);
|
||||
|
||||
/// Considers all of an operation's results for SSA maximization, following a
|
||||
/// provided strategy. This removes any implicit dataflow of the selected
|
||||
/// operation's results within the enclosing function. The function adds new
|
||||
/// block arguments wherever necessary to carry the results explicitly between
|
||||
/// blocks. Succeeds when it was possible to convert the selected operation's
|
||||
/// results into maximal SSA form.
|
||||
LogicalResult maximizeSSA(Operation *op, SSAMaximizationStrategy &strategy,
|
||||
PatternRewriter &rewriter);
|
||||
|
||||
/// Considers all values defined by a block (i.e., block arguments and operation
|
||||
/// results within the block) for SSA maximization, following a provided
|
||||
/// strategy. This removes any implicit dataflow of the selected values within
|
||||
/// the enclosing function. The function adds new block arguments wherever
|
||||
/// necessary to carry the values explicitly between blocks. Succeeds when it
|
||||
/// was possible to convert the selected values defined by the block into
|
||||
/// maximal SSA form.
|
||||
LogicalResult maximizeSSA(Block *block, SSAMaximizationStrategy &strategy,
|
||||
PatternRewriter &rewriter);
|
||||
|
||||
/// Considers all blocks within a region for SSA maximization, following a
|
||||
/// provided strategy. This removes any implicit dataflow of the values defined
|
||||
/// by selected blocks within the region. The function adds new block arguments
|
||||
/// wherever necessary to carry the region's values explicitly between blocks.
|
||||
/// Succeeds when it was possible to convert all of the values defined by
|
||||
/// selected blocks into maximal SSA form.
|
||||
LogicalResult maximizeSSA(Region ®ion, SSAMaximizationStrategy &strategy,
|
||||
PatternRewriter &rewriter);
|
||||
|
||||
namespace handshake {
|
||||
|
||||
// ============================================================================
|
||||
|
@ -309,12 +253,6 @@ insertMergeBlocks(mlir::Region &r, mlir::ConversionPatternRewriter &rewriter);
|
|||
|
||||
std::unique_ptr<mlir::Pass> createInsertMergeBlocksPass();
|
||||
|
||||
// Returns true if the region is into maximal SSA form i.e., if all the values
|
||||
// within the region are in maximal SSA form.
|
||||
bool isRegionSSAMaximized(Region ®ion);
|
||||
|
||||
std::unique_ptr<mlir::Pass> createMaximizeSSAPass();
|
||||
|
||||
} // namespace circt
|
||||
|
||||
#endif // CIRCT_CONVERSION_CFTOHANDSHAKE_H_
|
||||
|
|
|
@ -599,36 +599,6 @@ def HandshakeRemoveBlock : Pass<"handshake-remove-block-structure", "handshake::
|
|||
let constructor = "circt::createHandshakeRemoveBlockPass()";
|
||||
}
|
||||
|
||||
def InsertMergeBlocks : Pass<"insert-merge-blocks", "::mlir::ModuleOp"> {
|
||||
let summary = "Insert explicit merge blocks";
|
||||
let description = [{
|
||||
This pass inserts additional merge blocks for each block with more than
|
||||
two successors. A merge block is a block that only contains one operation,
|
||||
a terminator, and has two predecessors.
|
||||
The order successors are merged together mirrors the order different control
|
||||
paths are created. Thus, each block with two successors will have a corresponding
|
||||
merge block.
|
||||
|
||||
This pass brings the CFG into a canonical form for further transformations.
|
||||
|
||||
Treats loops and sub-CFGs with irregular control flow like single blocks.
|
||||
}];
|
||||
let constructor = "circt::createInsertMergeBlocksPass()";
|
||||
let dependentDialects = ["mlir::cf::ControlFlowDialect", "mlir::func::FuncDialect"];
|
||||
}
|
||||
|
||||
def MaximizeSSA : Pass<"maximize-ssa", "::mlir::ModuleOp"> {
|
||||
let summary = "Convert every function in the module into maximal SSA form";
|
||||
let description = [{
|
||||
Convert the region within every function into maximal SSA form. This
|
||||
ensures that every value used within a block is also defined within the
|
||||
block, making dataflow explicit and removing block dominance-based dataflow
|
||||
semantics. The pass achieves this by adding block arguments wherever
|
||||
necessary to forward values to the block(s) where they are used.
|
||||
}];
|
||||
let constructor = "circt::createMaximizeSSAPass()";
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ConvertToArcs
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -29,6 +29,8 @@ std::unique_ptr<mlir::Pass> createFlattenMemRefPass();
|
|||
std::unique_ptr<mlir::Pass> createFlattenMemRefCallsPass();
|
||||
std::unique_ptr<mlir::Pass> createStripDebugInfoWithPredPass(
|
||||
const std::function<bool(mlir::Location)> &pred);
|
||||
std::unique_ptr<mlir::Pass> createMaximizeSSAPass();
|
||||
std::unique_ptr<mlir::Pass> createInsertMergeBlocksPass();
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Utility functions.
|
||||
|
@ -38,6 +40,73 @@ std::unique_ptr<mlir::Pass> createStripDebugInfoWithPredPass(
|
|||
// shape of size 1).
|
||||
bool isUniDimensional(mlir::MemRefType memref);
|
||||
|
||||
// Returns true if the region is into maximal SSA form i.e., if all the values
|
||||
// within the region are in maximal SSA form.
|
||||
bool isRegionSSAMaximized(Region ®ion);
|
||||
|
||||
/// Strategy class to control the behavior of SSA maximization. The class
|
||||
/// exposes overridable filter functions to dynamically select which blocks,
|
||||
/// block arguments, operations, and operation results should be put into
|
||||
/// maximal SSA form. All filter functions should return true whenever the
|
||||
/// entity they operate on should be considered for SSA maximization. By
|
||||
/// default, all filter functions always return true.
|
||||
class SSAMaximizationStrategy {
|
||||
public:
|
||||
/// Determines whether a block should have the values it defines (i.e., block
|
||||
/// arguments and operation results within the block) SSA maximized.
|
||||
virtual bool maximizeBlock(Block *block);
|
||||
/// Determines whether a block argument should be SSA maximized.
|
||||
virtual bool maximizeArgument(BlockArgument arg);
|
||||
/// Determines whether an operation should have its results SSA maximized.
|
||||
virtual bool maximizeOp(Operation *op);
|
||||
/// Determines whether an operation's result should be SSA maximized.
|
||||
virtual bool maximizeResult(OpResult res);
|
||||
|
||||
virtual ~SSAMaximizationStrategy() = default;
|
||||
};
|
||||
|
||||
/// Converts a single value within a function into maximal SSA form. This
|
||||
/// removes any implicit dataflow of this specific value within the enclosing
|
||||
/// function. The function adds new block arguments wherever necessary to carry
|
||||
/// the value explicitly between blocks.
|
||||
/// Succeeds when it was possible to convert the value into maximal SSA form.
|
||||
LogicalResult maximizeSSA(Value value, PatternRewriter &rewriter);
|
||||
|
||||
/// Considers all of an operation's results for SSA maximization, following a
|
||||
/// provided strategy. This removes any implicit dataflow of the selected
|
||||
/// operation's results within the enclosing function. The function adds new
|
||||
/// block arguments wherever necessary to carry the results explicitly between
|
||||
/// blocks. Succeeds when it was possible to convert the selected operation's
|
||||
/// results into maximal SSA form.
|
||||
LogicalResult maximizeSSA(Operation *op, SSAMaximizationStrategy &strategy,
|
||||
PatternRewriter &rewriter);
|
||||
|
||||
/// Considers all values defined by a block (i.e., block arguments and operation
|
||||
/// results within the block) for SSA maximization, following a provided
|
||||
/// strategy. This removes any implicit dataflow of the selected values within
|
||||
/// the enclosing function. The function adds new block arguments wherever
|
||||
/// necessary to carry the values explicitly between blocks. Succeeds when it
|
||||
/// was possible to convert the selected values defined by the block into
|
||||
/// maximal SSA form.
|
||||
LogicalResult maximizeSSA(Block *block, SSAMaximizationStrategy &strategy,
|
||||
PatternRewriter &rewriter);
|
||||
|
||||
/// Considers all blocks within a region for SSA maximization, following a
|
||||
/// provided strategy. This removes any implicit dataflow of the values defined
|
||||
/// by selected blocks within the region. The function adds new block arguments
|
||||
/// wherever necessary to carry the region's values explicitly between blocks.
|
||||
/// Succeeds when it was possible to convert all of the values defined by
|
||||
/// selected blocks into maximal SSA form.
|
||||
LogicalResult maximizeSSA(Region ®ion, SSAMaximizationStrategy &strategy,
|
||||
PatternRewriter &rewriter);
|
||||
|
||||
/// Manually run merge block insertion on a region.
|
||||
///
|
||||
/// This transformation does treat loops like a single block and thus does not
|
||||
/// affect them.
|
||||
LogicalResult insertMergeBlocks(mlir::Region &r,
|
||||
mlir::ConversionPatternRewriter &rewriter);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Registration
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -70,4 +70,34 @@ def MapArithToCombPass : InterfacePass<"map-arith-to-comb", "circt::hw::HWModule
|
|||
let dependentDialects = ["circt::hw::HWDialect, mlir::arith::ArithDialect, circt::comb::CombDialect"];
|
||||
}
|
||||
|
||||
def InsertMergeBlocks : Pass<"insert-merge-blocks", "::mlir::ModuleOp"> {
|
||||
let summary = "Insert explicit merge blocks";
|
||||
let description = [{
|
||||
This pass inserts additional merge blocks for each block with more than
|
||||
two successors. A merge block is a block that only contains one operation,
|
||||
a terminator, and has two predecessors.
|
||||
The order successors are merged together mirrors the order different control
|
||||
paths are created. Thus, each block with two successors will have a corresponding
|
||||
merge block.
|
||||
|
||||
This pass brings the CFG into a canonical form for further transformations.
|
||||
|
||||
Treats loops and sub-CFGs with irregular control flow like single blocks.
|
||||
}];
|
||||
let constructor = "circt::createInsertMergeBlocksPass()";
|
||||
let dependentDialects = ["mlir::cf::ControlFlowDialect", "mlir::func::FuncDialect"];
|
||||
}
|
||||
|
||||
def MaximizeSSA : Pass<"maximize-ssa", "::mlir::ModuleOp"> {
|
||||
let summary = "Convert every function in the module into maximal SSA form";
|
||||
let description = [{
|
||||
Convert the region within every function into maximal SSA form. This
|
||||
ensures that every value used within a block is also defined within the
|
||||
block, making dataflow explicit and removing block dominance-based dataflow
|
||||
semantics. The pass achieves this by adding block arguments wherever
|
||||
necessary to forward values to the block(s) where they are used.
|
||||
}];
|
||||
let constructor = "circt::createMaximizeSSAPass()";
|
||||
}
|
||||
|
||||
#endif // CIRCT_TRANSFORMS_PASSES
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
add_circt_library(CIRCTCFToHandshake
|
||||
CFToHandshake.cpp
|
||||
InsertMergeBlocks.cpp
|
||||
MaximizeSSA.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/CFToHandshake
|
||||
|
@ -22,4 +20,4 @@ add_circt_library(CIRCTCFToHandshake
|
|||
MLIRSupport
|
||||
MLIRTransforms
|
||||
MLIRAffineToStandard
|
||||
)
|
||||
)
|
||||
|
|
|
@ -2,6 +2,8 @@ add_circt_library(CIRCTTransforms
|
|||
FlattenMemRefs.cpp
|
||||
StripDebugInfoWithPred.cpp
|
||||
MapArithToComb.cpp
|
||||
MaximizeSSA.cpp
|
||||
InsertMergeBlocks.cpp
|
||||
|
||||
ADDITIONAL_HEADER_DIRS
|
||||
${CIRCT_MAIN_INCLUDE_DIR}/circt/Transforms
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../PassDetail.h"
|
||||
#include "circt/Conversion/CFToHandshake.h"
|
||||
#include "PassDetail.h"
|
||||
#include "circt/Transforms/Passes.h"
|
||||
#include "mlir/Analysis/CFGLoopInfo.h"
|
||||
#include "mlir/Conversion/LLVMCommon/ConversionTarget.h"
|
||||
#include "mlir/Conversion/LLVMCommon/Pattern.h"
|
|
@ -11,8 +11,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "../PassDetail.h"
|
||||
#include "circt/Conversion/CFToHandshake.h"
|
||||
#include "PassDetail.h"
|
||||
#include "circt/Transforms/Passes.h"
|
||||
#include "mlir/Dialect/Func/IR/FuncOps.h"
|
||||
#include "mlir/IR/MLIRContext.h"
|
Loading…
Reference in New Issue