Skip to content

Commit

Permalink
[mlir] Remove EDSC BlockBuilder, BlockHandle and related functionality
Browse files Browse the repository at this point in the history
Callback-based constructions of blocks where the body is populated in the same
function as the block creation is a natural extension of callback-based loop
construction. They provide more concise and simple APIs than EDSC BlockBuilder
at less than 20% infrastructural code cost, and are compatible with
ScopedContext. BlockBuilder, Blockhandle and related functionality has been
deprecated, remove them.

Differential Revision: https://reviews.llvm.org/D82015
  • Loading branch information
ftynse committed Jun 19, 2020
1 parent 5c5ec96 commit 0af2262
Show file tree
Hide file tree
Showing 4 changed files with 3 additions and 256 deletions.
55 changes: 3 additions & 52 deletions mlir/include/mlir/Dialect/StandardOps/EDSC/Intrinsics.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,63 +47,14 @@ using std_view = ValueBuilder<ViewOp>;
using std_zero_extendi = ValueBuilder<ZeroExtendIOp>;
using std_sign_extendi = ValueBuilder<SignExtendIOp>;

/// Branches into the mlir::Block* captured by BlockHandle `b` with `operands`.
///
/// Prerequisites:
/// All Handles have already captured previously constructed IR objects.
BranchOp std_br(BlockHandle bh, ValueRange operands);
/// Branches into `block` with `operands`.
BranchOp std_br(Block *block, ValueRange operands);

/// Creates a new mlir::Block* and branches to it from the current block.
/// Argument types are specified by `operands`.
/// Captures the new block in `bh` and the actual `operands` in `captures`. To
/// insert the new mlir::Block*, a local ScopedContext is constructed and
/// released to the current block. The branch operation is then added to the
/// new block.
///
/// Prerequisites:
/// `b` has not yet captured an mlir::Block*.
/// No `captures` have captured any mlir::Value.
/// All `operands` have already captured an mlir::Value
/// captures.size() == operands.size()
/// captures and operands are pairwise of the same type.
BranchOp std_br(BlockHandle *bh, ArrayRef<Type> types,
MutableArrayRef<Value> captures, ValueRange operands);

/// Branches into the mlir::Block* captured by BlockHandle `trueBranch` with
/// `trueOperands` if `cond` evaluates to `true` (resp. `falseBranch` and
/// `falseOperand` if `cond` evaluates to `false`).
///
/// Prerequisites:
/// All Handles have captured previously constructed IR objects.
CondBranchOp std_cond_br(Value cond, BlockHandle trueBranch,
ValueRange trueOperands, BlockHandle falseBranch,
ValueRange falseOperands);
/// Branches into `trueBranch` with `trueOperands` if `cond` evaluates to `true`
/// or to `falseBranch` and `falseOperand` if `cond` evaluates to `false`.
CondBranchOp std_cond_br(Value cond, Block *trueBranch, ValueRange trueOperands,
Block *falseBranch, ValueRange falseOperands);

/// Eagerly creates new mlir::Block* with argument types specified by
/// `trueOperands`/`falseOperands`.
/// Captures the new blocks in `trueBranch`/`falseBranch` and the arguments in
/// `trueCaptures/falseCaptures`.
/// To insert the new mlir::Block*, a local ScopedContext is constructed and
/// released. The branch operation is then added in the original location and
/// targeting the eagerly constructed blocks.
///
/// Prerequisites:
/// `trueBranch`/`falseBranch` has not yet captured an mlir::Block*.
/// No `trueCaptures`/`falseCaptures` have captured any mlir::Value.
/// All `trueOperands`/`trueOperands` have already captured an mlir::Value
/// `trueCaptures`.size() == `trueOperands`.size()
/// `falseCaptures`.size() == `falseOperands`.size()
/// `trueCaptures` and `trueOperands` are pairwise of the same type
/// `falseCaptures` and `falseOperands` are pairwise of the same type.
CondBranchOp
std_cond_br(Value cond, BlockHandle *trueBranch, ArrayRef<Type> trueTypes,
MutableArrayRef<Value> trueCaptures, ValueRange trueOperands,
BlockHandle *falseBranch, ArrayRef<Type> falseTypes,
MutableArrayRef<Value> falseCaptures, ValueRange falseOperands);

/// Provide an index notation around sdt_load and std_store.
using StdIndexedValue =
TemplatedIndexedValue<intrinsics::std_load, intrinsics::std_store>;
Expand Down
91 changes: 0 additions & 91 deletions mlir/include/mlir/EDSC/Builders.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ namespace mlir {
class OperationFolder;

namespace edsc {
class BlockHandle;
class NestedBuilder;

/// Helper class to transparently handle builder insertion points by RAII.
Expand Down Expand Up @@ -147,96 +146,6 @@ class NestedBuilder {
ScopedContext *bodyScope = nullptr;
};

// This class exists solely to handle the C++ vexing parse case when
// trying to enter a Block that has already been constructed.
class Append {};

/// Deprecated. Use buildInNewBlock or appendToBlock instead.
///
/// A BlockBuilder is a NestedBuilder for mlir::Block*.
/// This exists by opposition to LoopBuilder which is not related to an
/// mlir::Block* but to a mlir::Value.
/// It is meant to be used as a temporary object for representing any nested
/// MLIR construct that is "related to" an mlir::Block*.
class BlockBuilder : public NestedBuilder {
public:
/// Enters the mlir::Block* previously captured by `bh` and sets the insertion
/// point to its end. If the block already contains a terminator, set the
/// insertion point before the terminator.
BlockBuilder(BlockHandle bh, Append);

/// Constructs a new mlir::Block with argument types derived from `args`.
/// Captures the new block in `bh` and its arguments into `args`.
/// Enters the new mlir::Block* and sets the insertion point to its end.
///
/// Prerequisites:
/// The Value `args` are typed delayed Values; i.e. they are
/// not yet bound to mlir::Value.
BlockBuilder(BlockHandle *bh) : BlockBuilder(bh, {}, {}) {}
BlockBuilder(BlockHandle *bh, ArrayRef<Type> types,
MutableArrayRef<Value> args);

/// Constructs a new mlir::Block with argument types derived from `args` and
/// appends it as the last block in the region.
/// Captures the new block in `bh` and its arguments into `args`.
/// Enters the new mlir::Block* and sets the insertion point to its end.
///
/// Prerequisites:
/// The Value `args` are typed delayed Values; i.e. they are
/// not yet bound to mlir::Value.
BlockBuilder(BlockHandle *bh, Region &region, ArrayRef<Type> types,
MutableArrayRef<Value> args);

/// The only purpose of this operator is to serve as a sequence point so that
/// the evaluation of `fun` (which build IR snippets in a scoped fashion) is
/// scoped within a BlockBuilder.
void operator()(function_ref<void(void)> fun = nullptr);

private:
BlockBuilder(BlockBuilder &) = delete;
BlockBuilder &operator=(BlockBuilder &other) = delete;
};

/// Deprecated. Use Block * instead.
///
/// A BlockHandle represents a (potentially "delayed") Block abstraction.
/// This extra abstraction is necessary because an mlir::Block is not an
/// mlir::Value.
/// A BlockHandle should be captured by pointer but otherwise passed by Value
/// everywhere.
class BlockHandle {
public:
/// A BlockHandle constructed without an mlir::Block* represents a "delayed"
/// Block. A delayed Block represents the declaration (in the PL sense) of a
/// placeholder for an mlir::Block* that will be constructed and captured at
/// some later point in the program.
BlockHandle() : block(nullptr) {}

/// A BlockHandle constructed with an mlir::Block* represents an "eager"
/// Block. An eager Block represents both the declaration and the definition
/// (in the PL sense) of a placeholder for an mlir::Block* that has already
/// been constructed in the past and that is captured "now" in the program.
BlockHandle(mlir::Block *block) : block(block) {}

/// BlockHandle is a value type, use the default copy constructor and
/// assignment operator.
BlockHandle(const BlockHandle &) = default;
BlockHandle &operator=(const BlockHandle &) = default;

/// Delegates block creation to MLIR and wrap the resulting mlir::Block.
static BlockHandle create(ArrayRef<Type> argTypes);

/// Delegates block creation to MLIR and wrap the resulting mlir::Block.
static BlockHandle createInRegion(Region &region, ArrayRef<Type> argTypes);

operator bool() { return block != nullptr; }
operator mlir::Block *() { return block; }
mlir::Block *getBlock() { return block; }

private:
mlir::Block *block;
};

/// Creates a block in the region that contains the insertion block of the
/// OpBuilder currently at the top of ScopedContext stack (appends the block to
/// the region). Be aware that this will NOT update the insertion point of the
Expand Down
41 changes: 0 additions & 41 deletions mlir/lib/Dialect/StandardOps/EDSC/Intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,55 +12,14 @@
using namespace mlir;
using namespace mlir::edsc;

BranchOp mlir::edsc::intrinsics::std_br(BlockHandle bh, ValueRange operands) {
assert(bh && "Expected already captured BlockHandle");
SmallVector<Value, 4> ops(operands.begin(), operands.end());
return OperationBuilder<BranchOp>(bh.getBlock(), ops);
}

BranchOp mlir::edsc::intrinsics::std_br(Block *block, ValueRange operands) {
return OperationBuilder<BranchOp>(block, operands);
}

BranchOp mlir::edsc::intrinsics::std_br(BlockHandle *bh, ArrayRef<Type> types,
MutableArrayRef<Value> captures,
ValueRange operands) {
assert(!*bh && "Unexpected already captured BlockHandle");
BlockBuilder(bh, types, captures)(/* no body */);
SmallVector<Value, 4> ops(operands.begin(), operands.end());
return OperationBuilder<BranchOp>(bh->getBlock(), ops);
}

CondBranchOp mlir::edsc::intrinsics::std_cond_br(Value cond, Block *trueBranch,
ValueRange trueOperands,
Block *falseBranch,
ValueRange falseOperands) {
return OperationBuilder<CondBranchOp>(cond, trueBranch, trueOperands,
falseBranch, falseOperands);
}

CondBranchOp mlir::edsc::intrinsics::std_cond_br(Value cond,
BlockHandle trueBranch,
ValueRange trueOperands,
BlockHandle falseBranch,
ValueRange falseOperands) {
SmallVector<Value, 4> trueOps(trueOperands.begin(), trueOperands.end());
SmallVector<Value, 4> falseOps(falseOperands.begin(), falseOperands.end());
return OperationBuilder<CondBranchOp>(cond, trueBranch.getBlock(), trueOps,
falseBranch.getBlock(), falseOps);
}

CondBranchOp mlir::edsc::intrinsics::std_cond_br(
Value cond, BlockHandle *trueBranch, ArrayRef<Type> trueTypes,
MutableArrayRef<Value> trueCaptures, ValueRange trueOperands,
BlockHandle *falseBranch, ArrayRef<Type> falseTypes,
MutableArrayRef<Value> falseCaptures, ValueRange falseOperands) {
assert(!*trueBranch && "Unexpected already captured BlockHandle");
assert(!*falseBranch && "Unexpected already captured BlockHandle");
BlockBuilder(trueBranch, trueTypes, trueCaptures)(/* no body */);
BlockBuilder(falseBranch, falseTypes, falseCaptures)(/* no body */);
SmallVector<Value, 4> trueOps(trueOperands.begin(), trueOperands.end());
SmallVector<Value, 4> falseOps(falseOperands.begin(), falseOperands.end());
return OperationBuilder<CondBranchOp>(cond, trueBranch->getBlock(), trueOps,
falseBranch->getBlock(), falseOps);
}
72 changes: 0 additions & 72 deletions mlir/lib/EDSC/Builders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,35 +58,6 @@ MLIRContext *mlir::edsc::ScopedContext::getContext() {
return getBuilderRef().getContext();
}

BlockHandle mlir::edsc::BlockHandle::create(ArrayRef<Type> argTypes) {
auto &currentB = ScopedContext::getBuilderRef();
auto *ib = currentB.getInsertionBlock();
auto ip = currentB.getInsertionPoint();
BlockHandle res;
res.block = ScopedContext::getBuilderRef().createBlock(ib->getParent());
// createBlock sets the insertion point inside the block.
// We do not want this behavior when using declarative builders with nesting.
currentB.setInsertionPoint(ib, ip);
for (auto t : argTypes) {
res.block->addArgument(t);
}
return res;
}

BlockHandle mlir::edsc::BlockHandle::createInRegion(Region &region,
ArrayRef<Type> argTypes) {
BlockHandle res;
region.push_back(new Block);
res.block = &region.back();
// createBlock sets the insertion point inside the block.
// We do not want this behavior when using declarative builders with nesting.
OpBuilder::InsertionGuard g(ScopedContext::getBuilderRef());
ScopedContext::getBuilderRef().setInsertionPoint(res.block,
res.block->begin());
res.block->addArguments(argTypes);
return res;
}

Block *mlir::edsc::createBlock(TypeRange argTypes) {
assert(ScopedContext::getContext() != nullptr && "ScopedContext not set up");
OpBuilder &builder = ScopedContext::getBuilderRef();
Expand Down Expand Up @@ -140,46 +111,3 @@ Block *mlir::edsc::buildInNewBlock(Region &region, TypeRange argTypes,
return block;
}

mlir::edsc::BlockBuilder::BlockBuilder(BlockHandle bh, Append) {
assert(bh && "Expected already captured BlockHandle");
enter(bh.getBlock());
}

mlir::edsc::BlockBuilder::BlockBuilder(BlockHandle *bh, ArrayRef<Type> types,
MutableArrayRef<Value> args) {
assert(!*bh && "BlockHandle already captures a block, use "
"the explicit BockBuilder(bh, Append())({}) syntax instead.");
assert((args.empty() || args.size() == types.size()) &&
"if args captures are specified, their number must match the number "
"of types");
*bh = BlockHandle::create(types);
if (!args.empty())
for (auto it : llvm::zip(args, bh->getBlock()->getArguments()))
std::get<0>(it) = Value(std::get<1>(it));
enter(bh->getBlock());
}

mlir::edsc::BlockBuilder::BlockBuilder(BlockHandle *bh, Region &region,
ArrayRef<Type> types,
MutableArrayRef<Value> args) {
assert(!*bh && "BlockHandle already captures a block, use "
"the explicit BockBuilder(bh, Append())({}) syntax instead.");
assert((args.empty() || args.size() == types.size()) &&
"if args captures are specified, their number must match the number "
"of types");
*bh = BlockHandle::createInRegion(region, types);
if (!args.empty())
for (auto it : llvm::zip(args, bh->getBlock()->getArguments()))
std::get<0>(it) = Value(std::get<1>(it));
enter(bh->getBlock());
}

/// Only serves as an ordering point between entering nested block and creating
/// stmts.
void mlir::edsc::BlockBuilder::operator()(function_ref<void(void)> fun) {
// Call to `exit` must be explicit and asymmetric (cannot happen in the
// destructor) because of ordering wrt comma operator.
if (fun)
fun();
exit();
}

0 comments on commit 0af2262

Please sign in to comment.