diff --git a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td --- a/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td +++ b/mlir/include/mlir/Dialect/Transform/IR/TransformOps.td @@ -24,7 +24,7 @@ ["getSuccessorEntryOperands", "getSuccessorRegions", "getRegionInvocationBounds"]>, DeclareOpInterfaceMethods, - FunctionalStyleTransformOpTrait, MemoryEffectsOpInterface, + DeclareOpInterfaceMethods, IsolatedFromAbove, PossibleTopLevelTransformOpTrait, SingleBlockImplicitTerminator<"::mlir::transform::YieldOp">]> { let summary = "Attempts sequences of transforms until one succeeds"; diff --git a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp --- a/mlir/lib/Dialect/Transform/IR/TransformOps.cpp +++ b/mlir/lib/Dialect/Transform/IR/TransformOps.cpp @@ -240,6 +240,17 @@ return emitSilenceableError() << "all alternatives failed"; } +void transform::AlternativesOp::getEffects( + SmallVectorImpl &effects) { + consumesHandle(getOperands(), effects); + producesHandle(getResults(), effects); + for (Region *region : getRegions()) { + if (!region->empty()) + producesHandle(region->front().getArguments(), effects); + } + modifiesPayload(effects); +} + LogicalResult transform::AlternativesOp::verify() { for (Region &alternative : getAlternatives()) { Block &block = alternative.front(); diff --git a/mlir/lib/Dialect/Transform/Transforms/CheckUses.cpp b/mlir/lib/Dialect/Transform/Transforms/CheckUses.cpp --- a/mlir/lib/Dialect/Transform/Transforms/CheckUses.cpp +++ b/mlir/lib/Dialect/Transform/Transforms/CheckUses.cpp @@ -140,7 +140,13 @@ return live(); #ifndef NDEBUG - // Check that the definition point actually allcoates the value. + // Check that the definition point actually allocates the value. If the + // definition is a block argument, it may be just forwarding the operand of + // the parent op without doing a new allocation, allow that. We currently + // don't have the capability to analyze region-based control flow here. + // + // TODO: when this ported to the dataflow analysis infra, we should have + // proper support for region-based control flow. Operation *valueSource = operand.get().isa() ? operand.get().getDefiningOp() @@ -149,7 +155,8 @@ SmallVector instances; iface.getEffectsOnResource(transform::TransformMappingResource::get(), instances); - assert(hasEffect(instances, operand.get()) && + assert((operand.get().isa() || + hasEffect(instances, operand.get())) && "expected the op defining the value to have an allocation effect " "on it"); #endif diff --git a/mlir/test/Dialect/Transform/check-use-after-free.mlir b/mlir/test/Dialect/Transform/check-use-after-free.mlir --- a/mlir/test/Dialect/Transform/check-use-after-free.mlir +++ b/mlir/test/Dialect/Transform/check-use-after-free.mlir @@ -167,3 +167,13 @@ return } +// ----- + +// This should not crash. + +transform.sequence failures(propagate) { +^bb0(%arg0: !pdl.operation): + alternatives %arg0 : !pdl.operation { + ^bb0(%arg1: !pdl.operation): + } +}