[flang-commits] [flang] b5fa9af - [flang][hlfir] Evaluate actual args before impure elemental calls.

Slava Zakharin via flang-commits flang-commits at lists.llvm.org
Mon Jul 3 10:01:33 PDT 2023


Author: Slava Zakharin
Date: 2023-07-03T10:01:26-07:00
New Revision: b5fa9af4ae4955289693ce4076871cd0c92d5684

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

LOG: [flang][hlfir] Evaluate actual args before impure elemental calls.

Actual argument expressions must be evaluated before the invocation
of the sequence of per-element calls of an impure elemental subprogram.
Otherwise, the side effects of the calls may affect the input for
the consequent elements.
The proposed changes are described by Jean in D154174.

Reviewed By: tblah

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

Added: 
    

Modified: 
    flang/lib/Lower/ConvertCall.cpp
    flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index 626d9ef0f706e0..3ba7d3cfb6ea6e 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -1597,6 +1597,30 @@ class ElementalCallBuilder {
     }
     assert(shape &&
            "elemental array calls must have at least one array arguments");
+
+    // Evaluate the actual argument array expressions before the elemental
+    // call of an impure subprogram or a subprogram with intent(out) or
+    // intent(inout) arguments. Note that the scalar arguments are handled
+    // above.
+    if (mustBeOrdered) {
+      for (unsigned i = 0; i < numArgs; ++i) {
+        auto &preparedActual = loweredActuals[i];
+        if (preparedActual) {
+          hlfir::Entity actual = preparedActual->getOriginalActual();
+          if (!actual.isVariable() && actual.isArray()) {
+            mlir::Type storageType = actual.getType();
+            hlfir::AssociateOp associate = hlfir::genAssociateExpr(
+                loc, builder, actual, storageType, "adapt.impure_arg_eval");
+            preparedActual->setOriginalActual(hlfir::Entity{associate});
+
+            fir::FirOpBuilder *bldr = &builder;
+            callContext.stmtCtx.attachCleanup(
+                [=]() { bldr->create<hlfir::EndAssociateOp>(loc, associate); });
+          }
+        }
+      }
+    }
+
     // Push a new local scope so that any temps made inside the elemental
     // iterations are cleaned up inside the iterations.
     if (!callContext.resultType) {

diff  --git a/flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90 b/flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90
index 65a9aa37c700ff..d015ba3b0707e0 100644
--- a/flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90
+++ b/flang/test/Lower/HLFIR/elemental-user-procedure-ref.f90
@@ -146,3 +146,38 @@ elemental subroutine ordered_elem(a)
 ! CHECK:           }
 ! CHECK:           return
 ! CHECK:         }
+
+subroutine impure_elemental_arg_eval(x)
+  real :: x(10, 20)
+  interface
+    impure elemental subroutine impure_elem(a)
+      real, intent(in) :: a
+    end subroutine
+  end interface
+  call impure_elem((x))
+end subroutine
+! CHECK-LABEL:   func.func @_QPimpure_elemental_arg_eval(
+! CHECK-SAME:      %[[VAL_0:.*]]: !fir.ref<!fir.array<10x20xf32>> {fir.bindc_name = "x"}) {
+! CHECK:           %[[VAL_1:.*]] = arith.constant 10 : index
+! CHECK:           %[[VAL_2:.*]] = arith.constant 20 : index
+! CHECK:           %[[VAL_3:.*]] = fir.shape %[[VAL_1]], %[[VAL_2]] : (index, index) -> !fir.shape<2>
+! CHECK:           %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_0]](%[[VAL_3]]) {uniq_name = "_QFimpure_elemental_arg_evalEx"} : (!fir.ref<!fir.array<10x20xf32>>, !fir.shape<2>) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>)
+! CHECK:           %[[VAL_5:.*]] = hlfir.elemental %[[VAL_3]] unordered : (!fir.shape<2>) -> !hlfir.expr<10x20xf32> {
+! CHECK:           ^bb0(%[[VAL_6:.*]]: index, %[[VAL_7:.*]]: index):
+! CHECK:             %[[VAL_8:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_6]], %[[VAL_7]])  : (!fir.ref<!fir.array<10x20xf32>>, index, index) -> !fir.ref<f32>
+! CHECK:             %[[VAL_9:.*]] = fir.load %[[VAL_8]] : !fir.ref<f32>
+! CHECK:             %[[VAL_10:.*]] = hlfir.no_reassoc %[[VAL_9]] : f32
+! CHECK:             hlfir.yield_element %[[VAL_10]] : f32
+! CHECK:           }
+! CHECK:           %[[VAL_11:.*]]:3 = hlfir.associate %[[VAL_5]](%[[VAL_3]]) {uniq_name = "adapt.impure_arg_eval"} : (!hlfir.expr<10x20xf32>, !fir.shape<2>) -> (!fir.ref<!fir.array<10x20xf32>>, !fir.ref<!fir.array<10x20xf32>>, i1)
+! CHECK:           %[[VAL_13:.*]] = arith.constant 1 : index
+! CHECK:           fir.do_loop %[[VAL_14:.*]] = %[[VAL_13]] to %[[VAL_2]] step %[[VAL_13]] {
+! CHECK:             fir.do_loop %[[VAL_15:.*]] = %[[VAL_13]] to %[[VAL_1]] step %[[VAL_13]] {
+! CHECK:               %[[VAL_16:.*]] = hlfir.designate %[[VAL_11]]#0 (%[[VAL_15]], %[[VAL_14]])  : (!fir.ref<!fir.array<10x20xf32>>, index, index) -> !fir.ref<f32>
+! CHECK:               fir.call @_QPimpure_elem(%[[VAL_16]]) fastmath<contract> : (!fir.ref<f32>) -> ()
+! CHECK:             }
+! CHECK:           }
+! CHECK:           hlfir.end_associate %[[VAL_11]]#1, %[[VAL_11]]#2 : !fir.ref<!fir.array<10x20xf32>>, i1
+! CHECK:           hlfir.destroy %[[VAL_5]] : !hlfir.expr<10x20xf32>
+! CHECK:           return
+! CHECK:         }


        


More information about the flang-commits mailing list