@@ -442,7 +442,7 @@ def StoreOp : CIR_Op<"store", [
442442
443443def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp", "IfOp",
444444 "SwitchOp", "DoWhileOp",
445- "WhileOp", "LoopOp "]>,
445+ "WhileOp", "ForOp "]>,
446446 Terminator]> {
447447 let summary = "Return from function";
448448 let description = [{
@@ -635,7 +635,7 @@ def ConditionOp : CIR_Op<"condition", [
635635//===----------------------------------------------------------------------===//
636636
637637def YieldOp : CIR_Op<"yield", [ReturnLike, Terminator,
638- ParentOneOf<["IfOp", "ScopeOp", "SwitchOp", "WhileOp", "LoopOp ", "AwaitOp",
638+ ParentOneOf<["IfOp", "ScopeOp", "SwitchOp", "WhileOp", "ForOp ", "AwaitOp",
639639 "TernaryOp", "GlobalOp", "DoWhileOp"]>]> {
640640 let summary = "Represents the default branching behaviour of a region";
641641 let description = [{
@@ -1159,106 +1159,6 @@ def BrCondOp : CIR_Op<"brcond",
11591159 }];
11601160}
11611161
1162- //===----------------------------------------------------------------------===//
1163- // LoopOp
1164- //===----------------------------------------------------------------------===//
1165-
1166- def LoopOpKind_For : I32EnumAttrCase<"For", 1, "for">;
1167-
1168- def LoopOpKind : I32EnumAttr<
1169- "LoopOpKind",
1170- "Loop kind",
1171- [LoopOpKind_For]> {
1172- let cppNamespace = "::mlir::cir";
1173- }
1174-
1175- def LoopOp : CIR_Op<"loop",
1176- [LoopOpInterface,
1177- DeclareOpInterfaceMethods<LoopLikeOpInterface>,
1178- DeclareOpInterfaceMethods<RegionBranchOpInterface>,
1179- RecursivelySpeculatable, NoRegionArguments]> {
1180- let summary = "Loop";
1181- let description = [{
1182- `cir.loop` represents C/C++ loop forms. It defines 3 blocks:
1183- - `cond`: region can contain multiple blocks, terminated by regular
1184- `cir.yield` when control should yield back to the parent, and
1185- `cir.continue` when execution continues to the next region.
1186- The region destination depends on the loop form specified.
1187- - `step`: region with one block, containing code to compute the
1188- loop step, must be terminated with `cir.yield`.
1189- - `body`: region for the loop's body, can contain an arbitrary
1190- number of blocks.
1191-
1192- The loop form: `for`, `while` and `dowhile` must also be specified and
1193- each implies the loop regions execution order.
1194-
1195- ```mlir
1196- // while (true) {
1197- // i = i + 1;
1198- // }
1199- cir.loop while(cond : {
1200- cir.continue
1201- }, step : {
1202- cir.yield
1203- }) {
1204- %3 = cir.load %1 : cir.ptr <i32>, i32
1205- %4 = cir.const(1 : i32) : i32
1206- %5 = cir.binop(add, %3, %4) : i32
1207- cir.store %5, %1 : i32, cir.ptr <i32>
1208- cir.yield
1209- }
1210- ```
1211- }];
1212-
1213- let arguments = (ins Arg<LoopOpKind, "loop kind">:$kind);
1214- let regions = (region AnyRegion:$cond, AnyRegion:$body,
1215- SizedRegion<1>:$step);
1216-
1217- let assemblyFormat = [{
1218- $kind
1219- `(`
1220- `cond` `:` $cond `,`
1221- `step` `:` $step
1222- `)`
1223- $body
1224- attr-dict
1225- }];
1226-
1227- let skipDefaultBuilders = 1;
1228- let builders = [
1229- OpBuilder<(ins
1230- "cir::LoopOpKind":$kind,
1231- CArg<"function_ref<void(OpBuilder &, Location)>",
1232- "nullptr">:$condBuilder,
1233- CArg<"function_ref<void(OpBuilder &, Location)>",
1234- "nullptr">:$bodyBuilder,
1235- CArg<"function_ref<void(OpBuilder &, Location)>",
1236- "nullptr">:$stepBuilder
1237- )>
1238- ];
1239-
1240- let hasVerifier = 1;
1241-
1242- let extraClassDeclaration = [{
1243- Region *maybeGetStep() {
1244- if (getKind() == LoopOpKind::For)
1245- return &getStep();
1246- return nullptr;
1247- }
1248-
1249- llvm::SmallVector<Region *> getRegionsInExecutionOrder() {
1250- switch(getKind()) {
1251- case LoopOpKind::For:
1252- return llvm::SmallVector<Region *, 3>{&getCond(), &getBody(), &getStep()};
1253- // case LoopOpKind::While:
1254- // return llvm::SmallVector<Region *, 2>{&getCond(), &getBody()};
1255- // case LoopOpKind::DoWhile:
1256- // return llvm::SmallVector<Region *, 2>{&getBody(), &getCond()};
1257- }
1258- }
1259- }];
1260- }
1261-
12621162//===----------------------------------------------------------------------===//
12631163// While & DoWhileOp
12641164//===----------------------------------------------------------------------===//
@@ -1337,6 +1237,73 @@ def DoWhileOp : WhileOpBase<"do"> {
13371237 }];
13381238}
13391239
1240+ //===----------------------------------------------------------------------===//
1241+ // ForOp
1242+ //===----------------------------------------------------------------------===//
1243+
1244+ def ForOp : CIR_Op<"for", [LoopOpInterface, NoRegionArguments]> {
1245+ let summary = "C/C++ for loop counterpart";
1246+ let description = [{
1247+ Represents a C/C++ for loop. It consists of three regions:
1248+
1249+ - `cond`: single block region with the loop's condition. Should be
1250+ terminated with a `cir.condition` operation.
1251+ - `body`: contains the loop body and an arbitrary number of blocks.
1252+ - `step`: single block region with the loop's step.
1253+
1254+ Example:
1255+
1256+ ```mlir
1257+ cir.for cond {
1258+ cir.condition(%val)
1259+ } body {
1260+ cir.break
1261+ ^bb2:
1262+ cir.yield
1263+ } step {
1264+ cir.yield
1265+ }
1266+ ```
1267+ }];
1268+
1269+ let regions = (region SizedRegion<1>:$cond,
1270+ MinSizedRegion<1>:$body,
1271+ SizedRegion<1>:$step);
1272+ let assemblyFormat = [{
1273+ `:` `cond` $cond
1274+ `body` $body
1275+ `step` $step
1276+ attr-dict
1277+ }];
1278+
1279+ let builders = [
1280+ OpBuilder<(ins "function_ref<void(OpBuilder &, Location)>":$condBuilder,
1281+ "function_ref<void(OpBuilder &, Location)>":$bodyBuilder,
1282+ "function_ref<void(OpBuilder &, Location)>":$stepBuilder), [{
1283+ OpBuilder::InsertionGuard guard($_builder);
1284+
1285+ // Build condition region.
1286+ $_builder.createBlock($_state.addRegion());
1287+ condBuilder($_builder, $_state.location);
1288+
1289+ // Build body region.
1290+ $_builder.createBlock($_state.addRegion());
1291+ bodyBuilder($_builder, $_state.location);
1292+
1293+ // Build step region.
1294+ $_builder.createBlock($_state.addRegion());
1295+ stepBuilder($_builder, $_state.location);
1296+ }]>
1297+ ];
1298+
1299+ let extraClassDeclaration = [{
1300+ Region *maybeGetStep() { return &getStep(); }
1301+ llvm::SmallVector<Region *> getRegionsInExecutionOrder() {
1302+ return llvm::SmallVector<Region *, 3>{&getCond(), &getBody(), &getStep()};
1303+ }
1304+ }];
1305+ }
1306+
13401307//===----------------------------------------------------------------------===//
13411308// GlobalOp
13421309//===----------------------------------------------------------------------===//
@@ -2684,7 +2651,7 @@ def AllocException : CIR_Op<"alloc_exception", [
26842651
26852652def ThrowOp : CIR_Op<"throw", [
26862653 ParentOneOf<["FuncOp", "ScopeOp", "IfOp", "SwitchOp",
2687- "DoWhileOp", "WhileOp", "LoopOp "]>,
2654+ "DoWhileOp", "WhileOp", "ForOp "]>,
26882655 Terminator]> {
26892656 let summary = "(Re)Throws an exception";
26902657 let description = [{
0 commit comments