Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang] Warn when F128 is unsupported #102147

Merged
merged 5 commits into from
Aug 28, 2024
Merged

[flang] Warn when F128 is unsupported #102147

merged 5 commits into from
Aug 28, 2024

Conversation

tblah
Copy link
Contributor

@tblah tblah commented Aug 6, 2024

This generates warning: REAL(KIND=16) is not an enabled type for this target if that type is used in a build not correctly configured to support this type. Uses of selected_real_kind(30) return -1.

The added braces to the previous if statement are so that clang-format does not try to indent the new comment. Even if the clang-format off directive is moved to the start, that comment still gets indented so it looks weird. I chose to disable clang-format for the preprocessor block to allow the nested if statement to be indented for clarity.

Note: some lit tests will fail on systems not configured to support f128. I'll update them once we are settled on what the right error message is.

Closes #101207

@tblah tblah requested review from clementval and klausler August 6, 2024 13:59
@llvmbot llvmbot added the flang Flang issues not falling into any other category label Aug 6, 2024
@tblah tblah marked this pull request as draft August 6, 2024 14:00
flang/include/flang/Tools/TargetSetup.h Outdated Show resolved Hide resolved
tblah added 4 commits August 27, 2024 11:08
This generates `warning: REAL(KIND=16) is not an enabled type for this target`
if that type is used in a build not correctly configured to support this type.
Uses of `selected_real_kind(30)` return -1.

The added braces to the previous if statement are so that clang-format
does not try to indent the new comment. Even if the clang-format off
directive is moved to the start, that comment still gets indented so it
looks weird. I chose to disable clang-format for the preprocessor block
to allow the nested if statement to be indented for clarity.

Note: some lit tests will fail on systems not configured to support
f128. I'll update them once we are settled on what the right error
message is.
@tblah tblah marked this pull request as ready for review August 27, 2024 13:18
@tblah tblah changed the title DRAFT: [flang] Warn when F128 is unsupported [flang] Warn when F128 is unsupported Aug 27, 2024
@llvmbot
Copy link
Member

llvmbot commented Aug 27, 2024

@llvm/pr-subscribers-flang-fir-hlfir

Author: Tom Eccles (tblah)

Changes

This generates warning: REAL(KIND=16) is not an enabled type for this target if that type is used in a build not correctly configured to support this type. Uses of selected_real_kind(30) return -1.

The added braces to the previous if statement are so that clang-format does not try to indent the new comment. Even if the clang-format off directive is moved to the start, that comment still gets indented so it looks weird. I chose to disable clang-format for the preprocessor block to allow the nested if statement to be indented for clarity.

Note: some lit tests will fail on systems not configured to support f128. I'll update them once we are settled on what the right error message is.

Closes #101207


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

13 Files Affected:

  • (modified) flang/include/flang/Tools/TargetSetup.h (+18-1)
  • (modified) flang/module/ieee_arithmetic.f90 (+49)
  • (modified) flang/test/CMakeLists.txt (+10)
  • (modified) flang/test/Evaluate/folding07.f90 (+1)
  • (modified) flang/test/Lower/Intrinsics/ieee_class_queries.f90 (+1)
  • (modified) flang/test/Lower/Intrinsics/ieee_unordered.f90 (+1)
  • (modified) flang/test/Lower/common-block.f90 (+1-1)
  • (modified) flang/test/Semantics/kinds03.f90 (+1)
  • (modified) flang/test/Semantics/modfile26.f90 (+1)
  • (modified) flang/test/Semantics/realkinds-aarch64-01.f90 (+1)
  • (modified) flang/test/lit.cfg.py (+2-1)
  • (modified) flang/test/lit.site.cfg.py.in (+1)
  • (modified) flang/tools/f18/CMakeLists.txt (+24-1)
diff --git a/flang/include/flang/Tools/TargetSetup.h b/flang/include/flang/Tools/TargetSetup.h
index 238d66c9241dd0..60609de8809cf0 100644
--- a/flang/include/flang/Tools/TargetSetup.h
+++ b/flang/include/flang/Tools/TargetSetup.h
@@ -11,6 +11,7 @@
 
 #include "flang/Evaluate/target.h"
 #include "llvm/Target/TargetMachine.h"
+#include <cfloat>
 
 namespace Fortran::tools {
 
@@ -21,9 +22,25 @@ namespace Fortran::tools {
 
   const llvm::Triple &targetTriple{targetMachine.getTargetTriple()};
   // FIXME: Handle real(3) ?
-  if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64)
+  if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64) {
     targetCharacteristics.DisableType(
         Fortran::common::TypeCategory::Real, /*kind=*/10);
+  }
+
+  // Figure out if we can support F128: see
+  // flang/runtime/Float128Math/math-entries.h
+#ifdef FLANG_RUNTIME_F128_MATH_LIB
+  // we can use libquadmath wrappers
+  constexpr bool f128Support = true;
+#elif LDBL_MANT_DIG == 113
+  // we can use libm wrappers
+  constexpr bool f128Support = true;
+#else
+  constexpr bool f128Support = false;
+#endif
+
+  if constexpr (!f128Support)
+    targetCharacteristics.DisableType(Fortran::common::TypeCategory::Real, 16);
 
   targetCharacteristics.set_compilerOptionsString(compilerOptions)
       .set_compilerVersionString(compilerVersion);
diff --git a/flang/module/ieee_arithmetic.f90 b/flang/module/ieee_arithmetic.f90
index 7c7721d78c1ed3..32e640b9e24574 100644
--- a/flang/module/ieee_arithmetic.f90
+++ b/flang/module/ieee_arithmetic.f90
@@ -161,6 +161,8 @@ end function ieee_round_ne
   G(1) G(2) G(4) G(8) G(16)
 #define SPECIFICS_L(G) \
   G(1) G(2) G(4) G(8)
+
+#if FLANG_SUPPORT_R16
 #if __x86_64__
 #define SPECIFICS_R(G) \
   G(2) G(3) G(4) G(8) G(10) G(16)
@@ -168,12 +170,24 @@ end function ieee_round_ne
 #define SPECIFICS_R(G) \
   G(2) G(3) G(4) G(8) G(16)
 #endif
+#else
+#if __x86_64__
+#define SPECIFICS_R(G) \
+  G(2) G(3) G(4) G(8) G(10)
+#else
+#define SPECIFICS_R(G) \
+  G(2) G(3) G(4) G(8)
+#endif
+#endif
+
 #define SPECIFICS_II(G) \
   G(1,1) G(1,2) G(1,4) G(1,8) G(1,16) \
   G(2,1) G(2,2) G(2,4) G(2,8) G(2,16) \
   G(4,1) G(4,2) G(4,4) G(4,8) G(4,16) \
   G(8,1) G(8,2) G(8,4) G(8,8) G(8,16) \
   G(16,1) G(16,2) G(16,4) G(16,8) G(16,16)
+
+#if FLANG_SUPPORT_R16
 #if __x86_64__
 #define SPECIFICS_RI(G) \
   G(2,1) G(2,2) G(2,4) G(2,8) G(2,16) \
@@ -190,7 +204,24 @@ end function ieee_round_ne
   G(8,1) G(8,2) G(8,4) G(8,8) G(8,16) \
   G(16,1) G(16,2) G(16,4) G(16,8) G(16,16)
 #endif
+#else
+#if __x86_64__
+#define SPECIFICS_RI(G) \
+  G(2,1) G(2,2) G(2,4) G(2,8) \
+  G(3,1) G(3,2) G(3,4) G(3,8) \
+  G(4,1) G(4,2) G(4,4) G(4,8) \
+  G(8,1) G(8,2) G(8,4) G(8,8) \
+  G(10,1) G(10,2) G(10,4) G(10,8)
+#else
+#define SPECIFICS_RI(G) \
+  G(2,1) G(2,2) G(2,4) G(2,8) \
+  G(3,1) G(3,2) G(3,4) G(3,8) \
+  G(4,1) G(4,2) G(4,4) G(4,8) \
+  G(8,1) G(8,2) G(8,4) G(8,8)
+#endif
+#endif
 
+#if FLANG_SUPPORT_R16
 #if __x86_64__
 #define SPECIFICS_RR(G) \
   G(2,2) G(2,3) G(2,4) G(2,8) G(2,10) G(2,16) \
@@ -207,6 +238,22 @@ end function ieee_round_ne
   G(8,2) G(8,3) G(8,4) G(8,8) G(8,16) \
   G(16,2) G(16,3) G(16,4) G(16,8) G(16,16)
 #endif
+#else
+#if __x86_64__
+#define SPECIFICS_RR(G) \
+  G(2,2) G(2,3) G(2,4) G(2,8) G(2,10) \
+  G(3,2) G(3,3) G(3,4) G(3,8) G(3,10) \
+  G(4,2) G(4,3) G(4,4) G(4,8) G(4,10) \
+  G(8,2) G(8,3) G(8,4) G(8,8) G(8,10) \
+  G(10,2) G(10,3) G(10,4) G(10,8) G(10,10)
+#else
+#define SPECIFICS_RR(G) \
+  G(2,2) G(2,3) G(2,4) G(2,8) \
+  G(3,2) G(3,3) G(3,4) G(3,8) \
+  G(4,2) G(4,3) G(4,4) G(4,8) \
+  G(8,2) G(8,3) G(8,4) G(8,8)
+#endif
+#endif
 
 #define IEEE_CLASS_R(XKIND) \
   elemental type(ieee_class_type) function ieee_class_a##XKIND(x); \
@@ -462,8 +509,10 @@ end function ieee_real_a##AKIND##_i##KKIND;
   interface ieee_real
     SPECIFICS_I(IEEE_REAL_I)
     SPECIFICS_R(IEEE_REAL_R)
+#if FLANG_SUPPORT_R16
     SPECIFICS_II(IEEE_REAL_II)
     SPECIFICS_RI(IEEE_REAL_RI)
+#endif
   end interface ieee_real
   public :: ieee_real
 #undef IEEE_REAL_I
diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index 43ad1e3312b643..a18a5c6519eda4 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -11,6 +11,16 @@ llvm_canonicalize_cmake_booleans(
 
 set(FLANG_TOOLS_DIR ${FLANG_BINARY_DIR}/bin)
 
+# Check if 128-bit float computations can be done via long double
+check_cxx_source_compiles(
+  "#include <cfloat>
+   #if LDBL_MANT_DIG != 113
+   #error LDBL_MANT_DIG != 113
+   #endif
+   int main() { return 0; }
+  "
+  HAVE_LDBL_MANT_DIG_113)
+
 # FIXME In out-of-tree builds, "SHLIBDIR" is undefined and passing it to
 # `configure_lit_site_cfg` leads to a configuration error. This is currently
 # only required by plugins/examples, which are not supported in out-of-tree
diff --git a/flang/test/Evaluate/folding07.f90 b/flang/test/Evaluate/folding07.f90
index 3b6a99df388268..d51df7acf7b8a6 100644
--- a/flang/test/Evaluate/folding07.f90
+++ b/flang/test/Evaluate/folding07.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: %python %S/test_folding.py %s %flang_fc1
 ! Test numeric model inquiry intrinsics
 
diff --git a/flang/test/Lower/Intrinsics/ieee_class_queries.f90 b/flang/test/Lower/Intrinsics/ieee_class_queries.f90
index bb7787ea903e23..b2f9df83a902a0 100644
--- a/flang/test/Lower/Intrinsics/ieee_class_queries.f90
+++ b/flang/test/Lower/Intrinsics/ieee_class_queries.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: bbc -emit-fir -o - %s | FileCheck %s
 
   ! CHECK-LABEL: func @_QQmain
diff --git a/flang/test/Lower/Intrinsics/ieee_unordered.f90 b/flang/test/Lower/Intrinsics/ieee_unordered.f90
index a6146eff7f06e7..b7e81d53a2d750 100644
--- a/flang/test/Lower/Intrinsics/ieee_unordered.f90
+++ b/flang/test/Lower/Intrinsics/ieee_unordered.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: bbc -emit-fir -hlfir=false -o - %s | FileCheck %s
 
 ! CHECK-LABEL: func @_QQmain
diff --git a/flang/test/Lower/common-block.f90 b/flang/test/Lower/common-block.f90
index 94e61b8bcc33db..b5c1389df45d35 100644
--- a/flang/test/Lower/common-block.f90
+++ b/flang/test/Lower/common-block.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: bbc %s -o - | tco | FileCheck %s
 ! RUN: %flang -emit-llvm -S -mmlir -disable-external-name-interop %s -o - | FileCheck %s
 
@@ -78,4 +79,3 @@ subroutine s7()
   real(16) r16
   common /co1/ r16
 end subroutine
-
diff --git a/flang/test/Semantics/kinds03.f90 b/flang/test/Semantics/kinds03.f90
index 751d4a9ffa3cbb..a15a4a9baa7315 100644
--- a/flang/test/Semantics/kinds03.f90
+++ b/flang/test/Semantics/kinds03.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: %python %S/test_symbols.py %s %flang_fc1
  !DEF: /MainProgram1/ipdt DerivedType
  !DEF: /MainProgram1/ipdt/k TypeParam INTEGER(4)
diff --git a/flang/test/Semantics/modfile26.f90 b/flang/test/Semantics/modfile26.f90
index 09dc8b0954d633..9c5d0015d91631 100644
--- a/flang/test/Semantics/modfile26.f90
+++ b/flang/test/Semantics/modfile26.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: %python %S/test_modfile.py %s %flang_fc1
 ! Intrinsics SELECTED_INT_KIND, SELECTED_REAL_KIND, PRECISION, RANGE,
 ! RADIX, DIGITS
diff --git a/flang/test/Semantics/realkinds-aarch64-01.f90 b/flang/test/Semantics/realkinds-aarch64-01.f90
index e22920ff991e93..2520c0b84c0e67 100644
--- a/flang/test/Semantics/realkinds-aarch64-01.f90
+++ b/flang/test/Semantics/realkinds-aarch64-01.f90
@@ -1,4 +1,5 @@
 ! REQUIRES: aarch64-registered-target
+! REQUIRES: flang-supports-f128-math
 ! RUN: %python %S/test_modfile.py %s %flang_fc1 -triple aarch64-unknown-linux-gnu
 
 module m1
diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index 37869e7e2ecd7e..4acbc0606d1977 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -216,8 +216,9 @@
 # Add features and substitutions to test F128 math support.
 # %f128-lib substitution may be used to generate check prefixes
 # for LIT tests checking for F128 library support.
-if config.flang_runtime_f128_math_lib:
+if config.flang_runtime_f128_math_lib or config.have_ldbl_mant_dig_113:
     config.available_features.add("flang-supports-f128-math")
+if config.flang_runtime_f128_math_lib:
     config.available_features.add(
         "flang-f128-math-lib-" + config.flang_runtime_f128_math_lib
     )
diff --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in
index fe6186d7140713..d1a0ac763cf8a0 100644
--- a/flang/test/lit.site.cfg.py.in
+++ b/flang/test/lit.site.cfg.py.in
@@ -31,6 +31,7 @@ if "openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"):
 else:
     config.openmp_module_dir = None
 config.flang_runtime_f128_math_lib = "@FLANG_RUNTIME_F128_MATH_LIB@"
+config.have_ldbl_mant_dig_113 = "@HAVE_LDBL_MANT_DIG_113@"
 
 import lit.llvm
 lit.llvm.initialize(lit_config, config)
diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt
index cec4e2d8107206..344a781c41e957 100644
--- a/flang/tools/f18/CMakeLists.txt
+++ b/flang/tools/f18/CMakeLists.txt
@@ -31,6 +31,25 @@ set(MODULES_WITHOUT_IMPLEMENTATION
 
 set(MODULES ${MODULES_WITH_IMPLEMENTATION} ${MODULES_WITHOUT_IMPLEMENTATION})
 
+# Check if 128-bit float computations can be done via long double.
+check_cxx_source_compiles(
+  "#include <cfloat>
+   #if LDBL_MANT_DIG != 113
+   #error LDBL_MANT_DIG != 113
+   #endif
+   int main() { return 0; }
+  "
+  HAVE_LDBL_MANT_DIG_113)
+
+# Figure out whether we can support REAL(KIND=16)
+if (FLANG_RUNTIME_F128_MATH_LIB)
+  set(FLANG_SUPPORT_R16 "1")
+elseif (HAVE_LDBL_MANT_DIG_113)
+  set(FLANG_SUPPORT_R16 "1")
+else()
+  set(FLANG_SUPPORT_R16 "0")
+endif()
+
 # Init variable to hold extra object files coming from the Fortran modules;
 # these module files will be contributed from the CMakeLists in flang/tools/f18.
 set(module_objects "")
@@ -76,6 +95,10 @@ if (NOT CMAKE_CROSSCOMPILING)
       endif()
     endif()
 
+    set(decls "")
+    if (FLANG_SUPPORT_R16)
+      set(decls "-DFLANG_SUPPORT_R16")
+    endif()
 
     # Some modules have an implementation part that needs to be added to the
     # FortranRuntime library.
@@ -92,7 +115,7 @@ if (NOT CMAKE_CROSSCOMPILING)
     # TODO: We may need to flag this with conditional, in case Flang is built w/o OpenMP support
     add_custom_command(OUTPUT ${base}.mod ${object_output}
       COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR}
-      COMMAND flang-new ${opts} -cpp ${compile_with} -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
+      COMMAND flang-new ${opts} ${decls} -cpp ${compile_with} -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
         ${FLANG_SOURCE_DIR}/module/${filename}.f90
       DEPENDS flang-new ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${FLANG_SOURCE_DIR}/module/__fortran_builtins.f90 ${depends}
     )

@llvmbot
Copy link
Member

llvmbot commented Aug 27, 2024

@llvm/pr-subscribers-flang-semantics

Author: Tom Eccles (tblah)

Changes

This generates warning: REAL(KIND=16) is not an enabled type for this target if that type is used in a build not correctly configured to support this type. Uses of selected_real_kind(30) return -1.

The added braces to the previous if statement are so that clang-format does not try to indent the new comment. Even if the clang-format off directive is moved to the start, that comment still gets indented so it looks weird. I chose to disable clang-format for the preprocessor block to allow the nested if statement to be indented for clarity.

Note: some lit tests will fail on systems not configured to support f128. I'll update them once we are settled on what the right error message is.

Closes #101207


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

13 Files Affected:

  • (modified) flang/include/flang/Tools/TargetSetup.h (+18-1)
  • (modified) flang/module/ieee_arithmetic.f90 (+49)
  • (modified) flang/test/CMakeLists.txt (+10)
  • (modified) flang/test/Evaluate/folding07.f90 (+1)
  • (modified) flang/test/Lower/Intrinsics/ieee_class_queries.f90 (+1)
  • (modified) flang/test/Lower/Intrinsics/ieee_unordered.f90 (+1)
  • (modified) flang/test/Lower/common-block.f90 (+1-1)
  • (modified) flang/test/Semantics/kinds03.f90 (+1)
  • (modified) flang/test/Semantics/modfile26.f90 (+1)
  • (modified) flang/test/Semantics/realkinds-aarch64-01.f90 (+1)
  • (modified) flang/test/lit.cfg.py (+2-1)
  • (modified) flang/test/lit.site.cfg.py.in (+1)
  • (modified) flang/tools/f18/CMakeLists.txt (+24-1)
diff --git a/flang/include/flang/Tools/TargetSetup.h b/flang/include/flang/Tools/TargetSetup.h
index 238d66c9241dd0..60609de8809cf0 100644
--- a/flang/include/flang/Tools/TargetSetup.h
+++ b/flang/include/flang/Tools/TargetSetup.h
@@ -11,6 +11,7 @@
 
 #include "flang/Evaluate/target.h"
 #include "llvm/Target/TargetMachine.h"
+#include <cfloat>
 
 namespace Fortran::tools {
 
@@ -21,9 +22,25 @@ namespace Fortran::tools {
 
   const llvm::Triple &targetTriple{targetMachine.getTargetTriple()};
   // FIXME: Handle real(3) ?
-  if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64)
+  if (targetTriple.getArch() != llvm::Triple::ArchType::x86_64) {
     targetCharacteristics.DisableType(
         Fortran::common::TypeCategory::Real, /*kind=*/10);
+  }
+
+  // Figure out if we can support F128: see
+  // flang/runtime/Float128Math/math-entries.h
+#ifdef FLANG_RUNTIME_F128_MATH_LIB
+  // we can use libquadmath wrappers
+  constexpr bool f128Support = true;
+#elif LDBL_MANT_DIG == 113
+  // we can use libm wrappers
+  constexpr bool f128Support = true;
+#else
+  constexpr bool f128Support = false;
+#endif
+
+  if constexpr (!f128Support)
+    targetCharacteristics.DisableType(Fortran::common::TypeCategory::Real, 16);
 
   targetCharacteristics.set_compilerOptionsString(compilerOptions)
       .set_compilerVersionString(compilerVersion);
diff --git a/flang/module/ieee_arithmetic.f90 b/flang/module/ieee_arithmetic.f90
index 7c7721d78c1ed3..32e640b9e24574 100644
--- a/flang/module/ieee_arithmetic.f90
+++ b/flang/module/ieee_arithmetic.f90
@@ -161,6 +161,8 @@ end function ieee_round_ne
   G(1) G(2) G(4) G(8) G(16)
 #define SPECIFICS_L(G) \
   G(1) G(2) G(4) G(8)
+
+#if FLANG_SUPPORT_R16
 #if __x86_64__
 #define SPECIFICS_R(G) \
   G(2) G(3) G(4) G(8) G(10) G(16)
@@ -168,12 +170,24 @@ end function ieee_round_ne
 #define SPECIFICS_R(G) \
   G(2) G(3) G(4) G(8) G(16)
 #endif
+#else
+#if __x86_64__
+#define SPECIFICS_R(G) \
+  G(2) G(3) G(4) G(8) G(10)
+#else
+#define SPECIFICS_R(G) \
+  G(2) G(3) G(4) G(8)
+#endif
+#endif
+
 #define SPECIFICS_II(G) \
   G(1,1) G(1,2) G(1,4) G(1,8) G(1,16) \
   G(2,1) G(2,2) G(2,4) G(2,8) G(2,16) \
   G(4,1) G(4,2) G(4,4) G(4,8) G(4,16) \
   G(8,1) G(8,2) G(8,4) G(8,8) G(8,16) \
   G(16,1) G(16,2) G(16,4) G(16,8) G(16,16)
+
+#if FLANG_SUPPORT_R16
 #if __x86_64__
 #define SPECIFICS_RI(G) \
   G(2,1) G(2,2) G(2,4) G(2,8) G(2,16) \
@@ -190,7 +204,24 @@ end function ieee_round_ne
   G(8,1) G(8,2) G(8,4) G(8,8) G(8,16) \
   G(16,1) G(16,2) G(16,4) G(16,8) G(16,16)
 #endif
+#else
+#if __x86_64__
+#define SPECIFICS_RI(G) \
+  G(2,1) G(2,2) G(2,4) G(2,8) \
+  G(3,1) G(3,2) G(3,4) G(3,8) \
+  G(4,1) G(4,2) G(4,4) G(4,8) \
+  G(8,1) G(8,2) G(8,4) G(8,8) \
+  G(10,1) G(10,2) G(10,4) G(10,8)
+#else
+#define SPECIFICS_RI(G) \
+  G(2,1) G(2,2) G(2,4) G(2,8) \
+  G(3,1) G(3,2) G(3,4) G(3,8) \
+  G(4,1) G(4,2) G(4,4) G(4,8) \
+  G(8,1) G(8,2) G(8,4) G(8,8)
+#endif
+#endif
 
+#if FLANG_SUPPORT_R16
 #if __x86_64__
 #define SPECIFICS_RR(G) \
   G(2,2) G(2,3) G(2,4) G(2,8) G(2,10) G(2,16) \
@@ -207,6 +238,22 @@ end function ieee_round_ne
   G(8,2) G(8,3) G(8,4) G(8,8) G(8,16) \
   G(16,2) G(16,3) G(16,4) G(16,8) G(16,16)
 #endif
+#else
+#if __x86_64__
+#define SPECIFICS_RR(G) \
+  G(2,2) G(2,3) G(2,4) G(2,8) G(2,10) \
+  G(3,2) G(3,3) G(3,4) G(3,8) G(3,10) \
+  G(4,2) G(4,3) G(4,4) G(4,8) G(4,10) \
+  G(8,2) G(8,3) G(8,4) G(8,8) G(8,10) \
+  G(10,2) G(10,3) G(10,4) G(10,8) G(10,10)
+#else
+#define SPECIFICS_RR(G) \
+  G(2,2) G(2,3) G(2,4) G(2,8) \
+  G(3,2) G(3,3) G(3,4) G(3,8) \
+  G(4,2) G(4,3) G(4,4) G(4,8) \
+  G(8,2) G(8,3) G(8,4) G(8,8)
+#endif
+#endif
 
 #define IEEE_CLASS_R(XKIND) \
   elemental type(ieee_class_type) function ieee_class_a##XKIND(x); \
@@ -462,8 +509,10 @@ end function ieee_real_a##AKIND##_i##KKIND;
   interface ieee_real
     SPECIFICS_I(IEEE_REAL_I)
     SPECIFICS_R(IEEE_REAL_R)
+#if FLANG_SUPPORT_R16
     SPECIFICS_II(IEEE_REAL_II)
     SPECIFICS_RI(IEEE_REAL_RI)
+#endif
   end interface ieee_real
   public :: ieee_real
 #undef IEEE_REAL_I
diff --git a/flang/test/CMakeLists.txt b/flang/test/CMakeLists.txt
index 43ad1e3312b643..a18a5c6519eda4 100644
--- a/flang/test/CMakeLists.txt
+++ b/flang/test/CMakeLists.txt
@@ -11,6 +11,16 @@ llvm_canonicalize_cmake_booleans(
 
 set(FLANG_TOOLS_DIR ${FLANG_BINARY_DIR}/bin)
 
+# Check if 128-bit float computations can be done via long double
+check_cxx_source_compiles(
+  "#include <cfloat>
+   #if LDBL_MANT_DIG != 113
+   #error LDBL_MANT_DIG != 113
+   #endif
+   int main() { return 0; }
+  "
+  HAVE_LDBL_MANT_DIG_113)
+
 # FIXME In out-of-tree builds, "SHLIBDIR" is undefined and passing it to
 # `configure_lit_site_cfg` leads to a configuration error. This is currently
 # only required by plugins/examples, which are not supported in out-of-tree
diff --git a/flang/test/Evaluate/folding07.f90 b/flang/test/Evaluate/folding07.f90
index 3b6a99df388268..d51df7acf7b8a6 100644
--- a/flang/test/Evaluate/folding07.f90
+++ b/flang/test/Evaluate/folding07.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: %python %S/test_folding.py %s %flang_fc1
 ! Test numeric model inquiry intrinsics
 
diff --git a/flang/test/Lower/Intrinsics/ieee_class_queries.f90 b/flang/test/Lower/Intrinsics/ieee_class_queries.f90
index bb7787ea903e23..b2f9df83a902a0 100644
--- a/flang/test/Lower/Intrinsics/ieee_class_queries.f90
+++ b/flang/test/Lower/Intrinsics/ieee_class_queries.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: bbc -emit-fir -o - %s | FileCheck %s
 
   ! CHECK-LABEL: func @_QQmain
diff --git a/flang/test/Lower/Intrinsics/ieee_unordered.f90 b/flang/test/Lower/Intrinsics/ieee_unordered.f90
index a6146eff7f06e7..b7e81d53a2d750 100644
--- a/flang/test/Lower/Intrinsics/ieee_unordered.f90
+++ b/flang/test/Lower/Intrinsics/ieee_unordered.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: bbc -emit-fir -hlfir=false -o - %s | FileCheck %s
 
 ! CHECK-LABEL: func @_QQmain
diff --git a/flang/test/Lower/common-block.f90 b/flang/test/Lower/common-block.f90
index 94e61b8bcc33db..b5c1389df45d35 100644
--- a/flang/test/Lower/common-block.f90
+++ b/flang/test/Lower/common-block.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: bbc %s -o - | tco | FileCheck %s
 ! RUN: %flang -emit-llvm -S -mmlir -disable-external-name-interop %s -o - | FileCheck %s
 
@@ -78,4 +79,3 @@ subroutine s7()
   real(16) r16
   common /co1/ r16
 end subroutine
-
diff --git a/flang/test/Semantics/kinds03.f90 b/flang/test/Semantics/kinds03.f90
index 751d4a9ffa3cbb..a15a4a9baa7315 100644
--- a/flang/test/Semantics/kinds03.f90
+++ b/flang/test/Semantics/kinds03.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: %python %S/test_symbols.py %s %flang_fc1
  !DEF: /MainProgram1/ipdt DerivedType
  !DEF: /MainProgram1/ipdt/k TypeParam INTEGER(4)
diff --git a/flang/test/Semantics/modfile26.f90 b/flang/test/Semantics/modfile26.f90
index 09dc8b0954d633..9c5d0015d91631 100644
--- a/flang/test/Semantics/modfile26.f90
+++ b/flang/test/Semantics/modfile26.f90
@@ -1,3 +1,4 @@
+! REQUIRES: flang-supports-f128-math
 ! RUN: %python %S/test_modfile.py %s %flang_fc1
 ! Intrinsics SELECTED_INT_KIND, SELECTED_REAL_KIND, PRECISION, RANGE,
 ! RADIX, DIGITS
diff --git a/flang/test/Semantics/realkinds-aarch64-01.f90 b/flang/test/Semantics/realkinds-aarch64-01.f90
index e22920ff991e93..2520c0b84c0e67 100644
--- a/flang/test/Semantics/realkinds-aarch64-01.f90
+++ b/flang/test/Semantics/realkinds-aarch64-01.f90
@@ -1,4 +1,5 @@
 ! REQUIRES: aarch64-registered-target
+! REQUIRES: flang-supports-f128-math
 ! RUN: %python %S/test_modfile.py %s %flang_fc1 -triple aarch64-unknown-linux-gnu
 
 module m1
diff --git a/flang/test/lit.cfg.py b/flang/test/lit.cfg.py
index 37869e7e2ecd7e..4acbc0606d1977 100644
--- a/flang/test/lit.cfg.py
+++ b/flang/test/lit.cfg.py
@@ -216,8 +216,9 @@
 # Add features and substitutions to test F128 math support.
 # %f128-lib substitution may be used to generate check prefixes
 # for LIT tests checking for F128 library support.
-if config.flang_runtime_f128_math_lib:
+if config.flang_runtime_f128_math_lib or config.have_ldbl_mant_dig_113:
     config.available_features.add("flang-supports-f128-math")
+if config.flang_runtime_f128_math_lib:
     config.available_features.add(
         "flang-f128-math-lib-" + config.flang_runtime_f128_math_lib
     )
diff --git a/flang/test/lit.site.cfg.py.in b/flang/test/lit.site.cfg.py.in
index fe6186d7140713..d1a0ac763cf8a0 100644
--- a/flang/test/lit.site.cfg.py.in
+++ b/flang/test/lit.site.cfg.py.in
@@ -31,6 +31,7 @@ if "openmp" in "@LLVM_ENABLE_RUNTIMES@".lower().split(";"):
 else:
     config.openmp_module_dir = None
 config.flang_runtime_f128_math_lib = "@FLANG_RUNTIME_F128_MATH_LIB@"
+config.have_ldbl_mant_dig_113 = "@HAVE_LDBL_MANT_DIG_113@"
 
 import lit.llvm
 lit.llvm.initialize(lit_config, config)
diff --git a/flang/tools/f18/CMakeLists.txt b/flang/tools/f18/CMakeLists.txt
index cec4e2d8107206..344a781c41e957 100644
--- a/flang/tools/f18/CMakeLists.txt
+++ b/flang/tools/f18/CMakeLists.txt
@@ -31,6 +31,25 @@ set(MODULES_WITHOUT_IMPLEMENTATION
 
 set(MODULES ${MODULES_WITH_IMPLEMENTATION} ${MODULES_WITHOUT_IMPLEMENTATION})
 
+# Check if 128-bit float computations can be done via long double.
+check_cxx_source_compiles(
+  "#include <cfloat>
+   #if LDBL_MANT_DIG != 113
+   #error LDBL_MANT_DIG != 113
+   #endif
+   int main() { return 0; }
+  "
+  HAVE_LDBL_MANT_DIG_113)
+
+# Figure out whether we can support REAL(KIND=16)
+if (FLANG_RUNTIME_F128_MATH_LIB)
+  set(FLANG_SUPPORT_R16 "1")
+elseif (HAVE_LDBL_MANT_DIG_113)
+  set(FLANG_SUPPORT_R16 "1")
+else()
+  set(FLANG_SUPPORT_R16 "0")
+endif()
+
 # Init variable to hold extra object files coming from the Fortran modules;
 # these module files will be contributed from the CMakeLists in flang/tools/f18.
 set(module_objects "")
@@ -76,6 +95,10 @@ if (NOT CMAKE_CROSSCOMPILING)
       endif()
     endif()
 
+    set(decls "")
+    if (FLANG_SUPPORT_R16)
+      set(decls "-DFLANG_SUPPORT_R16")
+    endif()
 
     # Some modules have an implementation part that needs to be added to the
     # FortranRuntime library.
@@ -92,7 +115,7 @@ if (NOT CMAKE_CROSSCOMPILING)
     # TODO: We may need to flag this with conditional, in case Flang is built w/o OpenMP support
     add_custom_command(OUTPUT ${base}.mod ${object_output}
       COMMAND ${CMAKE_COMMAND} -E make_directory ${FLANG_INTRINSIC_MODULES_DIR}
-      COMMAND flang-new ${opts} -cpp ${compile_with} -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
+      COMMAND flang-new ${opts} ${decls} -cpp ${compile_with} -module-dir ${FLANG_INTRINSIC_MODULES_DIR}
         ${FLANG_SOURCE_DIR}/module/${filename}.f90
       DEPENDS flang-new ${FLANG_SOURCE_DIR}/module/${filename}.f90 ${FLANG_SOURCE_DIR}/module/__fortran_builtins.f90 ${depends}
     )

@tblah
Copy link
Contributor Author

tblah commented Aug 27, 2024

I've updated this so that the test suite passes without f128 support. This is ready for review.

I'm concerned that there is now a lot of duplication in code figuring out whether we can support f128. I'm not very familiar with CMake. Is there any way this could be refactored?

@tblah tblah requested review from DavidTruby and pawosm-arm August 27, 2024 13:20
I didn't notice this test because it only runs on x86
@tblah tblah requested review from clementval and klausler August 28, 2024 13:35
@tblah tblah merged commit 114ff99 into llvm:main Aug 28, 2024
8 checks passed
tblah added a commit that referenced this pull request Aug 29, 2024
tblah added a commit that referenced this pull request Aug 29, 2024
Reverts #102147

It seems some systems which should support F128 are wrongly detected as
not supporting.

This might be due to checking `LDBL_MANT_DIG` instead of
`__LDBL_MANT_DIG__`. I will investigate.
@@ -462,8 +509,10 @@ end function ieee_real_a##AKIND##_i##KKIND;
interface ieee_real
SPECIFICS_I(IEEE_REAL_I)
SPECIFICS_R(IEEE_REAL_R)
#if FLANG_SUPPORT_R16
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe these intrinsics may work for targets where LDBL_MANT_DIG != 113 (e.g. x86). They can be folded by Flang given that libquadmath is linked to the compiler itself. They can also execute in runtime, because they will be lowered to "basic" float128 operations that LLVM backend may support for the target (e.g. x86).

Maybe we can just issue a warning about incomplete real*16 support and do not change the module file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disabled these parts of the library when REAL16 is unsupported because we also disable REAL10 on unsupported machines. Is something different about REAL16 that means we should just build with warnings?

#endif

if constexpr (!f128Support)
targetCharacteristics.DisableType(Fortran::common::TypeCategory::Real, 16);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as below. Some basic real*16 operations may still work, but math may not. I think it may be too much to disable it all.

@vzakhari
Copy link
Contributor

Can someone please explain the value of this warning about the type not enabled for a target? E.g. flang-new fails on a very simple program with real*10 on arm, so should this warning be turned into an error?

program main
  real(10) :: x
  x = 1.0_10
  print *, x
end program main
flang-new: .../llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp:1736: llvm::SDValue llvm::SelectionDAG::getConstant(const llvm::ConstantInt&, const llvm::SDLoc&, llvm::EVT, bool, bool): Assertion `Elt->getBitWidth() == EltVT.getSizeInBits() && "APInt size does not match type size!"' failed.

@tblah
Copy link
Contributor Author

tblah commented Aug 30, 2024

Can someone please explain the value of this warning about the type not enabled for a target? E.g. flang-new fails on a very simple program with real*10 on arm, so should this warning be turned into an error?

I agree it should be an error

tblah added a commit to tblah/llvm-project that referenced this pull request Sep 2, 2024
This generates `warning: REAL(KIND=16) is not an enabled type for this
target` if that type is used in a build not correctly configured to
support this type. Uses of `selected_real_kind(30)` return -1.
tblah added a commit that referenced this pull request Sep 5, 2024
This generates `warning: REAL(KIND=16) is not an enabled type for this
target` if that type is used in a build not correctly configured to
support this type. Uses of `selected_real_kind(30)` return -1.

Relanding #102147 because the test errors turned out to be specific to a
downstream configuration.
@DanielCChen
Copy link
Contributor

@tblah
This PR caused some regressions in our in-house test run.

    DOUBLE PRECISION, ALLOCATABLE :: doubleArrAlloc( :,: )
    doubleArrAlloc = RESHAPE([ (((REAL(j, 16) / REAL(i, 16)),&
                                    j = 1, 10), i = 1, 10) ], [ 10,10 ])
END

The above code is supposed to compile successfully, but Flang now failed with

error: Semantic errors in a.f
./a.f:2:35: error: too many actual arguments for intrinsic 'real'
      doubleArrAlloc = RESHAPE([ (((REAL(j, 16) / REAL(i, 16)),&
                                    ^^^^^^^^^^^
./a.f:2:49: error: too many actual arguments for intrinsic 'real'
      doubleArrAlloc = RESHAPE([ (((REAL(j, 16) / REAL(i, 16)),&
                                                  ^^^^^^^^^^^

@tblah
Copy link
Contributor Author

tblah commented Sep 11, 2024

@tblah This PR caused some regressions in our in-house test run.

    DOUBLE PRECISION, ALLOCATABLE :: doubleArrAlloc( :,: )
    doubleArrAlloc = RESHAPE([ (((REAL(j, 16) / REAL(i, 16)),&
                                    j = 1, 10), i = 1, 10) ], [ 10,10 ])
END

The above code is supposed to compile successfully, but Flang now failed with

error: Semantic errors in a.f
./a.f:2:35: error: too many actual arguments for intrinsic 'real'
      doubleArrAlloc = RESHAPE([ (((REAL(j, 16) / REAL(i, 16)),&
                                    ^^^^^^^^^^^
./a.f:2:49: error: too many actual arguments for intrinsic 'real'
      doubleArrAlloc = RESHAPE([ (((REAL(j, 16) / REAL(i, 16)),&
                                                  ^^^^^^^^^^^

Hi Daniel. That error message is probably incorrect. I think it is failing because REAL(kind=16) is not supported on your system. Have you tried the steps listed in https://flang.llvm.org/docs/Real16MathSupport.html?

@klausler
Copy link
Contributor

#108222

@DanielCChen
Copy link
Contributor

Hi Tom,
On PowerPC, we don't support REAL16 on AIX, so for the above test case, the new error message from @klausler fix is fine.
However, we support REAL
16 on LoP (Linux on Power). I think we currently using IBM long double format (ppc_f128), but I believe eventually we will switch to IEEE 128 format (f128). We don't really need to link to the libquadmath library to make it work.
This PR seems reply on the cmake macro -DFLANG_RUNTIME_F128_MATH_LIB=libquadmath being specified, which caused ~100+ runtime test cases to fail when they compiled and ran successfully on LoP.

@vzakhari
Copy link
Contributor

However, we support REAL_16 on LoP (Linux on Power). I think we currently using IBM long double format (ppc_f128)...

Hi Daniel, what is the value of LDBL_MANT_DIG in your LoP compiler/runtime build configuration? You can check HAVE_LDBL_MANT_DIG_113 in the CMakeCache.txt in your build location.

@DanielCChen
Copy link
Contributor

Hi Slava and Tom,
Currently we have LDBL_MANT_DIG as 106 as we are defaulting to IBM long double format which is different from IEEE 128.
We had some internal discussion about this. It seems we will at some point in the future to switch to IEEE 128 format by default on LoP. By then, it should satisfy the check in this PR and we should no longer see those warning messages.
Therefore, I think we can live with those "regressions" until then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:fir-hlfir 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 link failure when calling exp intrinsic with quad precision
6 participants