[EDSC] Cleanup declarative builder insertion point with blocks

Declarative builders want to provide the same nesting interface for blocks and loops. MLIR on the other hand has different behaviors:
1. when an AffineForOp is created the insertion point does not enter the loop body;
2. when a Block is created, the insertion point does enter the block body.

Guard against the second behavior in EDSC to make the interface unsurprising.
This also surfaces two places in the eager branch API where I was guarding against this behavior indirectly by creating a new ScopedContext.

Instead, uniformize everything to properly reset the insertion point in the unique place that builds the mlir::Block*.

PiperOrigin-RevId: 237619513
This commit is contained in:
Nicolas Vasilache 2019-03-09 11:27:59 -08:00 committed by jpienaar
parent 497d645337
commit 861eb87471
3 changed files with 32 additions and 16 deletions

View File

@ -125,8 +125,14 @@ InstructionHandle::create(StringRef name, ArrayRef<ValueHandle> operands,
}
BlockHandle mlir::edsc::BlockHandle::create(ArrayRef<Type> argTypes) {
auto *currentB = ScopedContext::getBuilder();
auto *ib = currentB->getInsertionBlock();
auto ip = currentB->getInsertionPoint();
BlockHandle res;
res.block = ScopedContext::getBuilder()->createBlock();
// 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);
}

View File

@ -51,14 +51,7 @@ InstructionHandle mlir::edsc::intrinsics::BR(BlockHandle *bh,
ArrayRef<ValueHandle> operands) {
assert(!*bh && "Unexpected already captured BlockHandle");
enforceEmptyCapturesMatchOperands(captures, operands);
{ // Clone the scope explicitly to avoid modifying the insertion point in the
// current scope which result in surprising usage.
auto *currentB = ScopedContext::getBuilder();
FuncBuilder b(currentB->getInsertionBlock(), currentB->getInsertionPoint());
Location loc = ScopedContext::getLocation();
ScopedContext scope(b, loc);
BlockBuilder(bh, captures)({/* no body */});
} // Release before adding the branch to the eagerly created block.
BlockBuilder(bh, captures)({/* no body */});
SmallVector<Value *, 4> ops(operands.begin(), operands.end());
return InstructionHandle::create<BranchOp>(bh->getBlock(), ops);
}
@ -83,14 +76,8 @@ InstructionHandle mlir::edsc::intrinsics::COND_BR(
assert(!*falseBranch && "Unexpected already captured BlockHandle");
enforceEmptyCapturesMatchOperands(trueCaptures, trueOperands);
enforceEmptyCapturesMatchOperands(falseCaptures, falseOperands);
{ // Clone the scope explicitly.
auto *currentB = ScopedContext::getBuilder();
FuncBuilder b(currentB->getInsertionBlock(), currentB->getInsertionPoint());
Location loc = ScopedContext::getLocation();
ScopedContext scope(b, loc);
BlockBuilder(trueBranch, trueCaptures)({/* no body */});
BlockBuilder(falseBranch, falseCaptures)({/* no body */});
} // Release before adding the branch to the eagerly created block.
BlockBuilder(trueBranch, trueCaptures)({/* no body */});
BlockBuilder(falseBranch, falseCaptures)({/* no body */});
SmallVector<Value *, 4> trueOps(trueOperands.begin(), trueOperands.end());
SmallVector<Value *, 4> falseOps(falseOperands.begin(), falseOperands.end());
return InstructionHandle::create<CondBranchOp>(

View File

@ -401,6 +401,29 @@ TEST_FUNC(custom_ops) {
f->print(llvm::outs());
}
TEST_FUNC(insertion_in_block) {
using namespace edsc;
using namespace edsc::intrinsics;
using namespace edsc::op;
auto indexType = IndexType::get(&globalContext());
auto f = makeFunction("insertion_in_block", {}, {indexType, indexType});
ScopedContext scope(f.get());
BlockHandle b1;
// clang-format off
ValueHandle::create<ConstantIntOp>(0, 32);
BlockBuilder(&b1, {})({
ValueHandle::create<ConstantIntOp>(1, 32)
});
ValueHandle::create<ConstantIntOp>(2, 32);
// CHECK-LABEL: @insertion_in_block
// CHECK: {{.*}} = constant 0 : i32
// CHECK: {{.*}} = constant 2 : i32
// CHECK: ^bb1: // no predecessors
// CHECK: {{.*}} = constant 1 : i32
// clang-format on
f->print(llvm::outs());
}
int main() {
RUN_TESTS();
return 0;