From c50441d26503258ea5106155a8bf3a152f978983 Mon Sep 17 00:00:00 2001 From: Vinicius Couto Espindola Date: Thu, 18 Jan 2024 20:15:45 -0300 Subject: [PATCH 1/4] [CIR][Interfaces] Implement LoopOpInterface Adds an interface to generically handle lowering and analysis of loop operations in CIR. It can also perform verification of invariants common to all loop operations. [ghstack-poisoned] --- .../include/clang/CIR/Dialect/IR/CIRDialect.h | 1 + clang/include/clang/CIR/Dialect/IR/CIROps.td | 18 +++- .../clang/CIR/Interfaces/CMakeLists.txt | 1 + .../clang/CIR/Interfaces/LoopOpInterface.h | 36 +++++++ .../clang/CIR/Interfaces/LoopOpInterface.td | 100 ++++++++++++++++++ clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 33 ++---- .../CIR/Dialect/Transforms/LifetimeCheck.cpp | 25 +---- clang/lib/CIR/Interfaces/CMakeLists.txt | 1 + clang/lib/CIR/Interfaces/LoopOpInterface.cpp | 52 +++++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 6 +- clang/test/CIR/IR/invalid.cir | 2 +- clang/test/CIR/Transforms/merge-cleanups.cir | 30 ------ 12 files changed, 222 insertions(+), 83 deletions(-) create mode 100644 clang/include/clang/CIR/Interfaces/LoopOpInterface.h create mode 100644 clang/include/clang/CIR/Interfaces/LoopOpInterface.td create mode 100644 clang/lib/CIR/Interfaces/LoopOpInterface.cpp diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h index 004b9c92a414..93a50cc8f3d6 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h @@ -33,6 +33,7 @@ #include "clang/CIR/Interfaces/ASTAttrInterfaces.h" #include "clang/CIR/Interfaces/CIROpInterfaces.h" +#include "clang/CIR/Interfaces/LoopOpInterface.h" namespace mlir { namespace OpTrait { diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 15e1ae1d6f3e..098f6f3260a4 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -20,6 +20,7 @@ include "clang/CIR/Dialect/IR/CIRAttrs.td" include "clang/CIR/Interfaces/ASTAttrInterfaces.td" include "clang/CIR/Interfaces/CIROpInterfaces.td" +include "clang/CIR/Interfaces/LoopOpInterface.td" include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/Interfaces/FunctionInterfaces.td" @@ -1147,7 +1148,8 @@ def LoopOpKind : I32EnumAttr< } def LoopOp : CIR_Op<"loop", - [DeclareOpInterfaceMethods, + [LoopOpInterface, + DeclareOpInterfaceMethods, DeclareOpInterfaceMethods, RecursivelySpeculatable, NoRegionArguments]> { let summary = "Loop"; @@ -1211,6 +1213,20 @@ def LoopOp : CIR_Op<"loop", ]; let hasVerifier = 1; + + let extraClassDeclaration = [{ + Region *maybeGetStep() { + if (getKind() == LoopOpKind::For) + return &getStep(); + return nullptr; + } + + llvm::SmallVector getRegionsInExecutionOrder() { + if (getKind() == LoopOpKind::For) + return llvm::SmallVector{&getCond(), &getBody(), &getStep()}; + return llvm::SmallVector{&getCond(), &getBody()}; + } + }]; } //===----------------------------------------------------------------------===// diff --git a/clang/include/clang/CIR/Interfaces/CMakeLists.txt b/clang/include/clang/CIR/Interfaces/CMakeLists.txt index fe835cade35c..383eda4311a3 100644 --- a/clang/include/clang/CIR/Interfaces/CMakeLists.txt +++ b/clang/include/clang/CIR/Interfaces/CMakeLists.txt @@ -22,3 +22,4 @@ endfunction() add_clang_mlir_attr_interface(ASTAttrInterfaces) add_clang_mlir_op_interface(CIROpInterfaces) +add_clang_mlir_op_interface(LoopOpInterface) diff --git a/clang/include/clang/CIR/Interfaces/LoopOpInterface.h b/clang/include/clang/CIR/Interfaces/LoopOpInterface.h new file mode 100644 index 000000000000..96198c635aa9 --- /dev/null +++ b/clang/include/clang/CIR/Interfaces/LoopOpInterface.h @@ -0,0 +1,36 @@ +//===- LoopOpInterface.h - Interface for CIR loop-like ops -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// +// +// Defines the interface to generically handle CIR loop operations. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_INTERFACES_CIR_LOOPOPINTERFACE_H_ +#define CLANG_INTERFACES_CIR_LOOPOPINTERFACE_H_ + +#include "mlir/IR/BuiltinTypes.h" +#include "mlir/IR/OpDefinition.h" +#include "mlir/IR/Operation.h" +#include "mlir/Interfaces/ControlFlowInterfaces.h" +#include "mlir/Interfaces/LoopLikeInterface.h" + +namespace mlir { +namespace cir { +namespace detail { + +/// Verify invariants of the LoopOpInterface. +::mlir::LogicalResult verifyLoopOpInterface(::mlir::Operation *op); + +} // namespace detail +} // namespace cir +} // namespace mlir + +/// Include the tablegen'd interface declarations. +#include "clang/CIR/Interfaces/LoopOpInterface.h.inc" + +#endif // CLANG_INTERFACES_CIR_LOOPOPINTERFACE_H_ diff --git a/clang/include/clang/CIR/Interfaces/LoopOpInterface.td b/clang/include/clang/CIR/Interfaces/LoopOpInterface.td new file mode 100644 index 000000000000..ada6f8f86c5b --- /dev/null +++ b/clang/include/clang/CIR/Interfaces/LoopOpInterface.td @@ -0,0 +1,100 @@ +//===- LoopOpInterface.td - Interface for CIR loop-like ops ----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef CLANG_CIR_INTERFACES_LOOPOPINTERFACE +#define CLANG_CIR_INTERFACES_LOOPOPINTERFACE + +include "mlir/IR/OpBase.td" +include "mlir/Interfaces/ControlFlowInterfaces.td" +include "mlir/Interfaces/LoopLikeInterface.td" + +def LoopOpInterface : OpInterface<"LoopOpInterface", [ + DeclareOpInterfaceMethods, + DeclareOpInterfaceMethods +]> { + let description = [{ + Contains helper functions to query properties and perform transformations + on a loop. + }]; + let cppNamespace = "::mlir::cir"; + + let methods = [ + InterfaceMethod<[{ + Returns the loop's conditional region. + }], + /*retTy=*/"mlir::Region &", + /*methodName=*/"getCond" + >, + InterfaceMethod<[{ + Returns the loop's body region. + }], + /*retTy=*/"mlir::Region &", + /*methodName=*/"getBody" + >, + InterfaceMethod<[{ + Returns a pointer to the loop's step region or nullptr. + }], + /*retTy=*/"mlir::Region *", + /*methodName=*/"maybeGetStep", + /*args=*/(ins), + /*methodBody=*/"", + /*defaultImplementation=*/"return nullptr;" + >, + InterfaceMethod<[{ + Returns the first region to be executed in the loop. + }], + /*retTy=*/"mlir::Region &", + /*methodName=*/"getEntry", + /*args=*/(ins), + /*methodBody=*/"", + /*defaultImplementation=*/"return $_op.getCond();" + >, + InterfaceMethod<[{ + Returns a list of regions in order of execution. + }], + /*retTy=*/"llvm::SmallVector", + /*methodName=*/"getRegionsInExecutionOrder", + /*args=*/(ins), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + return llvm::SmallVector{&$_op.getRegion(0), &$_op.getRegion(1)}; + }] + >, + InterfaceMethod<[{ + Recursively walks the body of the loop in pre-order while skipping + nested loops and executing a callback on every other operation. + }], + /*retTy=*/"mlir::WalkResult", + /*methodName=*/"walkBodySkippingNestedLoops", + /*args=*/(ins "::llvm::function_ref":$callback), + /*methodBody=*/"", + /*defaultImplementation=*/[{ + return $_op.getBody().template walk([&](Operation *op) { + if (isa(op)) + return mlir::WalkResult::skip(); + callback(op); + return mlir::WalkResult::advance(); + }); + }] + > + ]; + + let extraClassDeclaration = [{ + /// Generic method to retrieve the successors of a LoopOpInterface operation. + static void getLoopOpSuccessorRegions( + ::mlir::cir::LoopOpInterface op, ::mlir::RegionBranchPoint point, + ::mlir::SmallVectorImpl<::mlir::RegionSuccessor> ®ions); + }]; + + let verify = [{ + /// Verify invariants of the LoopOpInterface. + return detail::verifyLoopOpInterface($_op); + }]; +} + +#endif // CLANG_CIR_INTERFACES_LOOPOPINTERFACE diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 4bec3353ff91..701d175cdcb2 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -14,6 +14,7 @@ #include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" +#include "clang/CIR/Interfaces/LoopOpInterface.h" #include "llvm/Support/ErrorHandling.h" #include @@ -232,7 +233,7 @@ void AllocaOp::build(::mlir::OpBuilder &odsBuilder, //===----------------------------------------------------------------------===// LogicalResult BreakOp::verify() { - if (!getOperation()->getParentOfType() && + if (!getOperation()->getParentOfType() && !getOperation()->getParentOfType()) return emitOpError("must be within a loop or switch"); return success(); @@ -251,7 +252,7 @@ void ConditionOp::getSuccessorRegions( // down its list of possible successors. // Parent is a loop: condition may branch to the body or to the parent op. - if (auto loopOp = dyn_cast(getOperation()->getParentOp())) { + if (auto loopOp = dyn_cast(getOperation()->getParentOp())) { regions.emplace_back(&loopOp.getBody(), loopOp.getBody().getArguments()); regions.emplace_back(loopOp->getResults()); } @@ -269,7 +270,7 @@ ConditionOp::getMutableSuccessorOperands(RegionBranchPoint point) { } LogicalResult ConditionOp::verify() { - if (!isa(getOperation()->getParentOp())) + if (!isa(getOperation()->getParentOp())) return emitOpError("condition must be within a conditional region"); return success(); } @@ -365,7 +366,7 @@ OpFoldResult ConstantOp::fold(FoldAdaptor /*adaptor*/) { return getValue(); } //===----------------------------------------------------------------------===// LogicalResult ContinueOp::verify() { - if (!this->getOperation()->getParentOfType()) + if (!this->getOperation()->getParentOfType()) return emitOpError("must be within a loop"); return success(); } @@ -1264,36 +1265,14 @@ void LoopOp::build(OpBuilder &builder, OperationState &result, stepBuilder(builder, result.location); } -/// Given the region at `index`, or the parent operation if `index` is None, -/// return the successor regions. These are the regions that may be selected -/// during the flow of control. `operands` is a set of optional attributes -/// that correspond to a constant value for each operand, or null if that -/// operand is not a constant. void LoopOp::getSuccessorRegions(mlir::RegionBranchPoint point, SmallVectorImpl ®ions) { - // If any index all the underlying regions branch back to the parent - // operation. - if (!point.isParent()) { - regions.push_back(RegionSuccessor()); - return; - } - - // FIXME: we want to look at cond region for getting more accurate results - // if the other regions will get a chance to execute. - regions.push_back(RegionSuccessor(&this->getCond())); - regions.push_back(RegionSuccessor(&this->getBody())); - regions.push_back(RegionSuccessor(&this->getStep())); + LoopOpInterface::getLoopOpSuccessorRegions(*this, point, regions); } llvm::SmallVector LoopOp::getLoopRegions() { return {&getBody()}; } LogicalResult LoopOp::verify() { - if (getCond().empty()) - return emitOpError() << "cond region must not be empty"; - - if (!llvm::isa(getCond().back().getTerminator())) - return emitOpError() << "cond region terminate with 'cir.condition'"; - return success(); } diff --git a/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp b/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp index 551024854077..03d41a9fd59c 100644 --- a/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp @@ -674,27 +674,10 @@ void LifetimeCheckPass::checkLoop(LoopOp loopOp) { SmallVector regionsToCheck; auto setupLoopRegionsToCheck = [&](bool isSubsequentTaken = false) { - regionsToCheck.clear(); - switch (loopOp.getKind()) { - case LoopOpKind::For: { - regionsToCheck.push_back(&loopOp.getCond()); - regionsToCheck.push_back(&loopOp.getBody()); - if (!isSubsequentTaken) - regionsToCheck.push_back(&loopOp.getStep()); - break; - } - case LoopOpKind::While: { - regionsToCheck.push_back(&loopOp.getCond()); - regionsToCheck.push_back(&loopOp.getBody()); - break; - } - case LoopOpKind::DoWhile: { - // Note this is the reverse order from While above. - regionsToCheck.push_back(&loopOp.getBody()); - regionsToCheck.push_back(&loopOp.getCond()); - break; - } - } + regionsToCheck = loopOp.getRegionsInExecutionOrder(); + // Drop step if it exists and we are not checking the subsequent taken. + if (loopOp.maybeGetStep() && !isSubsequentTaken) + regionsToCheck.pop_back(); }; // From 2.4.9 "Note": diff --git a/clang/lib/CIR/Interfaces/CMakeLists.txt b/clang/lib/CIR/Interfaces/CMakeLists.txt index f672eb3f6a9c..74d2c09ad61e 100644 --- a/clang/lib/CIR/Interfaces/CMakeLists.txt +++ b/clang/lib/CIR/Interfaces/CMakeLists.txt @@ -1,6 +1,7 @@ add_clang_library(MLIRCIRInterfaces ASTAttrInterfaces.cpp CIROpInterfaces.cpp + LoopOpInterface.cpp ADDITIONAL_HEADER_DIRS ${MLIR_MAIN_INCLUDE_DIR}/mlir/Interfaces diff --git a/clang/lib/CIR/Interfaces/LoopOpInterface.cpp b/clang/lib/CIR/Interfaces/LoopOpInterface.cpp new file mode 100644 index 000000000000..7a481a82d857 --- /dev/null +++ b/clang/lib/CIR/Interfaces/LoopOpInterface.cpp @@ -0,0 +1,52 @@ +//===- LoopOpInterface.cpp - Interface for CIR loop-like ops ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#include "clang/CIR/Interfaces/LoopOpInterface.h" + +#include "clang/CIR/Dialect/IR/CIRDialect.h" +#include "clang/CIR/Interfaces/LoopOpInterface.cpp.inc" + +namespace mlir { +namespace cir { + +void LoopOpInterface::getLoopOpSuccessorRegions( + LoopOpInterface op, RegionBranchPoint point, + SmallVectorImpl ®ions) { + assert(point.isParent() || point.getRegionOrNull()); + + // Branching to first region: go to condition or body (do-while). + if (point.isParent()) { + regions.emplace_back(&op.getEntry(), op.getEntry().getArguments()); + } + // Branching from condition: go to body or exit. + else if (&op.getCond() == point.getRegionOrNull()) { + regions.emplace_back(RegionSuccessor(op->getResults())); + regions.emplace_back(&op.getBody(), op.getBody().getArguments()); + } + // Branching from body: go to step (for) or condition (while). + else if (&op.getBody() == point.getRegionOrNull()) { + auto *afterBody = (op.maybeGetStep() ? op.maybeGetStep() : &op.getCond()); + regions.emplace_back(afterBody, afterBody->getArguments()); + } + // Branching from step: go to condition. + else if (op.maybeGetStep() == point.getRegionOrNull()) { + regions.emplace_back(&op.getCond(), op.getCond().getArguments()); + } +} + +/// Verify invariants of the LoopOpInterface. +LogicalResult detail::verifyLoopOpInterface(Operation *op) { + auto loopOp = cast(op); + if (!isa(loopOp.getCond().back().getTerminator())) + return op->emitOpError( + "expected condition region to terminate with 'cir.condition'"); + return success(); +} + +} // namespace cir +} // namespace mlir diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 242f3eecb377..acd06b09a8aa 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -447,14 +447,14 @@ class CIRLoopOpLowering : public mlir::OpConversionPattern { // Lower continue statements. mlir::Block &dest = (kind != LoopKind::For ? condFrontBlock : stepFrontBlock); - walkRegionSkipping( + walkRegionSkipping( loopOp.getBody(), [&](mlir::Operation *op) { if (isa(op)) lowerTerminator(op, &dest, rewriter); }); // Lower break statements. - walkRegionSkipping( + walkRegionSkipping( loopOp.getBody(), [&](mlir::Operation *op) { if (isa(op)) lowerTerminator(op, continueBlock, rewriter); @@ -1386,7 +1386,7 @@ class CIRSwitchOpLowering } // Handle break statements. - walkRegionSkipping( + walkRegionSkipping( region, [&](mlir::Operation *op) { if (isa(op)) lowerTerminator(op, exitBlock, rewriter); diff --git a/clang/test/CIR/IR/invalid.cir b/clang/test/CIR/IR/invalid.cir index 00ecacdcacad..a8601342919a 100644 --- a/clang/test/CIR/IR/invalid.cir +++ b/clang/test/CIR/IR/invalid.cir @@ -306,7 +306,7 @@ cir.func @cast24(%p : !u32i) { #true = #cir.bool : !cir.bool cir.func @b0() { cir.scope { - cir.loop while(cond : { // expected-error {{cond region terminate with 'cir.condition'}} + cir.loop while(cond : { // expected-error {{expected condition region to terminate with 'cir.condition'}} cir.yield }, step : { cir.yield diff --git a/clang/test/CIR/Transforms/merge-cleanups.cir b/clang/test/CIR/Transforms/merge-cleanups.cir index 52ba8b7842d2..17880efeac2a 100644 --- a/clang/test/CIR/Transforms/merge-cleanups.cir +++ b/clang/test/CIR/Transforms/merge-cleanups.cir @@ -61,22 +61,6 @@ module { cir.return } - cir.func @l0() { - cir.scope { - cir.loop while(cond : { - %0 = cir.const(#true) : !cir.bool - cir.condition(%0) - }, step : { - cir.yield - }) { - cir.br ^bb1 - ^bb1: - cir.return - } - } - cir.return - } - // CHECK: cir.switch (%4 : !s32i) [ // CHECK-NEXT: case (equal, 0) { // CHECK-NEXT: %5 = cir.load %2 : cir.ptr , !s32i @@ -114,20 +98,6 @@ module { // CHECK-NEXT: } // CHECK-NEXT: ] -// CHECK: cir.func @l0 -// CHECK-NEXT: cir.scope { -// CHECK-NEXT: cir.loop while(cond : { -// CHECK-NEXT: %0 = cir.const(#true) : !cir.bool -// CHECK-NEXT: cir.condition(%0) -// CHECK-NEXT: }, step : { -// CHECK-NEXT: cir.yield -// CHECK-NEXT: }) { -// CHECK-NEXT: cir.return -// CHECK-NEXT: } -// CHECK-NEXT: } -// CHECK-NEXT: cir.return -// CHECK-NEXT: } - // Should remove empty scopes. cir.func @removeEmptyScope() { cir.scope { From a676833b88df39785c27b8e6e82cb4b267a4b747 Mon Sep 17 00:00:00 2001 From: Vinicius Couto Espindola Date: Thu, 18 Jan 2024 20:23:20 -0300 Subject: [PATCH 2/4] Update on "[CIR][Interfaces] Implement LoopOpInterface" Adds an interface to generically handle lowering and analysis of loop operations in CIR. It can also perform verification of invariants common to all loop operations. [ghstack-poisoned] --- clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 701d175cdcb2..9763b05c1add 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -1272,9 +1272,7 @@ void LoopOp::getSuccessorRegions(mlir::RegionBranchPoint point, llvm::SmallVector LoopOp::getLoopRegions() { return {&getBody()}; } -LogicalResult LoopOp::verify() { - return success(); -} +LogicalResult LoopOp::verify() { return success(); } //===----------------------------------------------------------------------===// // GlobalOp From 591d04e7b47bab550cd28f854c42f6d7ff23060a Mon Sep 17 00:00:00 2001 From: Vinicius Couto Espindola Date: Sat, 20 Jan 2024 07:16:07 -0300 Subject: [PATCH 3/4] Update on "[CIR][Interfaces] Implement LoopOpInterface" Adds an interface to generically handle lowering and analysis of loop operations in CIR. It can also perform verification of invariants common to all loop operations. [ghstack-poisoned] --- clang/include/clang/CIR/Dialect/IR/CIRDialect.h | 2 +- clang/include/clang/CIR/Dialect/IR/CIROps.td | 11 ++++++++--- .../{LoopOpInterface.h => CIRLoopOpInterface.h} | 10 +++++----- .../{LoopOpInterface.td => CIRLoopOpInterface.td} | 8 ++++---- clang/include/clang/CIR/Interfaces/CMakeLists.txt | 2 +- clang/lib/CIR/CodeGen/CMakeLists.txt | 1 + clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 2 +- clang/lib/CIR/Dialect/IR/CMakeLists.txt | 1 + clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp | 1 + clang/lib/CIR/FrontendAction/CMakeLists.txt | 1 + .../{LoopOpInterface.cpp => CIRLoopOpInterface.cpp} | 10 ++++++---- clang/lib/CIR/Interfaces/CMakeLists.txt | 3 ++- clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt | 1 + clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt | 1 + 14 files changed, 34 insertions(+), 20 deletions(-) rename clang/include/clang/CIR/Interfaces/{LoopOpInterface.h => CIRLoopOpInterface.h} (77%) rename clang/include/clang/CIR/Interfaces/{LoopOpInterface.td => CIRLoopOpInterface.td} (93%) rename clang/lib/CIR/Interfaces/{LoopOpInterface.cpp => CIRLoopOpInterface.cpp} (83%) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h index 93a50cc8f3d6..f9bcf1c98311 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h @@ -33,7 +33,7 @@ #include "clang/CIR/Interfaces/ASTAttrInterfaces.h" #include "clang/CIR/Interfaces/CIROpInterfaces.h" -#include "clang/CIR/Interfaces/LoopOpInterface.h" +#include "clang/CIR/Interfaces/CIRLoopOpInterface.h" namespace mlir { namespace OpTrait { diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 098f6f3260a4..1d2af6e6fd75 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -20,7 +20,7 @@ include "clang/CIR/Dialect/IR/CIRAttrs.td" include "clang/CIR/Interfaces/ASTAttrInterfaces.td" include "clang/CIR/Interfaces/CIROpInterfaces.td" -include "clang/CIR/Interfaces/LoopOpInterface.td" +include "clang/CIR/Interfaces/CIRLoopOpInterface.td" include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/Interfaces/FunctionInterfaces.td" @@ -1222,9 +1222,14 @@ def LoopOp : CIR_Op<"loop", } llvm::SmallVector getRegionsInExecutionOrder() { - if (getKind() == LoopOpKind::For) + switch(getKind()) { + case LoopOpKind::For: return llvm::SmallVector{&getCond(), &getBody(), &getStep()}; - return llvm::SmallVector{&getCond(), &getBody()}; + case LoopOpKind::While: + return llvm::SmallVector{&getCond(), &getBody()}; + case LoopOpKind::DoWhile: + return llvm::SmallVector{&getBody(), &getCond()}; + } } }]; } diff --git a/clang/include/clang/CIR/Interfaces/LoopOpInterface.h b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.h similarity index 77% rename from clang/include/clang/CIR/Interfaces/LoopOpInterface.h rename to clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.h index 96198c635aa9..2e8a0c8e8a94 100644 --- a/clang/include/clang/CIR/Interfaces/LoopOpInterface.h +++ b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.h @@ -1,4 +1,4 @@ -//===- LoopOpInterface.h - Interface for CIR loop-like ops -----*- C++ -*-===// +//===- CIRLoopOpInterface.h - Interface for CIR loop-like ops --*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -10,8 +10,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_INTERFACES_CIR_LOOPOPINTERFACE_H_ -#define CLANG_INTERFACES_CIR_LOOPOPINTERFACE_H_ +#ifndef CLANG_INTERFACES_CIR_CIRLOOPOPINTERFACE_H_ +#define CLANG_INTERFACES_CIR_CIRLOOPOPINTERFACE_H_ #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/OpDefinition.h" @@ -31,6 +31,6 @@ ::mlir::LogicalResult verifyLoopOpInterface(::mlir::Operation *op); } // namespace mlir /// Include the tablegen'd interface declarations. -#include "clang/CIR/Interfaces/LoopOpInterface.h.inc" +#include "clang/CIR/Interfaces/CIRLoopOpInterface.h.inc" -#endif // CLANG_INTERFACES_CIR_LOOPOPINTERFACE_H_ +#endif // CLANG_INTERFACES_CIR_CIRLOOPOPINTERFACE_H_ diff --git a/clang/include/clang/CIR/Interfaces/LoopOpInterface.td b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td similarity index 93% rename from clang/include/clang/CIR/Interfaces/LoopOpInterface.td rename to clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td index ada6f8f86c5b..c2b871785ffd 100644 --- a/clang/include/clang/CIR/Interfaces/LoopOpInterface.td +++ b/clang/include/clang/CIR/Interfaces/CIRLoopOpInterface.td @@ -1,4 +1,4 @@ -//===- LoopOpInterface.td - Interface for CIR loop-like ops ----*- C++ -*-===// +//===- CIRLoopOpInterface.td - Interface for CIR loop-like ops -*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,8 +6,8 @@ // //===---------------------------------------------------------------------===// -#ifndef CLANG_CIR_INTERFACES_LOOPOPINTERFACE -#define CLANG_CIR_INTERFACES_LOOPOPINTERFACE +#ifndef CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE +#define CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE include "mlir/IR/OpBase.td" include "mlir/Interfaces/ControlFlowInterfaces.td" @@ -97,4 +97,4 @@ def LoopOpInterface : OpInterface<"LoopOpInterface", [ }]; } -#endif // CLANG_CIR_INTERFACES_LOOPOPINTERFACE +#endif // CLANG_CIR_INTERFACES_CIRLOOPOPINTERFACE diff --git a/clang/include/clang/CIR/Interfaces/CMakeLists.txt b/clang/include/clang/CIR/Interfaces/CMakeLists.txt index 383eda4311a3..c7132abca833 100644 --- a/clang/include/clang/CIR/Interfaces/CMakeLists.txt +++ b/clang/include/clang/CIR/Interfaces/CMakeLists.txt @@ -22,4 +22,4 @@ endfunction() add_clang_mlir_attr_interface(ASTAttrInterfaces) add_clang_mlir_op_interface(CIROpInterfaces) -add_clang_mlir_op_interface(LoopOpInterface) +add_clang_mlir_op_interface(CIRLoopOpInterface) diff --git a/clang/lib/CIR/CodeGen/CMakeLists.txt b/clang/lib/CIR/CodeGen/CMakeLists.txt index 62df7a8d3d68..5af8f15aac34 100644 --- a/clang/lib/CIR/CodeGen/CMakeLists.txt +++ b/clang/lib/CIR/CodeGen/CMakeLists.txt @@ -41,6 +41,7 @@ add_clang_library(clangCIR MLIRCIROpsIncGen MLIRCIRASTAttrInterfacesIncGen MLIRCIROpInterfacesIncGen + MLIRCIRLoopOpInterfaceIncGen ${dialect_libs} LINK_LIBS diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 9763b05c1add..bf04b61b5721 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -14,7 +14,7 @@ #include "clang/CIR/Dialect/IR/CIRAttrs.h" #include "clang/CIR/Dialect/IR/CIROpsEnums.h" #include "clang/CIR/Dialect/IR/CIRTypes.h" -#include "clang/CIR/Interfaces/LoopOpInterface.h" +#include "clang/CIR/Interfaces/CIRLoopOpInterface.h" #include "llvm/Support/ErrorHandling.h" #include diff --git a/clang/lib/CIR/Dialect/IR/CMakeLists.txt b/clang/lib/CIR/Dialect/IR/CMakeLists.txt index b8cc5b84e93e..f4609c3aad32 100644 --- a/clang/lib/CIR/Dialect/IR/CMakeLists.txt +++ b/clang/lib/CIR/Dialect/IR/CMakeLists.txt @@ -11,6 +11,7 @@ add_clang_library(MLIRCIR MLIRSymbolInterfacesIncGen MLIRCIRASTAttrInterfacesIncGen MLIRCIROpInterfacesIncGen + MLIRCIRLoopOpInterfaceIncGen LINK_LIBS PUBLIC MLIRIR diff --git a/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp b/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp index 03d41a9fd59c..ea324bd090b2 100644 --- a/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp +++ b/clang/lib/CIR/Dialect/Transforms/LifetimeCheck.cpp @@ -16,6 +16,7 @@ #include "clang/CIR/Dialect/IR/CIRDialect.h" #include "clang/CIR/Dialect/Passes.h" +#include "clang/CIR/Interfaces/CIRLoopOpInterface.h" #include "llvm/ADT/SetOperations.h" #include "llvm/ADT/SmallSet.h" diff --git a/clang/lib/CIR/FrontendAction/CMakeLists.txt b/clang/lib/CIR/FrontendAction/CMakeLists.txt index 31ca49fedf44..077bd733cbd8 100644 --- a/clang/lib/CIR/FrontendAction/CMakeLists.txt +++ b/clang/lib/CIR/FrontendAction/CMakeLists.txt @@ -12,6 +12,7 @@ add_clang_library(clangCIRFrontendAction MLIRCIROpsIncGen MLIRCIRASTAttrInterfacesIncGen MLIRCIROpInterfacesIncGen + MLIRCIRLoopOpInterfaceIncGen MLIRBuiltinLocationAttributesIncGen MLIRBuiltinTypeInterfacesIncGen MLIRFunctionInterfacesIncGen diff --git a/clang/lib/CIR/Interfaces/LoopOpInterface.cpp b/clang/lib/CIR/Interfaces/CIRLoopOpInterface.cpp similarity index 83% rename from clang/lib/CIR/Interfaces/LoopOpInterface.cpp rename to clang/lib/CIR/Interfaces/CIRLoopOpInterface.cpp index 7a481a82d857..ae5947a56944 100644 --- a/clang/lib/CIR/Interfaces/LoopOpInterface.cpp +++ b/clang/lib/CIR/Interfaces/CIRLoopOpInterface.cpp @@ -1,4 +1,4 @@ -//===- LoopOpInterface.cpp - Interface for CIR loop-like ops ---*- C++ -*-===// +//===- CIRLoopOpInterface.cpp - Interface for CIR loop-like ops *- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -6,10 +6,11 @@ // //===---------------------------------------------------------------------===// -#include "clang/CIR/Interfaces/LoopOpInterface.h" +#include "clang/CIR/Interfaces/CIRLoopOpInterface.h" #include "clang/CIR/Dialect/IR/CIRDialect.h" -#include "clang/CIR/Interfaces/LoopOpInterface.cpp.inc" +#include "clang/CIR/Interfaces/CIRLoopOpInterface.cpp.inc" +#include "llvm/Support/ErrorHandling.h" namespace mlir { namespace cir { @@ -28,8 +29,9 @@ void LoopOpInterface::getLoopOpSuccessorRegions( regions.emplace_back(RegionSuccessor(op->getResults())); regions.emplace_back(&op.getBody(), op.getBody().getArguments()); } - // Branching from body: go to step (for) or condition (while). + // Branching from body: go to step (for) or condition. else if (&op.getBody() == point.getRegionOrNull()) { + // FIXME(cir): Should we consider break/continue statements here? auto *afterBody = (op.maybeGetStep() ? op.maybeGetStep() : &op.getCond()); regions.emplace_back(afterBody, afterBody->getArguments()); } diff --git a/clang/lib/CIR/Interfaces/CMakeLists.txt b/clang/lib/CIR/Interfaces/CMakeLists.txt index 74d2c09ad61e..84322f4836e0 100644 --- a/clang/lib/CIR/Interfaces/CMakeLists.txt +++ b/clang/lib/CIR/Interfaces/CMakeLists.txt @@ -1,7 +1,7 @@ add_clang_library(MLIRCIRInterfaces ASTAttrInterfaces.cpp CIROpInterfaces.cpp - LoopOpInterface.cpp + CIRLoopOpInterface.cpp ADDITIONAL_HEADER_DIRS ${MLIR_MAIN_INCLUDE_DIR}/mlir/Interfaces @@ -9,6 +9,7 @@ add_clang_library(MLIRCIRInterfaces DEPENDS MLIRCIRASTAttrInterfacesIncGen MLIRCIROpInterfacesIncGen + MLIRCIRLoopOpInterfaceIncGen LINK_LIBS ${dialect_libs} diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt index 14b879ee1c44..f613972126c8 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt +++ b/clang/lib/CIR/Lowering/DirectToLLVM/CMakeLists.txt @@ -14,6 +14,7 @@ add_clang_library(clangCIRLoweringDirectToLLVM MLIRCIROpsIncGen MLIRCIRASTAttrInterfacesIncGen MLIRCIROpInterfacesIncGen + MLIRCIRLoopOpInterfaceIncGen MLIRBuiltinLocationAttributesIncGen MLIRBuiltinTypeInterfacesIncGen MLIRFunctionInterfacesIncGen diff --git a/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt b/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt index d4a945ab7915..3ae144024ae7 100644 --- a/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt +++ b/clang/lib/CIR/Lowering/ThroughMLIR/CMakeLists.txt @@ -14,6 +14,7 @@ add_clang_library(clangCIRLoweringThroughMLIR MLIRCIREnumsGen MLIRCIRASTAttrInterfacesIncGen MLIRCIROpInterfacesIncGen + MLIRCIRLoopOpInterfaceIncGen MLIRBuiltinLocationAttributesIncGen MLIRBuiltinTypeInterfacesIncGen MLIRFunctionInterfacesIncGen From 8293c1818cc5cdb264baad3684651854d5a4029a Mon Sep 17 00:00:00 2001 From: Vinicius Couto Espindola Date: Sat, 20 Jan 2024 10:39:42 -0300 Subject: [PATCH 4/4] Update on "[CIR][Interfaces] Implement LoopOpInterface" Adds an interface to generically handle lowering and analysis of loop operations in CIR. It can also perform verification of invariants common to all loop operations. [ghstack-poisoned] --- clang/include/clang/CIR/Dialect/IR/CIRDialect.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h index f9bcf1c98311..481ea6166aba 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIRDialect.h +++ b/clang/include/clang/CIR/Dialect/IR/CIRDialect.h @@ -32,8 +32,8 @@ #include "clang/CIR/Dialect/IR/CIRTypes.h" #include "clang/CIR/Interfaces/ASTAttrInterfaces.h" -#include "clang/CIR/Interfaces/CIROpInterfaces.h" #include "clang/CIR/Interfaces/CIRLoopOpInterface.h" +#include "clang/CIR/Interfaces/CIROpInterfaces.h" namespace mlir { namespace OpTrait {