[Mlir-commits] [mlir] 5c5ec96 - [mlir] Remove EDSC LoopBuilder, derived classes and related functionality
Alex Zinenko
llvmlistbot at llvm.org
Fri Jun 19 00:38:06 PDT 2020
Author: Alex Zinenko
Date: 2020-06-19T09:37:43+02:00
New Revision: 5c5ec96bd2c52b33b610b39e9cb9f5412722e6ea
URL: https://github.com/llvm/llvm-project/commit/5c5ec96bd2c52b33b610b39e9cb9f5412722e6ea
DIFF: https://github.com/llvm/llvm-project/commit/5c5ec96bd2c52b33b610b39e9cb9f5412722e6ea.diff
LOG: [mlir] Remove EDSC LoopBuilder, derived classes and related functionality
Callback-based loop construction, with loop bodies being constructed during the
construction of the parent op using a function, is now fully supported by the
core infrastructure. This provides almost the same level of brevity as EDSC
LoopBuilder at less than 30% infrastructural code cost. Functional equivalents
compatible with EDSC ScopedContext are implemented on top of the main builders.
LoopBuilder and related functionality has been deprecated, remove it.
Differential Revision: https://reviews.llvm.org/D81874
Added:
Modified:
mlir/include/mlir/Dialect/Affine/EDSC/Builders.h
mlir/include/mlir/Dialect/Linalg/EDSC/Builders.h
mlir/include/mlir/Dialect/SCF/EDSC/Builders.h
mlir/include/mlir/EDSC/Builders.h
mlir/lib/Dialect/Affine/EDSC/Builders.cpp
mlir/lib/Dialect/Linalg/EDSC/Builders.cpp
mlir/lib/Dialect/SCF/EDSC/Builders.cpp
mlir/lib/EDSC/Builders.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/Dialect/Affine/EDSC/Builders.h b/mlir/include/mlir/Dialect/Affine/EDSC/Builders.h
index 3cb326d2fd9e..5c99a430c862 100644
--- a/mlir/include/mlir/Dialect/Affine/EDSC/Builders.h
+++ b/mlir/include/mlir/Dialect/Affine/EDSC/Builders.h
@@ -22,53 +22,6 @@
namespace mlir {
namespace edsc {
-/// Constructs a new AffineForOp and captures the associated induction
-/// variable. A Value pointer is passed as the first argument and is the
-/// *only* way to capture the loop induction variable.
-LoopBuilder makeAffineLoopBuilder(Value *iv, ArrayRef<Value> lbs,
- ArrayRef<Value> ubs, int64_t step);
-
-/// Deprecated. Use affineLoopNestBuilder instead.
-///
-/// Explicit nested LoopBuilder. Offers a compressed multi-loop builder to avoid
-/// explicitly writing all the loops in a nest. This simple functionality is
-/// also useful to write rank-agnostic custom ops.
-///
-/// Usage:
-///
-/// ```c++
-/// AffineLoopNestBuilder({&i, &j, &k}, {lb, lb, lb}, {ub, ub, ub}, {1, 1,
-/// 1})(
-/// [&](){
-/// ...
-/// });
-/// ```
-///
-/// ```c++
-/// AffineLoopNestBuilder({&i}, {lb}, {ub}, {1})([&](){
-/// AffineLoopNestBuilder({&j}, {lb}, {ub}, {1})([&](){
-/// AffineLoopNestBuilder({&k}, {lb}, {ub}, {1})([&](){
-/// ...
-/// }),
-/// }),
-/// });
-/// ```
-class AffineLoopNestBuilder {
-public:
- /// This entry point accommodates the fact that AffineForOp implicitly uses
- /// multiple `lbs` and `ubs` with one single `iv` and `step` to encode `max`
- /// and and `min` constraints respectively.
- AffineLoopNestBuilder(Value *iv, ArrayRef<Value> lbs, ArrayRef<Value> ubs,
- int64_t step);
- AffineLoopNestBuilder(MutableArrayRef<Value> ivs, ArrayRef<Value> lbs,
- ArrayRef<Value> ubs, ArrayRef<int64_t> steps);
-
- void operator()(function_ref<void(void)> fun = nullptr);
-
-private:
- SmallVector<LoopBuilder, 4> loops;
-};
-
/// Creates a perfect nest of affine "for" loops, given the list of lower
/// bounds, upper bounds and steps. The three lists are expected to contain the
/// same number of elements. Uses the OpBuilder and Location stored in
diff --git a/mlir/include/mlir/Dialect/Linalg/EDSC/Builders.h b/mlir/include/mlir/Dialect/Linalg/EDSC/Builders.h
index f6b2d26e5156..15f89a8ec5e0 100644
--- a/mlir/include/mlir/Dialect/Linalg/EDSC/Builders.h
+++ b/mlir/include/mlir/Dialect/Linalg/EDSC/Builders.h
@@ -14,8 +14,6 @@
#define MLIR_DIALECT_LINALG_EDSC_BUILDERS_H_
#include "mlir/Dialect/Linalg/IR/LinalgOps.h"
-// TODO(ntv): Needed for SubViewOp::Range, clean this up.
-#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/Dialect/Utils/StructuredOpsUtils.h"
#include "mlir/EDSC/Builders.h"
#include "mlir/IR/AffineExpr.h"
@@ -24,37 +22,12 @@
namespace mlir {
class AffineForOp;
class BlockArgument;
-class SubViewOp;
namespace scf {
class ParallelOp;
} // namespace scf
namespace edsc {
-class AffineLoopNestBuilder;
-class LoopNestBuilder;
-class ParallelLoopNestBuilder;
-
-/// Helper template class for building scf.for and affine.loop nests from
-/// ranges.
-template <typename LoopTy> class GenericLoopNestRangeBuilder {
-public:
- GenericLoopNestRangeBuilder(MutableArrayRef<Value> ivs,
- ArrayRef<SubViewOp::Range> ranges);
- void operator()(std::function<void(void)> fun = nullptr) { (*builder)(fun); }
-
-private:
- using LoopOrAffineLoopBuilder =
- typename std::conditional_t<std::is_same<LoopTy, AffineForOp>::value,
- AffineLoopNestBuilder, LoopNestBuilder>;
- using BuilderType =
- typename std::conditional_t<std::is_same<LoopTy, scf::ParallelOp>::value,
- ParallelLoopNestBuilder,
- LoopOrAffineLoopBuilder>;
-
- std::unique_ptr<BuilderType> builder;
-};
-
inline void defaultRegionBuilder(ValueRange args) {}
/// Build a `linalg.generic` op with the specified `inputs`, `outputs` and
diff --git a/mlir/include/mlir/Dialect/SCF/EDSC/Builders.h b/mlir/include/mlir/Dialect/SCF/EDSC/Builders.h
index 607ea439d63a..1605f588bc00 100644
--- a/mlir/include/mlir/Dialect/SCF/EDSC/Builders.h
+++ b/mlir/include/mlir/Dialect/SCF/EDSC/Builders.h
@@ -22,55 +22,6 @@
namespace mlir {
namespace edsc {
-/// Constructs a new scf::ParallelOp and captures the associated induction
-/// variables. An array of Value pointers is passed as the first
-/// argument and is the *only* way to capture loop induction variables.
-LoopBuilder makeParallelLoopBuilder(MutableArrayRef<Value> ivs,
- ArrayRef<Value> lbs, ArrayRef<Value> ubs,
- ArrayRef<Value> steps);
-/// Constructs a new scf::ForOp and captures the associated induction
-/// variable. A Value pointer is passed as the first argument and is the
-/// *only* way to capture the loop induction variable.
-LoopBuilder makeLoopBuilder(Value *iv, Value lb, Value ub, Value step,
- MutableArrayRef<Value> iterArgsHandles,
- ValueRange iterArgsInitValues);
-LoopBuilder makeLoopBuilder(Value *iv, Value lb, Value ub, Value step,
- MutableArrayRef<Value> iterArgsHandles,
- ValueRange iterArgsInitValues);
-inline LoopBuilder makeLoopBuilder(Value *iv, Value lb, Value ub, Value step) {
- return makeLoopBuilder(iv, lb, ub, step, MutableArrayRef<Value>{}, {});
-}
-
-/// Helper class to sugar building scf.parallel loop nests from lower/upper
-/// bounds and step sizes.
-class ParallelLoopNestBuilder {
-public:
- ParallelLoopNestBuilder(MutableArrayRef<Value> ivs, ArrayRef<Value> lbs,
- ArrayRef<Value> ubs, ArrayRef<Value> steps);
-
- void operator()(function_ref<void(void)> fun = nullptr);
-
-private:
- SmallVector<LoopBuilder, 4> loops;
-};
-
-/// Helper class to sugar building scf.for loop nests from ranges.
-/// This is similar to edsc::AffineLoopNestBuilder except it operates on
-/// scf.for.
-class LoopNestBuilder {
-public:
- LoopNestBuilder(Value *iv, Value lb, Value ub, Value step);
- LoopNestBuilder(Value *iv, Value lb, Value ub, Value step,
- MutableArrayRef<Value> iterArgsHandles,
- ValueRange iterArgsInitValues);
- LoopNestBuilder(MutableArrayRef<Value> ivs, ArrayRef<Value> lbs,
- ArrayRef<Value> ubs, ArrayRef<Value> steps);
- ValueRange operator()(std::function<void(void)> fun = nullptr);
-
-private:
- SmallVector<LoopBuilder, 4> loops;
-};
-
/// Adapters for building loop nests using the builder and the location stored
/// in ScopedContext. Actual builders are in scf::buildLoopNest.
scf::ValueVector loopNestBuilder(ValueRange lbs, ValueRange ubs,
diff --git a/mlir/include/mlir/EDSC/Builders.h b/mlir/include/mlir/EDSC/Builders.h
index 5d9eb50613da..414717956d75 100644
--- a/mlir/include/mlir/EDSC/Builders.h
+++ b/mlir/include/mlir/EDSC/Builders.h
@@ -147,42 +147,6 @@ class NestedBuilder {
ScopedContext *bodyScope = nullptr;
};
-/// A LoopBuilder is a generic NestedBuilder for loop-like MLIR operations.
-/// More specifically it is meant to be used as a temporary object for
-/// representing any nested MLIR construct that is "related to" an mlir::Value
-/// (for now an induction variable).
-/// This is extensible and will evolve in the future as MLIR evolves, hence
-/// the name LoopBuilder (as opposed to say ForBuilder or AffineForBuilder).
-class LoopBuilder : public NestedBuilder {
-public:
- LoopBuilder(const LoopBuilder &) = delete;
- LoopBuilder(LoopBuilder &&) = default;
-
- LoopBuilder &operator=(const LoopBuilder &) = delete;
- LoopBuilder &operator=(LoopBuilder &&) = default;
-
- /// 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 LoopBuilder.
- void operator()(function_ref<void(void)> fun = nullptr);
- void setOp(Operation *op) { this->op = op; }
- Operation *getOp() { return op; }
-
-private:
- LoopBuilder() = default;
-
- friend LoopBuilder makeAffineLoopBuilder(Value *iv, ArrayRef<Value> lbs,
- ArrayRef<Value> ubs, int64_t step);
- friend LoopBuilder makeParallelLoopBuilder(MutableArrayRef<Value> ivs,
- ArrayRef<Value> lbs,
- ArrayRef<Value> ubs,
- ArrayRef<Value> steps);
- friend LoopBuilder makeLoopBuilder(Value *iv, Value lb, Value ub, Value step,
- MutableArrayRef<Value> iterArgsHandles,
- ValueRange iterArgsInitValues);
- Operation *op;
-};
-
// This class exists solely to handle the C++ vexing parse case when
// trying to enter a Block that has already been constructed.
class Append {};
diff --git a/mlir/lib/Dialect/Affine/EDSC/Builders.cpp b/mlir/lib/Dialect/Affine/EDSC/Builders.cpp
index 87a0b9defdc3..559f375c5dff 100644
--- a/mlir/lib/Dialect/Affine/EDSC/Builders.cpp
+++ b/mlir/lib/Dialect/Affine/EDSC/Builders.cpp
@@ -14,56 +14,6 @@
using namespace mlir;
using namespace mlir::edsc;
-static Optional<Value> emitStaticFor(ArrayRef<Value> lbs, ArrayRef<Value> ubs,
- int64_t step) {
- if (lbs.size() != 1 || ubs.size() != 1)
- return Optional<Value>();
-
- auto *lbDef = lbs.front().getDefiningOp();
- auto *ubDef = ubs.front().getDefiningOp();
- if (!lbDef || !ubDef)
- return Optional<Value>();
-
- auto lbConst = dyn_cast<ConstantIndexOp>(lbDef);
- auto ubConst = dyn_cast<ConstantIndexOp>(ubDef);
- if (!lbConst || !ubConst)
- return Optional<Value>();
- return ScopedContext::getBuilderRef()
- .create<AffineForOp>(ScopedContext::getLocation(), lbConst.getValue(),
- ubConst.getValue(), step)
- .getInductionVar();
-}
-
-LoopBuilder mlir::edsc::makeAffineLoopBuilder(Value *iv, ArrayRef<Value> lbs,
- ArrayRef<Value> ubs,
- int64_t step) {
- mlir::edsc::LoopBuilder result;
- if (auto staticForIv = emitStaticFor(lbs, ubs, step))
- *iv = staticForIv.getValue();
- else
- *iv = ScopedContext::getBuilderRef()
- .create<AffineForOp>(
- ScopedContext::getLocation(), lbs,
- ScopedContext::getBuilderRef().getMultiDimIdentityMap(
- lbs.size()),
- ubs,
- ScopedContext::getBuilderRef().getMultiDimIdentityMap(
- ubs.size()),
- step)
- .getInductionVar();
-
- auto *body = getForInductionVarOwner(*iv).getBody();
- result.enter(body);
- return result;
-}
-
-mlir::edsc::AffineLoopNestBuilder::AffineLoopNestBuilder(Value *iv,
- ArrayRef<Value> lbs,
- ArrayRef<Value> ubs,
- int64_t step) {
- loops.emplace_back(makeAffineLoopBuilder(iv, lbs, ubs, step));
-}
-
void mlir::edsc::affineLoopNestBuilder(
ValueRange lbs, ValueRange ubs, ArrayRef<int64_t> steps,
function_ref<void(ValueRange)> bodyBuilderFn) {
@@ -108,30 +58,6 @@ void mlir::edsc::affineLoopBuilder(ValueRange lbs, ValueRange ubs, int64_t step,
});
}
-mlir::edsc::AffineLoopNestBuilder::AffineLoopNestBuilder(
- MutableArrayRef<Value> ivs, ArrayRef<Value> lbs, ArrayRef<Value> ubs,
- ArrayRef<int64_t> steps) {
- assert(ivs.size() == lbs.size() && "Mismatch in number of arguments");
- assert(ivs.size() == ubs.size() && "Mismatch in number of arguments");
- assert(ivs.size() == steps.size() && "Mismatch in number of arguments");
- for (auto it : llvm::zip(ivs, lbs, ubs, steps))
- loops.emplace_back(makeAffineLoopBuilder(&std::get<0>(it), std::get<1>(it),
- std::get<2>(it), std::get<3>(it)));
-}
-
-void mlir::edsc::AffineLoopNestBuilder::operator()(
- function_ref<void(void)> fun) {
- if (fun)
- fun();
- // Iterate on the calling operator() on all the loops in the nest.
- // The iteration order is from innermost to outermost because enter/exit needs
- // to be asymmetric (i.e. enter() occurs on LoopBuilder construction, exit()
- // occurs on calling operator()). The asymmetry is required for properly
- // nesting imperfectly nested regions (see LoopBuilder::operator()).
- for (auto lit = loops.rbegin(), eit = loops.rend(); lit != eit; ++lit)
- (*lit)();
-}
-
static std::pair<AffineExpr, Value>
categorizeValueByAffineType(MLIRContext *context, Value val, unsigned &numDims,
unsigned &numSymbols) {
diff --git a/mlir/lib/Dialect/Linalg/EDSC/Builders.cpp b/mlir/lib/Dialect/Linalg/EDSC/Builders.cpp
index b2bd7679fc81..5016ca9b3055 100644
--- a/mlir/lib/Dialect/Linalg/EDSC/Builders.cpp
+++ b/mlir/lib/Dialect/Linalg/EDSC/Builders.cpp
@@ -21,55 +21,6 @@ using namespace mlir::edsc::intrinsics;
using namespace mlir::linalg;
using namespace mlir::scf;
-static void unpackRanges(ArrayRef<SubViewOp::Range> ranges,
- SmallVectorImpl<Value> &lbs,
- SmallVectorImpl<Value> &ubs,
- SmallVectorImpl<Value> &steps) {
- for (SubViewOp::Range range : ranges) {
- lbs.emplace_back(range.offset);
- ubs.emplace_back(range.size);
- steps.emplace_back(range.stride);
- }
-}
-
-namespace mlir {
-namespace edsc {
-
-template <>
-GenericLoopNestRangeBuilder<scf::ForOp>::GenericLoopNestRangeBuilder(
- MutableArrayRef<Value> ivs, ArrayRef<SubViewOp::Range> ranges) {
- SmallVector<Value, 4> lbs, ubs, steps;
- unpackRanges(ranges, lbs, ubs, steps);
- builder = std::make_unique<LoopNestBuilder>(ivs, lbs, ubs, steps);
-}
-
-template <>
-GenericLoopNestRangeBuilder<AffineForOp>::GenericLoopNestRangeBuilder(
- MutableArrayRef<Value> ivs, ArrayRef<SubViewOp::Range> ranges) {
- SmallVector<Value, 4> lbs, ubs, steps;
- unpackRanges(ranges, lbs, ubs, steps);
- SmallVector<int64_t, 4> constantSteps;
- constantSteps.reserve(steps.size());
- for (Value v : steps) {
- auto op = v.getDefiningOp<ConstantIndexOp>();
- assert(op && "Affine loops require constant steps");
- constantSteps.push_back(op.getValue());
- }
- builder =
- std::make_unique<AffineLoopNestBuilder>(ivs, lbs, ubs, constantSteps);
-}
-
-template <>
-GenericLoopNestRangeBuilder<scf::ParallelOp>::GenericLoopNestRangeBuilder(
- MutableArrayRef<Value> ivs, ArrayRef<SubViewOp::Range> ranges) {
- SmallVector<Value, 4> lbs, ubs, steps;
- unpackRanges(ranges, lbs, ubs, steps);
- builder = std::make_unique<ParallelLoopNestBuilder>(ivs, lbs, ubs, steps);
-}
-
-} // namespace edsc
-} // namespace mlir
-
Operation *mlir::edsc::makeGenericLinalgOp(
ArrayRef<IteratorType> iteratorTypes, ArrayRef<StructuredIndexed> inputs,
ArrayRef<StructuredIndexed> outputs,
diff --git a/mlir/lib/Dialect/SCF/EDSC/Builders.cpp b/mlir/lib/Dialect/SCF/EDSC/Builders.cpp
index 090c72fcd91f..082c8c371ddc 100644
--- a/mlir/lib/Dialect/SCF/EDSC/Builders.cpp
+++ b/mlir/lib/Dialect/SCF/EDSC/Builders.cpp
@@ -14,105 +14,6 @@
using namespace mlir;
using namespace mlir::edsc;
-mlir::edsc::ParallelLoopNestBuilder::ParallelLoopNestBuilder(
- MutableArrayRef<Value> ivs, ArrayRef<Value> lbs, ArrayRef<Value> ubs,
- ArrayRef<Value> steps) {
- assert(ivs.size() == lbs.size() && "Mismatch in number of arguments");
- assert(ivs.size() == ubs.size() && "Mismatch in number of arguments");
- assert(ivs.size() == steps.size() && "Mismatch in number of arguments");
-
- loops.emplace_back(makeParallelLoopBuilder(ivs, lbs, ubs, steps));
-}
-
-void mlir::edsc::ParallelLoopNestBuilder::operator()(
- function_ref<void(void)> fun) {
- if (fun)
- fun();
- // Iterate on the calling operator() on all the loops in the nest.
- // The iteration order is from innermost to outermost because enter/exit needs
- // to be asymmetric (i.e. enter() occurs on LoopBuilder construction, exit()
- // occurs on calling operator()). The asymmetry is required for properly
- // nesting imperfectly nested regions (see LoopBuilder::operator()).
- for (auto lit = loops.rbegin(), eit = loops.rend(); lit != eit; ++lit)
- (*lit)();
-}
-
-mlir::edsc::LoopNestBuilder::LoopNestBuilder(MutableArrayRef<Value> ivs,
- ArrayRef<Value> lbs,
- ArrayRef<Value> ubs,
- ArrayRef<Value> steps) {
- assert(ivs.size() == lbs.size() && "expected size of ivs and lbs to match");
- assert(ivs.size() == ubs.size() && "expected size of ivs and ubs to match");
- assert(ivs.size() == steps.size() &&
- "expected size of ivs and steps to match");
- loops.reserve(ivs.size());
- for (auto it : llvm::zip(ivs, lbs, ubs, steps))
- loops.emplace_back(makeLoopBuilder(&std::get<0>(it), std::get<1>(it),
- std::get<2>(it), std::get<3>(it)));
- assert(loops.size() == ivs.size() && "Mismatch loops vs ivs size");
-}
-
-mlir::edsc::LoopNestBuilder::LoopNestBuilder(
- Value *iv, Value lb, Value ub, Value step,
- MutableArrayRef<Value> iterArgsHandles, ValueRange iterArgsInitValues) {
- assert(iterArgsInitValues.size() == iterArgsHandles.size() &&
- "expected size of arguments and argument_handles to match");
- loops.emplace_back(
- makeLoopBuilder(iv, lb, ub, step, iterArgsHandles, iterArgsInitValues));
-}
-
-mlir::edsc::LoopNestBuilder::LoopNestBuilder(Value *iv, Value lb, Value ub,
- Value step) {
- SmallVector<Value, 0> noArgs;
- loops.emplace_back(makeLoopBuilder(iv, lb, ub, step, noArgs, {}));
-}
-
-ValueRange mlir::edsc::LoopNestBuilder::LoopNestBuilder::operator()(
- std::function<void(void)> fun) {
- if (fun)
- fun();
-
- for (auto &lit : reverse(loops))
- lit({});
-
- if (!loops.empty())
- return loops[0].getOp()->getResults();
- return {};
-}
-
-LoopBuilder mlir::edsc::makeParallelLoopBuilder(MutableArrayRef<Value> ivs,
- ArrayRef<Value> lbs,
- ArrayRef<Value> ubs,
- ArrayRef<Value> steps) {
- scf::ParallelOp parallelOp = OperationBuilder<scf::ParallelOp>(
- SmallVector<Value, 4>(lbs.begin(), lbs.end()),
- SmallVector<Value, 4>(ubs.begin(), ubs.end()),
- SmallVector<Value, 4>(steps.begin(), steps.end()));
- for (size_t i = 0, e = ivs.size(); i < e; ++i)
- ivs[i] = parallelOp.getBody()->getArgument(i);
- LoopBuilder result;
- result.enter(parallelOp.getBody());
- return result;
-}
-
-mlir::edsc::LoopBuilder
-mlir::edsc::makeLoopBuilder(Value *iv, Value lb, Value ub, Value step,
- MutableArrayRef<Value> iterArgsHandles,
- ValueRange iterArgsInitValues) {
- mlir::edsc::LoopBuilder result;
- scf::ForOp forOp =
- OperationBuilder<scf::ForOp>(lb, ub, step, iterArgsInitValues);
- *iv = Value(forOp.getInductionVar());
- auto *body = scf::getForInductionVarOwner(*iv).getBody();
- for (size_t i = 0, e = iterArgsHandles.size(); i < e; ++i) {
- // Skipping the induction variable.
- iterArgsHandles[i] = body->getArgument(i + 1);
- }
- result.setOp(forOp);
- result.enter(body);
- return result;
-}
-
mlir::scf::ValueVector
mlir::edsc::loopNestBuilder(ValueRange lbs, ValueRange ubs, ValueRange steps,
function_ref<void(ValueRange)> fun) {
diff --git a/mlir/lib/EDSC/Builders.cpp b/mlir/lib/EDSC/Builders.cpp
index d40c2f072d41..ffc1eeb99966 100644
--- a/mlir/lib/EDSC/Builders.cpp
+++ b/mlir/lib/EDSC/Builders.cpp
@@ -140,30 +140,6 @@ Block *mlir::edsc::buildInNewBlock(Region ®ion, TypeRange argTypes,
return block;
}
-void mlir::edsc::LoopBuilder::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.
- /// The particular use case concerns nested blocks:
- ///
- /// ```c++
- /// For (&i, lb, ub, 1)({
- /// /--- destructor for this `For` is not always called before ...
- /// V
- /// For (&j1, lb, ub, 1)({
- /// some_op_1,
- /// }),
- /// /--- ... this scope is entered, resulting in improperly nested IR.
- /// V
- /// For (&j2, lb, ub, 1)({
- /// some_op_2,
- /// }),
- /// });
- /// ```
- if (fun)
- fun();
- exit();
-}
-
mlir::edsc::BlockBuilder::BlockBuilder(BlockHandle bh, Append) {
assert(bh && "Expected already captured BlockHandle");
enter(bh.getBlock());
More information about the Mlir-commits
mailing list