2929#include  " flang/Optimizer/Builder/Todo.h" 
3030#include  " flang/Optimizer/Dialect/FIROpsSupport.h" 
3131#include  " flang/Optimizer/HLFIR/HLFIROps.h" 
32+ #include  " mlir/IR/IRMapping.h" 
3233#include  " llvm/Support/CommandLine.h" 
3334#include  " llvm/Support/Debug.h" 
3435#include  < optional> 
@@ -1619,37 +1620,33 @@ class ElementalCallBuilder {
16191620    for  (unsigned  i = 0 ; i < numArgs; ++i) {
16201621      auto  &preparedActual = loweredActuals[i];
16211622      if  (preparedActual) {
1622-         hlfir::Entity actual = preparedActual->getOriginalActual ();
16231623        //  Elemental procedure dummy arguments cannot be pointer/allocatables
16241624        //  (C15100), so it is safe to dereference any pointer or allocatable
16251625        //  actual argument now instead of doing this inside the elemental
16261626        //  region.
1627-         actual =  hlfir:: derefPointersAndAllocatables, actual );
1627+         preparedActual-> derefPointersAndAllocatables (loc, builder);
16281628        //  Better to load scalars outside of the loop when possible.
16291629        if  (!preparedActual->handleDynamicOptional () &&
16301630            impl ().canLoadActualArgumentBeforeLoop (i))
1631-           actual =  hlfir:: loadTrivialScalar, actual );
1631+           preparedActual-> loadTrivialScalar (loc, builder);
16321632        //  TODO: merge shape instead of using the first one.
1633-         if  (!shape && actual. isArray ()) {
1633+         if  (!shape && preparedActual-> isArray ()) {
16341634          if  (preparedActual->handleDynamicOptional ())
16351635            optionalWithShape = &*preparedActual;
16361636          else 
1637-             shape = hlfir:: genShape, actual );
1637+             shape = preparedActual-> genShape (loc, builder);
16381638        }
16391639        //  15.8.3 p1. Elemental procedure with intent(out)/intent(inout)
16401640        //  arguments must be called in element order.
16411641        if  (impl ().argMayBeModifiedByCall (i))
16421642          mustBeOrdered = true ;
1643-         //  Propagates pointer dereferences and scalar loads.
1644-         preparedActual->setOriginalActual (actual);
16451643      }
16461644    }
16471645    if  (!shape && optionalWithShape) {
16481646      //  If all array operands appear in optional positions, then none of them
16491647      //  is allowed to be absent as per 15.5.2.12 point 3. (6). Just pick the
16501648      //  first operand.
1651-       shape =
1652-           hlfir::genShape (loc, builder, optionalWithShape->getOriginalActual ());
1649+       shape = optionalWithShape->genShape (loc, builder);
16531650      //  TODO: There is an opportunity to add a runtime check here that
16541651      //  this array is present as required. Also, the optionality of all actual
16551652      //  could be checked and reset given the Fortran requirement.
@@ -1663,16 +1660,10 @@ class ElementalCallBuilder {
16631660    //  intent(inout) arguments. Note that the scalar arguments are handled
16641661    //  above.
16651662    if  (mustBeOrdered) {
1666-       for  (unsigned  i = 0 ; i < numArgs; ++i) {
1667-         auto  &preparedActual = loweredActuals[i];
1663+       for  (auto  &preparedActual : loweredActuals) {
16681664        if  (preparedActual) {
1669-           hlfir::Entity actual = preparedActual->getOriginalActual ();
1670-           if  (!actual.isVariable () && actual.isArray ()) {
1671-             mlir::Type storageType = actual.getType ();
1672-             hlfir::AssociateOp associate = hlfir::genAssociateExpr (
1673-                 loc, builder, actual, storageType, " adapt.impure_arg_eval" 
1674-             preparedActual->setOriginalActual (hlfir::Entity{associate});
1675- 
1665+           if  (hlfir::AssociateOp associate =
1666+                   preparedActual->associateIfArrayExpr (loc, builder)) {
16761667            fir::FirOpBuilder *bldr = &builder;
16771668            callContext.stmtCtx .attachCleanup (
16781669                [=]() { bldr->create <hlfir::EndAssociateOp>(loc, associate); });
@@ -1852,9 +1843,8 @@ class ElementalIntrinsicCallBuilder
18521843    if  (intrinsic)
18531844      if  (intrinsic->name  == " adjustr" name  == " adjustl" 
18541845          intrinsic->name  == " merge" 
1855-         return  hlfir::genCharLength (
1856-             callContext.loc , callContext.getBuilder (),
1857-             loweredActuals[0 ].value ().getOriginalActual ());
1846+         return  loweredActuals[0 ].value ().genCharLength (
1847+             callContext.loc , callContext.getBuilder ());
18581848    //  Character MIN/MAX is the min/max of the arguments length that are
18591849    //  present.
18601850    TODO (callContext.loc ,
@@ -1874,7 +1864,7 @@ class ElementalIntrinsicCallBuilder
18741864      //  the same declared and dynamic types. So any of them can be used
18751865      //  for the mold.
18761866      assert (!loweredActuals.empty ());
1877-       return  loweredActuals.front ()->getOriginalActual ( );
1867+       return  loweredActuals.front ()->getPolymorphicMold (callContext. loc );
18781868    }
18791869
18801870    return  {};
@@ -2137,7 +2127,7 @@ genProcedureRef(CallContext &callContext) {
21372127  Fortran::lower::CallerInterface caller (callContext.procRef ,
21382128                                         callContext.converter );
21392129  mlir::FunctionType callSiteType = caller.genFunctionType ();
2140- 
2130+    const   bool  isElemental = callContext. isElementalProcWithArrayArgs (); 
21412131  Fortran::lower::PreparedActualArguments loweredActuals;
21422132  //  Lower the actual arguments
21432133  for  (const  Fortran::lower::CallInterface<
@@ -2162,6 +2152,21 @@ genProcedureRef(CallContext &callContext) {
21622152        }
21632153      }
21642154
2155+       if  (isElemental && !arg.hasValueAttribute () &&
2156+           Fortran::evaluate::IsVariable (*expr) &&
2157+           Fortran::evaluate::HasVectorSubscript (*expr)) {
2158+         //  Vector subscripted arguments are copied in calls, except in elemental
2159+         //  calls without VALUE attribute where Fortran 2018 15.5.2.4 point 21
2160+         //  does not apply and the address of each element must be passed.
2161+         hlfir::ElementalAddrOp elementalAddr =
2162+             Fortran::lower::convertVectorSubscriptedExprToElementalAddr (
2163+                 loc, callContext.converter , *expr, callContext.symMap ,
2164+                 callContext.stmtCtx );
2165+         loweredActuals.emplace_back (
2166+             Fortran::lower::PreparedActualArgument{elementalAddr});
2167+         continue ;
2168+       }
2169+ 
21652170      auto  loweredActual = Fortran::lower::convertExprToHLFIR (
21662171          loc, callContext.converter , *expr, callContext.symMap ,
21672172          callContext.stmtCtx );
@@ -2178,7 +2183,7 @@ genProcedureRef(CallContext &callContext) {
21782183      //  Optional dummy argument for which there is no actual argument.
21792184      loweredActuals.emplace_back (std::nullopt );
21802185    }
2181-   if  (callContext. isElementalProcWithArrayArgs () ) {
2186+   if  (isElemental ) {
21822187    bool  isImpure = false ;
21832188    if  (const  Fortran::semantics::Symbol *procSym =
21842189            callContext.procRef .proc ().GetSymbol ())
@@ -2189,6 +2194,27 @@ genProcedureRef(CallContext &callContext) {
21892194  return  genUserCall (loweredActuals, caller, callSiteType, callContext);
21902195}
21912196
2197+ hlfir::Entity Fortran::lower::PreparedActualArgument::getActual (
2198+     mlir::Location loc, fir::FirOpBuilder &builder) const  {
2199+   if  (auto  *actualEntity = std::get_if<hlfir::Entity>(&actual)) {
2200+     if  (oneBasedElementalIndices)
2201+       return  hlfir::getElementAt (loc, builder, *actualEntity,
2202+                                  *oneBasedElementalIndices);
2203+     return  *actualEntity;
2204+   }
2205+   assert (oneBasedElementalIndices && " expect elemental context" 
2206+   hlfir::ElementalAddrOp elementalAddr =
2207+       std::get<hlfir::ElementalAddrOp>(actual);
2208+   mlir::IRMapping mapper;
2209+   auto  alwaysFalse = [](hlfir::ElementalOp) -> bool  { return  false ; };
2210+   mlir::Value addr = hlfir::inlineElementalOp (
2211+       loc, builder, elementalAddr, *oneBasedElementalIndices, mapper,
2212+       /* mustRecursivelyInline=*/ 
2213+   assert (elementalAddr.getCleanup ().empty () && " no clean-up expected" 
2214+   elementalAddr.erase ();
2215+   return  hlfir::Entity{addr};
2216+ }
2217+ 
21922218bool  Fortran::lower::isIntrinsicModuleProcRef (
21932219    const  Fortran::evaluate::ProcedureRef &procRef) {
21942220  const  Fortran::semantics::Symbol *symbol = procRef.proc ().GetSymbol ();
0 commit comments