aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
authorAndy Kaylor <akaylor@nvidia.com>2025-04-01 13:03:24 -0700
committerGitHub <noreply@github.com>2025-04-01 13:03:24 -0700
commit9f3d8e8fb8d389176e12c06de59cce3fd1ab8db2 (patch)
tree5d6c5e8d41a8b0298f81ca32abe4ed388ef79902 /clang/lib
parentce296f1ebac896d03bdb783d9c5d3c93ab76f1ac (diff)
downloadllvm-9f3d8e8fb8d389176e12c06de59cce3fd1ab8db2.zip
llvm-9f3d8e8fb8d389176e12c06de59cce3fd1ab8db2.tar.gz
llvm-9f3d8e8fb8d389176e12c06de59cce3fd1ab8db2.tar.bz2
[CIR] Upstream support for while and do..while loops (#133157)
This adds basic support for while and do..while loops. Support for break and continue are left for a subsequent patch.
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenFunction.h4
-rw-r--r--clang/lib/CIR/CodeGen/CIRGenStmt.cpp113
-rw-r--r--clang/lib/CIR/Dialect/IR/CIRDialect.cpp14
3 files changed, 115 insertions, 16 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 3b8171e..5cae4d5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -395,6 +395,8 @@ public:
LValue emitBinaryOperatorLValue(const BinaryOperator *e);
+ mlir::LogicalResult emitDoStmt(const clang::DoStmt &s);
+
/// Emit an expression as an initializer for an object (variable, field, etc.)
/// at the given location. The expression is not necessarily the normal
/// initializer for the object, and the address is not necessarily
@@ -493,6 +495,8 @@ public:
/// inside a function, including static vars etc.
void emitVarDecl(const clang::VarDecl &d);
+ mlir::LogicalResult emitWhileStmt(const clang::WhileStmt &s);
+
/// ----------------------
/// CIR build helpers
/// -----------------
diff --git a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
index aa04ff6..b5c1f0a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenStmt.cpp
@@ -75,6 +75,10 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
case Stmt::ForStmtClass:
return emitForStmt(cast<ForStmt>(*s));
+ case Stmt::WhileStmtClass:
+ return emitWhileStmt(cast<WhileStmt>(*s));
+ case Stmt::DoStmtClass:
+ return emitDoStmt(cast<DoStmt>(*s));
case Stmt::OMPScopeDirectiveClass:
case Stmt::OMPErrorDirectiveClass:
@@ -97,8 +101,6 @@ mlir::LogicalResult CIRGenFunction::emitStmt(const Stmt *s,
case Stmt::SYCLKernelCallStmtClass:
case Stmt::IfStmtClass:
case Stmt::SwitchStmtClass:
- case Stmt::WhileStmtClass:
- case Stmt::DoStmtClass:
case Stmt::CoroutineBodyStmtClass:
case Stmt::CoreturnStmtClass:
case Stmt::CXXTryStmtClass:
@@ -387,3 +389,110 @@ mlir::LogicalResult CIRGenFunction::emitForStmt(const ForStmt &s) {
terminateBody(builder, forOp.getBody(), getLoc(s.getEndLoc()));
return mlir::success();
}
+
+mlir::LogicalResult CIRGenFunction::emitDoStmt(const DoStmt &s) {
+ cir::DoWhileOp doWhileOp;
+
+ // TODO: pass in array of attributes.
+ auto doStmtBuilder = [&]() -> mlir::LogicalResult {
+ mlir::LogicalResult loopRes = mlir::success();
+ assert(!cir::MissingFeatures::loopInfoStack());
+ // From LLVM: if there are any cleanups between here and the loop-exit
+ // scope, create a block to stage a loop exit along.
+ // We probably already do the right thing because of ScopeOp, but make
+ // sure we handle all cases.
+ assert(!cir::MissingFeatures::requiresCleanups());
+
+ doWhileOp = builder.createDoWhile(
+ getLoc(s.getSourceRange()),
+ /*condBuilder=*/
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ assert(!cir::MissingFeatures::createProfileWeightsForLoop());
+ assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
+ // C99 6.8.5p2/p4: The first substatement is executed if the
+ // expression compares unequal to 0. The condition must be a
+ // scalar type.
+ mlir::Value condVal = evaluateExprAsBool(s.getCond());
+ builder.createCondition(condVal);
+ },
+ /*bodyBuilder=*/
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ // The scope of the do-while loop body is a nested scope.
+ if (emitStmt(s.getBody(), /*useCurrentScope=*/false).failed())
+ loopRes = mlir::failure();
+ emitStopPoint(&s);
+ });
+ return loopRes;
+ };
+
+ mlir::LogicalResult res = mlir::success();
+ mlir::Location scopeLoc = getLoc(s.getSourceRange());
+ builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ LexicalScope lexScope{
+ *this, loc, builder.getInsertionBlock()};
+ res = doStmtBuilder();
+ });
+
+ if (res.failed())
+ return res;
+
+ terminateBody(builder, doWhileOp.getBody(), getLoc(s.getEndLoc()));
+ return mlir::success();
+}
+
+mlir::LogicalResult CIRGenFunction::emitWhileStmt(const WhileStmt &s) {
+ cir::WhileOp whileOp;
+
+ // TODO: pass in array of attributes.
+ auto whileStmtBuilder = [&]() -> mlir::LogicalResult {
+ mlir::LogicalResult loopRes = mlir::success();
+ assert(!cir::MissingFeatures::loopInfoStack());
+ // From LLVM: if there are any cleanups between here and the loop-exit
+ // scope, create a block to stage a loop exit along.
+ // We probably already do the right thing because of ScopeOp, but make
+ // sure we handle all cases.
+ assert(!cir::MissingFeatures::requiresCleanups());
+
+ whileOp = builder.createWhile(
+ getLoc(s.getSourceRange()),
+ /*condBuilder=*/
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ assert(!cir::MissingFeatures::createProfileWeightsForLoop());
+ assert(!cir::MissingFeatures::emitCondLikelihoodViaExpectIntrinsic());
+ mlir::Value condVal;
+ // If the for statement has a condition scope,
+ // emit the local variable declaration.
+ if (s.getConditionVariable())
+ emitDecl(*s.getConditionVariable());
+ // C99 6.8.5p2/p4: The first substatement is executed if the
+ // expression compares unequal to 0. The condition must be a
+ // scalar type.
+ condVal = evaluateExprAsBool(s.getCond());
+ builder.createCondition(condVal);
+ },
+ /*bodyBuilder=*/
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ // The scope of the while loop body is a nested scope.
+ if (emitStmt(s.getBody(), /*useCurrentScope=*/false).failed())
+ loopRes = mlir::failure();
+ emitStopPoint(&s);
+ });
+ return loopRes;
+ };
+
+ mlir::LogicalResult res = mlir::success();
+ mlir::Location scopeLoc = getLoc(s.getSourceRange());
+ builder.create<cir::ScopeOp>(scopeLoc, /*scopeBuilder=*/
+ [&](mlir::OpBuilder &b, mlir::Location loc) {
+ LexicalScope lexScope{
+ *this, loc, builder.getInsertionBlock()};
+ res = whileStmtBuilder();
+ });
+
+ if (res.failed())
+ return res;
+
+ terminateBody(builder, whileOp.getBody(), getLoc(s.getEndLoc()));
+ return mlir::success();
+}
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index cdcfa77..4ace083 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -539,20 +539,6 @@ Block *cir::BrCondOp::getSuccessorForOperands(ArrayRef<Attribute> operands) {
}
//===----------------------------------------------------------------------===//
-// ForOp
-//===----------------------------------------------------------------------===//
-
-void cir::ForOp::getSuccessorRegions(
- mlir::RegionBranchPoint point,
- llvm::SmallVectorImpl<mlir::RegionSuccessor> &regions) {
- LoopOpInterface::getLoopOpSuccessorRegions(*this, point, regions);
-}
-
-llvm::SmallVector<Region *> cir::ForOp::getLoopRegions() {
- return {&getBody()};
-}
-
-//===----------------------------------------------------------------------===//
// GlobalOp
//===----------------------------------------------------------------------===//