Skip to content

Conversation

ceseo
Copy link
Contributor

@ceseo ceseo commented Oct 8, 2025

Change the behavior of min0/max0 when they are called with non-default integer kinds by preserving the argument kinds instead of converting to default integer.

Fixes #132646

Change the behavior of min0/max0 when they are called with
non-default integer kinds by preserving the argument kinds
instead of converting to default integer.

Fixes llvm#132646
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:semantics labels Oct 8, 2025
@ceseo
Copy link
Contributor Author

ceseo commented Oct 8, 2025

For discussion: should we mimic the behavior of gfortran?

@llvmbot
Copy link
Member

llvmbot commented Oct 8, 2025

@llvm/pr-subscribers-flang-semantics

Author: Carlos Seo (ceseo)

Changes

Change the behavior of min0/max0 when they are called with non-default integer kinds by preserving the argument kinds instead of converting to default integer.

Fixes #132646


Full diff: https://github.com/llvm/llvm-project/pull/162551.diff

3 Files Affected:

  • (modified) flang/docs/Extensions.md (+3)
  • (modified) flang/lib/Evaluate/intrinsics.cpp (+6)
  • (modified) flang/test/Evaluate/folding04.f90 (+7-6)
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 420b7517922b7..3fef0ab742287 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -287,6 +287,9 @@ end
 * Specific intrinsics AMAX0, AMAX1, AMIN0, AMIN1, DMAX1, DMIN1, MAX0, MAX1,
   MIN0, and MIN1 accept more argument types than specified. They are replaced by
   the related generics followed by conversions to the specified result types.
+  For MAX0 and MIN0, the result type matches the argument types rather than
+  being converted to default INTEGER, preserving the kind of the arguments.
+  For example, `MAX0(1_8, 2_8)` returns `INTEGER(8)`, not `INTEGER(4)`.
 * When a scalar CHARACTER actual argument of the same kind is known to
   have a length shorter than the associated dummy argument, it is extended
   on the right with blanks, similar to assignment.
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index fe679da4ff98b..46375ed0e08f6 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -3654,6 +3654,12 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
                             .GetTypeAndShape())
                       .type()};
               DynamicType newType{GetReturnType(*specIter->second, defaults_)};
+              // For MAX0/MIN0, preserve the generic type rather than forcing
+              // to default integer. This allows, for example, MAX0(1_8,2_8) to
+              // return INTEGER(8) instead of INTEGER(4).
+              if (genericType.category() == newType.category()) {
+                newType = genericType;
+              }
               if (genericType.category() == newType.category() ||
                   ((genericType.category() == TypeCategory::Integer ||
                        genericType.category() == TypeCategory::Real) &&
diff --git a/flang/test/Evaluate/folding04.f90 b/flang/test/Evaluate/folding04.f90
index 027db20f608b2..390197eb9cfdd 100644
--- a/flang/test/Evaluate/folding04.f90
+++ b/flang/test/Evaluate/folding04.f90
@@ -79,15 +79,16 @@ module parentheses
 module specific_extremums
   ! f18 accepts all type kinds for the arguments of specific extremum intrinsics
   ! instead of of only default kind (or double precision for DMAX1 and DMIN1).
-  ! This extensions is implemented by using the related generic intrinsic and
-  ! converting the result.
+  ! This extension is implemented by using the related generic intrinsic.
+  ! For MAX0/MIN0, the result type matches the argument types (preserving kind).
+  ! For AMAX0/AMIN0/MAX1/MIN1, the result is converted to the specified type.
   ! The tests below are cases where an implementation that converts the arguments to the
   ! standard required types instead would give different results than the implementation
-  ! specified for f18 (converting the result).
+  ! specified for f18.
   integer(8), parameter :: max_i32_8 = 2_8**31-1
-  integer, parameter :: expected_min0 = int(min(max_i32_8, 2_8*max_i32_8), 4)
-  !WARN: portability: Argument types do not match specific intrinsic 'min0' requirements; using 'min' generic instead and converting the result to INTEGER(4) if needed [-Wuse-generic-intrinsic-when-specific-doesnt-match]
-  integer, parameter :: result_min0 =  min0(max_i32_8, 2_8*max_i32_8)
+  integer(8), parameter :: expected_min0 = min(max_i32_8, 2_8*max_i32_8)
+  !WARN: portability: Argument types do not match specific intrinsic 'min0' requirements; using 'min' generic instead and converting the result to INTEGER(8) if needed [-Wuse-generic-intrinsic-when-specific-doesnt-match]
+  integer(8), parameter :: result_min0 =  min0(max_i32_8, 2_8*max_i32_8)
   ! result_min0 would be -2  if arguments were converted to default integer.
   logical, parameter :: test_min0 = expected_min0 .EQ. result_min0
 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Flang] Incorrect execution results of max0 intrinsic function for various arguments
2 participants