[flang-commits] [flang] [flang] Region-based HLFIR operation for conditional expressions lowering (PR #194411)
Caroline Newcombe via flang-commits
flang-commits at lists.llvm.org
Thu May 7 14:03:11 PDT 2026
================
@@ -1847,56 +1847,48 @@ class HlfirBuilder {
llvm_unreachable("unknown descriptor inquiry");
}
- /// Build nested if-then-else chain by walking the right-skewed
- /// ConditionalExpr tree. The assignValue callback generates and assigns
- /// each value to avoid evaluating non-taken branches.
- template <typename T, typename Callback>
- void
- buildConditionalIfChain(const Fortran::evaluate::ConditionalExpr<T> &condExpr,
- const Callback &assignValue) {
+ /// Generate a conditional expression as an hlfir.conditional op whose
+ /// regions yield the then/else values. Materialization into memory is
+ /// deferred to the bufferization pass.
+ template <typename T>
+ hlfir::Entity
+ genConditionalOp(const Fortran::evaluate::ConditionalExpr<T> &condExpr,
+ mlir::Type elementType, bool isPolymorphic) {
const mlir::Location loc{getLoc()};
fir::FirOpBuilder &builder{getBuilder()};
+ // Lower the condition to i1.
getStmtCtx().pushScope();
const hlfir::EntityWithAttributes condEntity{gen(condExpr.condition())};
mlir::Value condition{hlfir::loadTrivialScalar(loc, builder, condEntity)};
condition = builder.createConvert(loc, builder.getI1Type(), condition);
- builder.genIfOp(loc, {}, condition, /*withElseRegion=*/true)
- .genThen([&]() {
- getStmtCtx().pushScope();
- assignValue(condExpr.thenValue());
- getStmtCtx().finalizeAndPop();
- })
- .genElse([&]() {
- getStmtCtx().pushScope();
- assignValue(condExpr.elseValue());
- getStmtCtx().finalizeAndPop();
- })
- .end();
getStmtCtx().finalizeAndPop();
- }
-
- /// Generate scalar conditional with lazy evaluation using assignment.
- /// Creates a temporary and assigns the selected branch value to it.
- template <typename T>
- hlfir::Entity
- genScalarConditional(const Fortran::evaluate::ConditionalExpr<T> &condExpr,
- mlir::Type elementType,
- const llvm::SmallVector<mlir::Value, 1> &typeParams) {
- const mlir::Location loc{getLoc()};
- fir::FirOpBuilder &builder{getBuilder()};
- const mlir::Value tempStorage{builder.createTemporary(
- loc, elementType, ".cond.scalar",
- /*shape=*/mlir::ValueRange{}, /*typeParams=*/typeParams)};
- const hlfir::DeclareOp tempDecl{hlfir::DeclareOp::create(
- builder, loc, tempStorage, ".cond.result",
- /*shape=*/mlir::Value{}, /*typeParams=*/typeParams)};
- const hlfir::Entity temp{tempDecl};
- buildConditionalIfChain(
- condExpr, [&](const Fortran::evaluate::Expr<T> &expr) {
- hlfir::Entity entity{gen(expr)};
- hlfir::AssignOp::create(builder, loc, entity, temp);
- });
- return temp;
+ // Build the hlfir.expr result type.
+ const hlfir::ExprType::Shape shape(condExpr.Rank(),
+ hlfir::ExprType::getUnknownExtent());
+ const mlir::Type exprType{hlfir::ExprType::get(builder.getContext(), shape,
+ elementType, isPolymorphic)};
+ auto condOp =
+ hlfir::ConditionalOp::create(builder, loc, exprType, condition);
+ // Populate each region inside a scope so that any cleanups
+ // (hlfir.destroy) emitted by gen() stay inside the region, avoiding
+ // dominance violations. The ConditionalOpConversion in bufferization
+ // defers these destroy ops until after the assign into the temp.
+ builder.setInsertionPointToStart(&condOp.getThenRegion().front());
+ getStmtCtx().pushScope();
+ const hlfir::Entity thenEntity{gen(condExpr.thenValue())};
----------------
cenewcombe wrote:
Done ✔️
https://github.com/llvm/llvm-project/pull/194411
More information about the flang-commits
mailing list