[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:00:50 PDT 2026


================
@@ -857,6 +858,137 @@ struct CharExtremumOpConversion
   }
 };
 
+struct ConditionalOpConversion
+    : public mlir::OpConversionPattern<hlfir::ConditionalOp> {
+  using mlir::OpConversionPattern<hlfir::ConditionalOp>::OpConversionPattern;
+  explicit ConditionalOpConversion(mlir::MLIRContext *ctx)
+      : mlir::OpConversionPattern<hlfir::ConditionalOp>{ctx} {
+    // This pattern recursively converts nested ConditionalOp's
+    // by cloning and then converting them, so we have to allow
+    // for recursive pattern application. The recursion is bounded
+    // by the nesting level of ConditionalOp's.
+    setHasBoundedRewriteRecursion();
+  }
+  /// Compute the MLIR type of the temp's DeclareOp base result,
+  /// given the hlfir.expr type of the conditional. This must match
+  /// what createAndDeclareTemp + hlfir::DeclareOp would produce.
+  static mlir::Type computeTempBaseType(fir::FirOpBuilder &builder,
+                                        hlfir::ExprType exprType) {
+    const mlir::Type eleTy{exprType.getEleTy()};
+    const bool isPolymorphic{exprType.isPolymorphic()};
+    const bool isArray{exprType.isArray()};
+    mlir::Type elemOrSeqType{eleTy};
+    if (isArray)
+      elemOrSeqType = fir::SequenceType::get(exprType.getShape(), eleTy);
+    // Polymorphic: runtime allocate produces fir.class<fir.heap<T>>,
+    // DeclareOp strips the heap attribute → fir.class<T>.
+    if (isPolymorphic)
+      return fir::ClassType::get(elemOrSeqType);
+    // Arrays (non-polymorphic): heap alloc → fir.heap<seqTy>,
+    // DeclareOp wraps in box → fir.box<seqTy>.
+    if (isArray)
+      return fir::BoxType::get(elemOrSeqType);
+    // Scalar, non-polymorphic.
+    if (auto charTy{mlir::dyn_cast<fir::CharacterType>(eleTy)})
+      if (charTy.hasDynamicLen())
+        return fir::BoxCharType::get(builder.getContext(), charTy.getFKind());
+    if (fir::isRecordWithTypeParameters(eleTy))
+      return fir::BoxType::get(eleTy);
+    return fir::ReferenceType::get(eleTy);
+  }
+
+  llvm::LogicalResult
+  matchAndRewrite(hlfir::ConditionalOp condOp, OpAdaptor adaptor,
+                  mlir::ConversionPatternRewriter &rewriter) const override {
+    const mlir::Location loc{condOp->getLoc()};
+    fir::FirOpBuilder builder(rewriter, condOp.getOperation());
+    HLFIRListener listener{builder, rewriter};
+    builder.setListener(&listener);
+    // Use ExprType to ensure both branches produce identical MLIR temp types.
+    const auto exprType{
+        mlir::cast<hlfir::ExprType>(condOp.getResult().getType())};
+    const bool isPolymorphic{exprType.isPolymorphic()};
+    const bool isArray{exprType.isArray()};
+    mlir::Type elemOrSeqType{exprType.getEleTy()};
+    if (isArray)
+      elemOrSeqType =
+          fir::SequenceType::get(exprType.getShape(), elemOrSeqType);
----------------
cenewcombe wrote:

This change is implemented  in the new helper function. Thanks!

https://github.com/llvm/llvm-project/pull/194411


More information about the flang-commits mailing list