Change syntax of regions in the generic form of operations
The generic form of operations currently supports optional regions to be located after the operation type. As we are going to add a type to each region in a leading position in the region syntax, similarly to functions, it becomes ambiguous to have regions immediately after the operation type. Put regions between operands the optional list of successors in the generic operation syntax and wrap them in parentheses. The effect on the exisitng IR syntax is minimal since only three operations (`affine.for`, `affine.if` and `gpu.kernel`) currently use regions. -- PiperOrigin-RevId: 246787087
This commit is contained in:
parent
e2e89f5c83
commit
d3380a504f
|
@ -69,12 +69,14 @@ class EdscTest(unittest.TestCase):
|
||||||
x = i + j
|
x = i + j
|
||||||
code = str(fun)
|
code = str(fun)
|
||||||
# TODO(zinenko,ntv): use FileCheck for these tests
|
# TODO(zinenko,ntv): use FileCheck for these tests
|
||||||
|
self.assertIn(' "affine.for"() ( {\n', code)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
' "affine.for"() {lower_bound: () -> (0), step: 1 : index, upper_bound: () -> (42)} : () -> () {\n',
|
"{lower_bound: () -> (0), step: 1 : index, upper_bound: () -> (42)}",
|
||||||
code)
|
code)
|
||||||
self.assertIn(" ^bb1(%i0: index):", code)
|
self.assertIn(" ^bb1(%i0: index):", code)
|
||||||
|
self.assertIn(' "affine.for"(%c42, %2) ( {\n', code)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
' "affine.for"(%c42, %2) {lower_bound: (d0) -> (d0), step: 2 : index, upper_bound: (d0) -> (d0)} : (index, index) -> () {\n',
|
"{lower_bound: (d0) -> (d0), step: 2 : index, upper_bound: (d0) -> (d0)} : (index, index) -> ()",
|
||||||
code)
|
code)
|
||||||
self.assertIn(" ^bb2(%i1: index):", code)
|
self.assertIn(" ^bb2(%i1: index):", code)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
|
@ -89,21 +91,13 @@ class EdscTest(unittest.TestCase):
|
||||||
i + j + k + l
|
i + j + k + l
|
||||||
|
|
||||||
code = str(fun)
|
code = str(fun)
|
||||||
self.assertIn(
|
self.assertIn(' "affine.for"() ( {\n', code)
|
||||||
' "affine.for"() {lower_bound: () -> (0), step: 1 : index, upper_bound: () -> (5)} : () -> () {\n',
|
|
||||||
code)
|
|
||||||
self.assertIn(" ^bb1(%i0: index):", code)
|
self.assertIn(" ^bb1(%i0: index):", code)
|
||||||
self.assertIn(
|
self.assertIn(' "affine.for"() ( {\n', code)
|
||||||
' "affine.for"() {lower_bound: () -> (1), step: 3 : index, upper_bound: () -> (15)} : () -> () {\n',
|
|
||||||
code)
|
|
||||||
self.assertIn(" ^bb2(%i1: index):", code)
|
self.assertIn(" ^bb2(%i1: index):", code)
|
||||||
self.assertIn(
|
self.assertIn(' "affine.for"() ( {\n', code)
|
||||||
' "affine.for"() {lower_bound: () -> (2), step: 5 : index, upper_bound: () -> (25)} : () -> () {\n',
|
|
||||||
code)
|
|
||||||
self.assertIn(" ^bb3(%i2: index):", code)
|
self.assertIn(" ^bb3(%i2: index):", code)
|
||||||
self.assertIn(
|
self.assertIn(' "affine.for"() ( {\n', code)
|
||||||
' "affine.for"() {lower_bound: () -> (3), step: 7 : index, upper_bound: () -> (35)} : () -> () {\n',
|
|
||||||
code)
|
|
||||||
self.assertIn(" ^bb4(%i3: index):", code)
|
self.assertIn(" ^bb4(%i3: index):", code)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
' %2 = "affine.apply"(%i0, %i1, %i2, %i3) {map: (d0, d1, d2, d3) -> (d0 + d1 + d2 + d3)} : (index, index, index, index) -> index',
|
' %2 = "affine.apply"(%i0, %i1, %i2, %i3) {map: (d0, d1, d2, d3) -> (d0 + d1 + d2 + d3)} : (index, index, index, index) -> index',
|
||||||
|
@ -367,11 +361,13 @@ class EdscTest(unittest.TestCase):
|
||||||
E.ret([fun.arg(0)])
|
E.ret([fun.arg(0)])
|
||||||
|
|
||||||
code = str(fun)
|
code = str(fun)
|
||||||
|
self.assertIn('"affine.for"()', code)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
'"affine.for"() {lower_bound: () -> (0), step: 1 : index, upper_bound: () -> (10)}',
|
"{lower_bound: () -> (0), step: 1 : index, upper_bound: () -> (10)}",
|
||||||
code)
|
code)
|
||||||
|
self.assertIn('"affine.for"()', code)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
'"affine.for"() {lower_bound: () -> (0), step: 1 : index, upper_bound: () -> (42)}',
|
"{lower_bound: () -> (0), step: 1 : index, upper_bound: () -> (42)}",
|
||||||
code)
|
code)
|
||||||
self.assertIn("%0 = load %arg0[%i0, %i1] : memref<10x42xf32>", code)
|
self.assertIn("%0 = load %arg0[%i0, %i1] : memref<10x42xf32>", code)
|
||||||
self.assertIn("%1 = addf %0, %cst : f32", code)
|
self.assertIn("%1 = addf %0, %cst : f32", code)
|
||||||
|
@ -392,8 +388,9 @@ class EdscTest(unittest.TestCase):
|
||||||
E.ret([])
|
E.ret([])
|
||||||
|
|
||||||
code = str(fun)
|
code = str(fun)
|
||||||
|
self.assertIn('"affine.for"()', code)
|
||||||
self.assertIn(
|
self.assertIn(
|
||||||
'"affine.for"() {lower_bound: () -> (0), step: 1 : index, upper_bound: () -> (32)} : () -> ()',
|
"{lower_bound: () -> (0), step: 1 : index, upper_bound: () -> (32)} : () -> ()",
|
||||||
code)
|
code)
|
||||||
self.assertIn("%0 = load %arg0[%i0, %i2] : memref<32x32xf32>", code)
|
self.assertIn("%0 = load %arg0[%i0, %i2] : memref<32x32xf32>", code)
|
||||||
self.assertIn("%1 = load %arg1[%i2, %i1] : memref<32x32xf32>", code)
|
self.assertIn("%1 = load %arg1[%i2, %i1] : memref<32x32xf32>", code)
|
||||||
|
|
|
@ -1413,9 +1413,11 @@ Syntax:
|
||||||
|
|
||||||
``` {.ebnf}
|
``` {.ebnf}
|
||||||
operation ::= op-result? string-literal `(` ssa-use-list? `)`
|
operation ::= op-result? string-literal `(` ssa-use-list? `)`
|
||||||
(`[` successor-list `]`)? attribute-dict? `:` function-type
|
(`[` successor-list `]`)? (`(` region-list `)`)?
|
||||||
|
attribute-dict? `:` function-type
|
||||||
op-result ::= ssa-id ((`:` integer-literal) | (`,` ssa-id)*) `=`
|
op-result ::= ssa-id ((`:` integer-literal) | (`,` ssa-id)*) `=`
|
||||||
successor-list ::= successor (`,` successor)*
|
successor-list ::= successor (`,` successor)*
|
||||||
|
region-list ::= region (`,` region)*
|
||||||
```
|
```
|
||||||
|
|
||||||
MLIR represents computations within functions with a uniform concept called
|
MLIR represents computations within functions with a uniform concept called
|
||||||
|
@ -1428,7 +1430,8 @@ operations), and have application-specific semantics. For example, MLIR supports
|
||||||
The internal representation of an operation is simple: an operation is
|
The internal representation of an operation is simple: an operation is
|
||||||
identified by a unique string (e.g. `dim`, `tf.Conv2d`, `x86.repmovsb`,
|
identified by a unique string (e.g. `dim`, `tf.Conv2d`, `x86.repmovsb`,
|
||||||
`ppc.eieio`, etc), can return zero or more results, take zero or more SSA
|
`ppc.eieio`, etc), can return zero or more results, take zero or more SSA
|
||||||
operands, and may have zero or more attributes. When parsed or printed in the
|
operands, may have zero or more attributes, may have zero or more successors,
|
||||||
|
and zero or more enclosed [regions](#regions). When parsed or printed in the
|
||||||
_generic assembly form_, these are all printed literally, and a function type is
|
_generic assembly form_, these are all printed literally, and a function type is
|
||||||
used to indicate the types of the results and operands.
|
used to indicate the types of the results and operands.
|
||||||
|
|
||||||
|
|
|
@ -1582,6 +1582,16 @@ void FunctionPrinter::printGenericOp(Operation *op) {
|
||||||
os << ']';
|
os << ']';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Print regions.
|
||||||
|
if (op->getNumRegions() != 0) {
|
||||||
|
os << " (";
|
||||||
|
interleaveComma(op->getRegions(), [&](Region ®ion) {
|
||||||
|
printRegion(region, /*printEntryBlockArgs=*/true,
|
||||||
|
/*printBlockTerminators=*/true);
|
||||||
|
});
|
||||||
|
os << ')';
|
||||||
|
}
|
||||||
|
|
||||||
auto attrs = op->getAttrs();
|
auto attrs = op->getAttrs();
|
||||||
printOptionalAttrDict(attrs);
|
printOptionalAttrDict(attrs);
|
||||||
|
|
||||||
|
@ -1600,11 +1610,6 @@ void FunctionPrinter::printGenericOp(Operation *op) {
|
||||||
[&](Value *result) { printType(result->getType()); });
|
[&](Value *result) { printType(result->getType()); });
|
||||||
os << ')';
|
os << ')';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print any trailing regions.
|
|
||||||
for (auto ®ion : op->getRegions())
|
|
||||||
printRegion(region, /*printEntryBlockArgs=*/true,
|
|
||||||
/*printBlockTerminators=*/true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionPrinter::printSuccessorAndUseList(Operation *term,
|
void FunctionPrinter::printSuccessorAndUseList(Operation *term,
|
||||||
|
|
|
@ -3083,6 +3083,20 @@ Operation *FunctionParser::parseGenericOperation() {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse the region list.
|
||||||
|
CleanupOpStateRegions guard{result};
|
||||||
|
if (consumeIf(Token::l_paren)) {
|
||||||
|
do {
|
||||||
|
// Create temporary regions with function as parent.
|
||||||
|
result.regions.emplace_back(new Region(function));
|
||||||
|
if (parseOperationRegion(*result.regions.back(),
|
||||||
|
/*entryArguments*/ {}))
|
||||||
|
return nullptr;
|
||||||
|
} while (consumeIf(Token::comma));
|
||||||
|
if (parseToken(Token::r_paren, "expected ')' to end region list"))
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (getToken().is(Token::l_brace)) {
|
if (getToken().is(Token::l_brace)) {
|
||||||
if (parseAttributeDict(result.attributes))
|
if (parseAttributeDict(result.attributes))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -3125,16 +3139,6 @@ Operation *FunctionParser::parseGenericOperation() {
|
||||||
result.addSuccessor(successor, operands);
|
result.addSuccessor(successor, operands);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse the optional regions for this operation.
|
|
||||||
CleanupOpStateRegions guard{result};
|
|
||||||
while (getToken().is(Token::l_brace)) {
|
|
||||||
// Create temporary regions with function as parent.
|
|
||||||
result.regions.emplace_back(new Region(function));
|
|
||||||
if (parseOperationRegion(*result.regions.back(),
|
|
||||||
/*entryArguments=*/llvm::None))
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.createOperation(result);
|
return builder.createOperation(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ func @empty() {
|
||||||
// GENERIC: "affine.for"()
|
// GENERIC: "affine.for"()
|
||||||
// GENERIC-NEXT: ^bb1(%i0: index):
|
// GENERIC-NEXT: ^bb1(%i0: index):
|
||||||
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
||||||
// GENERIC-NEXT: }
|
// GENERIC-NEXT: })
|
||||||
affine.for %i = 0 to 10 {
|
affine.for %i = 0 to 10 {
|
||||||
} {some_attr: true}
|
} {some_attr: true}
|
||||||
|
|
||||||
|
@ -20,8 +20,8 @@ func @empty() {
|
||||||
//
|
//
|
||||||
// GENERIC: "affine.if"()
|
// GENERIC: "affine.if"()
|
||||||
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
||||||
// GENERIC-NEXT: } {
|
// GENERIC-NEXT: }, {
|
||||||
// GENERIC-NEXT: }
|
// GENERIC-NEXT: })
|
||||||
affine.if () : () () {
|
affine.if () : () () {
|
||||||
} {some_attr: true}
|
} {some_attr: true}
|
||||||
|
|
||||||
|
@ -30,10 +30,10 @@ func @empty() {
|
||||||
//
|
//
|
||||||
// GENERIC: "affine.if"()
|
// GENERIC: "affine.if"()
|
||||||
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
||||||
// GENERIC-NEXT: } {
|
// GENERIC-NEXT: }, {
|
||||||
// GENERIC-NEXT: "foo"() : () -> ()
|
// GENERIC-NEXT: "foo"() : () -> ()
|
||||||
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
||||||
// GENERIC-NEXT: }
|
// GENERIC-NEXT: })
|
||||||
affine.if () : () () {
|
affine.if () : () () {
|
||||||
} else {
|
} else {
|
||||||
"foo"() : () -> ()
|
"foo"() : () -> ()
|
||||||
|
@ -49,10 +49,10 @@ func @affine_terminator() {
|
||||||
// CHECK: affine.for %i
|
// CHECK: affine.for %i
|
||||||
// CHECK-NEXT: }
|
// CHECK-NEXT: }
|
||||||
//
|
//
|
||||||
// GENERIC: "affine.for"() {lower_bound: #map0, step: 1 : index, upper_bound: #map1} : () -> () {
|
// GENERIC: "affine.for"() ( {
|
||||||
// GENERIC-NEXT: ^bb1(%i0: index): // no predecessors
|
// GENERIC-NEXT: ^bb1(%i0: index): // no predecessors
|
||||||
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
// GENERIC-NEXT: "affine.terminator"() : () -> ()
|
||||||
// GENERIC-NEXT: }
|
// GENERIC-NEXT: }) {lower_bound: #map0, step: 1 : index, upper_bound: #map1} : () -> ()
|
||||||
affine.for %i = 0 to 10 {
|
affine.for %i = 0 to 10 {
|
||||||
"affine.terminator"() : () -> ()
|
"affine.terminator"() : () -> ()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,9 @@
|
||||||
|
|
||||||
func @not_enough_sizes(%sz : index) {
|
func @not_enough_sizes(%sz : index) {
|
||||||
// expected-error@+1 {{expected 6 or more operands}}
|
// expected-error@+1 {{expected 6 or more operands}}
|
||||||
"gpu.launch"(%sz, %sz, %sz, %sz, %sz)
|
"gpu.launch"(%sz, %sz, %sz, %sz, %sz) ({
|
||||||
: (index, index, index, index, index) -> () {
|
|
||||||
return
|
return
|
||||||
}
|
}) : (index, index, index, index, index) -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,12 +12,11 @@ func @not_enough_sizes(%sz : index) {
|
||||||
|
|
||||||
func @no_region_attrs(%sz : index) {
|
func @no_region_attrs(%sz : index) {
|
||||||
// expected-error@+1 {{unexpected number of region arguments}}
|
// expected-error@+1 {{unexpected number of region arguments}}
|
||||||
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz)
|
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz) ({
|
||||||
: (index, index, index, index, index, index) -> () {
|
|
||||||
^bb1(%bx: index, %by: index, %bz: index,
|
^bb1(%bx: index, %by: index, %bz: index,
|
||||||
%tx: index, %ty: index, %tz: index):
|
%tx: index, %ty: index, %tz: index):
|
||||||
return
|
return
|
||||||
}
|
}) : (index, index, index, index, index, index) -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,8 +24,7 @@ func @no_region_attrs(%sz : index) {
|
||||||
|
|
||||||
func @isolation_arg(%sz : index) {
|
func @isolation_arg(%sz : index) {
|
||||||
// expected-note@+1 {{required by region isolation constraints}}
|
// expected-note@+1 {{required by region isolation constraints}}
|
||||||
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz)
|
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz) ({
|
||||||
: (index, index, index, index, index, index) -> () {
|
|
||||||
^bb1(%bx: index, %by: index, %bz: index,
|
^bb1(%bx: index, %by: index, %bz: index,
|
||||||
%tx: index, %ty: index, %tz: index,
|
%tx: index, %ty: index, %tz: index,
|
||||||
%szbx: index, %szby: index, %szbz: index,
|
%szbx: index, %szby: index, %szbz: index,
|
||||||
|
@ -35,7 +32,7 @@ func @isolation_arg(%sz : index) {
|
||||||
// expected-error@+1 {{using value defined outside the region}}
|
// expected-error@+1 {{using value defined outside the region}}
|
||||||
"use"(%sz) : (index) -> ()
|
"use"(%sz) : (index) -> ()
|
||||||
return
|
return
|
||||||
}
|
}) : (index, index, index, index, index, index) -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,8 +41,7 @@ func @isolation_arg(%sz : index) {
|
||||||
func @isolation_op(%sz : index) {
|
func @isolation_op(%sz : index) {
|
||||||
%val = "produce"() : () -> (index)
|
%val = "produce"() : () -> (index)
|
||||||
// expected-note@+1 {{required by region isolation constraints}}
|
// expected-note@+1 {{required by region isolation constraints}}
|
||||||
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz)
|
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz) ({
|
||||||
: (index, index, index, index, index, index) -> () {
|
|
||||||
^bb1(%bx: index, %by: index, %bz: index,
|
^bb1(%bx: index, %by: index, %bz: index,
|
||||||
%tx: index, %ty: index, %tz: index,
|
%tx: index, %ty: index, %tz: index,
|
||||||
%szbx: index, %szby: index, %szbz: index,
|
%szbx: index, %szby: index, %szbz: index,
|
||||||
|
@ -53,7 +49,7 @@ func @isolation_op(%sz : index) {
|
||||||
// expected-error@+1 {{using value defined outside the region}}
|
// expected-error@+1 {{using value defined outside the region}}
|
||||||
"use"(%val) : (index) -> ()
|
"use"(%val) : (index) -> ()
|
||||||
return
|
return
|
||||||
}
|
}) : (index, index, index, index, index, index) -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,18 +57,17 @@ func @isolation_op(%sz : index) {
|
||||||
|
|
||||||
func @nested_isolation(%sz : index) {
|
func @nested_isolation(%sz : index) {
|
||||||
// expected-note@+1 {{required by region isolation constraints}}
|
// expected-note@+1 {{required by region isolation constraints}}
|
||||||
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz)
|
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz) ({
|
||||||
: (index, index, index, index, index, index) -> () {
|
|
||||||
^bb1(%bx: index, %by: index, %bz: index,
|
^bb1(%bx: index, %by: index, %bz: index,
|
||||||
%tx: index, %ty: index, %tz: index,
|
%tx: index, %ty: index, %tz: index,
|
||||||
%szbx: index, %szby: index, %szbz: index,
|
%szbx: index, %szby: index, %szbz: index,
|
||||||
%sztx: index, %szty: index, %sztz: index):
|
%sztx: index, %szty: index, %sztz: index):
|
||||||
"region"() : () -> () {
|
"region"() ({
|
||||||
"region"() : () -> () {
|
"region"() ({
|
||||||
// expected-error@+1 {{using value defined outside the region}}
|
// expected-error@+1 {{using value defined outside the region}}
|
||||||
"use"(%sz) : (index) -> ()
|
"use"(%sz) : (index) -> ()
|
||||||
}
|
}) : () -> ()
|
||||||
}
|
}) : () -> ()
|
||||||
}
|
}) : (index, index, index, index, index, index) -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,39 +2,41 @@
|
||||||
|
|
||||||
// CHECK-LABEL:func @no_args(%arg0: index)
|
// CHECK-LABEL:func @no_args(%arg0: index)
|
||||||
func @no_args(%sz : index) {
|
func @no_args(%sz : index) {
|
||||||
// CHECK: "gpu.launch"(%arg0, %arg0, %arg0, %arg0, %arg0, %arg0) : (index, index, index, index, index, index) -> () {
|
// CHECK: "gpu.launch"(%arg0, %arg0, %arg0, %arg0, %arg0, %arg0)
|
||||||
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz)
|
// CHECK-SAME: {
|
||||||
: (index, index, index, index, index, index) -> () {
|
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz) ({
|
||||||
^bb1(%bx: index, %by: index, %bz: index,
|
^bb1(%bx: index, %by: index, %bz: index,
|
||||||
%tx: index, %ty: index, %tz: index,
|
%tx: index, %ty: index, %tz: index,
|
||||||
%szbx: index, %szby: index, %szbz: index,
|
%szbx: index, %szby: index, %szbz: index,
|
||||||
%sztx: index, %szty: index, %sztz: index):
|
%sztx: index, %szty: index, %sztz: index):
|
||||||
return
|
return
|
||||||
}
|
// CHECK: (index, index, index, index, index, index) -> ()
|
||||||
|
}) : (index, index, index, index, index, index) -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL:func @args(%arg0: index, %arg1: index, %arg2: f32, %arg3: memref<?xf32, 1>) {
|
// CHECK-LABEL:func @args(%arg0: index, %arg1: index, %arg2: f32, %arg3: memref<?xf32, 1>) {
|
||||||
func @args(%blk : index, %thrd : index, %float : f32, %data : memref<?xf32,1>) {
|
func @args(%blk : index, %thrd : index, %float : f32, %data : memref<?xf32,1>) {
|
||||||
// CHECK: "gpu.launch"(%arg0, %arg0, %arg0, %arg1, %arg1, %arg1, %arg2, %arg3) : (index, index, index, index, index, index, f32, memref<?xf32, 1>) -> () {
|
// CHECK: "gpu.launch"(%arg0, %arg0, %arg0, %arg1, %arg1, %arg1, %arg2, %arg3)
|
||||||
"gpu.launch"(%blk, %blk, %blk, %thrd, %thrd, %thrd, %float, %data)
|
// CHECK-SAME: {
|
||||||
: (index, index, index, index, index, index, f32, memref<?xf32,1>) -> () {
|
"gpu.launch"(%blk, %blk, %blk, %thrd, %thrd, %thrd, %float, %data) ({
|
||||||
^bb1(%bx: index, %by: index, %bz: index,
|
^bb1(%bx: index, %by: index, %bz: index,
|
||||||
%tx: index, %ty: index, %tz: index,
|
%tx: index, %ty: index, %tz: index,
|
||||||
%szbx: index, %szby: index, %szbz: index,
|
%szbx: index, %szby: index, %szbz: index,
|
||||||
%sztx: index, %szty: index, %sztz: index,
|
%sztx: index, %szty: index, %sztz: index,
|
||||||
%data0: f32, %data1: memref<?xf32,1>):
|
%data0: f32, %data1: memref<?xf32,1>):
|
||||||
return
|
return
|
||||||
}
|
// CHECK: (index, index, index, index, index, index, f32, memref<?xf32, 1>) -> ()
|
||||||
|
}) : (index, index, index, index, index, index, f32, memref<?xf32,1>) -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is possible to use values passed into the region as arguments.
|
// It is possible to use values passed into the region as arguments.
|
||||||
// CHECK-LABEL: func @passing_values
|
// CHECK-LABEL: func @passing_values
|
||||||
func @passing_values(%blk : index, %thrd : index, %float : f32, %data : memref<?xf32,1>) {
|
func @passing_values(%blk : index, %thrd : index, %float : f32, %data : memref<?xf32,1>) {
|
||||||
// CHECK: "gpu.launch"(%arg0, %arg0, %arg0, %arg1, %arg1, %arg1, %arg2, %arg3) : (index, index, index, index, index, index, f32, memref<?xf32, 1>) -> () {
|
// CHECK: "gpu.launch"(%arg0, %arg0, %arg0, %arg1, %arg1, %arg1, %arg2, %arg3)
|
||||||
"gpu.launch"(%blk, %blk, %blk, %thrd, %thrd, %thrd, %float, %data)
|
// CHECK-SAME: {
|
||||||
: (index, index, index, index, index, index, f32, memref<?xf32,1>) -> () {
|
"gpu.launch"(%blk, %blk, %blk, %thrd, %thrd, %thrd, %float, %data) ({
|
||||||
// CHECK: ^bb1(%i0: index, %i1: index, %i2: index, %i3: index, %i4: index, %i5: index, %i6: index, %i7: index, %i8: index, %i9: index, %i10: index, %i11: index, %i12: f32, %i13: memref<?xf32, 1>)
|
// CHECK: ^bb1(%i0: index, %i1: index, %i2: index, %i3: index, %i4: index, %i5: index, %i6: index, %i7: index, %i8: index, %i9: index, %i10: index, %i11: index, %i12: f32, %i13: memref<?xf32, 1>)
|
||||||
^bb1(%bx: index, %by: index, %bz: index,
|
^bb1(%bx: index, %by: index, %bz: index,
|
||||||
%tx: index, %ty: index, %tz: index,
|
%tx: index, %ty: index, %tz: index,
|
||||||
|
@ -44,7 +46,7 @@ func @passing_values(%blk : index, %thrd : index, %float : f32, %data : memref<?
|
||||||
// CHECK: "use"(%i12)
|
// CHECK: "use"(%i12)
|
||||||
"use"(%data0): (f32) -> ()
|
"use"(%data0): (f32) -> ()
|
||||||
return
|
return
|
||||||
}
|
}) : (index, index, index, index, index, index, f32, memref<?xf32,1>) -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,20 +54,19 @@ func @passing_values(%blk : index, %thrd : index, %float : f32, %data : memref<?
|
||||||
// cross kernel launch region boundaries.
|
// cross kernel launch region boundaries.
|
||||||
// CHECK-LABEL: func @nested_isolation
|
// CHECK-LABEL: func @nested_isolation
|
||||||
func @nested_isolation(%sz : index) {
|
func @nested_isolation(%sz : index) {
|
||||||
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz)
|
"gpu.launch"(%sz, %sz, %sz, %sz, %sz, %sz) ({
|
||||||
: (index, index, index, index, index, index) -> () {
|
|
||||||
^bb1(%bx: index, %by: index, %bz: index,
|
^bb1(%bx: index, %by: index, %bz: index,
|
||||||
%tx: index, %ty: index, %tz: index,
|
%tx: index, %ty: index, %tz: index,
|
||||||
%szbx: index, %szby: index, %szbz: index,
|
%szbx: index, %szby: index, %szbz: index,
|
||||||
%sztx: index, %szty: index, %sztz: index):
|
%sztx: index, %szty: index, %sztz: index):
|
||||||
"region"() : () -> () {
|
"region"() ({
|
||||||
// CHECK: %0 = "produce"()
|
// CHECK: %0 = "produce"()
|
||||||
%val = "produce"() : () -> (index)
|
%val = "produce"() : () -> (index)
|
||||||
"region"() : () -> () {
|
"region"() ({
|
||||||
// CHECK: "use"(%0)
|
// CHECK: "use"(%0)
|
||||||
"use"(%val) : (index) -> ()
|
"use"(%val) : (index) -> ()
|
||||||
}
|
}) : () -> ()
|
||||||
}
|
}) : () -> ()
|
||||||
}
|
}) : (index, index, index, index, index, index) -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -882,7 +882,7 @@ func @negative_in_tensor_size() -> tensor<1x-1xi32>
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
func @invalid_nested_dominance() {
|
func @invalid_nested_dominance() {
|
||||||
"foo.region"() : () -> () {
|
"foo.region"() ({
|
||||||
// expected-error @+1 {{operand #0 does not dominate this use}}
|
// expected-error @+1 {{operand #0 does not dominate this use}}
|
||||||
"foo.use" (%1) : (i32) -> ()
|
"foo.use" (%1) : (i32) -> ()
|
||||||
br ^bb2
|
br ^bb2
|
||||||
|
@ -891,7 +891,7 @@ func @invalid_nested_dominance() {
|
||||||
// expected-note @+1 {{operand defined here}}
|
// expected-note @+1 {{operand defined here}}
|
||||||
%1 = constant 0 : i32
|
%1 = constant 0 : i32
|
||||||
"foo.yield" () : () -> ()
|
"foo.yield" () : () -> ()
|
||||||
}
|
}) : () -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,13 +925,13 @@ func @invalid_tuple_missing_greater(tuple<i32)
|
||||||
// Should not crash because of deletion order here.
|
// Should not crash because of deletion order here.
|
||||||
func @invalid_region_dominance() {
|
func @invalid_region_dominance() {
|
||||||
"foo.use" (%1) : (i32) -> ()
|
"foo.use" (%1) : (i32) -> ()
|
||||||
"foo.region"() : () -> () {
|
"foo.region"() ({
|
||||||
%1 = constant 0 : i32 // This value is used outside of the region.
|
%1 = constant 0 : i32 // This value is used outside of the region.
|
||||||
"foo.yield" () : () -> ()
|
"foo.yield" () : () -> ()
|
||||||
} {
|
}, {
|
||||||
// expected-error @+1 {{expected operation name in quotes}}
|
// expected-error @+1 {{expected operation name in quotes}}
|
||||||
%2 = constant 1 i32 // Syntax error causes region deletion.
|
%2 = constant 1 i32 // Syntax error causes region deletion.
|
||||||
}
|
}) : () -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -942,13 +942,13 @@ func @invalid_region_block() {
|
||||||
"foo.branch"()[^bb2] : () -> () // Attempt to jump into the region.
|
"foo.branch"()[^bb2] : () -> () // Attempt to jump into the region.
|
||||||
|
|
||||||
^bb1:
|
^bb1:
|
||||||
"foo.region"() : () -> () {
|
"foo.region"() ({
|
||||||
^bb2:
|
^bb2:
|
||||||
"foo.yield"() : () -> ()
|
"foo.yield"() : () -> ()
|
||||||
} {
|
}, {
|
||||||
// expected-error @+1 {{expected operation name in quotes}}
|
// expected-error @+1 {{expected operation name in quotes}}
|
||||||
%2 = constant 1 i32 // Syntax error causes region deletion.
|
%2 = constant 1 i32 // Syntax error causes region deletion.
|
||||||
}
|
}) : () -> ()
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
@ -956,20 +956,27 @@ func @invalid_region_block() {
|
||||||
// Should not crash because of deletion order here.
|
// Should not crash because of deletion order here.
|
||||||
func @invalid_region_dominance() {
|
func @invalid_region_dominance() {
|
||||||
"foo.use" (%1) : (i32) -> ()
|
"foo.use" (%1) : (i32) -> ()
|
||||||
"foo.region"() : () -> () {
|
"foo.region"() ({
|
||||||
"foo.region"() : () -> () {
|
"foo.region"() ({
|
||||||
%1 = constant 0 : i32 // This value is used outside of the region.
|
%1 = constant 0 : i32 // This value is used outside of the region.
|
||||||
"foo.yield" () : () -> ()
|
"foo.yield" () : () -> ()
|
||||||
}
|
}) : () -> ()
|
||||||
} {
|
}, {
|
||||||
// expected-error @+1 {{expected operation name in quotes}}
|
// expected-error @+1 {{expected operation name in quotes}}
|
||||||
%2 = constant 1 i32 // Syntax error causes region deletion.
|
%2 = constant 1 i32 // Syntax error causes region deletion.
|
||||||
}
|
}) : () -> ()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// -----
|
// -----
|
||||||
|
|
||||||
|
func @unfinished_region_list() {
|
||||||
|
// expected-error@+1 {{expected ')' to end region list}}
|
||||||
|
"region"() ({},{},{} : () -> ()
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----
|
||||||
|
|
||||||
func @multi_result_missing_count() {
|
func @multi_result_missing_count() {
|
||||||
// expected-error@+1 {{expected integer number of results}}
|
// expected-error@+1 {{expected integer number of results}}
|
||||||
%0: = "foo" () : () -> (i32, i32)
|
%0: = "foo" () : () -> (i32, i32)
|
||||||
|
|
|
@ -800,16 +800,27 @@ func @verbose_if(%N: index) {
|
||||||
%c = constant 200 : index
|
%c = constant 200 : index
|
||||||
|
|
||||||
// CHECK: affine.if #set{{.*}}(%c200)[%arg0, %c200] {
|
// CHECK: affine.if #set{{.*}}(%c200)[%arg0, %c200] {
|
||||||
"affine.if"(%c, %N, %c) { condition: #set0 } : (index, index, index) -> () {
|
"affine.if"(%c, %N, %c) ({
|
||||||
// CHECK-NEXT: "add"
|
// CHECK-NEXT: "add"
|
||||||
%y = "add"(%c, %N) : (index, index) -> index
|
%y = "add"(%c, %N) : (index, index) -> index
|
||||||
"affine.terminator"() : () -> ()
|
"affine.terminator"() : () -> ()
|
||||||
// CHECK-NEXT: } else {
|
// CHECK-NEXT: } else {
|
||||||
} { // The else region.
|
}, { // The else region.
|
||||||
// CHECK-NEXT: "add"
|
// CHECK-NEXT: "add"
|
||||||
%z = "add"(%c, %c) : (index, index) -> index
|
%z = "add"(%c, %c) : (index, index) -> index
|
||||||
"affine.terminator"() : () -> ()
|
"affine.terminator"() : () -> ()
|
||||||
}
|
})
|
||||||
|
{ condition: #set0 } : (index, index, index) -> ()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// CHECK-LABEL: func @terminator_with_regions
|
||||||
|
func @terminator_with_regions() {
|
||||||
|
// Combine successors and regions in the same operation.
|
||||||
|
// CHECK: "region"()[^bb1] ( {
|
||||||
|
// CHECK: }) : () -> ()
|
||||||
|
"region"()[^bb2] ({}) : () -> ()
|
||||||
|
^bb2:
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -193,7 +193,7 @@ func @up_propagate() -> i32 {
|
||||||
// CHECK-LABEL: func @up_propagate_region
|
// CHECK-LABEL: func @up_propagate_region
|
||||||
func @up_propagate_region() -> i32 {
|
func @up_propagate_region() -> i32 {
|
||||||
// CHECK-NEXT: %0 = "foo.region"
|
// CHECK-NEXT: %0 = "foo.region"
|
||||||
%0 = "foo.region"() : () -> (i32) {
|
%0 = "foo.region"() ({
|
||||||
// CHECK-NEXT: %c0_i32 = constant 0 : i32
|
// CHECK-NEXT: %c0_i32 = constant 0 : i32
|
||||||
// CHECK-NEXT: %true = constant 1 : i1
|
// CHECK-NEXT: %true = constant 1 : i1
|
||||||
// CHECK-NEXT: cond_br
|
// CHECK-NEXT: cond_br
|
||||||
|
@ -217,6 +217,6 @@ func @up_propagate_region() -> i32 {
|
||||||
%c1_i32_0 = constant 1 : i32
|
%c1_i32_0 = constant 1 : i32
|
||||||
%2 = addi %arg, %c1_i32_0 : i32
|
%2 = addi %arg, %c1_i32_0 : i32
|
||||||
"foo.yield" (%2) : (i32) -> ()
|
"foo.yield" (%2) : (i32) -> ()
|
||||||
}
|
}) : () -> (i32)
|
||||||
return %0 : i32
|
return %0 : i32
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue