Skip to content

[flang] IEEE_NEXT_AFTER, IEEE_NEXT_DOWN, IEEE_NEXT_UP, NEAREST #100782

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

Merged
merged 1 commit into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions flang/include/flang/Optimizer/Builder/IntrinsicCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ struct IntrinsicLibrary {
mlir::Value genModulo(mlir::Type, llvm::ArrayRef<mlir::Value>);
void genMoveAlloc(llvm::ArrayRef<fir::ExtendedValue>);
void genMvbits(llvm::ArrayRef<fir::ExtendedValue>);
enum class NearestProc { Nearest, NextAfter, NextDown, NextUp };
template <NearestProc>
mlir::Value genNearest(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genNint(mlir::Type, llvm::ArrayRef<mlir::Value>);
fir::ExtendedValue genNorm2(mlir::Type, llvm::ArrayRef<fir::ExtendedValue>);
Expand Down Expand Up @@ -422,9 +424,12 @@ struct IntrinsicLibrary {
mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args);

/// Generate code to raise \p except if \p cond is absent,
/// Generate code to raise \p excepts if \p cond is absent,
/// or present and true.
void genRaiseExcept(int except, mlir::Value cond = {});
void genRaiseExcept(int excepts, mlir::Value cond = {});

/// Generate a quiet NaN of a given floating point type.
mlir::Value genQNan(mlir::Type resultType);

/// Define the different FIR generators that can be mapped to intrinsic to
/// generate the related code.
Expand Down
8 changes: 4 additions & 4 deletions flang/include/flang/Optimizer/Builder/Runtime/Exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ class FirOpBuilder;

namespace fir::runtime {

/// Generate a runtime call to map an ieee_flag_type exception value to a
/// libm fenv.h value.
mlir::Value genMapException(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value except);
/// Generate a runtime call to map a set of ieee_flag_type exceptions to a
/// libm fenv.h excepts value.
mlir::Value genMapExcept(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value excepts);

} // namespace fir::runtime
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_EXCEPTIONS_H
9 changes: 3 additions & 6 deletions flang/include/flang/Runtime/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#define FORTRAN_RUNTIME_EXCEPTIONS_H_

#include "flang/Runtime/entry-names.h"
#include "flang/Runtime/magic-numbers.h"
#include <cinttypes>

namespace Fortran::runtime {
Expand All @@ -21,11 +20,9 @@ class Descriptor;

extern "C" {

// Map a (single) IEEE_FLAG_TYPE exception value to a libm fenv.h value.
// This could be extended to handle sets of exceptions, but there is no
// current use case for that. This mapping is done at runtime to support
// cross compilation.
std::int32_t RTNAME(MapException)(std::int32_t except);
// Map a set of IEEE_FLAG_TYPE exception values to a libm fenv.h excepts value.
// This mapping is done at runtime to support cross compilation.
std::uint32_t RTNAME(MapException)(std::uint32_t excepts);

} // extern "C"
} // namespace Fortran::runtime
Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Runtime/magic-numbers.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,10 @@ The denorm value is a nonstandard extension.
#define _FORTRAN_RUNTIME_IEEE_OVERFLOW 8
#define _FORTRAN_RUNTIME_IEEE_UNDERFLOW 16
#define _FORTRAN_RUNTIME_IEEE_INEXACT 32
#define _FORTRAN_RUNTIME_IEEE_ALL \
_FORTRAN_RUNTIME_IEEE_INVALID | _FORTRAN_RUNTIME_IEEE_DENORM | \
_FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO | _FORTRAN_RUNTIME_IEEE_OVERFLOW | \
_FORTRAN_RUNTIME_IEEE_UNDERFLOW | _FORTRAN_RUNTIME_IEEE_INEXACT

#if 0
ieee_round_type values
Expand Down
4 changes: 3 additions & 1 deletion flang/lib/Evaluate/real.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -330,12 +330,12 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::SQRT(Rounding rounding) const {
template <typename W, int P>
ValueWithRealFlags<Real<W, P>> Real<W, P>::NEAREST(bool upward) const {
ValueWithRealFlags<Real> result;
bool isNegative{IsNegative()};
if (IsFinite()) {
Fraction fraction{GetFraction()};
int expo{Exponent()};
Fraction one{1};
Fraction nearest;
bool isNegative{IsNegative()};
if (upward != isNegative) { // upward in magnitude
auto next{fraction.AddUnsigned(one)};
if (next.carry) {
Expand All @@ -359,6 +359,8 @@ ValueWithRealFlags<Real<W, P>> Real<W, P>::NEAREST(bool upward) const {
}
}
result.flags = result.value.Normalize(isNegative, expo, nearest);
} else if (IsInfinite() && upward == isNegative) {
result.value = isNegative ? HUGE().Negate() : HUGE(); // largest mag finite
} else {
result.flags.set(RealFlag::InvalidArgument);
result.value = *this;
Expand Down
Loading
Loading