[flang-commits] [flang] 66ec326 - [flang] Fix lowering of optional char proc args

Leandro Lupori via flang-commits flang-commits at lists.llvm.org
Mon Mar 6 06:38:22 PST 2023


Author: Leandro Lupori
Date: 2023-03-06T11:33:43-03:00
New Revision: 66ec32633207885abc717b271cfb7730674d380e

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

LOG: [flang] Fix lowering of optional char proc args

Optional character function arguments were not being lowered
properly. As they are passed as a tuple, containing the (boxed)
function address and the character length, it is not possible for
fir.absent to handle it directly. Instead, a tuple needs to be
created and filled with an absent function address and a dummy
character length.

Fixes #60225

Reviewed By: jeanPerier

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

Added: 
    flang/test/Lower/HLFIR/dummy-argument-optional.f90

Modified: 
    flang/include/flang/Optimizer/Builder/FIRBuilder.h
    flang/lib/Lower/ConvertCall.cpp
    flang/lib/Lower/ConvertExpr.cpp
    flang/lib/Optimizer/Builder/FIRBuilder.cpp
    flang/test/Lower/dummy-argument-optional.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Optimizer/Builder/FIRBuilder.h b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
index 6882da731b652..085e91f0c6fa6 100644
--- a/flang/include/flang/Optimizer/Builder/FIRBuilder.h
+++ b/flang/include/flang/Optimizer/Builder/FIRBuilder.h
@@ -426,6 +426,10 @@ class FirOpBuilder : public mlir::OpBuilder, public mlir::OpBuilder::Listener {
                                    mlir::Value ub, mlir::Value step,
                                    mlir::Type type);
 
+  /// Create an AbsentOp of \p argTy type and handle special cases, such as
+  /// Character Procedure Tuple arguments.
+  mlir::Value genAbsentOp(mlir::Location loc, mlir::Type argTy);
+
   /// Set default FastMathFlags value for all operations
   /// supporting mlir::arith::FastMathAttr that will be created
   /// by this builder.

diff  --git a/flang/lib/Lower/ConvertCall.cpp b/flang/lib/Lower/ConvertCall.cpp
index e171059813bd8..6418d7dcb82c4 100644
--- a/flang/lib/Lower/ConvertCall.cpp
+++ b/flang/lib/Lower/ConvertCall.cpp
@@ -764,7 +764,7 @@ struct ConditionallyPreparedDummy {
       if (type == i1Type)
         elseResultValues.push_back(builder.createBool(loc, false));
       else
-        elseResultValues.push_back(builder.create<fir::AbsentOp>(loc, type));
+        elseResultValues.push_back(builder.genAbsentOp(loc, type));
     }
     builder.create<fir::ResultOp>(loc, elseResultValues);
   }
@@ -1047,7 +1047,7 @@ genUserCall(PreparedActualArguments &loweredActuals,
     mlir::Type argTy = callSiteType.getInput(arg.firArgument);
     if (!preparedActual) {
       // Optional dummy argument for which there is no actual argument.
-      caller.placeInput(arg, builder.create<fir::AbsentOp>(loc, argTy));
+      caller.placeInput(arg, builder.genAbsentOp(loc, argTy));
       continue;
     }
     const auto *expr = arg.entity->UnwrapExpr();

diff  --git a/flang/lib/Lower/ConvertExpr.cpp b/flang/lib/Lower/ConvertExpr.cpp
index 9d7476b76c7ae..0ed8d9112c758 100644
--- a/flang/lib/Lower/ConvertExpr.cpp
+++ b/flang/lib/Lower/ConvertExpr.cpp
@@ -2455,7 +2455,7 @@ class ScalarExprLowering {
       mlir::Type argTy = callSiteType.getInput(arg.firArgument);
       if (!actual) {
         // Optional dummy argument for which there is no actual argument.
-        caller.placeInput(arg, builder.create<fir::AbsentOp>(loc, argTy));
+        caller.placeInput(arg, builder.genAbsentOp(loc, argTy));
         continue;
       }
       const auto *expr = actual->UnwrapExpr();

diff  --git a/flang/lib/Optimizer/Builder/FIRBuilder.cpp b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
index 21f36a7e152cd..9367afa3fb36c 100644
--- a/flang/lib/Optimizer/Builder/FIRBuilder.cpp
+++ b/flang/lib/Optimizer/Builder/FIRBuilder.cpp
@@ -614,6 +614,18 @@ mlir::Value fir::FirOpBuilder::genExtentFromTriplet(mlir::Location loc,
   return create<mlir::arith::SelectOp>(loc, cmp, div, zero);
 }
 
+mlir::Value fir::FirOpBuilder::genAbsentOp(mlir::Location loc,
+                                           mlir::Type argTy) {
+  if (!fir::isCharacterProcedureTuple(argTy))
+    return create<fir::AbsentOp>(loc, argTy);
+
+  auto boxProc =
+      create<fir::AbsentOp>(loc, argTy.cast<mlir::TupleType>().getType(0));
+  mlir::Value charLen = create<fir::UndefOp>(loc, getCharacterLengthType());
+  return fir::factory::createCharacterProcedureTuple(*this, loc, argTy, boxProc,
+                                                     charLen);
+}
+
 void fir::FirOpBuilder::setCommonAttributes(mlir::Operation *op) const {
   auto fmi = mlir::dyn_cast<mlir::arith::ArithFastMathInterface>(*op);
   if (!fmi)

diff  --git a/flang/test/Lower/HLFIR/dummy-argument-optional.f90 b/flang/test/Lower/HLFIR/dummy-argument-optional.f90
new file mode 100644
index 0000000000000..32ab0e0f6a117
--- /dev/null
+++ b/flang/test/Lower/HLFIR/dummy-argument-optional.f90
@@ -0,0 +1,60 @@
+! RUN: bbc -emit-fir -hlfir -o - %s | FileCheck %s
+
+! Test OPTIONAL lowering on caller/callee
+module opt
+  implicit none
+contains
+
+! Test optional character function
+! CHECK-LABEL: func @_QMoptPchar_proc(
+! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.char<1,3>>,
+character(len=3) function char_proc(i)
+  integer :: i
+  char_proc = "XYZ"
+end function
+! CHECK-LABEL: func @_QMoptPuse_char_proc(
+! CHECK-SAME: %[[arg0:.*]]: tuple<!fir.boxproc<() -> ()>, i64> {fir.char_proc},
+subroutine use_char_proc(f, c)
+  optional :: f
+  interface
+    character(len=3) function f(i)
+      integer :: i
+    end function
+  end interface
+  character(len=3) :: c
+! CHECK: %[[boxProc:.*]] = fir.extract_value %[[arg0]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>) -> !fir.boxproc<() -> ()>
+! CHECK: %[[boxAddr:.*]] = fir.box_addr %[[boxProc]] : (!fir.boxproc<() -> ()>) -> (() -> ())
+! CHECK: %[[boxProc2:.*]] = fir.emboxproc %[[boxAddr]] : (() -> ()) -> !fir.boxproc<() -> ()>
+! CHECK: %[[tuple:.*]] = fir.undefined tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple2:.*]] = fir.insert_value %[[tuple]], %[[boxProc2]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxproc<() -> ()>) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple3:.*]] = fir.insert_value %[[tuple2]], %{{.*}}, [1 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, i64) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[boxProc3:.*]] = fir.extract_value %[[tuple3]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>) -> !fir.boxproc<() -> ()>
+! CHECK: %{{.*}} = fir.is_present %[[boxProc3]] : (!fir.boxproc<() -> ()>) -> i1
+  if (present(f)) then
+    c = f(0)
+  else
+    c = "ABC"
+  end if
+end subroutine
+! CHECK-LABEL: func @_QMoptPcall_use_char_proc(
+subroutine call_use_char_proc()
+  character(len=3) :: c
+! CHECK: %[[boxProc:.*]] = fir.absent !fir.boxproc<() -> ()>
+! CHECK: %[[undef:.*]] = fir.undefined index
+! CHECK: %[[charLen:.*]] = fir.convert %[[undef]] : (index) -> i64
+! CHECK: %[[tuple:.*]] = fir.undefined tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple2:.*]] = fir.insert_value %[[tuple]], %[[boxProc]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxproc<() -> ()>) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple3:.*]] = fir.insert_value %[[tuple2]], %[[charLen]], [1 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, i64) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: fir.call @_QMoptPuse_char_proc(%[[tuple3]], %{{.*}}){{.*}} : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxchar<1>) -> ()
+  call use_char_proc(c=c)
+! CHECK: %[[funcAddr:.*]] = fir.address_of(@_QMoptPchar_proc) : (!fir.ref<!fir.char<1,3>>, index, {{.*}}) -> !fir.boxchar<1>
+! CHECK: %[[c3:.*]] = arith.constant 3 : i64
+! CHECK: %[[boxProc2:.*]] = fir.emboxproc %[[funcAddr]] : ((!fir.ref<!fir.char<1,3>>, index, {{.*}}) -> !fir.boxchar<1>) -> !fir.boxproc<() -> ()>
+! CHECK: %[[tuple4:.*]] = fir.undefined tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple5:.*]] = fir.insert_value %[[tuple4]], %[[boxProc2]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxproc<() -> ()>) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple6:.*]] = fir.insert_value %[[tuple5]], %[[c3]], [1 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, i64) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: fir.call @_QMoptPuse_char_proc(%[[tuple6]], {{.*}}){{.*}} : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxchar<1>) -> ()
+  call use_char_proc(char_proc, c)
+end subroutine
+
+end module

diff  --git a/flang/test/Lower/dummy-argument-optional.f90 b/flang/test/Lower/dummy-argument-optional.f90
index 624ed709a7185..e7dafbaea09c9 100644
--- a/flang/test/Lower/dummy-argument-optional.f90
+++ b/flang/test/Lower/dummy-argument-optional.f90
@@ -1,4 +1,5 @@
 ! RUN: bbc -emit-fir %s -o - | FileCheck %s
+! RUN: flang-new -fc1 -fdefault-integer-8 -emit-fir %s -o - | FileCheck %s
 
 ! Test OPTIONAL lowering on caller/callee and PRESENT intrinsic.
 module opt
@@ -68,6 +69,53 @@ subroutine call_character_scalar()
   call character_scalar()
 end subroutine
 
+! Test optional character function
+! CHECK-LABEL: func @_QMoptPchar_proc(
+! CHECK-SAME: %[[arg0:.*]]: !fir.ref<!fir.char<1,3>>,
+character(len=3) function char_proc(i)
+  integer :: i
+  char_proc = "XYZ"
+end function
+! CHECK-LABEL: func @_QMoptPuse_char_proc(
+! CHECK-SAME: %[[arg0:.*]]: tuple<!fir.boxproc<() -> ()>, i64> {fir.char_proc},
+subroutine use_char_proc(f, c)
+  optional :: f
+  interface
+    character(len=3) function f(i)
+      integer :: i
+    end function
+  end interface
+  character(len=3) :: c
+! CHECK: %[[boxProc:.*]] = fir.extract_value %[[arg0]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>) -> !fir.boxproc<() -> ()>
+! CHECK: %[[procAddr:.*]] = fir.box_addr %[[boxProc]] : (!fir.boxproc<() -> ()>) -> (() -> ())
+! CHECK: %{{.*}} = fir.is_present %[[procAddr]] : (() -> ()) -> i1
+  if (present(f)) then
+    c = f(0)
+  else
+    c = "ABC"
+  end if
+end subroutine
+! CHECK-LABEL: func @_QMoptPcall_use_char_proc(
+subroutine call_use_char_proc()
+  character(len=3) :: c
+! CHECK: %[[boxProc:.*]] = fir.absent !fir.boxproc<() -> ()>
+! CHECK: %[[undef:.*]] = fir.undefined index
+! CHECK: %[[charLen:.*]] = fir.convert %[[undef]] : (index) -> i64
+! CHECK: %[[tuple:.*]] = fir.undefined tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple2:.*]] = fir.insert_value %[[tuple]], %[[boxProc]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxproc<() -> ()>) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple3:.*]] = fir.insert_value %[[tuple2]], %[[charLen]], [1 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, i64) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: fir.call @_QMoptPuse_char_proc(%[[tuple3]], %{{.*}}){{.*}} : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxchar<1>) -> ()
+  call use_char_proc(c=c)
+! CHECK: %[[funcAddr:.*]] = fir.address_of(@_QMoptPchar_proc) : (!fir.ref<!fir.char<1,3>>, index, {{.*}}) -> !fir.boxchar<1>
+! CHECK: %[[c3:.*]] = arith.constant 3 : i64
+! CHECK: %[[boxProc2:.*]] = fir.emboxproc %[[funcAddr]] : ((!fir.ref<!fir.char<1,3>>, index, {{.*}}) -> !fir.boxchar<1>) -> !fir.boxproc<() -> ()>
+! CHECK: %[[tuple4:.*]] = fir.undefined tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple5:.*]] = fir.insert_value %[[tuple4]], %[[boxProc2]], [0 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxproc<() -> ()>) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: %[[tuple6:.*]] = fir.insert_value %[[tuple5]], %[[c3]], [1 : index] : (tuple<!fir.boxproc<() -> ()>, i64>, i64) -> tuple<!fir.boxproc<() -> ()>, i64>
+! CHECK: fir.call @_QMoptPuse_char_proc(%[[tuple6]], {{.*}}){{.*}} : (tuple<!fir.boxproc<() -> ()>, i64>, !fir.boxchar<1>) -> ()
+  call use_char_proc(char_proc, c)
+end subroutine
+
 ! Test optional assumed shape
 ! CHECK-LABEL: func @_QMoptPassumed_shape(
 ! CHECK-SAME: %[[arg0:.*]]: !fir.box<!fir.array<?xf32>> {fir.bindc_name = "x", fir.optional}) {


        


More information about the flang-commits mailing list