This is an archive of the discontinued LLVM Phabricator instance.

[flang] Improve constant folding for type parameter inquiries
ClosedPublic

Authored by PeteSteinfeld on Apr 5 2021, 11:14 AM.

Details

Summary

We were not folding type parameter inquiries for the form 'var%typeParam'
where 'typeParam' was a KIND or LEN type parameter of a derived type and 'var'
was a designator of the derived type. I fixed this by adding code to the
function 'FoldOperation()' for 'TypeParamInquiry's to handle this case. I also
cleaned up the code for the case where there is no designator.

In order to make the error messages correctly refer to both the points of
declaration and instantiation, I needed to add an argument to the function
'InstantiateIntrinsicType()' for the location of the instantiation.

I also changed the formatting of 'TypeParamInquiry' to correctly format this
case. I also added tests for both KIND and LEN type parameter inquiries in
resolve104.f90.

Making these changes revealed an error in resolve89.f90 and caused one of the
error messages in assign04.f90 to be different.

Diff Detail

Event Timeline

PeteSteinfeld requested review of this revision.Apr 5 2021, 11:14 AM
PeteSteinfeld created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptApr 5 2021, 11:14 AM
PeteSteinfeld added a project: Restricted Project.Apr 5 2021, 11:15 AM
klausler added inline comments.Apr 5 2021, 11:38 AM
flang/lib/Evaluate/fold-integer.cpp
664

LEN type parameter inquiries are not safe to fold in all cases; the actual LEN parameter expression may not be constant. Consider

subroutine foo(n)
  type :: t(len)
  integer, len :: len
  end type t
  type(t(n)) :: x
  n = n + 1
  print *, x%len
end

The value of x%len at its point of use needs to return the original value of the dummy argument, not its later updated value.

In general, folding type parameter inquiries can be done only for KIND= parameters and for LEN= parameters whose expressions are constant expressions.

Yes, the value of the type parameter is derived from the associated object at the time that the object is instantiated. I believe that the current code is folding the value of the type parameter from the instantiated value. Here's a modified version of your example that illustrates that:

subroutine foo(n)
  type :: t(len)
  integer, len :: len
  end type t

  type(t(n)) :: x1
  real(x1%len) :: r1 ! Error since the KIND of r1 isn't constant
  type(t(4)) :: x2
  real(x2%len) :: r2

  block
    real(x2%len) :: r3 ! OK, the KIND of r3 is x2%len, which is folded to 4
  end block
  n = 99
  block
    real(x2%len) :: r4 ! Still OK, because the x2%len gets folded to 4
  end block
end

Yes, the value of the type parameter is derived from the associated object at the time that the object is instantiated. I believe that the current code is folding the value of the type parameter from the instantiated value. Here's a modified version of your example that illustrates that:

subroutine foo(n)
  type :: t(len)
  integer, len :: len
  end type t

  type(t(n)) :: x1
  real(x1%len) :: r1 ! Error since the KIND of r1 isn't constant
  type(t(4)) :: x2
  real(x2%len) :: r2

  block
    real(x2%len) :: r3 ! OK, the KIND of r3 is x2%len, which is folded to 4
  end block
  n = 99
  block
    real(x2%len) :: r4 ! Still OK, because the x2%len gets folded to 4
  end block
end

You're using non-constant expressions to define the LEN type parameter and then catching the error in the outer context, which requires a constant expression. But what about cases where a non-constant expression is used to define a LEN type parameter that is referenced in a context that does not require a constant expression? If the type parameter inquiry is replaced with the actual parameter expression, we'll produce bad results.

subroutine foo(n)
  type :: t(len)
    integer, len :: len
  end type
  type(t(n)) :: x
  print *, x%len
  n = n + 1
  print *, x%len   ! <--- must not be changed due to modification to 'n'
end subroutine
PeteSteinfeld added inline comments.Apr 5 2021, 3:09 PM
flang/lib/Evaluate/fold-integer.cpp
664

D'oh! I had intended for this new code to be specific to constant expressions, and I just realized that I didn't test for that. Stay tuned for an update.

Responding to Peter's comments to make these changes specific to constant
expressions.

klausler accepted this revision.Apr 5 2021, 3:23 PM
This revision is now accepted and ready to land.Apr 5 2021, 3:23 PM

We have a buildbot CI failure due to this patch.
https://lab.llvm.org/buildbot/#/builders/33/builds/3463

FAILED: lib/libFortranEvaluate.so.13git 
: && /usr/bin/clang++-10 -fPIC -stdlib=libc++ -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wstring-conversion -fdiagnostics-color -ffunction-sections -fdata-sections -Werror -Wno-deprecated-copy -Wno-string-conversion -Wno-unused-command-line-argument -Wstring-conversion           -Wcovered-switch-default -Wno-nested-anon-types -O3  -stdlib=libc++ -Wl,-z,defs -Wl,-z,nodelete   -Wl,-rpath-link,/home/flang/flang-aarch64-ubuntu-clang/flang-aarch64-ubuntu-clang/build/./lib  -Wl,-O3 -Wl,--gc-sections -shared -Wl,-soname,libFortranEvaluate.so.13git -o lib/libFortranEvaluate.so.13git tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/call.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/characteristics.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/check-expression.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/common.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/complex.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/constant.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/expression.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/fold.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/fold-character.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/fold-complex.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/fold-designator.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/fold-integer.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/fold-logical.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/fold-real.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/formatting.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/host.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/initial-image.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/integer.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/intrinsics.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/intrinsics-library.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/logical.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/real.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/shape.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/static-data.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/tools.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/type.cpp.o tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/variable.cpp.o  -Wl,-rpath,"\$ORIGIN/../lib"  lib/libFortranDecimal.so.13git  lib/libFortranParser.so.13git  lib/libFortranCommon.so.13git  lib/libLLVMSupport.so.13git  -Wl,-rpath-link,/home/flang/flang-aarch64-ubuntu-clang/flang-aarch64-ubuntu-clang/build/lib && :
/usr/bin/ld: tools/flang/lib/Evaluate/CMakeFiles/obj.FortranEvaluate.dir/fold-integer.cpp.o: in function `Fortran::evaluate::FoldOperation(Fortran::evaluate::FoldingContext&, Fortran::evaluate::TypeParamInquiry&&)':
fold-integer.cpp:(.text._ZN7Fortran8evaluate13FoldOperationERNS0_14FoldingContextEONS0_16TypeParamInquiryE+0xe8): undefined reference to `Fortran::semantics::DerivedTypeSpec::DerivedTypeSpec(Fortran::semantics::DerivedTypeSpec const&)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

@PeteSteinfeld I have reverted this patch since I could not find a quick fix.
https://reviews.llvm.org/rGb7ef804807855e607da3eba221c1fc59e27f778e

Thank you @kiranchandramohan ! @PeteSteinfeld , you can reproduce this by using -DBUILD_SHARED_LIBS=On (I was having a look anyway).

@PeteSteinfeld I have reverted this patch since I could not find a quick fix.
https://reviews.llvm.org/rGb7ef804807855e607da3eba221c1fc59e27f778e

Thank you @kiranchandramohan ! @PeteSteinfeld , you can reproduce this by using -DBUILD_SHARED_LIBS=On (I was having a look anyway).

Thank you, @awarzynski . I'll take a look ...

PeteSteinfeld reopened this revision.Apr 6 2021, 9:42 AM

I'll be submitting a fix for the problem with building shared libraries soon ...

This revision is now accepted and ready to land.Apr 6 2021, 9:42 AM

Fix building with shared libraries.

@awarzynski or @kiranchandramohan , can you please verify that this now builds with shared libraries?

@awarzynski or @kiranchandramohan , can you please verify that this now builds with shared libraries?

Tested with -DBUILD_SHARED_LIBS=On. Builds fine for me, thank you for fixing this!