From d3c0dd6e4d7783a45f66f544ed0934dc8adaa933 Mon Sep 17 00:00:00 2001 From: Peixin Qiao Date: Sat, 22 Oct 2022 09:15:02 +0800 Subject: [PATCH] [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 --- flang/lib/Lower/CallInterface.cpp | 10 ++++++++-- flang/test/Lower/array-elemental-calls-2.f90 | 12 +++--------- flang/test/Lower/array-elemental-calls.f90 | 6 +----- flang/test/Lower/array-elemental-subroutines.f90 | 4 +--- flang/test/Lower/array-expression.f90 | 4 +--- flang/test/Lower/call-by-value-attr.f90 | 16 +++++++++++++--- 6 files changed, 27 insertions(+), 25 deletions(-) diff --git a/flang/lib/Lower/CallInterface.cpp b/flang/lib/Lower/CallInterface.cpp index 71d7722..5dfe9499 100644 --- a/flang/lib/Lower/CallInterface.cpp +++ b/flang/lib/Lower/CallInterface.cpp @@ -921,12 +921,18 @@ private: : 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() && + !obj.attrs.test(Attrs::Optional) && + dynamicType.category() != + Fortran::common::TypeCategory::Derived)) { passBy = PassEntityBy::Value; prop = Property::Value; if (type.isa()) diff --git a/flang/test/Lower/array-elemental-calls-2.f90 b/flang/test/Lower/array-elemental-calls-2.f90 index 7ec7512..723c62f 100644 --- a/flang/test/Lower/array-elemental-calls-2.f90 +++ b/flang/test/Lower/array-elemental-calls-2.f90 @@ -131,37 +131,31 @@ end subroutine ! 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 -! CHECK: %[[VAL_28:.*]] = fir.call @_QPelem_func_real(%[[VAL_0]]) : (!fir.ref) -> 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> ! 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 -! CHECK: fir.call @_QPelem_func_real(%[[VAL_0]]) : (!fir.ref) -> 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 -! CHECK: fir.call @_QPelem_func_real(%[[VAL_0]]) : (!fir.ref) -> 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 1159416..8efb2bf 100644 --- a/flang/test/Lower/array-elemental-calls.f90 +++ b/flang/test/Lower/array-elemental-calls.f90 @@ -34,16 +34,12 @@ end ! CHECK-SAME: %[[arg0:.*]]: !fir.ref>{{.*}}, %[[arg1:.*]]: !fir.ref>{{.*}}) { 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 ! CHECK: fir.do_loop ! CHECK: %[[j:.*]] = fir.array_fetch %[[jload]], %{{.*}} : (!fir.array<100xi32>, index) -> i32 - ! CHECK: fir.store %[[j]] to %[[tmpA]] : !fir.ref - ! CHECK: fir.call @_QMscalar_in_elemPelem_by_valueref(%[[tmpA]], %[[tmpB]]) : (!fir.ref, !fir.ref) -> 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 652e614..4abf8fc 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>{{.*}}, %[[VAL_1:.*]]: !fir.box>>{{.*}}, %[[VAL_2:.*]]: !fir.ref{{.*}}, %[[VAL_3:.*]]: !fir.ref>{{.*}}) { -! 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>, 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> -! CHECK: fir.store %[[VAL_14]] to %[[VAL_4]] : !fir.ref> ! 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.slice<1>, index) -> !fir.ref> ! CHECK: %[[VAL_25:.*]] = fir.box_elesize %[[VAL_1]] : (!fir.box>>) -> index ! CHECK: %[[VAL_26:.*]] = fir.emboxchar %[[VAL_24]], %[[VAL_25]] : (!fir.ref>, index) -> !fir.boxchar<1> -! CHECK: fir.call @_QPfoo(%[[VAL_21]], %[[VAL_26]], %[[VAL_2]], %[[VAL_4]]) : (!fir.ref, !fir.boxchar<1>, !fir.ref, !fir.ref>) -> () +! CHECK: fir.call @_QPfoo(%[[VAL_21]], %[[VAL_26]], %[[VAL_2]], %[[VAL_14]]) : (!fir.ref, !fir.boxchar<1>, !fir.ref, !fir.complex<4>) -> () ! CHECK: } ! CHECK: return ! CHECK: } diff --git a/flang/test/Lower/array-expression.f90 b/flang/test/Lower/array-expression.f90 index 734187a..a251a7a 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>{{.*}}, %[[b:.*]]: !fir.ref>{{.*}}) subroutine test16(a,b) - ! CHECK: %[[tmp:.*]] = fir.alloca f32 {adapt.valuebyref ! CHECK-DAG: %[[aarr:.*]] = fir.array_load %[[a]](%{{.*}}) : (!fir.ref>, !fir.shape<1>) -> !fir.array<100xf32> ! CHECK-DAG: %[[barr:.*]] = fir.array_load %[[b]](%{{.*}}) : (!fir.ref>, !fir.shape<1>) -> !fir.array<100xf32> interface @@ -493,8 +492,7 @@ subroutine test16(a,b) 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 + ! 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 d354318..eaf39c1 100644 --- a/flang/test/Lower/call-by-value-attr.f90 +++ b/flang/test/Lower/call-by-value-attr.f90 @@ -16,7 +16,6 @@ program call_by_value_attr 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 @@ program call_by_value_attr !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 @@ program call_by_value_attr 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 +! CHECK: fir.call @_QPtest_numeric_scalar_value(%[[VAL_1]]) : (!fir.ref) -> () +! 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 -- 2.7.4