[flang-commits] [flang] d3c0dd6 - [flang] Fix the interface for numerical/logical scalar with VALUE attribute

Peixin Qiao via flang-commits flang-commits at lists.llvm.org
Fri Oct 21 18:15:57 PDT 2022


Author: Peixin Qiao
Date: 2022-10-22T09:15:02+08:00
New Revision: d3c0dd6e4d7783a45f66f544ed0934dc8adaa933

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

LOG: [flang] Fix the interface for numerical/logical scalar with VALUE attribute

Programmers may use procedure without BIND(C) attribute to interoperate
with C code. For numerical/logical scalar with VALUE attribute, pass the
argument by value so that the behavior is consistent with gfortran or
nvfortran. The argument with the OPTIONAL attribute cannot be passed by
value since the actual argument may be absent.

For the derived type, pass-by-value is not supported yet, so pass the
argument by reference for now.

Reviewed By: jeanPerier

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

Added: 
    

Modified: 
    flang/lib/Lower/CallInterface.cpp
    flang/test/Lower/array-elemental-calls-2.f90
    flang/test/Lower/array-elemental-calls.f90
    flang/test/Lower/array-elemental-subroutines.f90
    flang/test/Lower/array-expression.f90
    flang/test/Lower/call-by-value-attr.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp
index 71d772282172c..5dfe949939ad9 100644
--- a/flang/lib/Lower/CallInterface.cpp
+++ b/flang/lib/Lower/CallInterface.cpp
@@ -921,12 +921,18 @@ class Fortran::lower::CallInterfaceImpl {
                                : PassEntityBy::BoxChar,
                    entity, characteristics);
     } else {
-      // Pass as fir.ref unless it's by VALUE and BIND(C)
+      // Pass as fir.ref unless it's by VALUE and BIND(C). Also pass-by-value
+      // for numerical/logical scalar without OPTIONAL so that the behavior is
+      // consistent with gfortran/nvfortran.
+      // TODO: pass-by-value for derived type is not supported yet
       mlir::Type passType = fir::ReferenceType::get(type);
       PassEntityBy passBy = PassEntityBy::BaseAddress;
       Property prop = Property::BaseAddress;
       if (isValueAttr) {
-        if (isBindC) {
+        if (isBindC || (!type.isa<fir::SequenceType>() &&
+                        !obj.attrs.test(Attrs::Optional) &&
+                        dynamicType.category() !=
+                            Fortran::common::TypeCategory::Derived)) {
           passBy = PassEntityBy::Value;
           prop = Property::Value;
           if (type.isa<fir::SequenceType>())

diff  --git a/flang/test/Lower/array-elemental-calls-2.f90 b/flang/test/Lower/array-elemental-calls-2.f90
index 7ec7512e7efc8..723c62f4e43c4 100644
--- a/flang/test/Lower/array-elemental-calls-2.f90
+++ b/flang/test/Lower/array-elemental-calls-2.f90
@@ -131,37 +131,31 @@ subroutine check_compare()
 ! CHECK-LABEL: func @_QMtest_opsPcheck_pow() {
 subroutine check_pow()
   print *,  elem_func_real(x**y)
-! CHECK:  %[[VAL_0:.*]] = fir.alloca f64
 ! CHECK:  fir.do_loop
 ! CHECK:  %[[VAL_25:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xf64>, index) -> f64
 ! CHECK:  %[[VAL_26:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xf64>, index) -> f64
 ! CHECK:  %[[VAL_27:.*]] = math.powf %[[VAL_25]], %[[VAL_26]] : f64
-! CHECK:  fir.store %[[VAL_27]] to %[[VAL_0]] : !fir.ref<f64>
-! CHECK:  %[[VAL_28:.*]] = fir.call @_QPelem_func_real(%[[VAL_0]]) : (!fir.ref<f64>) -> i32
+! CHECK:  %[[VAL_28:.*]] = fir.call @_QPelem_func_real(%[[VAL_27]]) : (f64) -> i32
 end subroutine
 
 ! CHECK-LABEL: func @_QMtest_opsPcheck_cmplx_part() {
 subroutine check_cmplx_part()
   print *,  elem_func_real(AIMAG(z1 + z2))
-! CHECK:  %[[VAL_0:.*]] = fir.alloca f64
 ! CHECK:  %[[VAL_13:.*]] = fir.load %{{.*}} : !fir.ref<!fir.complex<8>>
 ! CHECK:  fir.do_loop
 ! CHECK:  %[[VAL_23:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10x!fir.complex<8>>, index) -> !fir.complex<8>
 ! CHECK:  %[[VAL_24:.*]] = fir.addc %[[VAL_23]], %[[VAL_13]] : !fir.complex<8>
 ! CHECK:  %[[VAL_25:.*]] = fir.extract_value %[[VAL_24]], [1 : index] : (!fir.complex<8>) -> f64
-! CHECK:  fir.store %[[VAL_25]] to %[[VAL_0]] : !fir.ref<f64>
-! CHECK:  fir.call @_QPelem_func_real(%[[VAL_0]]) : (!fir.ref<f64>) -> i32
+! CHECK:  fir.call @_QPelem_func_real(%[[VAL_25]]) : (f64) -> i32
 end subroutine
 
 ! CHECK-LABEL: func @_QMtest_opsPcheck_parentheses() {
 subroutine check_parentheses()
   print *,  elem_func_real((x))
-! CHECK:  %[[VAL_0:.*]] = fir.alloca f64
 ! CHECK:  fir.do_loop
 ! CHECK:  %[[VAL_21:.*]] = fir.array_fetch %{{.*}}, %{{.*}} : (!fir.array<10xf64>, index) -> f64
 ! CHECK:  %[[VAL_22:.*]] = fir.no_reassoc %[[VAL_21]] : f64
-! CHECK:  fir.store %[[VAL_22]] to %[[VAL_0]] : !fir.ref<f64>
-! CHECK:  fir.call @_QPelem_func_real(%[[VAL_0]]) : (!fir.ref<f64>) -> i32
+! CHECK:  fir.call @_QPelem_func_real(%[[VAL_22]]) : (f64) -> i32
 end subroutine
 
 ! CHECK-LABEL: func @_QMtest_opsPcheck_parentheses_logical() {

diff  --git a/flang/test/Lower/array-elemental-calls.f90 b/flang/test/Lower/array-elemental-calls.f90
index 115941681d6d0..8efb2bf5327a5 100644
--- a/flang/test/Lower/array-elemental-calls.f90
+++ b/flang/test/Lower/array-elemental-calls.f90
@@ -34,16 +34,12 @@ subroutine test_elem_by_ref(i, j)
 ! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.array<100xi32>>{{.*}}, %[[arg1:.*]]: !fir.ref<!fir.array<100xi32>>{{.*}}) {
 subroutine test_elem_by_valueref(i, j)
   integer :: i(100), j(100)
-  ! CHECK-DAG: %[[tmpA:.*]] = fir.alloca i32 {adapt.valuebyref}
-  ! CHECK-DAG: %[[tmpB:.*]] = fir.alloca f32 {adapt.valuebyref}
   ! CHECK: %[[jload:.*]] = fir.array_load %[[arg1]]
   ! CHECK: %[[cst:.*]] = arith.constant 4.200000e+01 : f32
-  ! CHECK: fir.store %[[cst]] to %[[tmpB]] : !fir.ref<f32>
 
   ! CHECK: fir.do_loop
     ! CHECK: %[[j:.*]] = fir.array_fetch %[[jload]], %{{.*}} : (!fir.array<100xi32>, index) -> i32
-    ! CHECK: fir.store %[[j]] to %[[tmpA]] : !fir.ref<i32>
-    ! CHECK: fir.call @_QMscalar_in_elemPelem_by_valueref(%[[tmpA]], %[[tmpB]]) : (!fir.ref<i32>, !fir.ref<f32>) -> i32
+    ! CHECK: fir.call @_QMscalar_in_elemPelem_by_valueref(%[[j]], %[[cst]]) : (i32, f32) -> i32
     ! CHECK: fir.result
   i = elem_by_valueref(j, 42.)
 end

diff  --git a/flang/test/Lower/array-elemental-subroutines.f90 b/flang/test/Lower/array-elemental-subroutines.f90
index 652e614fa9fab..4abf8fccd909c 100644
--- a/flang/test/Lower/array-elemental-subroutines.f90
+++ b/flang/test/Lower/array-elemental-subroutines.f90
@@ -3,7 +3,6 @@
 
 ! CHECK-LABEL: func @_QPtest_elem_sub(
 ! CHECK-SAME:    %[[VAL_0:.*]]: !fir.box<!fir.array<?xf32>>{{.*}}, %[[VAL_1:.*]]: !fir.box<!fir.array<?x!fir.char<1,?>>>{{.*}}, %[[VAL_2:.*]]: !fir.ref<i32>{{.*}}, %[[VAL_3:.*]]: !fir.ref<!fir.complex<4>>{{.*}}) {
-! CHECK:         %[[VAL_4:.*]] = fir.alloca !fir.complex<4> {adapt.valuebyref}
 ! CHECK:         %[[VAL_5:.*]] = arith.constant 0 : index
 ! CHECK:         %[[VAL_6:.*]]:3 = fir.box_dims %[[VAL_0]], %[[VAL_5]] : (!fir.box<!fir.array<?xf32>>, index) -> (index, index, index)
 ! CHECK:         %[[VAL_7:.*]] = arith.constant 10 : i64
@@ -14,7 +13,6 @@
 ! CHECK:         %[[VAL_12:.*]] = fir.convert %[[VAL_11]] : (i64) -> index
 ! CHECK:         %[[VAL_13:.*]] = fir.slice %[[VAL_8]], %[[VAL_12]], %[[VAL_10]] : (index, index, index) -> !fir.slice<1>
 ! CHECK:         %[[VAL_14:.*]] = fir.load %[[VAL_3]] : !fir.ref<!fir.complex<4>>
-! CHECK:         fir.store %[[VAL_14]] to %[[VAL_4]] : !fir.ref<!fir.complex<4>>
 ! CHECK:         %[[VAL_15:.*]] = arith.constant 1 : index
 ! CHECK:         %[[VAL_16:.*]] = arith.constant 0 : index
 ! CHECK:         %[[VAL_17:.*]] = arith.subi %[[VAL_6]]#1, %[[VAL_15]] : index
@@ -27,7 +25,7 @@
 ! CHECK:           %[[VAL_24:.*]] = fir.array_coor %[[VAL_1]] {{\[}}%[[VAL_13]]] %[[VAL_23]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>, !fir.slice<1>, index) -> !fir.ref<!fir.char<1,?>>
 ! CHECK:           %[[VAL_25:.*]] = fir.box_elesize %[[VAL_1]] : (!fir.box<!fir.array<?x!fir.char<1,?>>>) -> index
 ! CHECK:           %[[VAL_26:.*]] = fir.emboxchar %[[VAL_24]], %[[VAL_25]] : (!fir.ref<!fir.char<1,?>>, index) -> !fir.boxchar<1>
-! CHECK:           fir.call @_QPfoo(%[[VAL_21]], %[[VAL_26]], %[[VAL_2]], %[[VAL_4]]) : (!fir.ref<f32>, !fir.boxchar<1>, !fir.ref<i32>, !fir.ref<!fir.complex<4>>) -> ()
+! CHECK:           fir.call @_QPfoo(%[[VAL_21]], %[[VAL_26]], %[[VAL_2]], %[[VAL_14]]) : (!fir.ref<f32>, !fir.boxchar<1>, !fir.ref<i32>, !fir.complex<4>) -> ()
 ! CHECK:         }
 ! CHECK:         return
 ! CHECK:       }

diff  --git a/flang/test/Lower/array-expression.f90 b/flang/test/Lower/array-expression.f90
index 734187a88e03d..a251a7a60937e 100644
--- a/flang/test/Lower/array-expression.f90
+++ b/flang/test/Lower/array-expression.f90
@@ -482,7 +482,6 @@ end subroutine test15
 ! CHECK-LABEL: func @_QPtest16(
 ! CHECK-SAME: %[[a:.*]]: !fir.ref<!fir.array<100xf32>>{{.*}}, %[[b:.*]]: !fir.ref<!fir.array<100xf32>>{{.*}})
 subroutine test16(a,b)
-  ! CHECK: %[[tmp:.*]] = fir.alloca f32 {adapt.valuebyref
   ! CHECK-DAG: %[[aarr:.*]] = fir.array_load %[[a]](%{{.*}}) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
   ! CHECK-DAG: %[[barr:.*]] = fir.array_load %[[b]](%{{.*}}) : (!fir.ref<!fir.array<100xf32>>, !fir.shape<1>) -> !fir.array<100xf32>
   interface
@@ -493,8 +492,7 @@ end function f2
   real :: a(100), b(100)
   ! CHECK: %[[loop:.*]] = fir.do_loop %[[i:.*]] = %{{.*}} to %{{.*}} step %{{.*}} iter_args(%[[bth:.*]] = %[[barr]]) -> (!fir.array<100xf32>) {
   ! CHECK: %[[val:.*]] = fir.array_fetch %[[aarr]], %[[i]] : (!fir.array<100xf32>, index) -> f32
-  ! CHECK: fir.store %[[val]] to %[[tmp]]
-  ! CHECK: %[[fres:.*]] = fir.call @_QPf2(%[[tmp]]) : (!fir.ref<f32>) -> f32
+  ! CHECK: %[[fres:.*]] = fir.call @_QPf2(%[[val]]) : (f32) -> f32
   ! CHECK: %[[res:.*]] = fir.array_update %[[bth]], %[[fres]], %[[i]] : (!fir.array<100xf32>, f32, index) -> !fir.array<100xf32>
   ! CHECK: fir.result %[[res]] : !fir.array<100xf32>
   ! CHECK: fir.array_merge_store %[[barr]], %[[loop]] to %[[b]]

diff  --git a/flang/test/Lower/call-by-value-attr.f90 b/flang/test/Lower/call-by-value-attr.f90
index d354318b87f82..eaf39c18121c6 100644
--- a/flang/test/Lower/call-by-value-attr.f90
+++ b/flang/test/Lower/call-by-value-attr.f90
@@ -16,7 +16,6 @@ end subroutine subra
   integer, dimension(15) :: b
   v = 17
   call subri(v)
-  !CHECK: %[[COPY:.*]] = fir.alloca i32
   !CHECK: %[[ARRAY_A:.*]] = fir.address_of(@_QFEa)
   !CHECK: %[[CONST_10_1:.*]] = arith.constant 10 : index
   !CHECK: %[[ARRAY_B:.*]] = fir.address_of(@_QFEb)
@@ -25,8 +24,7 @@ end subroutine subra
   !CHECK: %[[CONST:.*]] = arith.constant 17
   !CHECK: fir.store %[[CONST]] to %[[VALUE]]
   !CHECK: %[[LOAD:.*]] = fir.load %[[VALUE]]
-  !CHECK: fir.store %[[LOAD]] to %[[COPY]]
-  !CHECK: fir.call @_QPsubri(%[[COPY]]) : {{.*}}
+  !CHECK: fir.call @_QPsubri(%[[LOAD]]) : {{.*}}
   a = (/ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 /)
   !CHECK: %[[SHAPE_1:.*]] = fir.shape %[[CONST_10_1]]
   !CHECK: %[[ARRAY_LOAD_1:.*]] = fir.array_load %[[ARRAY_A]](%[[SHAPE_1]]) : {{.*}}
@@ -87,6 +85,18 @@ end subroutine subra
   call subra(b(5:15))
 end program call_by_value_attr
 
+! CHECK-LABEL: func.func @_QPsubri(
+! CHECK-SAME:                      %[[VAL_0:.*]]: i32 {fir.bindc_name = "val"}) {
+! CHECK:         %[[VAL_1:.*]] = fir.alloca i32
+! CHECK:         fir.store %[[VAL_0]] to %[[VAL_1]] : !fir.ref<i32>
+! CHECK:         fir.call @_QPtest_numeric_scalar_value(%[[VAL_1]]) : (!fir.ref<i32>) -> ()
+! CHECK:         return
+! CHECK:       }
+
+subroutine subri(val)
+  integer, value :: val
+  call test_numeric_scalar_value(val)
+end subroutine subri
 
 ! CHECK-LABEL: func @_QPtest_litteral_copies_1
 subroutine test_litteral_copies_1


        


More information about the flang-commits mailing list