Skip to content

Commit 3c0971a

Browse files
committed
[mlir][emitc] Switching to custom assembly in tablegen similar to the scf dialect
1 parent f6ba7a9 commit 3c0971a

File tree

6 files changed

+100
-163
lines changed

6 files changed

+100
-163
lines changed

mlir/include/mlir/Dialect/EmitC/IR/EmitC.td

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,8 +1320,9 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
13201320
not equal any of the case values, control-flow transfer to the "default"
13211321
region.
13221322

1323-
The operation does not return any value. Moreover, case regions and
1324-
default region must be explicitly terminated using the `emitc.yield` operation.
1323+
The operation does not return any value. Moreover, case regions must be
1324+
explicitly terminated using the `emitc.yield` operation. Default region is
1325+
yielded implicitly.
13251326

13261327
Example:
13271328

@@ -1339,7 +1340,6 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
13391340
default: {
13401341
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
13411342
emitc.call_opaque "func2" (%3) : (f32) -> ()
1342-
emitc.yield
13431343
}
13441344

13451345
// Output:
@@ -1365,6 +1365,11 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
13651365
let regions = (region SizedRegion<1>:$defaultRegion,
13661366
VariadicRegion<SizedRegion<1>>:$caseRegions);
13671367

1368+
let assemblyFormat = [{
1369+
$arg `:` type($arg) attr-dict custom<SwitchCases>($cases, $caseRegions) `\n`
1370+
`` `default` $defaultRegion
1371+
}];
1372+
13681373
let extraClassDeclaration = [{
13691374
/// Get the number of cases.
13701375
unsigned getNumCases();
@@ -1376,7 +1381,6 @@ def EmitC_SwitchOp : EmitC_Op<"switch", [RecursiveMemoryEffects,
13761381
Block &getCaseBlock(unsigned idx);
13771382
}];
13781383

1379-
let hasCustomAssemblyFormat = 1;
13801384
let hasVerifier = 1;
13811385
}
13821386

mlir/lib/Dialect/EmitC/IR/EmitC.cpp

Lines changed: 2 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1108,8 +1108,7 @@ parseSwitchCases(OpAsmParser &parser, DenseI64ArrayAttr &cases,
11081108
while (succeeded(parser.parseOptionalKeyword("case"))) {
11091109
int64_t value;
11101110
Region &region = *caseRegions.emplace_back(std::make_unique<Region>());
1111-
1112-
if (parser.parseInteger(value) || parser.parseColon() ||
1111+
if (parser.parseInteger(value) ||
11131112
parser.parseRegion(region, /*arguments=*/{}))
11141113
return failure();
11151114
caseValues.push_back(value);
@@ -1123,69 +1122,11 @@ static void printSwitchCases(OpAsmPrinter &p, Operation *op,
11231122
DenseI64ArrayAttr cases, RegionRange caseRegions) {
11241123
for (auto [value, region] : llvm::zip(cases.asArrayRef(), caseRegions)) {
11251124
p.printNewline();
1126-
p << "case " << value << ": ";
1125+
p << "case " << value << ' ';
11271126
p.printRegion(*region, /*printEntryBlockArgs=*/false);
11281127
}
11291128
}
11301129

1131-
ParseResult SwitchOp::parse(OpAsmParser &parser, OperationState &result) {
1132-
OpAsmParser::UnresolvedOperand arg;
1133-
DenseI64ArrayAttr casesAttr;
1134-
SmallVector<std::unique_ptr<Region>, 2> caseRegionsRegions;
1135-
std::unique_ptr<Region> defaultRegionRegion = std::make_unique<Region>();
1136-
1137-
if (parser.parseOperand(arg))
1138-
return failure();
1139-
1140-
Type argType;
1141-
// Parse the case's type.
1142-
if (parser.parseColon() || parser.parseType(argType))
1143-
return failure();
1144-
1145-
auto loc = parser.getCurrentLocation();
1146-
if (parser.parseOptionalAttrDict(result.attributes))
1147-
return failure();
1148-
1149-
if (failed(verifyInherentAttrs(result.name, result.attributes, [&]() {
1150-
return parser.emitError(loc)
1151-
<< "'" << result.name.getStringRef() << "' op ";
1152-
})))
1153-
return failure();
1154-
1155-
auto odsResult = parseSwitchCases(parser, casesAttr, caseRegionsRegions);
1156-
if (odsResult)
1157-
return failure();
1158-
1159-
result.getOrAddProperties<SwitchOp::Properties>().cases = casesAttr;
1160-
1161-
if (parser.parseKeyword("default") || parser.parseColon())
1162-
return failure();
1163-
1164-
if (parser.parseRegion(*defaultRegionRegion))
1165-
return failure();
1166-
1167-
result.addRegion(std::move(defaultRegionRegion));
1168-
result.addRegions(caseRegionsRegions);
1169-
1170-
if (parser.resolveOperand(arg, argType, result.operands))
1171-
return failure();
1172-
1173-
return success();
1174-
}
1175-
1176-
void SwitchOp::print(OpAsmPrinter &p) {
1177-
p << ' ' << getArg();
1178-
SmallVector<StringRef, 2> elidedAttrs;
1179-
elidedAttrs.push_back("cases");
1180-
p.printOptionalAttrDict((*this)->getAttrs(), elidedAttrs);
1181-
p << ' ';
1182-
printSwitchCases(p, *this, getCasesAttr(), getCaseRegions());
1183-
p.printNewline();
1184-
p << "default ";
1185-
p.printRegion(getDefaultRegion(), /*printEntryBlockArgs=*/true,
1186-
/*printBlockTerminators=*/true);
1187-
}
1188-
11891130
static LogicalResult verifyRegion(emitc::SwitchOp op, Region &region,
11901131
const Twine &name) {
11911132
auto yield = dyn_cast<emitc::YieldOp>(region.front().back());

mlir/test/Conversion/SCFToEmitC/switch.mlir

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,16 @@
33
// CHECK-LABEL: func.func @switch_no_result(
44
// CHECK-SAME: %[[VAL_0:.*]]: index) {
55
// CHECK: emitc.switch %[[VAL_0]]
6-
// CHECK: case 2: {
6+
// CHECK: case 2 {
77
// CHECK: %[[VAL_1:.*]] = arith.constant 10 : i32
88
// CHECK: emitc.yield
99
// CHECK: }
10-
// CHECK: case 5: {
10+
// CHECK: case 5 {
1111
// CHECK: %[[VAL_2:.*]] = arith.constant 20 : i32
1212
// CHECK: emitc.yield
1313
// CHECK: }
1414
// CHECK: default {
1515
// CHECK: %[[VAL_3:.*]] = arith.constant 30 : i32
16-
// CHECK: emitc.yield
1716
// CHECK: }
1817
// CHECK: return
1918
// CHECK: }
@@ -29,29 +28,27 @@ func.func @switch_no_result(%arg0 : index) {
2928
}
3029
default {
3130
%3 = arith.constant 30 : i32
32-
scf.yield
3331
}
3432
return
3533
}
3634

3735
// CHECK-LABEL: func.func @switch_one_result(
3836
// CHECK-SAME: %[[VAL_0:.*]]: index) {
39-
// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #[[?]]<"">}> : () -> i32
37+
// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
4038
// CHECK: emitc.switch %[[VAL_0]]
41-
// CHECK: case 2: {
39+
// CHECK: case 2 {
4240
// CHECK: %[[VAL_2:.*]] = arith.constant 10 : i32
4341
// CHECK: emitc.assign %[[VAL_2]] : i32 to %[[VAL_1]] : i32
4442
// CHECK: emitc.yield
4543
// CHECK: }
46-
// CHECK: case 5: {
44+
// CHECK: case 5 {
4745
// CHECK: %[[VAL_3:.*]] = arith.constant 20 : i32
4846
// CHECK: emitc.assign %[[VAL_3]] : i32 to %[[VAL_1]] : i32
4947
// CHECK: emitc.yield
5048
// CHECK: }
5149
// CHECK: default {
5250
// CHECK: %[[VAL_4:.*]] = arith.constant 30 : i32
5351
// CHECK: emitc.assign %[[VAL_4]] : i32 to %[[VAL_1]] : i32
54-
// CHECK: emitc.yield
5552
// CHECK: }
5653
// CHECK: return
5754
// CHECK: }
@@ -74,17 +71,17 @@ func.func @switch_one_result(%arg0 : index) {
7471

7572
// CHECK-LABEL: func.func @switch_two_results(
7673
// CHECK-SAME: %[[VAL_0:.*]]: index) {
77-
// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #[[?]]<"">}> : () -> i32
78-
// CHECK: %[[VAL_2:.*]] = "emitc.variable"() <{value = #[[?]]<"">}> : () -> f32
74+
// CHECK: %[[VAL_1:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> i32
75+
// CHECK: %[[VAL_2:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> f32
7976
// CHECK: emitc.switch %[[VAL_0]]
80-
// CHECK: case 2: {
77+
// CHECK: case 2 {
8178
// CHECK: %[[VAL_3:.*]] = arith.constant 10 : i32
8279
// CHECK: %[[VAL_4:.*]] = arith.constant 1.200000e+00 : f32
8380
// CHECK: emitc.assign %[[VAL_3]] : i32 to %[[VAL_1]] : i32
8481
// CHECK: emitc.assign %[[VAL_4]] : f32 to %[[VAL_2]] : f32
8582
// CHECK: emitc.yield
8683
// CHECK: }
87-
// CHECK: case 5: {
84+
// CHECK: case 5 {
8885
// CHECK: %[[VAL_5:.*]] = arith.constant 20 : i32
8986
// CHECK: %[[VAL_6:.*]] = arith.constant 2.400000e+00 : f32
9087
// CHECK: emitc.assign %[[VAL_5]] : i32 to %[[VAL_1]] : i32
@@ -96,7 +93,6 @@ func.func @switch_one_result(%arg0 : index) {
9693
// CHECK: %[[VAL_8:.*]] = arith.constant 3.600000e+00 : f32
9794
// CHECK: emitc.assign %[[VAL_7]] : i32 to %[[VAL_1]] : i32
9895
// CHECK: emitc.assign %[[VAL_8]] : f32 to %[[VAL_2]] : f32
99-
// CHECK: emitc.yield
10096
// CHECK: }
10197
// CHECK: return
10298
// CHECK: }

mlir/test/Dialect/EmitC/invalid_ops.mlir

Lines changed: 19 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -470,18 +470,18 @@ func.func @member_of_ptr(%arg0: i32) {
470470
// -----
471471

472472
func.func @emitc_switch() {
473-
%0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
473+
%0 = "emitc.variable"(){value = 1 : i16} : () -> i16
474474

475475
// expected-error@+1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
476-
emitc.switch %0 : ui16
477-
case 2: {
476+
emitc.switch %0 : i16
477+
case 2 {
478478
%1 = emitc.call_opaque "func_b" () : () -> i32
479479
}
480-
case 5: {
480+
case 5 {
481481
%2 = emitc.call_opaque "func_a" () : () -> i32
482482
emitc.yield
483483
}
484-
default: {
484+
default {
485485
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
486486
emitc.call_opaque "func2" (%3) : (f32) -> ()
487487
emitc.yield
@@ -492,41 +492,19 @@ func.func @emitc_switch() {
492492
// -----
493493

494494
func.func @emitc_switch() {
495-
%0 = "emitc.variable"(){value = 1 : ui16} : () -> ui16
495+
%0 = "emitc.variable"(){value = 1 : i32} : () -> i32
496496

497-
// expected-error@+1 {{'emitc.switch' op expected region to end with emitc.yield, but got emitc.call_opaque}}
498-
emitc.switch %0 : ui16
499-
case 2: {
500-
%1 = emitc.call_opaque "func_b" () : () -> i32
501-
emitc.yield
502-
}
503-
case 5: {
504-
%2 = emitc.call_opaque "func_a" () : () -> i32
505-
emitc.yield
506-
}
507-
default: {
508-
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
509-
emitc.call_opaque "func2" (%3) : (f32) -> ()
510-
}
511-
return
512-
}
513-
514-
// -----
515-
516-
func.func @emitc_switch() {
517-
%0 = "emitc.variable"(){value = 1 : i16} : () -> i16
518-
519-
emitc.switch %0 : i16
520-
case 2: {
497+
emitc.switch %0 : i32
498+
case 2 {
521499
%1 = emitc.call_opaque "func_b" () : () -> i32
522500
emitc.yield
523501
}
524502
// expected-error@+1 {{custom op 'emitc.switch' expected integer value}}
525-
case : {
503+
case {
526504
%2 = emitc.call_opaque "func_a" () : () -> i32
527505
emitc.yield
528506
}
529-
default: {
507+
default {
530508
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
531509
emitc.call_opaque "func2" (%3) : (f32) -> ()
532510
emitc.yield
@@ -537,14 +515,14 @@ func.func @emitc_switch() {
537515
// -----
538516

539517
func.func @emitc_switch() {
540-
%0 = "emitc.variable"(){value = 1 : i16} : () -> i16
518+
%0 = "emitc.variable"(){value = 1 : i8} : () -> i8
541519

542-
emitc.switch %0 : i16
543-
case 2: {
520+
emitc.switch %0 : i8
521+
case 2 {
544522
%1 = emitc.call_opaque "func_b" () : () -> i32
545523
emitc.yield
546524
}
547-
case 3: {
525+
case 3 {
548526
%2 = emitc.call_opaque "func_a" () : () -> i32
549527
emitc.yield
550528
}
@@ -555,19 +533,19 @@ func.func @emitc_switch() {
555533
// -----
556534

557535
func.func @emitc_switch() {
558-
%0 = "emitc.variable"(){value = 1 : i16} : () -> i16
536+
%0 = "emitc.variable"(){value = 1 : i64} : () -> i64
559537

560538
// expected-error@+1 {{'emitc.switch' op has duplicate case value: 2}}
561-
emitc.switch %0 : i16
562-
case 2: {
539+
emitc.switch %0 : i64
540+
case 2 {
563541
%1 = emitc.call_opaque "func_b" () : () -> i32
564542
emitc.yield
565543
}
566-
case 2: {
544+
case 2 {
567545
%2 = emitc.call_opaque "func_a" () : () -> i32
568546
emitc.yield
569547
}
570-
default: {
548+
default {
571549
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
572550
emitc.call_opaque "func2" (%3) : (f32) -> ()
573551
emitc.yield

mlir/test/Dialect/EmitC/ops.mlir

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,3 +261,23 @@ func.func @member_access(%arg0: !emitc.opaque<"mystruct">, %arg1: !emitc.opaque<
261261
%2 = "emitc.member_of_ptr" (%arg2) {member = "a"} : (!emitc.ptr<!emitc.opaque<"mystruct">>) -> i32
262262
return
263263
}
264+
265+
func.func @switch() {
266+
%0 = "emitc.variable"(){value = 1 : index} : () -> !emitc.ptrdiff_t
267+
268+
emitc.switch %0 : !emitc.ptrdiff_t
269+
case 1 {
270+
%1 = emitc.call_opaque "func_b" () : () -> i32
271+
emitc.yield
272+
}
273+
case 2 {
274+
%2 = emitc.call_opaque "func_a" () : () -> i32
275+
emitc.yield
276+
}
277+
default {
278+
%3 = "emitc.variable"(){value = 42.0 : f32} : () -> f32
279+
emitc.call_opaque "func2" (%3) : (f32) -> ()
280+
}
281+
282+
return
283+
}

0 commit comments

Comments
 (0)