[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