[flang-commits] [flang] [flang] IEEE_RINT, IEEE_INT (PR #110509)

via flang-commits flang-commits at lists.llvm.org
Mon Sep 30 06:41:03 PDT 2024


https://github.com/vdonaldson created https://github.com/llvm/llvm-project/pull/110509

IEEE_RINT rounds a real value to an integer-valued real.

IEEE_INT rounds a real value to an integer value.
The primary IEEE_INT result is generated with a call to IEEE_RINT.

>From eb41ba2dba11faef408a81196fd19bc52466d549 Mon Sep 17 00:00:00 2001
From: V Donaldson <vdonaldson at nvidia.com>
Date: Mon, 30 Sep 2024 06:34:21 -0700
Subject: [PATCH] [flang] IEEE_RINT, IEEE_INT

IEEE_RINT rounds a real value to an integer-valued real.

IEEE_INT rounds a real value to an integer value.
The primary IEEE_INT result is generated with a call to IEEE_RINT.
---
 .../flang/Optimizer/Builder/IntrinsicCall.h   |   2 +
 flang/lib/Optimizer/Builder/IntrinsicCall.cpp | 101 ++++++-
 flang/runtime/Float128Math/CMakeLists.txt     |   1 +
 flang/runtime/Float128Math/math-entries.h     |   3 +
 flang/runtime/Float128Math/nearbyint.cpp      |  22 ++
 flang/test/Lower/Intrinsics/ieee_rint_int.f90 | 247 ++++++++++++++++++
 6 files changed, 372 insertions(+), 4 deletions(-)
 create mode 100644 flang/runtime/Float128Math/nearbyint.cpp
 create mode 100644 flang/test/Lower/Intrinsics/ieee_rint_int.f90

diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index 78bb82b17d4050..766f11a29cdd5d 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -273,6 +273,7 @@ struct IntrinsicLibrary {
   template <bool isGet>
   void genIeeeGetOrSetStatus(llvm::ArrayRef<fir::ExtendedValue>);
   void genIeeeGetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
+  mlir::Value genIeeeInt(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIeeeIsFinite(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIeeeIsNan(mlir::Type, llvm::ArrayRef<mlir::Value>);
   mlir::Value genIeeeIsNegative(mlir::Type, llvm::ArrayRef<mlir::Value>);
@@ -283,6 +284,7 @@ struct IntrinsicLibrary {
   template <mlir::arith::CmpFPredicate pred>
   mlir::Value genIeeeQuietCompare(mlir::Type resultType,
                                   llvm::ArrayRef<mlir::Value>);
+  mlir::Value genIeeeRint(mlir::Type, llvm::ArrayRef<mlir::Value>);
   template <bool isFlag>
   void genIeeeSetFlagOrHaltingMode(llvm::ArrayRef<fir::ExtendedValue>);
   void genIeeeSetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 4e6d92213c1241..70c85f9f179917 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -96,11 +96,9 @@ static bool isStaticallyPresent(const fir::ExtendedValue &exv) {
 }
 
 /// IEEE module procedure names not yet implemented for genModuleProcTODO.
-static constexpr char ieee_int[] = "ieee_int";
 static constexpr char ieee_get_underflow_mode[] = "ieee_get_underflow_mode";
 static constexpr char ieee_real[] = "ieee_real";
 static constexpr char ieee_rem[] = "ieee_rem";
-static constexpr char ieee_rint[] = "ieee_rint";
 static constexpr char ieee_set_underflow_mode[] = "ieee_set_underflow_mode";
 
 using I = IntrinsicLibrary;
@@ -330,7 +328,7 @@ static constexpr IntrinsicHandler handlers[]{
      /*isElemental=*/false},
     {"ieee_get_status", &I::genIeeeGetOrSetStatus</*isGet=*/true>},
     {"ieee_get_underflow_mode", &I::genModuleProcTODO<ieee_get_underflow_mode>},
-    {"ieee_int", &I::genModuleProcTODO<ieee_int>},
+    {"ieee_int", &I::genIeeeInt},
     {"ieee_is_finite", &I::genIeeeIsFinite},
     {"ieee_is_nan", &I::genIeeeIsNan},
     {"ieee_is_negative", &I::genIeeeIsNegative},
@@ -363,7 +361,7 @@ static constexpr IntrinsicHandler handlers[]{
     {"ieee_quiet_ne", &I::genIeeeQuietCompare<mlir::arith::CmpFPredicate::UNE>},
     {"ieee_real", &I::genModuleProcTODO<ieee_real>},
     {"ieee_rem", &I::genModuleProcTODO<ieee_rem>},
-    {"ieee_rint", &I::genModuleProcTODO<ieee_rint>},
+    {"ieee_rint", &I::genIeeeRint},
     {"ieee_round_eq", &I::genIeeeTypeCompare<mlir::arith::CmpIPredicate::eq>},
     {"ieee_round_ne", &I::genIeeeTypeCompare<mlir::arith::CmpIPredicate::ne>},
     {"ieee_set_flag", &I::genIeeeSetFlagOrHaltingMode</*isFlag=*/true>},
@@ -1238,6 +1236,14 @@ static constexpr MathOperation mathOperations[] = {
     {"log_gamma", "lgamma", genFuncType<Ty::Real<8>, Ty::Real<8>>, genLibCall},
     {"log_gamma", RTNAME_STRING(LgammaF128), FuncTypeReal16Real16,
      genLibF128Call},
+    {"nearbyint", "llvm.nearbyint.f32", genFuncType<Ty::Real<4>, Ty::Real<4>>,
+     genLibCall},
+    {"nearbyint", "llvm.nearbyint.f64", genFuncType<Ty::Real<8>, Ty::Real<8>>,
+     genLibCall},
+    {"nearbyint", "llvm.nearbyint.f80", genFuncType<Ty::Real<10>, Ty::Real<10>>,
+     genLibCall},
+    {"nearbyint", RTNAME_STRING(NearbyintF128), FuncTypeReal16Real16,
+     genLibF128Call},
     // llvm.lround behaves the same way as libm's lround.
     {"nint", "llvm.lround.i64.f64", genFuncType<Ty::Integer<8>, Ty::Real<8>>,
      genLibCall},
@@ -4461,6 +4467,62 @@ void IntrinsicLibrary::genIeeeGetOrSetStatus(
   genRuntimeCall(isGet ? "fegetenv" : "fesetenv", i32Ty, addr);
 }
 
+// IEEE_INT
+mlir::Value IntrinsicLibrary::genIeeeInt(mlir::Type resultType,
+                                         llvm::ArrayRef<mlir::Value> args) {
+  // Convert real argument A to an integer, with rounding according to argument
+  // ROUND. Signal IEEE_INVALID if A is a NaN, an infinity, or out of range,
+  // and return either the largest or smallest integer result value (*).
+  // For valid results (when IEEE_INVALID is not signaled), signal IEEE_INEXACT
+  // if A is not an exact integral value (*). The (*) choices are processor
+  // dependent implementation choices not mandated by the standard.
+  // The primary result is generated with a call to IEEE_RINT.
+  assert(args.size() == 3);
+  mlir::FloatType realType = mlir::cast<mlir::FloatType>(args[0].getType());
+  mlir::Value realResult = genIeeeRint(realType, {args[0], args[1]});
+  int intWidth = mlir::cast<mlir::IntegerType>(resultType).getWidth();
+  mlir::Value intLBound = builder.create<mlir::arith::ConstantOp>(
+      loc, resultType,
+      builder.getIntegerAttr(resultType,
+                             llvm::APInt::getBitsSet(intWidth,
+                                                     /*lo=*/intWidth - 1,
+                                                     /*hi=*/intWidth)));
+  mlir::Value intUBound = builder.create<mlir::arith::ConstantOp>(
+      loc, resultType,
+      builder.getIntegerAttr(resultType,
+                             llvm::APInt::getBitsSet(intWidth, /*lo=*/0,
+                                                     /*hi=*/intWidth - 1)));
+  mlir::Value realLBound =
+      builder.create<fir::ConvertOp>(loc, realType, intLBound);
+  mlir::Value realUBound = builder.create<mlir::arith::NegFOp>(loc, realLBound);
+  mlir::Value aGreaterThanLBound = builder.create<mlir::arith::CmpFOp>(
+      loc, mlir::arith::CmpFPredicate::OGE, realResult, realLBound);
+  mlir::Value aLessThanUBound = builder.create<mlir::arith::CmpFOp>(
+      loc, mlir::arith::CmpFPredicate::OLT, realResult, realUBound);
+  mlir::Value resultIsValid = builder.create<mlir::arith::AndIOp>(
+      loc, aGreaterThanLBound, aLessThanUBound);
+
+  // Result is valid. It may be exact or inexact.
+  mlir::Value result;
+  fir::IfOp ifOp = builder.create<fir::IfOp>(loc, resultType, resultIsValid,
+                                             /*withElseRegion=*/true);
+  builder.setInsertionPointToStart(&ifOp.getThenRegion().front());
+  mlir::Value inexact = builder.create<mlir::arith::CmpFOp>(
+      loc, mlir::arith::CmpFPredicate::ONE, args[0], realResult);
+  genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INEXACT, inexact);
+  result = builder.create<fir::ConvertOp>(loc, resultType, realResult);
+  builder.create<fir::ResultOp>(loc, result);
+
+  // Result is invalid.
+  builder.setInsertionPointToStart(&ifOp.getElseRegion().front());
+  genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INVALID);
+  result = builder.create<mlir::arith::SelectOp>(loc, aGreaterThanLBound,
+                                                 intUBound, intLBound);
+  builder.create<fir::ResultOp>(loc, result);
+  builder.setInsertionPointAfter(ifOp);
+  return ifOp.getResult(0);
+}
+
 // IEEE_IS_FINITE
 mlir::Value
 IntrinsicLibrary::genIeeeIsFinite(mlir::Type resultType,
@@ -4740,6 +4802,37 @@ IntrinsicLibrary::genIeeeQuietCompare(mlir::Type resultType,
   return builder.create<fir::ConvertOp>(loc, resultType, res);
 }
 
+// IEEE_RINT
+mlir::Value IntrinsicLibrary::genIeeeRint(mlir::Type resultType,
+                                          llvm::ArrayRef<mlir::Value> args) {
+  // Return the value of real argument A rounded to an integer value according
+  // to argument ROUND if present, otherwise according to the current rounding
+  // mode. If ROUND is not present, signal IEEE_INEXACT if A is not an exact
+  // integral value.
+  assert(args.size() == 2);
+  mlir::Value a = args[0];
+  mlir::func::FuncOp getRound = fir::factory::getLlvmGetRounding(builder);
+  mlir::func::FuncOp setRound = fir::factory::getLlvmSetRounding(builder);
+  mlir::Value mode;
+  if (isStaticallyPresent(args[1])) {
+    mode = builder.create<fir::CallOp>(loc, getRound).getResult(0);
+    genIeeeSetRoundingMode({args[1]});
+  }
+  if (mlir::cast<mlir::FloatType>(resultType).getWidth() == 16)
+    a = builder.create<fir::ConvertOp>(
+        loc, mlir::FloatType::getF32(builder.getContext()), a);
+  mlir::Value result = builder.create<fir::ConvertOp>(
+      loc, resultType, genRuntimeCall("nearbyint", a.getType(), a));
+  if (isStaticallyPresent(args[1])) {
+    builder.create<fir::CallOp>(loc, setRound, mode);
+  } else {
+    mlir::Value inexact = builder.create<mlir::arith::CmpFOp>(
+        loc, mlir::arith::CmpFPredicate::ONE, args[0], result);
+    genRaiseExcept(_FORTRAN_RUNTIME_IEEE_INEXACT, inexact);
+  }
+  return result;
+}
+
 // IEEE_SET_FLAG, IEEE_SET_HALTING_MODE
 template <bool isFlag>
 void IntrinsicLibrary::genIeeeSetFlagOrHaltingMode(
diff --git a/flang/runtime/Float128Math/CMakeLists.txt b/flang/runtime/Float128Math/CMakeLists.txt
index 87f791f225d0d3..c8a51cc2508b9f 100644
--- a/flang/runtime/Float128Math/CMakeLists.txt
+++ b/flang/runtime/Float128Math/CMakeLists.txt
@@ -47,6 +47,7 @@ set(sources
   mod-real.cpp
   modulo-real.cpp
   nearest.cpp
+  nearbyint.cpp
   norm2.cpp
   pow.cpp
   random.cpp
diff --git a/flang/runtime/Float128Math/math-entries.h b/flang/runtime/Float128Math/math-entries.h
index 151ed8a09fde0a..90a983b787f537 100644
--- a/flang/runtime/Float128Math/math-entries.h
+++ b/flang/runtime/Float128Math/math-entries.h
@@ -92,6 +92,7 @@ DEFINE_FALLBACK_I64(Llround)
 DEFINE_FALLBACK_F128(Log)
 DEFINE_FALLBACK_F128(Log10)
 DEFINE_FALLBACK_I32(Lround)
+DEFINE_FALLBACK_F128(Nearbyint)
 DEFINE_FALLBACK_F128(Nextafter)
 DEFINE_FALLBACK_F128(Pow)
 DEFINE_FALLBACK_F128(Qnan)
@@ -140,6 +141,7 @@ DEFINE_SIMPLE_ALIAS(Llround, llroundq)
 DEFINE_SIMPLE_ALIAS(Log, logq)
 DEFINE_SIMPLE_ALIAS(Log10, log10q)
 DEFINE_SIMPLE_ALIAS(Lround, lroundq)
+DEFINE_SIMPLE_ALIAS(Nearbyint, nearbyintq)
 DEFINE_SIMPLE_ALIAS(Nextafter, nextafterq)
 DEFINE_SIMPLE_ALIAS(Pow, powq)
 DEFINE_SIMPLE_ALIAS(Round, roundq)
@@ -194,6 +196,7 @@ DEFINE_SIMPLE_ALIAS(Llround, std::llround)
 DEFINE_SIMPLE_ALIAS(Log, std::log)
 DEFINE_SIMPLE_ALIAS(Log10, std::log10)
 DEFINE_SIMPLE_ALIAS(Lround, std::lround)
+DEFINE_SIMPLE_ALIAS(Nearbyint, std::nearbyint)
 DEFINE_SIMPLE_ALIAS(Nextafter, std::nextafter)
 DEFINE_SIMPLE_ALIAS(Pow, std::pow)
 DEFINE_SIMPLE_ALIAS(Round, std::round)
diff --git a/flang/runtime/Float128Math/nearbyint.cpp b/flang/runtime/Float128Math/nearbyint.cpp
new file mode 100644
index 00000000000000..9eecb0c5f3e2f7
--- /dev/null
+++ b/flang/runtime/Float128Math/nearbyint.cpp
@@ -0,0 +1,22 @@
+//===-- runtime/Float128Math/nearbyint.cpp --------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "math-entries.h"
+
+namespace Fortran::runtime {
+extern "C" {
+
+#if HAS_LDBL128 || HAS_FLOAT128
+CppTypeFor<TypeCategory::Real, 16> RTDEF(NearbyintF128)(
+    CppTypeFor<TypeCategory::Real, 16> x) {
+  return Nearbyint<true>::invoke(x);
+}
+#endif
+
+} // extern "C"
+} // namespace Fortran::runtime
diff --git a/flang/test/Lower/Intrinsics/ieee_rint_int.f90 b/flang/test/Lower/Intrinsics/ieee_rint_int.f90
new file mode 100644
index 00000000000000..e4b1a5e26f3589
--- /dev/null
+++ b/flang/test/Lower/Intrinsics/ieee_rint_int.f90
@@ -0,0 +1,247 @@
+! RUN: bbc -emit-fir -o - %s | FileCheck %s
+
+! CHECK-LABEL: c.func @_QQmain
+program p
+  use ieee_arithmetic, only: ieee_int, ieee_rint
+  use ieee_arithmetic, only: ieee_value, ieee_positive_inf
+  use ieee_arithmetic, only: ieee_to_zero, ieee_nearest, ieee_up, ieee_away
+
+  ! CHECK:     %[[V_10:[0-9]+]] = fir.alloca i32 {bindc_name = "n", uniq_name = "_QFEn"}
+  ! CHECK:     %[[V_11:[0-9]+]] = fir.declare %[[V_10]] {uniq_name = "_QFEn"} : (!fir.ref<i32>) -> !fir.ref<i32>
+  ! CHECK:     %[[V_12:[0-9]+]] = fir.alloca i128 {bindc_name = "n16", uniq_name = "_QFEn16"}
+  ! CHECK:     %[[V_13:[0-9]+]] = fir.declare %[[V_12]] {uniq_name = "_QFEn16"} : (!fir.ref<i128>) -> !fir.ref<i128>
+  ! CHECK:     %[[V_14:[0-9]+]] = fir.alloca i16 {bindc_name = "n2", uniq_name = "_QFEn2"}
+  ! CHECK:     %[[V_15:[0-9]+]] = fir.declare %[[V_14]] {uniq_name = "_QFEn2"} : (!fir.ref<i16>) -> !fir.ref<i16>
+  ! CHECK:     %[[V_16:[0-9]+]] = fir.alloca i64 {bindc_name = "n8", uniq_name = "_QFEn8"}
+  ! CHECK:     %[[V_17:[0-9]+]] = fir.declare %[[V_16]] {uniq_name = "_QFEn8"} : (!fir.ref<i64>) -> !fir.ref<i64>
+  ! CHECK:     %[[V_18:[0-9]+]] = fir.alloca f32 {bindc_name = "x", uniq_name = "_QFEx"}
+  ! CHECK:     %[[V_19:[0-9]+]] = fir.declare %[[V_18]] {uniq_name = "_QFEx"} : (!fir.ref<f32>) -> !fir.ref<f32>
+  ! CHECK:     %[[V_20:[0-9]+]] = fir.alloca f16 {bindc_name = "x2", uniq_name = "_QFEx2"}
+  ! CHECK:     %[[V_21:[0-9]+]] = fir.declare %[[V_20]] {uniq_name = "_QFEx2"} : (!fir.ref<f16>) -> !fir.ref<f16>
+  ! CHECK:     %[[V_22:[0-9]+]] = fir.alloca bf16 {bindc_name = "x3", uniq_name = "_QFEx3"}
+  ! CHECK:     %[[V_23:[0-9]+]] = fir.declare %[[V_22]] {uniq_name = "_QFEx3"} : (!fir.ref<bf16>) -> !fir.ref<bf16>
+  ! CHECK:     %[[V_24:[0-9]+]] = fir.alloca f32 {bindc_name = "x8", uniq_name = "_QFEx8"}
+  ! CHECK:     %[[V_25:[0-9]+]] = fir.declare %[[V_24]] {uniq_name = "_QFEx8"} : (!fir.ref<f32>) -> !fir.ref<f32>
+  ! CHECK:     %[[V_26:[0-9]+]] = fir.alloca f32 {bindc_name = "y", uniq_name = "_QFEy"}
+  ! CHECK:     %[[V_27:[0-9]+]] = fir.declare %[[V_26]] {uniq_name = "_QFEy"} : (!fir.ref<f32>) -> !fir.ref<f32>
+  ! CHECK:     %[[V_28:[0-9]+]] = fir.alloca f16 {bindc_name = "y2", uniq_name = "_QFEy2"}
+  ! CHECK:     %[[V_29:[0-9]+]] = fir.declare %[[V_28]] {uniq_name = "_QFEy2"} : (!fir.ref<f16>) -> !fir.ref<f16>
+  ! CHECK:     %[[V_30:[0-9]+]] = fir.alloca bf16 {bindc_name = "y3", uniq_name = "_QFEy3"}
+  ! CHECK:     %[[V_31:[0-9]+]] = fir.declare %[[V_30]] {uniq_name = "_QFEy3"} : (!fir.ref<bf16>) -> !fir.ref<bf16>
+  ! CHECK:     %[[V_32:[0-9]+]] = fir.alloca f32 {bindc_name = "y8", uniq_name = "_QFEy8"}
+  ! CHECK:     %[[V_33:[0-9]+]] = fir.declare %[[V_32]] {uniq_name = "_QFEy8"} : (!fir.ref<f32>) -> !fir.ref<f32>
+  integer(2) n2
+  integer(8) n8
+  integer(16) n16
+  real(2) x2, y2
+  real(3) x3, y3
+
+  ! CHECK:     fir.store %cst{{[_0-9]*}} to %[[V_19]] : !fir.ref<f32>
+  x = -200.7
+
+  ! CHECK:     %[[V_34:[0-9]+]] = fir.address_of(@_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.0)
+  ! CHECK:     %[[V_35:[0-9]+]] = fir.declare %[[V_34]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.0"}
+  ! CHECK:     %[[V_36:[0-9]+]] = fir.load %[[V_19]] : !fir.ref<f32>
+  ! CHECK:     %[[V_37:[0-9]+]] = fir.call @llvm.get.rounding() fastmath<contract> : () -> i32
+  ! CHECK:     %[[V_38:[0-9]+]] = fir.field_index _QM__fortran_builtinsT__builtin_ieee_round_type.mode, !fir.type<_QM__fortran_builtinsT__builtin_ieee_round_type{_QM__fortran_builtinsT__builtin_ieee_round_type.mode:i8}>
+  ! CHECK:     %[[V_39:[0-9]+]] = fir.coordinate_of %[[V_35]], %[[V_38]]
+  ! CHECK:     %[[V_40:[0-9]+]] = fir.load %[[V_39]] : !fir.ref<i8>
+  ! CHECK:     %[[V_41:[0-9]+]] = fir.convert %[[V_40]] : (i8) -> i32
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_41]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_42:[0-9]+]] = fir.call @llvm.nearbyint.f32(%[[V_36]]) fastmath<contract> : (f32) -> f32
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_37]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     fir.store %[[V_42]] to %[[V_27]] : !fir.ref<f32>
+  y = ieee_rint(x, ieee_nearest)
+
+  ! CHECK:     %[[V_43:[0-9]+]] = fir.declare %[[V_34]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.0"}
+  ! CHECK:     %[[V_44:[0-9]+]] = fir.load %[[V_19]] : !fir.ref<f32>
+  ! CHECK:     %[[V_45:[0-9]+]] = fir.call @llvm.get.rounding() fastmath<contract> : () -> i32
+  ! CHECK:     %[[V_46:[0-9]+]] = fir.coordinate_of %[[V_43]], %[[V_38]]
+  ! CHECK:     %[[V_47:[0-9]+]] = fir.load %[[V_46]] : !fir.ref<i8>
+  ! CHECK:     %[[V_48:[0-9]+]] = fir.convert %[[V_47]] : (i8) -> i32
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_48]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_49:[0-9]+]] = fir.call @llvm.nearbyint.f32(%[[V_44]]) fastmath<contract> : (f32) -> f32
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_45]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_50:[0-9]+]] = fir.convert %c-2147483648{{.*}} : (i32) -> f32
+  ! CHECK:     %[[V_51:[0-9]+]] = arith.negf %[[V_50]] fastmath<contract> : f32
+  ! CHECK:     %[[V_52:[0-9]+]] = arith.cmpf oge, %[[V_49]], %[[V_50]] fastmath<contract> : f32
+  ! CHECK:     %[[V_53:[0-9]+]] = arith.cmpf olt, %[[V_49]], %[[V_51]] fastmath<contract> : f32
+  ! CHECK:     %[[V_54:[0-9]+]] = arith.andi %[[V_52]], %[[V_53]] : i1
+  ! CHECK:     %[[V_55:[0-9]+]] = fir.if %[[V_54]] -> (i32) {
+  ! CHECK:       %[[V_128:[0-9]+]] = arith.cmpf one, %[[V_44]], %[[V_49]] fastmath<contract> : f32
+  ! CHECK:       fir.if %[[V_128]] {
+  ! CHECK:         %[[V_130:[0-9]+]] = fir.call @_FortranAMapException(%c32{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:         %[[V_131:[0-9]+]] = fir.call @feraiseexcept(%[[V_130]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:       }
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.convert %[[V_49]] : (f32) -> i32
+  ! CHECK:       fir.result %[[V_129]] : i32
+  ! CHECK:     } else {
+  ! CHECK:       %[[V_128:[0-9]+]] = fir.call @_FortranAMapException(%c1{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.call @feraiseexcept(%[[V_128]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_130:[0-9]+]] = arith.select %[[V_52]], %c2147483647{{.*}}, %c-2147483648{{.*}} : i32
+  ! CHECK:       fir.result %[[V_130]] : i32
+  ! CHECK:     }
+  ! CHECK:     fir.store %[[V_55]] to %[[V_11]] : !fir.ref<i32>
+  n = ieee_int(x, ieee_nearest)
+! print*, x, ' -> ', y, ' -> ', n
+
+  ! CHECK:     fir.store %cst{{[_0-9]*}} to %[[V_21]] : !fir.ref<f16>
+  x2 = huge(x2)
+
+  ! CHECK:     %[[V_56:[0-9]+]] = fir.address_of(@_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.1)
+  ! CHECK:     %[[V_57:[0-9]+]] = fir.declare %[[V_56]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.1"}
+  ! CHECK:     %[[V_58:[0-9]+]] = fir.load %[[V_21]] : !fir.ref<f16>
+  ! CHECK:     %[[V_59:[0-9]+]] = fir.call @llvm.get.rounding() fastmath<contract> : () -> i32
+  ! CHECK:     %[[V_60:[0-9]+]] = fir.coordinate_of %[[V_57]], %[[V_38]]
+  ! CHECK:     %[[V_61:[0-9]+]] = fir.load %[[V_60]] : !fir.ref<i8>
+  ! CHECK:     %[[V_62:[0-9]+]] = fir.convert %[[V_61]] : (i8) -> i32
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_62]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_63:[0-9]+]] = fir.convert %[[V_58]] : (f16) -> f32
+  ! CHECK:     %[[V_64:[0-9]+]] = fir.call @llvm.nearbyint.f32(%[[V_63]]) fastmath<contract> : (f32) -> f32
+  ! CHECK:     %[[V_65:[0-9]+]] = fir.convert %[[V_64]] : (f32) -> f16
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_59]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     fir.store %[[V_65]] to %[[V_29]] : !fir.ref<f16>
+  y2 = ieee_rint(x2, ieee_up)
+
+  ! CHECK:     %[[V_66:[0-9]+]] = fir.declare %[[V_56]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.1"}
+  ! CHECK:     %[[V_67:[0-9]+]] = fir.load %[[V_21]] : !fir.ref<f16>
+  ! CHECK:     %[[V_68:[0-9]+]] = fir.call @llvm.get.rounding() fastmath<contract> : () -> i32
+  ! CHECK:     %[[V_69:[0-9]+]] = fir.coordinate_of %[[V_66]], %[[V_38]]
+  ! CHECK:     %[[V_70:[0-9]+]] = fir.load %[[V_69]] : !fir.ref<i8>
+  ! CHECK:     %[[V_71:[0-9]+]] = fir.convert %[[V_70]] : (i8) -> i32
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_71]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_72:[0-9]+]] = fir.convert %[[V_67]] : (f16) -> f32
+  ! CHECK:     %[[V_73:[0-9]+]] = fir.call @llvm.nearbyint.f32(%[[V_72]]) fastmath<contract> : (f32) -> f32
+  ! CHECK:     %[[V_74:[0-9]+]] = fir.convert %[[V_73]] : (f32) -> f16
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_68]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_75:[0-9]+]] = fir.convert %c-9223372036854775808{{.*}} : (i64) -> f16
+  ! CHECK:     %[[V_76:[0-9]+]] = arith.negf %[[V_75]] fastmath<contract> : f16
+  ! CHECK:     %[[V_77:[0-9]+]] = arith.cmpf oge, %[[V_74]], %[[V_75]] fastmath<contract> : f16
+  ! CHECK:     %[[V_78:[0-9]+]] = arith.cmpf olt, %[[V_74]], %[[V_76]] fastmath<contract> : f16
+  ! CHECK:     %[[V_79:[0-9]+]] = arith.andi %[[V_77]], %[[V_78]] : i1
+  ! CHECK:     %[[V_80:[0-9]+]] = fir.if %[[V_79]] -> (i64) {
+  ! CHECK:       %[[V_128:[0-9]+]] = arith.cmpf one, %[[V_67]], %[[V_74]] fastmath<contract> : f16
+  ! CHECK:       fir.if %[[V_128]] {
+  ! CHECK:         %[[V_130:[0-9]+]] = fir.call @_FortranAMapException(%c32{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:         %[[V_131:[0-9]+]] = fir.call @feraiseexcept(%[[V_130]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:       }
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.convert %[[V_74]] : (f16) -> i64
+  ! CHECK:       fir.result %[[V_129]] : i64
+  ! CHECK:     } else {
+  ! CHECK:       %[[V_128:[0-9]+]] = fir.call @_FortranAMapException(%c1{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.call @feraiseexcept(%[[V_128]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_130:[0-9]+]] = arith.select %[[V_77]], %c9223372036854775807{{.*}}, %c-9223372036854775808{{.*}} : i64
+  ! CHECK:       fir.result %[[V_130]] : i64
+  ! CHECK:     }
+  ! CHECK:     fir.store %[[V_80]] to %[[V_17]] : !fir.ref<i64>
+  n8 = ieee_int(x2, ieee_up, 8)
+
+! print*, x2, ' -> ', y2, ' -> ', n8
+
+  ! CHECK:     fir.store %cst{{[_0-9]*}} to %[[V_23]] : !fir.ref<bf16>
+  x3 = -0.
+
+  ! CHECK:     %[[V_81:[0-9]+]] = fir.load %[[V_23]] : !fir.ref<bf16>
+  ! CHECK:     %[[V_82:[0-9]+]] = fir.convert %[[V_81]] : (bf16) -> f32
+  ! CHECK:     %[[V_83:[0-9]+]] = fir.call @llvm.nearbyint.f32(%[[V_82]]) fastmath<contract> : (f32) -> f32
+  ! CHECK:     %[[V_84:[0-9]+]] = fir.convert %[[V_83]] : (f32) -> bf16
+  ! CHECK:     %[[V_85:[0-9]+]] = arith.cmpf one, %[[V_81]], %[[V_84]] fastmath<contract> : bf16
+  ! CHECK:     fir.if %[[V_85]] {
+  ! CHECK:       %[[V_128:[0-9]+]] = fir.call @_FortranAMapException(%c32{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.call @feraiseexcept(%[[V_128]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:     }
+  ! CHECK:     fir.store %[[V_84]] to %[[V_31]] : !fir.ref<bf16>
+  y3 = ieee_rint(x3)
+
+  ! CHECK:     %[[V_86:[0-9]+]] = fir.address_of(@_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.2)
+  ! CHECK:     %[[V_87:[0-9]+]] = fir.declare %[[V_86]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.2"}
+  ! CHECK:     %[[V_88:[0-9]+]] = fir.load %[[V_23]] : !fir.ref<bf16>
+  ! CHECK:     %[[V_89:[0-9]+]] = fir.call @llvm.get.rounding() fastmath<contract> : () -> i32
+  ! CHECK:     %[[V_90:[0-9]+]] = fir.coordinate_of %[[V_87]], %[[V_38]]
+  ! CHECK:     %[[V_91:[0-9]+]] = fir.load %[[V_90]] : !fir.ref<i8>
+  ! CHECK:     %[[V_92:[0-9]+]] = fir.convert %[[V_91]] : (i8) -> i32
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_92]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_93:[0-9]+]] = fir.convert %[[V_88]] : (bf16) -> f32
+  ! CHECK:     %[[V_94:[0-9]+]] = fir.call @llvm.nearbyint.f32(%[[V_93]]) fastmath<contract> : (f32) -> f32
+  ! CHECK:     %[[V_95:[0-9]+]] = fir.convert %[[V_94]] : (f32) -> bf16
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_89]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_96:[0-9]+]] = fir.convert %c-170141183460469231731687303715884105728{{.*}} : (i128) -> bf16
+  ! CHECK:     %[[V_97:[0-9]+]] = arith.negf %[[V_96]] fastmath<contract> : bf16
+  ! CHECK:     %[[V_98:[0-9]+]] = arith.cmpf oge, %[[V_95]], %[[V_96]] fastmath<contract> : bf16
+  ! CHECK:     %[[V_99:[0-9]+]] = arith.cmpf olt, %[[V_95]], %[[V_97]] fastmath<contract> : bf16
+  ! CHECK:     %[[V_100:[0-9]+]] = arith.andi %[[V_98]], %[[V_99]] : i1
+  ! CHECK:     %[[V_101:[0-9]+]] = fir.if %[[V_100]] -> (i128) {
+  ! CHECK:       %[[V_128:[0-9]+]] = arith.cmpf one, %[[V_88]], %[[V_95]] fastmath<contract> : bf16
+  ! CHECK:       fir.if %[[V_128]] {
+  ! CHECK:         %[[V_130:[0-9]+]] = fir.call @_FortranAMapException(%c32{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:         %[[V_131:[0-9]+]] = fir.call @feraiseexcept(%[[V_130]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:       }
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.convert %[[V_95]] : (bf16) -> i128
+  ! CHECK:       fir.result %[[V_129]] : i128
+  ! CHECK:     } else {
+  ! CHECK:       %[[V_128:[0-9]+]] = fir.call @_FortranAMapException(%c1{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.call @feraiseexcept(%[[V_128]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_130:[0-9]+]] = arith.select %[[V_98]], %c170141183460469231731687303715884105727{{.*}}, %c-170141183460469231731687303715884105728{{.*}} : i128
+  ! CHECK:       fir.result %[[V_130]] : i128
+  ! CHECK:     }
+  ! CHECK:     fir.store %[[V_101]] to %[[V_13]] : !fir.ref<i128>
+  n16 = ieee_int(x3, ieee_away, 16)
+
+! print*, x3, ' -> ', y3, ' -> ', n16
+
+  ! CHECK:     %[[V_102:[0-9]+]] = fir.address_of(@_QQro._QMieee_arithmeticTieee_class_type.3)
+  ! CHECK:     %[[V_103:[0-9]+]] = fir.declare %[[V_102]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QMieee_arithmeticTieee_class_type.3"}
+  ! CHECK:     %[[V_104:[0-9]+]] = fir.field_index _QMieee_arithmeticTieee_class_type.which, !fir.type<_QMieee_arithmeticTieee_class_type{_QMieee_arithmeticTieee_class_type.which:i8}>
+  ! CHECK:     %[[V_105:[0-9]+]] = fir.coordinate_of %[[V_103]], %[[V_104]]
+  ! CHECK:     %[[V_106:[0-9]+]] = fir.load %[[V_105]] : !fir.ref<i8>
+  ! CHECK:     %[[V_107:[0-9]+]] = fir.address_of(@_FortranAIeeeValueTable_4) : !fir.ref<!fir.array<12xi32>>
+  ! CHECK:     %[[V_108:[0-9]+]] = fir.coordinate_of %[[V_107]], %[[V_106]]
+  ! CHECK:     %[[V_109:[0-9]+]] = fir.load %[[V_108]] : !fir.ref<i32>
+  ! CHECK:     %[[V_110:[0-9]+]] = arith.bitcast %[[V_109]] : i32 to f32
+  ! CHECK:     fir.store %[[V_110]] to %[[V_25]] : !fir.ref<f32>
+  x8 = ieee_value(x8, ieee_positive_inf)
+
+  ! CHECK:     %[[V_111:[0-9]+]] = fir.load %[[V_25]] : !fir.ref<f32>
+  ! CHECK:     %[[V_112:[0-9]+]] = fir.call @llvm.nearbyint.f32(%[[V_111]]) fastmath<contract> : (f32) -> f32
+  ! CHECK:     %[[V_113:[0-9]+]] = arith.cmpf one, %[[V_111]], %[[V_112]] fastmath<contract> : f32
+  ! CHECK:     fir.if %[[V_113]] {
+  ! CHECK:       %[[V_128:[0-9]+]] = fir.call @_FortranAMapException(%c32{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.call @feraiseexcept(%[[V_128]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:     }
+  ! CHECK:     fir.store %[[V_112]] to %[[V_33]] : !fir.ref<f32>
+  y8 = ieee_rint(x8)
+
+  ! CHECK:     %[[V_114:[0-9]+]] = fir.address_of(@_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.4)
+  ! CHECK:     %[[V_115:[0-9]+]] = fir.declare %[[V_114]] {fortran_attrs = #fir.var_attrs<parameter>, uniq_name = "_QQro._QM__fortran_builtinsT__builtin_ieee_round_type.4"}
+  ! CHECK:     %[[V_116:[0-9]+]] = fir.load %[[V_25]] : !fir.ref<f32>
+  ! CHECK:     %[[V_117:[0-9]+]] = fir.call @llvm.get.rounding() fastmath<contract> : () -> i32
+  ! CHECK:     %[[V_118:[0-9]+]] = fir.coordinate_of %[[V_115]], %[[V_38]]
+  ! CHECK:     %[[V_119:[0-9]+]] = fir.load %[[V_118]] : !fir.ref<i8>
+  ! CHECK:     %[[V_120:[0-9]+]] = fir.convert %[[V_119]] : (i8) -> i32
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_120]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_121:[0-9]+]] = fir.call @llvm.nearbyint.f32(%[[V_116]]) fastmath<contract> : (f32) -> f32
+  ! CHECK:     fir.call @llvm.set.rounding(%[[V_117]]) fastmath<contract> : (i32) -> ()
+  ! CHECK:     %[[V_122:[0-9]+]] = fir.convert %c-32768{{.*}} : (i16) -> f32
+  ! CHECK:     %[[V_123:[0-9]+]] = arith.negf %[[V_122]] fastmath<contract> : f32
+  ! CHECK:     %[[V_124:[0-9]+]] = arith.cmpf oge, %[[V_121]], %[[V_122]] fastmath<contract> : f32
+  ! CHECK:     %[[V_125:[0-9]+]] = arith.cmpf olt, %[[V_121]], %[[V_123]] fastmath<contract> : f32
+  ! CHECK:     %[[V_126:[0-9]+]] = arith.andi %[[V_124]], %[[V_125]] : i1
+  ! CHECK:     %[[V_127:[0-9]+]] = fir.if %[[V_126]] -> (i16) {
+  ! CHECK:       %[[V_128:[0-9]+]] = arith.cmpf one, %[[V_116]], %[[V_121]] fastmath<contract> : f32
+  ! CHECK:       fir.if %[[V_128]] {
+  ! CHECK:         %[[V_130:[0-9]+]] = fir.call @_FortranAMapException(%c32{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:         %[[V_131:[0-9]+]] = fir.call @feraiseexcept(%[[V_130]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:       }
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.convert %[[V_121]] : (f32) -> i16
+  ! CHECK:       fir.result %[[V_129]] : i16
+  ! CHECK:     } else {
+  ! CHECK:       %[[V_128:[0-9]+]] = fir.call @_FortranAMapException(%c1{{.*}}) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_129:[0-9]+]] = fir.call @feraiseexcept(%[[V_128]]) fastmath<contract> : (i32) -> i32
+  ! CHECK:       %[[V_130:[0-9]+]] = arith.select %[[V_124]], %c32767{{.*}}, %c-32768{{.*}} : i16
+  ! CHECK:       fir.result %[[V_130]] : i16
+  ! CHECK:     }
+  ! CHECK:     fir.store %[[V_127]] to %[[V_15]] : !fir.ref<i16>
+  n2 = ieee_int(x8, ieee_to_zero, 2)
+
+! print*, x8, ' -> ', y8, ' -> ', n2
+end



More information about the flang-commits mailing list