diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index ed66e83e0cd3..5f491a2372c2 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -872,11 +872,10 @@ def SelectOp : CIR_Op<"select", [Pure, // ConditionOp //===----------------------------------------------------------------------===// -def ConditionOp : CIR_Op<"condition", [ - Terminator, - DeclareOpInterfaceMethods -]> { +def ConditionOp : CIR_Op<"condition", [Terminator, CIR_ConditionOpInterface, + DeclareOpInterfaceMethods< + RegionBranchTerminatorOpInterface, + ["getSuccessorRegions"]>]> { let summary = "Loop continuation condition."; let description = [{ The `cir.condition` terminates conditional regions. It takes a single @@ -2195,10 +2194,8 @@ def BrCondOp : CIR_Op<"brcond", // While & DoWhileOp //===----------------------------------------------------------------------===// -class WhileOpBase : CIR_Op { +class WhileOpBase + : CIR_Op { defvar isWhile = !eq(mnemonic, "while"); let summary = "C/C++ " # !if(isWhile, "while", "do-while") # " loop"; let builders = [ @@ -2273,7 +2270,7 @@ def DoWhileOp : WhileOpBase<"do"> { // ForOp //===----------------------------------------------------------------------===// -def ForOp : CIR_Op<"for", [LoopOpInterface, NoRegionArguments]> { +def ForOp : CIR_Op<"for", [CIR_LoopOpInterface, NoRegionArguments]> { let summary = "C/C++ for loop counterpart"; let description = [{ Represents a C/C++ for loop. It consists of three regions: diff --git a/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td index 8fd4a321b396..36b71707ee65 100644 --- a/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td +++ b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td @@ -13,10 +13,10 @@ include "mlir/IR/OpBase.td" include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/Interfaces/LoopLikeInterface.td" -def LoopOpInterface : OpInterface<"LoopOpInterface", [ - DeclareOpInterfaceMethods, - DeclareOpInterfaceMethods -]> { +def CIR_LoopOpInterface + : OpInterface<"LoopOpInterface", + [DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods]> { let description = [{ Contains helper functions to query properties and perform transformations on a loop. @@ -96,4 +96,12 @@ def LoopOpInterface : OpInterface<"LoopOpInterface", [ }]; } +def CIR_ConditionOpInterface : OpInterface<"ConditionOpInterface", []> { + let description = [{ + A singleton interface for ConditionOp only. This is used to break off a + a dependency from LoopOpInterface onto ConditionOp. + }]; + let cppNamespace = "::cir"; +} + #endif // CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE diff --git a/clang/lib/CIR/Interfaces/CIRLoopOpInterface.cpp b/clang/lib/CIR/Interfaces/CIRLoopOpInterface.cpp index 085e1f6c245d..e3f508bcdf1c 100644 --- a/clang/lib/CIR/Interfaces/CIRLoopOpInterface.cpp +++ b/clang/lib/CIR/Interfaces/CIRLoopOpInterface.cpp @@ -44,11 +44,10 @@ void LoopOpInterface::getLoopOpSuccessorRegions( /// Verify invariants of the LoopOpInterface. llvm::LogicalResult detail::verifyLoopOpInterface(mlir::Operation *op) { - // FIXME: fix this so the conditionop isn't requiring MLIRCIR - // auto loopOp = mlir::cast(op); - // if (!mlir::isa(loopOp.getCond().back().getTerminator())) - // return op->emitOpError( - // "expected condition region to terminate with 'cir.condition'"); + auto loopOp = mlir::cast(op); + if (!mlir::isa(loopOp.getCond().back().getTerminator())) + return op->emitOpError( + "expected condition region to terminate with 'cir.condition'"); return llvm::success(); } diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index 30fc93ecb979..3e8f831afdae 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -1533,3 +1533,44 @@ cir.global external dsolocal @vfp = #cir.ptr : !cir.ptr> + +// ----- + +#false = #cir.bool : !cir.bool +#true = #cir.bool : !cir.bool +cir.func @b0() { + cir.scope { + cir.while { // expected-error {{expected condition region to terminate with 'cir.condition'}} + cir.yield + } do { + cir.br ^bb1 + ^bb1: + cir.return + } + } + cir.return +} + +// ----- + +cir.func @invalid_cond_region_terminator(%arg0 : !cir.bool) -> !cir.void { + cir.do { // expected-error {{op expected condition region to terminate with 'cir.condition'}} + cir.yield + } while { + cir.yield + } + cir.return +} + +// ----- + +cir.func @invalidConditionTerminator (%arg0 : !cir.bool) -> !cir.void { + cir.for : cond { // expected-error {{op expected condition region to terminate with 'cir.condition'}} + cir.yield + } body { + cir.yield + } step { + cir.yield + } + cir.return +} diff --git a/clang/test/CIR/IR/invalid_xfail.cir b/clang/test/CIR/IR/invalid_xfail.cir deleted file mode 100644 index c29dbf075b6b..000000000000 --- a/clang/test/CIR/IR/invalid_xfail.cir +++ /dev/null @@ -1,42 +0,0 @@ -// Test attempts to build bogus CIR -// RUN: cir-opt %s -verify-diagnostics -split-input-file -// XFAIL: * - -#false = #cir.bool : !cir.bool -#true = #cir.bool : !cir.bool -cir.func @b0() { - cir.scope { - cir.while { // expected-error {{expected condition region to terminate with 'cir.condition'}} - cir.yield - } do { - cir.br ^bb1 - ^bb1: - cir.return - } - } - cir.return -} - -// ----- - -cir.func @invalid_cond_region_terminator(%arg0 : !cir.bool) -> !cir.void { - cir.do { // expected-error {{op expected condition region to terminate with 'cir.condition'}} - cir.yield - } while { - cir.yield - } - cir.return -} - -// ----- - -cir.func @invalidConditionTerminator (%arg0 : !cir.bool) -> !cir.void { - cir.for : cond { // expected-error {{op expected condition region to terminate with 'cir.condition'}} - cir.yield - } body { - cir.yield - } step { - cir.yield - } - cir.return -}