-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang] Fold IEEE_SUPPORT_xxx() intrinsic functions #95866
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
Conversation
@llvm/pr-subscribers-flang-semantics Author: Peter Klausler (klausler) ChangesAll of the IEEE_SUPPORT_xxx() intrinsic functions must fold to constant logical values when they have constant arguments; and since they fold to .TRUE. for currently support architectures, always fold them. But also put in the infrastructure whereby a driver can initialize Evaluate's target information to set some of them to .FALSE. if that becomes necessary. Patch is 185.06 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/95866.diff 20 Files Affected:
diff --git a/flang/include/flang/Common/Fortran.h b/flang/include/flang/Common/Fortran.h
index 0701e3e8b64cc..5b2ed43a8f99c 100644
--- a/flang/include/flang/Common/Fortran.h
+++ b/flang/include/flang/Common/Fortran.h
@@ -67,12 +67,14 @@ ENUM_CLASS(
const char *AsFortran(DefinedIo);
// Floating-point rounding modes; these are packed into a byte to save
-// room in the runtime's format processing context structure.
+// room in the runtime's format processing context structure. These
+// enumerators are defined with the corresponding values returned from
+// llvm.get.rounding.
enum class RoundingMode : std::uint8_t {
- TiesToEven, // ROUND=NEAREST, RN - default IEEE rounding
ToZero, // ROUND=ZERO, RZ - truncation
- Down, // ROUND=DOWN, RD
+ TiesToEven, // ROUND=NEAREST, RN - default IEEE rounding
Up, // ROUND=UP, RU
+ Down, // ROUND=DOWN, RD
TiesAwayFromZero, // ROUND=COMPATIBLE, RC - ties round away from zero
};
diff --git a/flang/include/flang/Evaluate/common.h b/flang/include/flang/Evaluate/common.h
index c2c7711c4684e..d493e5fe04417 100644
--- a/flang/include/flang/Evaluate/common.h
+++ b/flang/include/flang/Evaluate/common.h
@@ -128,9 +128,9 @@ static constexpr bool Satisfies(RelationalOperator op, Relation relation) {
return false; // silence g++ warning
}
-ENUM_CLASS(
- RealFlag, Overflow, DivideByZero, InvalidArgument, Underflow, Inexact)
-
+// These are ordered like the bits in a common fenv.h header file.
+ENUM_CLASS(RealFlag, InvalidArgument, Denorm, DivideByZero, Overflow, Underflow,
+ Inexact)
using RealFlags = common::EnumSet<RealFlag, RealFlag_enumSize>;
template <typename A> struct ValueWithRealFlags {
diff --git a/flang/include/flang/Evaluate/target.h b/flang/include/flang/Evaluate/target.h
index 10033d02a5409..d076fcbf08307 100644
--- a/flang/include/flang/Evaluate/target.h
+++ b/flang/include/flang/Evaluate/target.h
@@ -13,6 +13,8 @@
#define FORTRAN_EVALUATE_TARGET_H_
#include "flang/Common/Fortran.h"
+#include "flang/Common/enum-class.h"
+#include "flang/Common/enum-set.h"
#include "flang/Evaluate/common.h"
#include <cstdint>
@@ -32,6 +34,11 @@ struct Rounding {
#endif
};
+ENUM_CLASS(IeeeFeature, Denormal, Divide, Flags, Halting, Inf, Io, NaN,
+ Rounding, Sqrt, Standard, Subnormal, UnderflowControl)
+
+using IeeeFeatures = common::EnumSet<IeeeFeature, 16>;
+
class TargetCharacteristics {
public:
TargetCharacteristics();
@@ -95,6 +102,9 @@ class TargetCharacteristics {
bool isPPC() const { return isPPC_; }
void set_isPPC(bool isPPC = false);
+ IeeeFeatures &ieeeFeatures() { return ieeeFeatures_; }
+ const IeeeFeatures &ieeeFeatures() const { return ieeeFeatures_; }
+
private:
static constexpr int maxKind{32};
std::uint8_t byteSize_[common::TypeCategory_enumSize][maxKind]{};
@@ -110,6 +120,11 @@ class TargetCharacteristics {
std::size_t maxAlignment_{8 /*at least*/};
std::string compilerOptionsString_;
std::string compilerVersionString_;
+ IeeeFeatures ieeeFeatures_{IeeeFeature::Denormal, IeeeFeature::Divide,
+ IeeeFeature::Flags, IeeeFeature::Halting, IeeeFeature::Inf,
+ IeeeFeature::Io, IeeeFeature::NaN, IeeeFeature::Rounding,
+ IeeeFeature::Sqrt, IeeeFeature::Standard, IeeeFeature::Subnormal,
+ IeeeFeature::UnderflowControl};
};
} // namespace Fortran::evaluate
diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index 378a5fca03264..35640c283f52d 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -1320,6 +1320,10 @@ bool IsBuiltinCPtr(const Symbol &);
bool IsEventType(const DerivedTypeSpec *);
bool IsLockType(const DerivedTypeSpec *);
bool IsNotifyType(const DerivedTypeSpec *);
+// Is this derived type IEEE_FLAG_TYPE from module ISO_IEEE_EXCEPTIONS?
+bool IsIeeeFlagType(const DerivedTypeSpec *);
+// Is this derived type IEEE_ROUND_TYPE from module ISO_IEEE_ARITHMETIC?
+bool IsIeeeRoundType(const DerivedTypeSpec *);
// Is this derived type TEAM_TYPE from module ISO_FORTRAN_ENV?
bool IsTeamType(const DerivedTypeSpec *);
// Is this derived type TEAM_TYPE, C_PTR, or C_FUNPTR?
diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index ec1fb411ff0e2..d3c44d00b79f9 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -275,10 +275,6 @@ struct IntrinsicLibrary {
mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
llvm::ArrayRef<mlir::Value>);
mlir::Value genIeeeSignbit(mlir::Type, llvm::ArrayRef<mlir::Value>);
- fir::ExtendedValue
- genIeeeSupportFlagOrHalting(mlir::Type,
- llvm::ArrayRef<fir::ExtendedValue>);
- mlir::Value genIeeeSupportRounding(mlir::Type, llvm::ArrayRef<mlir::Value>);
template <mlir::arith::CmpIPredicate pred>
mlir::Value genIeeeTypeCompare(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIeeeUnordered(mlir::Type, llvm::ArrayRef<mlir::Value>);
diff --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp
index a7c655b72f56e..37c2ae6c6bbe5 100644
--- a/flang/lib/Evaluate/fold-logical.cpp
+++ b/flang/lib/Evaluate/fold-logical.cpp
@@ -831,17 +831,44 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
}
}
}
- } else if (name == "__builtin_ieee_support_datatype" ||
- name == "__builtin_ieee_support_denormal" ||
- name == "__builtin_ieee_support_divide" ||
- name == "__builtin_ieee_support_inf" ||
- name == "__builtin_ieee_support_io" ||
- name == "__builtin_ieee_support_nan" ||
- name == "__builtin_ieee_support_sqrt" ||
- name == "__builtin_ieee_support_standard" ||
- name == "__builtin_ieee_support_subnormal" ||
- name == "__builtin_ieee_support_underflow_control") {
+ } else if (name == "__builtin_ieee_support_datatype") {
return Expr<T>{true};
+ } else if (name == "__builtin_ieee_support_denormal") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Denormal)};
+ } else if (name == "__builtin_ieee_support_divide") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Divide)};
+ } else if (name == "__builtin_ieee_support_flag") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Flags)};
+ } else if (name == "__builtin_ieee_support_halting") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Halting)};
+ } else if (name == "__builtin_ieee_support_inf") {
+ return Expr<T>{
+ context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Inf)};
+ } else if (name == "__builtin_ieee_support_io") {
+ return Expr<T>{
+ context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Io)};
+ } else if (name == "__builtin_ieee_support_nan") {
+ return Expr<T>{
+ context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::NaN)};
+ } else if (name == "__builtin_ieee_support_rounding") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Rounding)};
+ } else if (name == "__builtin_ieee_support_sqrt") {
+ return Expr<T>{
+ context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Sqrt)};
+ } else if (name == "__builtin_ieee_support_standard") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Standard)};
+ } else if (name == "__builtin_ieee_support_subnormal") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Subnormal)};
+ } else if (name == "__builtin_ieee_support_underflow_control") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::UnderflowControl)};
}
return Expr<T>{std::move(funcRef)};
}
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index ace316174a892..5b3dcd65ecd55 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -88,6 +88,8 @@ ENUM_CLASS(KindCode, none, defaultIntegerKind,
sameKind,
operand, // match any kind, with promotion (non-standard)
typeless, // BOZ literals are INTEGER with this kind
+ ieeeFlagType, // IEEE_FLAG_TYPE from ISO_FORTRAN_EXCEPTION
+ ieeeRoundType, // IEEE_ROUND_TYPE from ISO_FORTRAN_ARITHMETIC
teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
kindArg, // this argument is KIND=
effectiveKind, // for function results: "kindArg" value, possibly defaulted
@@ -121,6 +123,9 @@ static constexpr TypePattern DefaultChar{CharType, KindCode::defaultCharKind};
static constexpr TypePattern DefaultLogical{
LogicalType, KindCode::defaultLogicalKind};
static constexpr TypePattern BOZ{IntType, KindCode::typeless};
+static constexpr TypePattern IeeeFlagType{DerivedType, KindCode::ieeeFlagType};
+static constexpr TypePattern IeeeRoundType{
+ DerivedType, KindCode::ieeeRoundType};
static constexpr TypePattern TeamType{DerivedType, KindCode::teamType};
static constexpr TypePattern DoublePrecision{
RealType, KindCode::doublePrecision};
@@ -940,6 +945,12 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"__builtin_ieee_support_divide",
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
DefaultLogical},
+ {"__builtin_ieee_support_flag",
+ {{"flag", IeeeFlagType, Rank::scalar},
+ {"x", AnyReal, Rank::elemental, Optionality::optional}},
+ DefaultLogical},
+ {"__builtin_ieee_support_halting", {{"flag", IeeeFlagType, Rank::scalar}},
+ DefaultLogical},
{"__builtin_ieee_support_inf",
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
DefaultLogical},
@@ -949,6 +960,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"__builtin_ieee_support_nan",
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
DefaultLogical},
+ {"__builtin_ieee_support_rounding",
+ {{"round_value", IeeeRoundType, Rank::scalar},
+ {"x", AnyReal, Rank::elemental, Optionality::optional}},
+ DefaultLogical},
{"__builtin_ieee_support_sqrt",
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
DefaultLogical},
@@ -1851,6 +1866,16 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
case KindCode::typeless:
argOk = false;
break;
+ case KindCode::ieeeFlagType:
+ argOk = !type->IsUnlimitedPolymorphic() &&
+ type->category() == TypeCategory::Derived &&
+ semantics::IsIeeeFlagType(&type->GetDerivedTypeSpec());
+ break;
+ case KindCode::ieeeRoundType:
+ argOk = !type->IsUnlimitedPolymorphic() &&
+ type->category() == TypeCategory::Derived &&
+ semantics::IsIeeeRoundType(&type->GetDerivedTypeSpec());
+ break;
case KindCode::teamType:
argOk = !type->IsUnlimitedPolymorphic() &&
type->category() == TypeCategory::Derived &&
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 4699c5312868c..19fabb693a1ce 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1790,6 +1790,14 @@ bool IsNotifyType(const DerivedTypeSpec *derived) {
return IsBuiltinDerivedType(derived, "notify_type");
}
+bool IsIeeeFlagType(const DerivedTypeSpec *derived) {
+ return IsBuiltinDerivedType(derived, "ieee_flag_type");
+}
+
+bool IsIeeeRoundType(const DerivedTypeSpec *derived) {
+ return IsBuiltinDerivedType(derived, "ieee_round_type");
+}
+
bool IsTeamType(const DerivedTypeSpec *derived) {
return IsBuiltinDerivedType(derived, "team_type");
}
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 3204369b9328a..6f1c43ed74540 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -373,12 +373,6 @@ static constexpr IntrinsicHandler handlers[]{
{"ieee_signaling_ne",
&I::genIeeeSignalingCompare<mlir::arith::CmpFPredicate::UNE>},
{"ieee_signbit", &I::genIeeeSignbit},
- {"ieee_support_flag",
- &I::genIeeeSupportFlagOrHalting,
- {{{"flag", asValue}, {"x", asInquired, handleDynamicOptional}}},
- /*isElemental=*/false},
- {"ieee_support_halting", &I::genIeeeSupportFlagOrHalting},
- {"ieee_support_rounding", &I::genIeeeSupportRounding},
{"ieee_unordered", &I::genIeeeUnordered},
{"ieee_value", &I::genIeeeValue},
{"ieor", &I::genIeor},
@@ -4710,57 +4704,6 @@ mlir::Value IntrinsicLibrary::genIeeeSignbit(mlir::Type resultType,
return builder.createConvert(loc, resultType, sign);
}
-// IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING
-fir::ExtendedValue IntrinsicLibrary::genIeeeSupportFlagOrHalting(
- mlir::Type resultType, llvm::ArrayRef<fir::ExtendedValue> args) {
- // Check if a floating point exception or halting mode FLAG is supported.
- // An IEEE_SUPPORT_FLAG flag is supported either for all type kinds or none.
- // An optional kind argument X is therefore ignored.
- // Standard flags are all supported.
- // The nonstandard DENORM extension is not supported. (At least for now.)
- assert(args.size() == 1 || args.size() == 2);
- auto [fieldRef, fieldTy] = getFieldRef(builder, loc, fir::getBase(args[0]));
- mlir::Value flag = builder.create<fir::LoadOp>(loc, fieldRef);
- mlir::Value mask = builder.createIntegerConstant( // values are powers of 2
- loc, fieldTy,
- _FORTRAN_RUNTIME_IEEE_INVALID | _FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO |
- _FORTRAN_RUNTIME_IEEE_OVERFLOW | _FORTRAN_RUNTIME_IEEE_UNDERFLOW |
- _FORTRAN_RUNTIME_IEEE_INEXACT);
- return builder.createConvert(
- loc, resultType,
- builder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::ne,
- builder.create<mlir::arith::AndIOp>(loc, flag, mask),
- builder.createIntegerConstant(loc, fieldTy, 0)));
-}
-
-// IEEE_SUPPORT_ROUNDING
-mlir::Value
-IntrinsicLibrary::genIeeeSupportRounding(mlir::Type resultType,
- llvm::ArrayRef<mlir::Value> args) {
- // Check if floating point rounding mode ROUND_VALUE is supported.
- // Rounding is supported either for all type kinds or none.
- // An optional X kind argument is therefore ignored.
- // Values are chosen to match the llvm.get.rounding encoding:
- // 0 - toward zero [supported]
- // 1 - to nearest, ties to even [supported] - default
- // 2 - toward positive infinity [supported]
- // 3 - toward negative infinity [supported]
- // 4 - to nearest, ties away from zero [not supported]
- assert(args.size() == 1 || args.size() == 2);
- auto [fieldRef, fieldTy] = getFieldRef(builder, loc, args[0]);
- mlir::Value mode = builder.create<fir::LoadOp>(loc, fieldRef);
- mlir::Value lbOk = builder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::sge, mode,
- builder.createIntegerConstant(loc, fieldTy,
- _FORTRAN_RUNTIME_IEEE_TO_ZERO));
- mlir::Value ubOk = builder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::sle, mode,
- builder.createIntegerConstant(loc, fieldTy, _FORTRAN_RUNTIME_IEEE_DOWN));
- return builder.createConvert(
- loc, resultType, builder.create<mlir::arith::AndIOp>(loc, lbOk, ubOk));
-}
-
// IEEE_UNORDERED
mlir::Value
IntrinsicLibrary::genIeeeUnordered(mlir::Type resultType,
diff --git a/flang/module/__fortran_builtins.f90 b/flang/module/__fortran_builtins.f90
index 4746ca20a13a7..b33d843710127 100644
--- a/flang/module/__fortran_builtins.f90
+++ b/flang/module/__fortran_builtins.f90
@@ -6,6 +6,8 @@
!
!===------------------------------------------------------------------------===!
+include '../include/flang/Runtime/magic-numbers.h'
+
! These naming shenanigans prevent names from Fortran intrinsic modules
! from being usable on INTRINSIC statements, and force the program
! to USE the standard intrinsic modules in order to access the
@@ -49,6 +51,42 @@
integer(kind=int64), private :: __count
end type
+ type, public :: __builtin_ieee_flag_type
+ integer(kind=1), private :: flag = 0
+ end type
+
+ type(__builtin_ieee_flag_type), parameter, public :: &
+ __builtin_ieee_invalid = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_INVALID), &
+ __builtin_ieee_overflow = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_OVERFLOW), &
+ __builtin_ieee_divide_by_zero = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO), &
+ __builtin_ieee_underflow = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_UNDERFLOW), &
+ __builtin_ieee_inexact = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_INEXACT), &
+ __builtin_ieee_denorm = & ! extension
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_DENORM)
+
+ type, public :: __builtin_ieee_round_type
+ integer(kind=1), private :: mode = 0
+ end type
+
+ type(__builtin_ieee_round_type), parameter, public :: &
+ __builtin_ieee_to_zero = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_TO_ZERO), &
+ __builtin_ieee_nearest = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_NEAREST), &
+ __builtin_ieee_up = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_UP), &
+ __builtin_ieee_down = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_DOWN), &
+ __builtin_ieee_away = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_AWAY), &
+ __builtin_ieee_other = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_OTHER)
+
type, public :: __builtin_team_type
integer(kind=int64), private :: __id
end type
@@ -74,8 +112,10 @@
intrinsic :: __builtin_ieee_selected_real_kind
intrinsic :: __builtin_ieee_support_datatype, &
__builtin_ieee_support_denormal, __builtin_ieee_support_divide, &
+ __builtin_ieee_support_flag, __builtin_ieee_support_halting, &
__builtin_ieee_support_inf, __builtin_ieee_support_io, &
- __builtin_ieee_support_nan, __builtin_ieee_support_sqrt, &
+ __builtin_ieee_support_nan, __builtin_ieee_support_rounding, &
+ __builtin_ieee_support_sqrt, &
__builtin_ieee_support_standard, __builtin_ieee_support_subnormal, &
__builtin_ieee_support_underflow_control
public :: __builtin_fma
@@ -87,8 +127,10 @@
public :: __builtin_ieee_selected_real_kind
public :: __builtin_ieee_support_datatype, &
__builtin_ieee_support_denormal, __builtin_ieee_support_divide, &
+ __builtin_ieee_support_flag, __builtin_ieee_support_halting, &
__builtin_ieee_support_inf, __builtin_ieee_support_io, &
- __builtin_ieee_support_nan, __builtin_ieee_support_sqrt, &
+ __builtin_ieee_support_nan, __builtin_ieee_support_rounding, &
+ __builtin_ieee_support_sqrt, &
__builtin_ieee_support_standard, __builtin_ieee_support_subnormal, &
__builtin_ieee_support_underflow_control
diff --git a/flang/module/__fortran_ieee_exceptions.f90 b/flang/module/__fortran_ieee_exceptions.f90
index afcd183553192..810a2b0e400f2 100644
--- a/flang/module/__fortran_ieee_exceptions.f90
+++ b/flang/module/__fortran_ieee_exceptions.f90
@@ -14,25 +14,22 @@
include '../include/flang/Runtime/magic-numbers.h'
module __fortran_ieee_exceptions
+ use __fortran_builtins, only: &
+ ieee_flag_type => __builtin_ieee_flag_type, &
+ ieee_support_flag => __builtin_ieee_support_flag, &
+ ieee_support_halting => __builtin_ieee_support_halting, &
+ ieee_invalid => __builtin_ieee_invalid, &
+ ieee_overflow => __builtin_ieee_overflow, &
+ ieee_divide_by_zero => __builtin_ieee_divide_by_zero, &
+ ieee_underflow => __builtin_ieee_underflow, &
+ ieee_inexact => __builtin_ieee_inexact, &
+ ieee_denorm => __builtin_ieee_denorm
implicit none
-
- ! Set PRIVATE by default to explicitly only export what is meant
- ! to be exported by this MODULE.
private
- type, public :: ieee_flag_type ! Fortran 2018, 17.2 & 17.3
- private
- integer(kind=1) :: flag = 0
- end type ieee_flag_type
-
- type(ieee_flag_type), parameter, public :: &
- ieee_invalid = ieee_flag_type(_FORTRAN_RUNTIME_IEEE_INVALID), &
- ieee_overflow = ieee_flag_t...
[truncated]
|
@llvm/pr-subscribers-flang-fir-hlfir Author: Peter Klausler (klausler) ChangesAll of the IEEE_SUPPORT_xxx() intrinsic functions must fold to constant logical values when they have constant arguments; and since they fold to .TRUE. for currently support architectures, always fold them. But also put in the infrastructure whereby a driver can initialize Evaluate's target information to set some of them to .FALSE. if that becomes necessary. Patch is 185.06 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/95866.diff 20 Files Affected:
diff --git a/flang/include/flang/Common/Fortran.h b/flang/include/flang/Common/Fortran.h
index 0701e3e8b64cc..5b2ed43a8f99c 100644
--- a/flang/include/flang/Common/Fortran.h
+++ b/flang/include/flang/Common/Fortran.h
@@ -67,12 +67,14 @@ ENUM_CLASS(
const char *AsFortran(DefinedIo);
// Floating-point rounding modes; these are packed into a byte to save
-// room in the runtime's format processing context structure.
+// room in the runtime's format processing context structure. These
+// enumerators are defined with the corresponding values returned from
+// llvm.get.rounding.
enum class RoundingMode : std::uint8_t {
- TiesToEven, // ROUND=NEAREST, RN - default IEEE rounding
ToZero, // ROUND=ZERO, RZ - truncation
- Down, // ROUND=DOWN, RD
+ TiesToEven, // ROUND=NEAREST, RN - default IEEE rounding
Up, // ROUND=UP, RU
+ Down, // ROUND=DOWN, RD
TiesAwayFromZero, // ROUND=COMPATIBLE, RC - ties round away from zero
};
diff --git a/flang/include/flang/Evaluate/common.h b/flang/include/flang/Evaluate/common.h
index c2c7711c4684e..d493e5fe04417 100644
--- a/flang/include/flang/Evaluate/common.h
+++ b/flang/include/flang/Evaluate/common.h
@@ -128,9 +128,9 @@ static constexpr bool Satisfies(RelationalOperator op, Relation relation) {
return false; // silence g++ warning
}
-ENUM_CLASS(
- RealFlag, Overflow, DivideByZero, InvalidArgument, Underflow, Inexact)
-
+// These are ordered like the bits in a common fenv.h header file.
+ENUM_CLASS(RealFlag, InvalidArgument, Denorm, DivideByZero, Overflow, Underflow,
+ Inexact)
using RealFlags = common::EnumSet<RealFlag, RealFlag_enumSize>;
template <typename A> struct ValueWithRealFlags {
diff --git a/flang/include/flang/Evaluate/target.h b/flang/include/flang/Evaluate/target.h
index 10033d02a5409..d076fcbf08307 100644
--- a/flang/include/flang/Evaluate/target.h
+++ b/flang/include/flang/Evaluate/target.h
@@ -13,6 +13,8 @@
#define FORTRAN_EVALUATE_TARGET_H_
#include "flang/Common/Fortran.h"
+#include "flang/Common/enum-class.h"
+#include "flang/Common/enum-set.h"
#include "flang/Evaluate/common.h"
#include <cstdint>
@@ -32,6 +34,11 @@ struct Rounding {
#endif
};
+ENUM_CLASS(IeeeFeature, Denormal, Divide, Flags, Halting, Inf, Io, NaN,
+ Rounding, Sqrt, Standard, Subnormal, UnderflowControl)
+
+using IeeeFeatures = common::EnumSet<IeeeFeature, 16>;
+
class TargetCharacteristics {
public:
TargetCharacteristics();
@@ -95,6 +102,9 @@ class TargetCharacteristics {
bool isPPC() const { return isPPC_; }
void set_isPPC(bool isPPC = false);
+ IeeeFeatures &ieeeFeatures() { return ieeeFeatures_; }
+ const IeeeFeatures &ieeeFeatures() const { return ieeeFeatures_; }
+
private:
static constexpr int maxKind{32};
std::uint8_t byteSize_[common::TypeCategory_enumSize][maxKind]{};
@@ -110,6 +120,11 @@ class TargetCharacteristics {
std::size_t maxAlignment_{8 /*at least*/};
std::string compilerOptionsString_;
std::string compilerVersionString_;
+ IeeeFeatures ieeeFeatures_{IeeeFeature::Denormal, IeeeFeature::Divide,
+ IeeeFeature::Flags, IeeeFeature::Halting, IeeeFeature::Inf,
+ IeeeFeature::Io, IeeeFeature::NaN, IeeeFeature::Rounding,
+ IeeeFeature::Sqrt, IeeeFeature::Standard, IeeeFeature::Subnormal,
+ IeeeFeature::UnderflowControl};
};
} // namespace Fortran::evaluate
diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h
index 378a5fca03264..35640c283f52d 100644
--- a/flang/include/flang/Evaluate/tools.h
+++ b/flang/include/flang/Evaluate/tools.h
@@ -1320,6 +1320,10 @@ bool IsBuiltinCPtr(const Symbol &);
bool IsEventType(const DerivedTypeSpec *);
bool IsLockType(const DerivedTypeSpec *);
bool IsNotifyType(const DerivedTypeSpec *);
+// Is this derived type IEEE_FLAG_TYPE from module ISO_IEEE_EXCEPTIONS?
+bool IsIeeeFlagType(const DerivedTypeSpec *);
+// Is this derived type IEEE_ROUND_TYPE from module ISO_IEEE_ARITHMETIC?
+bool IsIeeeRoundType(const DerivedTypeSpec *);
// Is this derived type TEAM_TYPE from module ISO_FORTRAN_ENV?
bool IsTeamType(const DerivedTypeSpec *);
// Is this derived type TEAM_TYPE, C_PTR, or C_FUNPTR?
diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
index ec1fb411ff0e2..d3c44d00b79f9 100644
--- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
+++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h
@@ -275,10 +275,6 @@ struct IntrinsicLibrary {
mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
llvm::ArrayRef<mlir::Value>);
mlir::Value genIeeeSignbit(mlir::Type, llvm::ArrayRef<mlir::Value>);
- fir::ExtendedValue
- genIeeeSupportFlagOrHalting(mlir::Type,
- llvm::ArrayRef<fir::ExtendedValue>);
- mlir::Value genIeeeSupportRounding(mlir::Type, llvm::ArrayRef<mlir::Value>);
template <mlir::arith::CmpIPredicate pred>
mlir::Value genIeeeTypeCompare(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genIeeeUnordered(mlir::Type, llvm::ArrayRef<mlir::Value>);
diff --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp
index a7c655b72f56e..37c2ae6c6bbe5 100644
--- a/flang/lib/Evaluate/fold-logical.cpp
+++ b/flang/lib/Evaluate/fold-logical.cpp
@@ -831,17 +831,44 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
}
}
}
- } else if (name == "__builtin_ieee_support_datatype" ||
- name == "__builtin_ieee_support_denormal" ||
- name == "__builtin_ieee_support_divide" ||
- name == "__builtin_ieee_support_inf" ||
- name == "__builtin_ieee_support_io" ||
- name == "__builtin_ieee_support_nan" ||
- name == "__builtin_ieee_support_sqrt" ||
- name == "__builtin_ieee_support_standard" ||
- name == "__builtin_ieee_support_subnormal" ||
- name == "__builtin_ieee_support_underflow_control") {
+ } else if (name == "__builtin_ieee_support_datatype") {
return Expr<T>{true};
+ } else if (name == "__builtin_ieee_support_denormal") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Denormal)};
+ } else if (name == "__builtin_ieee_support_divide") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Divide)};
+ } else if (name == "__builtin_ieee_support_flag") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Flags)};
+ } else if (name == "__builtin_ieee_support_halting") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Halting)};
+ } else if (name == "__builtin_ieee_support_inf") {
+ return Expr<T>{
+ context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Inf)};
+ } else if (name == "__builtin_ieee_support_io") {
+ return Expr<T>{
+ context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Io)};
+ } else if (name == "__builtin_ieee_support_nan") {
+ return Expr<T>{
+ context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::NaN)};
+ } else if (name == "__builtin_ieee_support_rounding") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Rounding)};
+ } else if (name == "__builtin_ieee_support_sqrt") {
+ return Expr<T>{
+ context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Sqrt)};
+ } else if (name == "__builtin_ieee_support_standard") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Standard)};
+ } else if (name == "__builtin_ieee_support_subnormal") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::Subnormal)};
+ } else if (name == "__builtin_ieee_support_underflow_control") {
+ return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
+ IeeeFeature::UnderflowControl)};
}
return Expr<T>{std::move(funcRef)};
}
diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp
index ace316174a892..5b3dcd65ecd55 100644
--- a/flang/lib/Evaluate/intrinsics.cpp
+++ b/flang/lib/Evaluate/intrinsics.cpp
@@ -88,6 +88,8 @@ ENUM_CLASS(KindCode, none, defaultIntegerKind,
sameKind,
operand, // match any kind, with promotion (non-standard)
typeless, // BOZ literals are INTEGER with this kind
+ ieeeFlagType, // IEEE_FLAG_TYPE from ISO_FORTRAN_EXCEPTION
+ ieeeRoundType, // IEEE_ROUND_TYPE from ISO_FORTRAN_ARITHMETIC
teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
kindArg, // this argument is KIND=
effectiveKind, // for function results: "kindArg" value, possibly defaulted
@@ -121,6 +123,9 @@ static constexpr TypePattern DefaultChar{CharType, KindCode::defaultCharKind};
static constexpr TypePattern DefaultLogical{
LogicalType, KindCode::defaultLogicalKind};
static constexpr TypePattern BOZ{IntType, KindCode::typeless};
+static constexpr TypePattern IeeeFlagType{DerivedType, KindCode::ieeeFlagType};
+static constexpr TypePattern IeeeRoundType{
+ DerivedType, KindCode::ieeeRoundType};
static constexpr TypePattern TeamType{DerivedType, KindCode::teamType};
static constexpr TypePattern DoublePrecision{
RealType, KindCode::doublePrecision};
@@ -940,6 +945,12 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"__builtin_ieee_support_divide",
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
DefaultLogical},
+ {"__builtin_ieee_support_flag",
+ {{"flag", IeeeFlagType, Rank::scalar},
+ {"x", AnyReal, Rank::elemental, Optionality::optional}},
+ DefaultLogical},
+ {"__builtin_ieee_support_halting", {{"flag", IeeeFlagType, Rank::scalar}},
+ DefaultLogical},
{"__builtin_ieee_support_inf",
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
DefaultLogical},
@@ -949,6 +960,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"__builtin_ieee_support_nan",
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
DefaultLogical},
+ {"__builtin_ieee_support_rounding",
+ {{"round_value", IeeeRoundType, Rank::scalar},
+ {"x", AnyReal, Rank::elemental, Optionality::optional}},
+ DefaultLogical},
{"__builtin_ieee_support_sqrt",
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
DefaultLogical},
@@ -1851,6 +1866,16 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
case KindCode::typeless:
argOk = false;
break;
+ case KindCode::ieeeFlagType:
+ argOk = !type->IsUnlimitedPolymorphic() &&
+ type->category() == TypeCategory::Derived &&
+ semantics::IsIeeeFlagType(&type->GetDerivedTypeSpec());
+ break;
+ case KindCode::ieeeRoundType:
+ argOk = !type->IsUnlimitedPolymorphic() &&
+ type->category() == TypeCategory::Derived &&
+ semantics::IsIeeeRoundType(&type->GetDerivedTypeSpec());
+ break;
case KindCode::teamType:
argOk = !type->IsUnlimitedPolymorphic() &&
type->category() == TypeCategory::Derived &&
diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp
index 4699c5312868c..19fabb693a1ce 100644
--- a/flang/lib/Evaluate/tools.cpp
+++ b/flang/lib/Evaluate/tools.cpp
@@ -1790,6 +1790,14 @@ bool IsNotifyType(const DerivedTypeSpec *derived) {
return IsBuiltinDerivedType(derived, "notify_type");
}
+bool IsIeeeFlagType(const DerivedTypeSpec *derived) {
+ return IsBuiltinDerivedType(derived, "ieee_flag_type");
+}
+
+bool IsIeeeRoundType(const DerivedTypeSpec *derived) {
+ return IsBuiltinDerivedType(derived, "ieee_round_type");
+}
+
bool IsTeamType(const DerivedTypeSpec *derived) {
return IsBuiltinDerivedType(derived, "team_type");
}
diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
index 3204369b9328a..6f1c43ed74540 100644
--- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
+++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp
@@ -373,12 +373,6 @@ static constexpr IntrinsicHandler handlers[]{
{"ieee_signaling_ne",
&I::genIeeeSignalingCompare<mlir::arith::CmpFPredicate::UNE>},
{"ieee_signbit", &I::genIeeeSignbit},
- {"ieee_support_flag",
- &I::genIeeeSupportFlagOrHalting,
- {{{"flag", asValue}, {"x", asInquired, handleDynamicOptional}}},
- /*isElemental=*/false},
- {"ieee_support_halting", &I::genIeeeSupportFlagOrHalting},
- {"ieee_support_rounding", &I::genIeeeSupportRounding},
{"ieee_unordered", &I::genIeeeUnordered},
{"ieee_value", &I::genIeeeValue},
{"ieor", &I::genIeor},
@@ -4710,57 +4704,6 @@ mlir::Value IntrinsicLibrary::genIeeeSignbit(mlir::Type resultType,
return builder.createConvert(loc, resultType, sign);
}
-// IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING
-fir::ExtendedValue IntrinsicLibrary::genIeeeSupportFlagOrHalting(
- mlir::Type resultType, llvm::ArrayRef<fir::ExtendedValue> args) {
- // Check if a floating point exception or halting mode FLAG is supported.
- // An IEEE_SUPPORT_FLAG flag is supported either for all type kinds or none.
- // An optional kind argument X is therefore ignored.
- // Standard flags are all supported.
- // The nonstandard DENORM extension is not supported. (At least for now.)
- assert(args.size() == 1 || args.size() == 2);
- auto [fieldRef, fieldTy] = getFieldRef(builder, loc, fir::getBase(args[0]));
- mlir::Value flag = builder.create<fir::LoadOp>(loc, fieldRef);
- mlir::Value mask = builder.createIntegerConstant( // values are powers of 2
- loc, fieldTy,
- _FORTRAN_RUNTIME_IEEE_INVALID | _FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO |
- _FORTRAN_RUNTIME_IEEE_OVERFLOW | _FORTRAN_RUNTIME_IEEE_UNDERFLOW |
- _FORTRAN_RUNTIME_IEEE_INEXACT);
- return builder.createConvert(
- loc, resultType,
- builder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::ne,
- builder.create<mlir::arith::AndIOp>(loc, flag, mask),
- builder.createIntegerConstant(loc, fieldTy, 0)));
-}
-
-// IEEE_SUPPORT_ROUNDING
-mlir::Value
-IntrinsicLibrary::genIeeeSupportRounding(mlir::Type resultType,
- llvm::ArrayRef<mlir::Value> args) {
- // Check if floating point rounding mode ROUND_VALUE is supported.
- // Rounding is supported either for all type kinds or none.
- // An optional X kind argument is therefore ignored.
- // Values are chosen to match the llvm.get.rounding encoding:
- // 0 - toward zero [supported]
- // 1 - to nearest, ties to even [supported] - default
- // 2 - toward positive infinity [supported]
- // 3 - toward negative infinity [supported]
- // 4 - to nearest, ties away from zero [not supported]
- assert(args.size() == 1 || args.size() == 2);
- auto [fieldRef, fieldTy] = getFieldRef(builder, loc, args[0]);
- mlir::Value mode = builder.create<fir::LoadOp>(loc, fieldRef);
- mlir::Value lbOk = builder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::sge, mode,
- builder.createIntegerConstant(loc, fieldTy,
- _FORTRAN_RUNTIME_IEEE_TO_ZERO));
- mlir::Value ubOk = builder.create<mlir::arith::CmpIOp>(
- loc, mlir::arith::CmpIPredicate::sle, mode,
- builder.createIntegerConstant(loc, fieldTy, _FORTRAN_RUNTIME_IEEE_DOWN));
- return builder.createConvert(
- loc, resultType, builder.create<mlir::arith::AndIOp>(loc, lbOk, ubOk));
-}
-
// IEEE_UNORDERED
mlir::Value
IntrinsicLibrary::genIeeeUnordered(mlir::Type resultType,
diff --git a/flang/module/__fortran_builtins.f90 b/flang/module/__fortran_builtins.f90
index 4746ca20a13a7..b33d843710127 100644
--- a/flang/module/__fortran_builtins.f90
+++ b/flang/module/__fortran_builtins.f90
@@ -6,6 +6,8 @@
!
!===------------------------------------------------------------------------===!
+include '../include/flang/Runtime/magic-numbers.h'
+
! These naming shenanigans prevent names from Fortran intrinsic modules
! from being usable on INTRINSIC statements, and force the program
! to USE the standard intrinsic modules in order to access the
@@ -49,6 +51,42 @@
integer(kind=int64), private :: __count
end type
+ type, public :: __builtin_ieee_flag_type
+ integer(kind=1), private :: flag = 0
+ end type
+
+ type(__builtin_ieee_flag_type), parameter, public :: &
+ __builtin_ieee_invalid = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_INVALID), &
+ __builtin_ieee_overflow = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_OVERFLOW), &
+ __builtin_ieee_divide_by_zero = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO), &
+ __builtin_ieee_underflow = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_UNDERFLOW), &
+ __builtin_ieee_inexact = &
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_INEXACT), &
+ __builtin_ieee_denorm = & ! extension
+ __builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_DENORM)
+
+ type, public :: __builtin_ieee_round_type
+ integer(kind=1), private :: mode = 0
+ end type
+
+ type(__builtin_ieee_round_type), parameter, public :: &
+ __builtin_ieee_to_zero = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_TO_ZERO), &
+ __builtin_ieee_nearest = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_NEAREST), &
+ __builtin_ieee_up = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_UP), &
+ __builtin_ieee_down = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_DOWN), &
+ __builtin_ieee_away = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_AWAY), &
+ __builtin_ieee_other = &
+ __builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_OTHER)
+
type, public :: __builtin_team_type
integer(kind=int64), private :: __id
end type
@@ -74,8 +112,10 @@
intrinsic :: __builtin_ieee_selected_real_kind
intrinsic :: __builtin_ieee_support_datatype, &
__builtin_ieee_support_denormal, __builtin_ieee_support_divide, &
+ __builtin_ieee_support_flag, __builtin_ieee_support_halting, &
__builtin_ieee_support_inf, __builtin_ieee_support_io, &
- __builtin_ieee_support_nan, __builtin_ieee_support_sqrt, &
+ __builtin_ieee_support_nan, __builtin_ieee_support_rounding, &
+ __builtin_ieee_support_sqrt, &
__builtin_ieee_support_standard, __builtin_ieee_support_subnormal, &
__builtin_ieee_support_underflow_control
public :: __builtin_fma
@@ -87,8 +127,10 @@
public :: __builtin_ieee_selected_real_kind
public :: __builtin_ieee_support_datatype, &
__builtin_ieee_support_denormal, __builtin_ieee_support_divide, &
+ __builtin_ieee_support_flag, __builtin_ieee_support_halting, &
__builtin_ieee_support_inf, __builtin_ieee_support_io, &
- __builtin_ieee_support_nan, __builtin_ieee_support_sqrt, &
+ __builtin_ieee_support_nan, __builtin_ieee_support_rounding, &
+ __builtin_ieee_support_sqrt, &
__builtin_ieee_support_standard, __builtin_ieee_support_subnormal, &
__builtin_ieee_support_underflow_control
diff --git a/flang/module/__fortran_ieee_exceptions.f90 b/flang/module/__fortran_ieee_exceptions.f90
index afcd183553192..810a2b0e400f2 100644
--- a/flang/module/__fortran_ieee_exceptions.f90
+++ b/flang/module/__fortran_ieee_exceptions.f90
@@ -14,25 +14,22 @@
include '../include/flang/Runtime/magic-numbers.h'
module __fortran_ieee_exceptions
+ use __fortran_builtins, only: &
+ ieee_flag_type => __builtin_ieee_flag_type, &
+ ieee_support_flag => __builtin_ieee_support_flag, &
+ ieee_support_halting => __builtin_ieee_support_halting, &
+ ieee_invalid => __builtin_ieee_invalid, &
+ ieee_overflow => __builtin_ieee_overflow, &
+ ieee_divide_by_zero => __builtin_ieee_divide_by_zero, &
+ ieee_underflow => __builtin_ieee_underflow, &
+ ieee_inexact => __builtin_ieee_inexact, &
+ ieee_denorm => __builtin_ieee_denorm
implicit none
-
- ! Set PRIVATE by default to explicitly only export what is meant
- ! to be exported by this MODULE.
private
- type, public :: ieee_flag_type ! Fortran 2018, 17.2 & 17.3
- private
- integer(kind=1) :: flag = 0
- end type ieee_flag_type
-
- type(ieee_flag_type), parameter, public :: &
- ieee_invalid = ieee_flag_type(_FORTRAN_RUNTIME_IEEE_INVALID), &
- ieee_overflow = ieee_flag_t...
[truncated]
|
@@ -949,6 +960,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ | |||
{"__builtin_ieee_support_nan", | |||
{{"x", AnyReal, Rank::elemental, Optionality::optional}}, | |||
DefaultLogical}, | |||
{"__builtin_ieee_support_rounding", | |||
{{"round_value", IeeeRoundType, Rank::scalar}, | |||
{"x", AnyReal, Rank::elemental, Optionality::optional}}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Double check - Does this function description accommodate an optional array argument X
in addition to a scalar argument X
? That is, is it valid to use implementation type Rank::elemental
in this description for non-elemental , inquiry function ieee_support_rounding
(and similar function descriptions.)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @klausler for cleaning up obsolete lowering code and updating lit tests.
All of the IEEE_SUPPORT_xxx() intrinsic functions must fold to constant logical values when they have constant arguments; and since they fold to .TRUE. for currently support architectures, always fold them. But also put in the infrastructure whereby a driver can initialize Evaluate's target information to set some of them to .FALSE. if that becomes necessary.
All of the IEEE_SUPPORT_xxx() intrinsic functions must fold to constant logical values when they have constant arguments; and since they fold to .TRUE. for currently support architectures, always fold them. But also put in the infrastructure whereby a driver can initialize Evaluate's target information to set some of them to .FALSE. if that becomes necessary.
All of the IEEE_SUPPORT_xxx() intrinsic functions must fold to constant logical values when they have constant arguments; and since they fold to .TRUE. for currently support architectures, always fold them. But also put in the infrastructure whereby a driver can initialize Evaluate's target information to set some of them to .FALSE. if that becomes necessary.