[flang-commits] [flang] 7c9d3d5 - [flang][hlfir] Support MERGE with polymorphic arguments.

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Tue Aug 8 09:59:06 PDT 2023


Author: Slava Zakharin
Date: 2023-08-08T09:58:48-07:00
New Revision: 7c9d3d5c7b65542e0122dd0012fcffafdfaeda2a

URL: https://github.com/llvm/llvm-project/commit/7c9d3d5c7b65542e0122dd0012fcffafdfaeda2a
DIFF: https://github.com/llvm/llvm-project/commit/7c9d3d5c7b65542e0122dd0012fcffafdfaeda2a.diff

LOG: [flang][hlfir] Support MERGE with polymorphic arguments.

Pass the first argument as the polymorphic mold for the generated
hlfir.elemental.

Depends on D157316

Reviewed By: tblah, clementval

Differential Revision: https://reviews.llvm.org/D157317

Added: 
    flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90

Modified: 
    flang/lib/Lower/ConvertCall.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index d5f0a88414648f..6e637379017aa0 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -1659,9 +1659,13 @@ class ElementalCallBuilder {
       // use.
       return res;
     };
+    mlir::Value polymorphicMold;
+    if (fir::isPolymorphicType(*callContext.resultType))
+      polymorphicMold =
+          impl().getPolymorphicResultMold(loweredActuals, callContext);
     mlir::Value elemental =
         hlfir::genElementalOp(loc, builder, elementType, shape, typeParams,
-                              genKernel, !mustBeOrdered);
+                              genKernel, !mustBeOrdered, polymorphicMold);
     fir::FirOpBuilder *bldr = &builder;
     callContext.stmtCtx.attachCleanup(
         [=]() { bldr->create<hlfir::DestroyOp>(loc, elemental); });
@@ -1710,6 +1714,14 @@ class ElementalUserCallBuilder
          "compute elemental function result length parameters in HLFIR");
   }
 
+  mlir::Value getPolymorphicResultMold(
+      Fortran::lower::PreparedActualArguments &loweredActuals,
+      CallContext &callContext) {
+    fir::emitFatalError(callContext.loc,
+                        "elemental function call with polymorphic result");
+    return {};
+  }
+
 private:
   Fortran::lower::CallerInterface &caller;
   mlir::FunctionType callSiteType;
@@ -1752,6 +1764,25 @@ class ElementalIntrinsicCallBuilder
          "compute elemental character min/max function result length in HLFIR");
   }
 
+  mlir::Value getPolymorphicResultMold(
+      Fortran::lower::PreparedActualArguments &loweredActuals,
+      CallContext &callContext) {
+    if (!intrinsic)
+      return {};
+
+    if (intrinsic->name == "merge") {
+      // MERGE seems to be the only elemental function that can produce
+      // polymorphic result. The MERGE's result is polymorphic iff
+      // both TSOURCE and FSOURCE are polymorphic, and they also must have
+      // the same declared and dynamic types. So any of them can be used
+      // for the mold.
+      assert(!loweredActuals.empty());
+      return loweredActuals.front()->getOriginalActual();
+    }
+
+    return {};
+  }
+
 private:
   const Fortran::evaluate::SpecificIntrinsic *intrinsic;
   const fir::IntrinsicArgumentLoweringRules *argLowering;

diff  --git a/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90 b/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90
new file mode 100644
index 00000000000000..c2f97b6fccfeb9
--- /dev/null
+++ b/flang/test/Lower/HLFIR/elemental-polymorphic-merge.f90
@@ -0,0 +1,38 @@
+! Test that the produced hlfir.elemental had proper result type and the mold.
+! RUN: bbc --emit-hlfir --polymorphic-type -I nowhere -o - %s | FileCheck %s
+
+subroutine test_polymorphic_merge(x, y, r, m)
+  type t
+  end type t
+  class(t), allocatable :: r(:)
+  class(t), intent(in) :: y(:), x
+  logical :: m(:)
+  r = merge(x, y, m)
+end subroutine test_polymorphic_merge
+! CHECK-LABEL:   func.func @_QPtest_polymorphic_merge(
+! CHECK-SAME:        %[[VAL_0:.*]]: !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>> {fir.bindc_name = "x"},
+! CHECK-SAME:        %[[VAL_1:.*]]: !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>> {fir.bindc_name = "y"},
+! CHECK-SAME:        %[[VAL_2:.*]]: !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>> {fir.bindc_name = "r"},
+! CHECK-SAME:        %[[VAL_3:.*]]: !fir.box<!fir.array<?x!fir.logical<4>>> {fir.bindc_name = "m"}) {
+! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFtest_polymorphic_mergeEm"} : (!fir.box<!fir.array<?x!fir.logical<4>>>) -> (!fir.box<!fir.array<?x!fir.logical<4>>>, !fir.box<!fir.array<?x!fir.logical<4>>>)
+! CHECK:           %[[VAL_5:.*]]:2 = hlfir.declare %[[VAL_2]] {fortran_attrs = #fir.var_attrs<allocatable>, uniq_name = "_QFtest_polymorphic_mergeEr"} : (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>) -> (!fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>)
+! CHECK:           %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_0]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphic_mergeEx"} : (!fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>) -> (!fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>, !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>)
+! CHECK:           %[[VAL_7:.*]]:2 = hlfir.declare %[[VAL_1]] {fortran_attrs = #fir.var_attrs<intent_in>, uniq_name = "_QFtest_polymorphic_mergeEy"} : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>) -> (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>, !fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>)
+! CHECK:           %[[VAL_8:.*]] = arith.constant 0 : index
+! CHECK:           %[[VAL_9:.*]]:3 = fir.box_dims %[[VAL_7]]#0, %[[VAL_8]] : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>, index) -> (index, index, index)
+! CHECK:           %[[VAL_10:.*]] = fir.shape %[[VAL_9]]#1 : (index) -> !fir.shape<1>
+! CHECK:           %[[VAL_11:.*]] = hlfir.elemental %[[VAL_10]] mold %[[VAL_6]]#0 unordered : (!fir.shape<1>, !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>) -> !hlfir.expr<?x!fir.type<_QFtest_polymorphic_mergeTt>?> {
+! CHECK:           ^bb0(%[[VAL_12:.*]]: index):
+! CHECK:             %[[VAL_13:.*]] = hlfir.designate %[[VAL_7]]#0 (%[[VAL_12]])  : (!fir.class<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>, index) -> !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>
+! CHECK:             %[[VAL_14:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_12]])  : (!fir.box<!fir.array<?x!fir.logical<4>>>, index) -> !fir.ref<!fir.logical<4>>
+! CHECK:             %[[VAL_15:.*]] = fir.load %[[VAL_14]] : !fir.ref<!fir.logical<4>>
+! CHECK:             %[[VAL_16:.*]] = fir.convert %[[VAL_15]] : (!fir.logical<4>) -> i1
+! CHECK:             %[[VAL_17:.*]] = arith.select %[[VAL_16]], %[[VAL_6]]#1, %[[VAL_13]] : !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>
+! CHECK:             %[[VAL_18:.*]]:2 = hlfir.declare %[[VAL_17]] {uniq_name = ".tmp.intrinsic_result"} : (!fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>) -> (!fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>, !fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>)
+! CHECK:             %[[VAL_19:.*]] = hlfir.as_expr %[[VAL_18]]#0 : (!fir.class<!fir.type<_QFtest_polymorphic_mergeTt>>) -> !hlfir.expr<!fir.type<_QFtest_polymorphic_mergeTt>?>
+! CHECK:             hlfir.yield_element %[[VAL_19]] : !hlfir.expr<!fir.type<_QFtest_polymorphic_mergeTt>?>
+! CHECK:           }
+! CHECK:           hlfir.assign %[[VAL_11]] to %[[VAL_5]]#0 realloc : !hlfir.expr<?x!fir.type<_QFtest_polymorphic_mergeTt>?>, !fir.ref<!fir.class<!fir.heap<!fir.array<?x!fir.type<_QFtest_polymorphic_mergeTt>>>>>
+! CHECK:           hlfir.destroy %[[VAL_11]] : !hlfir.expr<?x!fir.type<_QFtest_polymorphic_mergeTt>?>
+! CHECK:           return
+! CHECK:         }


        


More information about the flang-commits mailing list