@@ -19,6 +19,7 @@ include "clang/CIR/Dialect/IR/CIRTypes.td"
1919include "clang/CIR/Dialect/IR/CIRAttrs.td"
2020
2121include "clang/CIR/Interfaces/CIROpInterfaces.td"
22+ include "clang/CIR/Interfaces/CIRLoopOpInterface.td"
2223
2324include "mlir/IR/BuiltinAttributeInterfaces.td"
2425include "mlir/IR/EnumAttr.td"
@@ -423,7 +424,7 @@ def StoreOp : CIR_Op<"store", [
423424// ReturnOp
424425//===----------------------------------------------------------------------===//
425426
426- def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp"]>,
427+ def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp", "ForOp" ]>,
427428 Terminator]> {
428429 let summary = "Return from function";
429430 let description = [{
@@ -460,12 +461,57 @@ def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp"]>,
460461 let hasVerifier = 1;
461462}
462463
464+ //===----------------------------------------------------------------------===//
465+ // ConditionOp
466+ //===----------------------------------------------------------------------===//
467+
468+ def ConditionOp : CIR_Op<"condition", [
469+ Terminator,
470+ DeclareOpInterfaceMethods<RegionBranchTerminatorOpInterface,
471+ ["getSuccessorRegions"]>
472+ ]> {
473+ let summary = "Loop continuation condition.";
474+ let description = [{
475+ The `cir.condition` terminates conditional regions. It takes a single
476+ `cir.bool` operand and, depending on its value, may branch to different
477+ regions:
478+
479+ - When in the `cond` region of a `cir.loop`, it continues the loop
480+ if true, or exits it if false.
481+ - When in the `ready` region of a `cir.await`, it branches to the `resume`
482+ region when true, and to the `suspend` region when false.
483+
484+ Example:
485+
486+ ```mlir
487+ cir.loop for(cond : {
488+ cir.condition(%arg0) // Branches to `step` region or exits.
489+ }, step : {
490+ [...]
491+ }) {
492+ [...]
493+ }
494+
495+ cir.await(user, ready : {
496+ cir.condition(%arg0) // Branches to `resume` or `suspend` region.
497+ }, suspend : {
498+ [...]
499+ }, resume : {
500+ [...]
501+ },)
502+ ```
503+ }];
504+ let arguments = (ins CIR_BoolType:$condition);
505+ let assemblyFormat = " `(` $condition `)` attr-dict ";
506+ let hasVerifier = 1;
507+ }
508+
463509//===----------------------------------------------------------------------===//
464510// YieldOp
465511//===----------------------------------------------------------------------===//
466512
467513def YieldOp : CIR_Op<"yield", [ReturnLike, Terminator,
468- ParentOneOf<["ScopeOp"]>]> {
514+ ParentOneOf<["ScopeOp", "ForOp" ]>]> {
469515 let summary = "Represents the default branching behaviour of a region";
470516 let description = [{
471517 The `cir.yield` operation terminates regions on different CIR operations,
@@ -666,6 +712,120 @@ def UnaryOp : CIR_Op<"unary", [Pure, SameOperandsAndResultType]> {
666712 let hasFolder = 1;
667713}
668714
715+ //===----------------------------------------------------------------------===//
716+ // BrCondOp
717+ //===----------------------------------------------------------------------===//
718+
719+ def BrCondOp : CIR_Op<"brcond",
720+ [DeclareOpInterfaceMethods<BranchOpInterface, ["getSuccessorForOperands"]>,
721+ Pure, Terminator, AttrSizedOperandSegments]> {
722+ let summary = "Conditional branch";
723+ let description = [{
724+ The `cir.brcond %cond, ^bb0, ^bb1` branches to 'bb0' block in case
725+ %cond (which must be a !cir.bool type) evaluates to true, otherwise
726+ it branches to 'bb1'.
727+
728+ Example:
729+
730+ ```mlir
731+ ...
732+ cir.brcond %a, ^bb3, ^bb4
733+ ^bb3:
734+ cir.return
735+ ^bb4:
736+ cir.yield
737+ ```
738+ }];
739+
740+ let builders = [
741+ OpBuilder<(ins "mlir::Value":$cond, "mlir::Block *":$destTrue, "mlir::Block *":$destFalse,
742+ CArg<"mlir::ValueRange", "{}">:$destOperandsTrue,
743+ CArg<"mlir::ValueRange", "{}">:$destOperandsFalse), [{
744+ build($_builder, $_state, cond, destOperandsTrue,
745+ destOperandsFalse, destTrue, destFalse);
746+ }]>
747+ ];
748+
749+ let arguments = (ins CIR_BoolType:$cond,
750+ Variadic<CIR_AnyType>:$destOperandsTrue,
751+ Variadic<CIR_AnyType>:$destOperandsFalse);
752+ let successors = (successor AnySuccessor:$destTrue, AnySuccessor:$destFalse);
753+ let assemblyFormat = [{
754+ $cond
755+ $destTrue (`(` $destOperandsTrue^ `:` type($destOperandsTrue) `)`)?
756+ `,`
757+ $destFalse (`(` $destOperandsFalse^ `:` type($destOperandsFalse) `)`)?
758+ attr-dict
759+ }];
760+ }
761+
762+ //===----------------------------------------------------------------------===//
763+ // ForOp
764+ //===----------------------------------------------------------------------===//
765+
766+ def ForOp : CIR_Op<"for", [LoopOpInterface, NoRegionArguments]> {
767+ let summary = "C/C++ for loop counterpart";
768+ let description = [{
769+ Represents a C/C++ for loop. It consists of three regions:
770+
771+ - `cond`: single block region with the loop's condition. Should be
772+ terminated with a `cir.condition` operation.
773+ - `body`: contains the loop body and an arbitrary number of blocks.
774+ - `step`: single block region with the loop's step.
775+
776+ Example:
777+
778+ ```mlir
779+ cir.for cond {
780+ cir.condition(%val)
781+ } body {
782+ cir.break
783+ ^bb2:
784+ cir.yield
785+ } step {
786+ cir.yield
787+ }
788+ ```
789+ }];
790+
791+ let regions = (region SizedRegion<1>:$cond,
792+ MinSizedRegion<1>:$body,
793+ SizedRegion<1>:$step);
794+ let assemblyFormat = [{
795+ `:` `cond` $cond
796+ `body` $body
797+ `step` $step
798+ attr-dict
799+ }];
800+
801+ let builders = [
802+ OpBuilder<(ins "llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>":$condBuilder,
803+ "llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>":$bodyBuilder,
804+ "llvm::function_ref<void(mlir::OpBuilder &, mlir::Location)>":$stepBuilder), [{
805+ mlir::OpBuilder::InsertionGuard guard($_builder);
806+
807+ // Build condition region.
808+ $_builder.createBlock($_state.addRegion());
809+ condBuilder($_builder, $_state.location);
810+
811+ // Build body region.
812+ $_builder.createBlock($_state.addRegion());
813+ bodyBuilder($_builder, $_state.location);
814+
815+ // Build step region.
816+ $_builder.createBlock($_state.addRegion());
817+ stepBuilder($_builder, $_state.location);
818+ }]>
819+ ];
820+
821+ let extraClassDeclaration = [{
822+ mlir::Region *maybeGetStep() { return &getStep(); }
823+ llvm::SmallVector<mlir::Region *> getRegionsInExecutionOrder() {
824+ return llvm::SmallVector<mlir::Region *, 3>{&getCond(), &getBody(), &getStep()};
825+ }
826+ }];
827+ }
828+
669829//===----------------------------------------------------------------------===//
670830// GlobalOp
671831//===----------------------------------------------------------------------===//
0 commit comments