[MLIR] Add a NoRegionArguments trait

- This trait will verify that all regions attached to an Op have no arguments
- Fixes https://bugs.llvm.org/show_bug.cgi?id=46521 : Add trait NoRegionArguments

Differential Revision: https://reviews.llvm.org/D83016
This commit is contained in:
Rahul Joshi 2020-07-01 17:54:12 -07:00
parent cf0b3affed
commit 52af9c59e3
12 changed files with 65 additions and 27 deletions

View File

@ -278,7 +278,8 @@ def AffineForOp : Affine_Op<"for",
}
def AffineIfOp : Affine_Op<"if",
[ImplicitAffineTerminator, RecursiveSideEffects]> {
[ImplicitAffineTerminator, RecursiveSideEffects,
NoRegionArguments]> {
let summary = "if-then-else operation";
let description = [{
Syntax:

View File

@ -183,7 +183,8 @@ def ForOp : SCF_Op<"for",
def IfOp : SCF_Op<"if",
[DeclareOpInterfaceMethods<RegionBranchOpInterface>,
SingleBlockImplicitTerminator<"YieldOp">, RecursiveSideEffects]> {
SingleBlockImplicitTerminator<"YieldOp">, RecursiveSideEffects,
NoRegionArguments]> {
let summary = "if-then-else operation";
let description = [{
The `scf.if` operation represents an if-then-else construct for

View File

@ -33,7 +33,7 @@ class ModuleOp
OpTrait::IsIsolatedFromAbove, OpTrait::AffineScope,
OpTrait::SymbolTable,
OpTrait::SingleBlockImplicitTerminator<ModuleTerminatorOp>::Impl,
SymbolOpInterface::Trait> {
SymbolOpInterface::Trait, OpTrait::NoRegionArguments> {
public:
using Op::Op;
using Op::print;

View File

@ -1737,6 +1737,9 @@ def AttrSizedOperandSegments : NativeOpTrait<"AttrSizedOperandSegments">;
// should be named as `result_segment_sizes`.
def AttrSizedResultSegments : NativeOpTrait<"AttrSizedResultSegments">;
// Op attached regions have no arguments
def NoRegionArguments : NativeOpTrait<"NoRegionArguments">;
//===----------------------------------------------------------------------===//
// OpInterface definitions
//===----------------------------------------------------------------------===//

View File

@ -400,6 +400,7 @@ LogicalResult verifyNSuccessors(Operation *op, unsigned numSuccessors);
LogicalResult verifyAtLeastNSuccessors(Operation *op, unsigned numSuccessors);
LogicalResult verifyOperandSizeAttr(Operation *op, StringRef sizeAttrName);
LogicalResult verifyResultSizeAttr(Operation *op, StringRef sizeAttrName);
LogicalResult verifyNoRegionArguments(Operation *op);
} // namespace impl
/// Helper class for implementing traits. Clients are not expected to interact
@ -1202,6 +1203,15 @@ public:
}
};
/// This trait provides a verifier for ops that are expecting their regions to
/// not have any arguments
template <typename ConcrentType>
struct NoRegionArguments : public TraitBase<ConcrentType, NoRegionArguments> {
static LogicalResult verifyTrait(Operation *op) {
return ::mlir::OpTrait::impl::verifyNoRegionArguments(op);
}
};
} // end namespace OpTrait
//===----------------------------------------------------------------------===//

View File

@ -1810,13 +1810,6 @@ static LogicalResult verify(AffineIfOp op) {
condition.getNumDims())))
return failure();
// Verify that the entry of each child region does not have arguments.
for (auto &region : op.getOperation()->getRegions()) {
for (auto &b : region)
if (b.getNumArguments() != 0)
return op.emitOpError(
"requires that child entry blocks have no arguments");
}
return success();
}

View File

@ -410,16 +410,6 @@ void IfOp::build(OpBuilder &builder, OperationState &result, Value cond,
}
static LogicalResult verify(IfOp op) {
// Verify that the entry of each child region does not have arguments.
for (auto &region : op.getOperation()->getRegions()) {
if (region.empty())
continue;
for (auto &b : region)
if (b.getNumArguments() != 0)
return op.emitOpError(
"requires that child entry blocks have no arguments");
}
if (op.getNumResults() != 0 && op.elseRegion().empty())
return op.emitOpError("must have an else block if defining values");

View File

@ -76,11 +76,6 @@ LogicalResult ModuleOp::verify() {
if (!llvm::hasSingleElement(bodyRegion))
return emitOpError("expected body region to have a single block");
// Check that the body has no block arguments.
auto *body = &bodyRegion.front();
if (body->getNumArguments() != 0)
return emitOpError("expected body to have no arguments");
// Check that none of the attributes are non-dialect attributes, except for
// the symbol related attributes.
for (auto attr : getOperation()->getMutableAttrDict().getAttrs()) {

View File

@ -1017,6 +1017,22 @@ LogicalResult OpTrait::impl::verifyResultSizeAttr(Operation *op,
return verifyValueSizeAttr(op, attrName, /*isOperand=*/false);
}
LogicalResult OpTrait::impl::verifyNoRegionArguments(Operation *op) {
for (Region &region : op->getRegions()) {
if (region.empty())
continue;
if (region.front().getNumArguments() != 0) {
if (op->getNumRegions() > 1)
return op->emitOpError("region #")
<< region.getRegionNumber() << " should have no arguments";
else
return op->emitOpError("region should have no arguments");
}
}
return success();
}
//===----------------------------------------------------------------------===//
// BinaryOp implementation
//===----------------------------------------------------------------------===//

View File

@ -309,3 +309,32 @@ func @vector_store_vector_memref() {
}
return
}
// -----
func @affine_if_with_then_region_args(%N: index) {
%c = constant 200 : index
%i = constant 20: index
// expected-error@+1 {{affine.if' op region #0 should have no arguments}}
affine.if affine_set<(i)[N] : (i - 2 >= 0, 4 - i >= 0)>(%i)[%c] {
^bb0(%arg:i32):
%w = affine.apply affine_map<(d0,d1)[s0] -> (d0+d1+s0)> (%i, %i) [%N]
}
return
}
// -----
func @affine_if_with_else_region_args(%N: index) {
%c = constant 200 : index
%i = constant 20: index
// expected-error@+1 {{affine.if' op region #1 should have no arguments}}
affine.if affine_set<(i)[N] : (i - 2 >= 0, 4 - i >= 0)>(%i)[%c] {
%w = affine.apply affine_map<(d0,d1)[s0] -> (d0+d1+s0)> (%i, %i) [%N]
} else {
^bb0(%arg:i32):
%w = affine.apply affine_map<(d0,d1)[s0] -> (d0-d1+s0)> (%i, %i) [%N]
}
return
}

View File

@ -105,7 +105,7 @@ func @loop_if_not_one_block_per_region(%arg0: i1) {
// -----
func @loop_if_illegal_block_argument(%arg0: i1) {
// expected-error@+1 {{requires that child entry blocks have no arguments}}
// expected-error@+1 {{region #0 should have no arguments}}
"scf.if"(%arg0) ({
^bb0(%0 : index):
scf.yield

View File

@ -16,7 +16,7 @@ func @module_op() {
// -----
func @module_op() {
// expected-error@+1 {{expected body to have no arguments}}
// expected-error@+1 {{region should have no arguments}}
module {
^bb1(%arg: i32):
"module_terminator"() : () -> ()