[mlir][DialectConversion] Fix recursive clone calls.

The framework was not tracking ops created in any regions of the cloned
op.

Differential Revision: https://reviews.llvm.org/D89668
This commit is contained in:
Sean Silva
2020-10-18 21:10:55 -07:00
parent f4abd3ed6d
commit 7885bf8b78
3 changed files with 41 additions and 4 deletions

View File

@@ -458,10 +458,8 @@ public:
/// ( leaving them alone if no entry is present). Replaces references to
/// cloned sub-operations to the corresponding operation that is copied,
/// and adds those mappings to the map.
Operation *clone(Operation &op, BlockAndValueMapping &mapper) {
return insert(op.clone(mapper));
}
Operation *clone(Operation &op) { return insert(op.clone()); }
Operation *clone(Operation &op, BlockAndValueMapping &mapper);
Operation *clone(Operation &op);
/// Creates a deep copy of this operation but keep the operation regions
/// empty. Operands are remapped using `mapper` (if present), and `mapper` is

View File

@@ -9,6 +9,7 @@
#include "mlir/IR/Builders.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Dialect.h"
#include "mlir/IR/IntegerSet.h"
#include "mlir/IR/Matchers.h"
@@ -459,3 +460,23 @@ LogicalResult OpBuilder::tryFold(Operation *op,
return success();
}
Operation *OpBuilder::clone(Operation &op, BlockAndValueMapping &mapper) {
Operation *newOp = op.clone(mapper);
// The `insert` call below handles the notification for inserting `newOp`
// itself. But if `newOp` has any regions, we need to notify the listener
// about any ops that got inserted inside those regions as part of cloning.
if (listener) {
auto walkFn = [&](Operation *walkedOp) {
listener->notifyOperationInserted(walkedOp);
};
for (Region &region : newOp->getRegions())
region.walk(walkFn);
}
return insert(newOp);
}
Operation *OpBuilder::clone(Operation &op) {
BlockAndValueMapping mapper;
return clone(op, mapper);
}

View File

@@ -86,3 +86,21 @@ func @tensor_from_elements(%arg0: index, %arg1: index) -> tensor<2xindex> {
%0 = tensor_from_elements %arg0, %arg1 : tensor<2xindex>
return %0 : tensor<2xindex>
}
// The dynamic_tensor_from_elements op clones each op in its body.
// Make sure that regions nested within such ops are recursively converted.
// CHECK-LABEL: func @recursively_convert_cloned_regions
func @recursively_convert_cloned_regions(%arg0: tensor<?xindex>, %arg1: index, %arg2: i1) -> tensor<?xindex> {
%tensor = dynamic_tensor_from_elements %arg1 {
^bb0(%iv: index):
%48 = scf.if %arg2 -> (index) {
scf.yield %iv : index
} else {
// CHECK-NOT: extract_element
%50 = extract_element %arg0[%iv] : tensor<?xindex>
scf.yield %50 : index
}
yield %48 : index
} : tensor<?xindex>
return %tensor : tensor<?xindex>
}