diff options
author | Andy Kaylor <akaylor@nvidia.com> | 2025-04-01 13:03:24 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-04-01 13:03:24 -0700 |
commit | 9f3d8e8fb8d389176e12c06de59cce3fd1ab8db2 (patch) | |
tree | 5d6c5e8d41a8b0298f81ca32abe4ed388ef79902 /clang/lib | |
parent | ce296f1ebac896d03bdb783d9c5d3c93ab76f1ac (diff) | |
download | llvm-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.h | 4 | ||||
-rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenStmt.cpp | 113 | ||||
-rw-r--r-- | clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 14 |
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> ®ions) { - LoopOpInterface::getLoopOpSuccessorRegions(*this, point, regions); -} - -llvm::SmallVector<Region *> cir::ForOp::getLoopRegions() { - return {&getBody()}; -} - -//===----------------------------------------------------------------------===// // GlobalOp //===----------------------------------------------------------------------===// |