@@ -19,6 +19,7 @@ include "clang/CIR/Dialect/IR/CIRTypes.td"
19
19
include "clang/CIR/Dialect/IR/CIRAttrs.td"
20
20
21
21
include "clang/CIR/Interfaces/CIROpInterfaces.td"
22
+ include "clang/CIR/Interfaces/CIRLoopOpInterface.td"
22
23
23
24
include "mlir/IR/BuiltinAttributeInterfaces.td"
24
25
include "mlir/IR/EnumAttr.td"
@@ -423,7 +424,7 @@ def StoreOp : CIR_Op<"store", [
423
424
// ReturnOp
424
425
//===----------------------------------------------------------------------===//
425
426
426
- def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp"]>,
427
+ def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp", "ForOp" ]>,
427
428
Terminator]> {
428
429
let summary = "Return from function";
429
430
let description = [{
@@ -460,12 +461,57 @@ def ReturnOp : CIR_Op<"return", [ParentOneOf<["FuncOp", "ScopeOp"]>,
460
461
let hasVerifier = 1;
461
462
}
462
463
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
+
463
509
//===----------------------------------------------------------------------===//
464
510
// YieldOp
465
511
//===----------------------------------------------------------------------===//
466
512
467
513
def YieldOp : CIR_Op<"yield", [ReturnLike, Terminator,
468
- ParentOneOf<["ScopeOp"]>]> {
514
+ ParentOneOf<["ScopeOp", "ForOp" ]>]> {
469
515
let summary = "Represents the default branching behaviour of a region";
470
516
let description = [{
471
517
The `cir.yield` operation terminates regions on different CIR operations,
@@ -666,6 +712,120 @@ def UnaryOp : CIR_Op<"unary", [Pure, SameOperandsAndResultType]> {
666
712
let hasFolder = 1;
667
713
}
668
714
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
+
669
829
//===----------------------------------------------------------------------===//
670
830
// GlobalOp
671
831
//===----------------------------------------------------------------------===//
0 commit comments