Skip to content

Commit 5843fd5

Browse files
committed
[flang] Fold IEEE_SUPPORT_xxx() intrinsic functions
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.
1 parent 86bee81 commit 5843fd5

File tree

20 files changed

+450
-390
lines changed

20 files changed

+450
-390
lines changed

flang/include/flang/Common/Fortran.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,14 @@ ENUM_CLASS(
6767
const char *AsFortran(DefinedIo);
6868

6969
// Floating-point rounding modes; these are packed into a byte to save
70-
// room in the runtime's format processing context structure.
70+
// room in the runtime's format processing context structure. These
71+
// enumerators are defined with the corresponding values returned from
72+
// llvm.get.rounding.
7173
enum class RoundingMode : std::uint8_t {
72-
TiesToEven, // ROUND=NEAREST, RN - default IEEE rounding
7374
ToZero, // ROUND=ZERO, RZ - truncation
74-
Down, // ROUND=DOWN, RD
75+
TiesToEven, // ROUND=NEAREST, RN - default IEEE rounding
7576
Up, // ROUND=UP, RU
77+
Down, // ROUND=DOWN, RD
7678
TiesAwayFromZero, // ROUND=COMPATIBLE, RC - ties round away from zero
7779
};
7880

flang/include/flang/Evaluate/common.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ static constexpr bool Satisfies(RelationalOperator op, Relation relation) {
128128
return false; // silence g++ warning
129129
}
130130

131-
ENUM_CLASS(
132-
RealFlag, Overflow, DivideByZero, InvalidArgument, Underflow, Inexact)
133-
131+
// These are ordered like the bits in a common fenv.h header file.
132+
ENUM_CLASS(RealFlag, InvalidArgument, Denorm, DivideByZero, Overflow, Underflow,
133+
Inexact)
134134
using RealFlags = common::EnumSet<RealFlag, RealFlag_enumSize>;
135135

136136
template <typename A> struct ValueWithRealFlags {

flang/include/flang/Evaluate/target.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#define FORTRAN_EVALUATE_TARGET_H_
1414

1515
#include "flang/Common/Fortran.h"
16+
#include "flang/Common/enum-class.h"
17+
#include "flang/Common/enum-set.h"
1618
#include "flang/Evaluate/common.h"
1719
#include <cstdint>
1820

@@ -32,6 +34,11 @@ struct Rounding {
3234
#endif
3335
};
3436

37+
ENUM_CLASS(IeeeFeature, Denormal, Divide, Flags, Halting, Inf, Io, NaN,
38+
Rounding, Sqrt, Standard, Subnormal, UnderflowControl)
39+
40+
using IeeeFeatures = common::EnumSet<IeeeFeature, 16>;
41+
3542
class TargetCharacteristics {
3643
public:
3744
TargetCharacteristics();
@@ -95,6 +102,9 @@ class TargetCharacteristics {
95102
bool isPPC() const { return isPPC_; }
96103
void set_isPPC(bool isPPC = false);
97104

105+
IeeeFeatures &ieeeFeatures() { return ieeeFeatures_; }
106+
const IeeeFeatures &ieeeFeatures() const { return ieeeFeatures_; }
107+
98108
private:
99109
static constexpr int maxKind{32};
100110
std::uint8_t byteSize_[common::TypeCategory_enumSize][maxKind]{};
@@ -110,6 +120,11 @@ class TargetCharacteristics {
110120
std::size_t maxAlignment_{8 /*at least*/};
111121
std::string compilerOptionsString_;
112122
std::string compilerVersionString_;
123+
IeeeFeatures ieeeFeatures_{IeeeFeature::Denormal, IeeeFeature::Divide,
124+
IeeeFeature::Flags, IeeeFeature::Halting, IeeeFeature::Inf,
125+
IeeeFeature::Io, IeeeFeature::NaN, IeeeFeature::Rounding,
126+
IeeeFeature::Sqrt, IeeeFeature::Standard, IeeeFeature::Subnormal,
127+
IeeeFeature::UnderflowControl};
113128
};
114129

115130
} // namespace Fortran::evaluate

flang/include/flang/Evaluate/tools.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,10 @@ bool IsBuiltinCPtr(const Symbol &);
13201320
bool IsEventType(const DerivedTypeSpec *);
13211321
bool IsLockType(const DerivedTypeSpec *);
13221322
bool IsNotifyType(const DerivedTypeSpec *);
1323+
// Is this derived type IEEE_FLAG_TYPE from module ISO_IEEE_EXCEPTIONS?
1324+
bool IsIeeeFlagType(const DerivedTypeSpec *);
1325+
// Is this derived type IEEE_ROUND_TYPE from module ISO_IEEE_ARITHMETIC?
1326+
bool IsIeeeRoundType(const DerivedTypeSpec *);
13231327
// Is this derived type TEAM_TYPE from module ISO_FORTRAN_ENV?
13241328
bool IsTeamType(const DerivedTypeSpec *);
13251329
// Is this derived type TEAM_TYPE, C_PTR, or C_FUNPTR?

flang/include/flang/Optimizer/Builder/IntrinsicCall.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,6 @@ struct IntrinsicLibrary {
275275
mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
276276
llvm::ArrayRef<mlir::Value>);
277277
mlir::Value genIeeeSignbit(mlir::Type, llvm::ArrayRef<mlir::Value>);
278-
fir::ExtendedValue
279-
genIeeeSupportFlagOrHalting(mlir::Type,
280-
llvm::ArrayRef<fir::ExtendedValue>);
281-
mlir::Value genIeeeSupportRounding(mlir::Type, llvm::ArrayRef<mlir::Value>);
282278
template <mlir::arith::CmpIPredicate pred>
283279
mlir::Value genIeeeTypeCompare(mlir::Type, llvm::ArrayRef<mlir::Value>);
284280
mlir::Value genIeeeUnordered(mlir::Type, llvm::ArrayRef<mlir::Value>);

flang/lib/Evaluate/fold-logical.cpp

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -831,17 +831,44 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
831831
}
832832
}
833833
}
834-
} else if (name == "__builtin_ieee_support_datatype" ||
835-
name == "__builtin_ieee_support_denormal" ||
836-
name == "__builtin_ieee_support_divide" ||
837-
name == "__builtin_ieee_support_inf" ||
838-
name == "__builtin_ieee_support_io" ||
839-
name == "__builtin_ieee_support_nan" ||
840-
name == "__builtin_ieee_support_sqrt" ||
841-
name == "__builtin_ieee_support_standard" ||
842-
name == "__builtin_ieee_support_subnormal" ||
843-
name == "__builtin_ieee_support_underflow_control") {
834+
} else if (name == "__builtin_ieee_support_datatype") {
844835
return Expr<T>{true};
836+
} else if (name == "__builtin_ieee_support_denormal") {
837+
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
838+
IeeeFeature::Denormal)};
839+
} else if (name == "__builtin_ieee_support_divide") {
840+
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
841+
IeeeFeature::Divide)};
842+
} else if (name == "__builtin_ieee_support_flag") {
843+
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
844+
IeeeFeature::Flags)};
845+
} else if (name == "__builtin_ieee_support_halting") {
846+
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
847+
IeeeFeature::Halting)};
848+
} else if (name == "__builtin_ieee_support_inf") {
849+
return Expr<T>{
850+
context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Inf)};
851+
} else if (name == "__builtin_ieee_support_io") {
852+
return Expr<T>{
853+
context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Io)};
854+
} else if (name == "__builtin_ieee_support_nan") {
855+
return Expr<T>{
856+
context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::NaN)};
857+
} else if (name == "__builtin_ieee_support_rounding") {
858+
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
859+
IeeeFeature::Rounding)};
860+
} else if (name == "__builtin_ieee_support_sqrt") {
861+
return Expr<T>{
862+
context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Sqrt)};
863+
} else if (name == "__builtin_ieee_support_standard") {
864+
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
865+
IeeeFeature::Standard)};
866+
} else if (name == "__builtin_ieee_support_subnormal") {
867+
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
868+
IeeeFeature::Subnormal)};
869+
} else if (name == "__builtin_ieee_support_underflow_control") {
870+
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
871+
IeeeFeature::UnderflowControl)};
845872
}
846873
return Expr<T>{std::move(funcRef)};
847874
}

flang/lib/Evaluate/intrinsics.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ ENUM_CLASS(KindCode, none, defaultIntegerKind,
8888
sameKind,
8989
operand, // match any kind, with promotion (non-standard)
9090
typeless, // BOZ literals are INTEGER with this kind
91+
ieeeFlagType, // IEEE_FLAG_TYPE from ISO_FORTRAN_EXCEPTION
92+
ieeeRoundType, // IEEE_ROUND_TYPE from ISO_FORTRAN_ARITHMETIC
9193
teamType, // TEAM_TYPE from module ISO_FORTRAN_ENV (for coarrays)
9294
kindArg, // this argument is KIND=
9395
effectiveKind, // for function results: "kindArg" value, possibly defaulted
@@ -121,6 +123,9 @@ static constexpr TypePattern DefaultChar{CharType, KindCode::defaultCharKind};
121123
static constexpr TypePattern DefaultLogical{
122124
LogicalType, KindCode::defaultLogicalKind};
123125
static constexpr TypePattern BOZ{IntType, KindCode::typeless};
126+
static constexpr TypePattern IeeeFlagType{DerivedType, KindCode::ieeeFlagType};
127+
static constexpr TypePattern IeeeRoundType{
128+
DerivedType, KindCode::ieeeRoundType};
124129
static constexpr TypePattern TeamType{DerivedType, KindCode::teamType};
125130
static constexpr TypePattern DoublePrecision{
126131
RealType, KindCode::doublePrecision};
@@ -940,6 +945,12 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
940945
{"__builtin_ieee_support_divide",
941946
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
942947
DefaultLogical},
948+
{"__builtin_ieee_support_flag",
949+
{{"flag", IeeeFlagType, Rank::scalar},
950+
{"x", AnyReal, Rank::elemental, Optionality::optional}},
951+
DefaultLogical},
952+
{"__builtin_ieee_support_halting", {{"flag", IeeeFlagType, Rank::scalar}},
953+
DefaultLogical},
943954
{"__builtin_ieee_support_inf",
944955
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
945956
DefaultLogical},
@@ -949,6 +960,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
949960
{"__builtin_ieee_support_nan",
950961
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
951962
DefaultLogical},
963+
{"__builtin_ieee_support_rounding",
964+
{{"round_value", IeeeRoundType, Rank::scalar},
965+
{"x", AnyReal, Rank::elemental, Optionality::optional}},
966+
DefaultLogical},
952967
{"__builtin_ieee_support_sqrt",
953968
{{"x", AnyReal, Rank::elemental, Optionality::optional}},
954969
DefaultLogical},
@@ -1851,6 +1866,16 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
18511866
case KindCode::typeless:
18521867
argOk = false;
18531868
break;
1869+
case KindCode::ieeeFlagType:
1870+
argOk = !type->IsUnlimitedPolymorphic() &&
1871+
type->category() == TypeCategory::Derived &&
1872+
semantics::IsIeeeFlagType(&type->GetDerivedTypeSpec());
1873+
break;
1874+
case KindCode::ieeeRoundType:
1875+
argOk = !type->IsUnlimitedPolymorphic() &&
1876+
type->category() == TypeCategory::Derived &&
1877+
semantics::IsIeeeRoundType(&type->GetDerivedTypeSpec());
1878+
break;
18541879
case KindCode::teamType:
18551880
argOk = !type->IsUnlimitedPolymorphic() &&
18561881
type->category() == TypeCategory::Derived &&

flang/lib/Evaluate/tools.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1790,6 +1790,14 @@ bool IsNotifyType(const DerivedTypeSpec *derived) {
17901790
return IsBuiltinDerivedType(derived, "notify_type");
17911791
}
17921792

1793+
bool IsIeeeFlagType(const DerivedTypeSpec *derived) {
1794+
return IsBuiltinDerivedType(derived, "ieee_flag_type");
1795+
}
1796+
1797+
bool IsIeeeRoundType(const DerivedTypeSpec *derived) {
1798+
return IsBuiltinDerivedType(derived, "ieee_round_type");
1799+
}
1800+
17931801
bool IsTeamType(const DerivedTypeSpec *derived) {
17941802
return IsBuiltinDerivedType(derived, "team_type");
17951803
}

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -373,12 +373,6 @@ static constexpr IntrinsicHandler handlers[]{
373373
{"ieee_signaling_ne",
374374
&I::genIeeeSignalingCompare<mlir::arith::CmpFPredicate::UNE>},
375375
{"ieee_signbit", &I::genIeeeSignbit},
376-
{"ieee_support_flag",
377-
&I::genIeeeSupportFlagOrHalting,
378-
{{{"flag", asValue}, {"x", asInquired, handleDynamicOptional}}},
379-
/*isElemental=*/false},
380-
{"ieee_support_halting", &I::genIeeeSupportFlagOrHalting},
381-
{"ieee_support_rounding", &I::genIeeeSupportRounding},
382376
{"ieee_unordered", &I::genIeeeUnordered},
383377
{"ieee_value", &I::genIeeeValue},
384378
{"ieor", &I::genIeor},
@@ -4710,57 +4704,6 @@ mlir::Value IntrinsicLibrary::genIeeeSignbit(mlir::Type resultType,
47104704
return builder.createConvert(loc, resultType, sign);
47114705
}
47124706

4713-
// IEEE_SUPPORT_FLAG, IEEE_SUPPORT_HALTING
4714-
fir::ExtendedValue IntrinsicLibrary::genIeeeSupportFlagOrHalting(
4715-
mlir::Type resultType, llvm::ArrayRef<fir::ExtendedValue> args) {
4716-
// Check if a floating point exception or halting mode FLAG is supported.
4717-
// An IEEE_SUPPORT_FLAG flag is supported either for all type kinds or none.
4718-
// An optional kind argument X is therefore ignored.
4719-
// Standard flags are all supported.
4720-
// The nonstandard DENORM extension is not supported. (At least for now.)
4721-
assert(args.size() == 1 || args.size() == 2);
4722-
auto [fieldRef, fieldTy] = getFieldRef(builder, loc, fir::getBase(args[0]));
4723-
mlir::Value flag = builder.create<fir::LoadOp>(loc, fieldRef);
4724-
mlir::Value mask = builder.createIntegerConstant( // values are powers of 2
4725-
loc, fieldTy,
4726-
_FORTRAN_RUNTIME_IEEE_INVALID | _FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO |
4727-
_FORTRAN_RUNTIME_IEEE_OVERFLOW | _FORTRAN_RUNTIME_IEEE_UNDERFLOW |
4728-
_FORTRAN_RUNTIME_IEEE_INEXACT);
4729-
return builder.createConvert(
4730-
loc, resultType,
4731-
builder.create<mlir::arith::CmpIOp>(
4732-
loc, mlir::arith::CmpIPredicate::ne,
4733-
builder.create<mlir::arith::AndIOp>(loc, flag, mask),
4734-
builder.createIntegerConstant(loc, fieldTy, 0)));
4735-
}
4736-
4737-
// IEEE_SUPPORT_ROUNDING
4738-
mlir::Value
4739-
IntrinsicLibrary::genIeeeSupportRounding(mlir::Type resultType,
4740-
llvm::ArrayRef<mlir::Value> args) {
4741-
// Check if floating point rounding mode ROUND_VALUE is supported.
4742-
// Rounding is supported either for all type kinds or none.
4743-
// An optional X kind argument is therefore ignored.
4744-
// Values are chosen to match the llvm.get.rounding encoding:
4745-
// 0 - toward zero [supported]
4746-
// 1 - to nearest, ties to even [supported] - default
4747-
// 2 - toward positive infinity [supported]
4748-
// 3 - toward negative infinity [supported]
4749-
// 4 - to nearest, ties away from zero [not supported]
4750-
assert(args.size() == 1 || args.size() == 2);
4751-
auto [fieldRef, fieldTy] = getFieldRef(builder, loc, args[0]);
4752-
mlir::Value mode = builder.create<fir::LoadOp>(loc, fieldRef);
4753-
mlir::Value lbOk = builder.create<mlir::arith::CmpIOp>(
4754-
loc, mlir::arith::CmpIPredicate::sge, mode,
4755-
builder.createIntegerConstant(loc, fieldTy,
4756-
_FORTRAN_RUNTIME_IEEE_TO_ZERO));
4757-
mlir::Value ubOk = builder.create<mlir::arith::CmpIOp>(
4758-
loc, mlir::arith::CmpIPredicate::sle, mode,
4759-
builder.createIntegerConstant(loc, fieldTy, _FORTRAN_RUNTIME_IEEE_DOWN));
4760-
return builder.createConvert(
4761-
loc, resultType, builder.create<mlir::arith::AndIOp>(loc, lbOk, ubOk));
4762-
}
4763-
47644707
// IEEE_UNORDERED
47654708
mlir::Value
47664709
IntrinsicLibrary::genIeeeUnordered(mlir::Type resultType,

flang/module/__fortran_builtins.f90

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
!
77
!===------------------------------------------------------------------------===!
88

9+
include '../include/flang/Runtime/magic-numbers.h'
10+
911
! These naming shenanigans prevent names from Fortran intrinsic modules
1012
! from being usable on INTRINSIC statements, and force the program
1113
! to USE the standard intrinsic modules in order to access the
@@ -49,6 +51,42 @@
4951
integer(kind=int64), private :: __count
5052
end type
5153

54+
type, public :: __builtin_ieee_flag_type
55+
integer(kind=1), private :: flag = 0
56+
end type
57+
58+
type(__builtin_ieee_flag_type), parameter, public :: &
59+
__builtin_ieee_invalid = &
60+
__builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_INVALID), &
61+
__builtin_ieee_overflow = &
62+
__builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_OVERFLOW), &
63+
__builtin_ieee_divide_by_zero = &
64+
__builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO), &
65+
__builtin_ieee_underflow = &
66+
__builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_UNDERFLOW), &
67+
__builtin_ieee_inexact = &
68+
__builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_INEXACT), &
69+
__builtin_ieee_denorm = & ! extension
70+
__builtin_ieee_flag_type(_FORTRAN_RUNTIME_IEEE_DENORM)
71+
72+
type, public :: __builtin_ieee_round_type
73+
integer(kind=1), private :: mode = 0
74+
end type
75+
76+
type(__builtin_ieee_round_type), parameter, public :: &
77+
__builtin_ieee_to_zero = &
78+
__builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_TO_ZERO), &
79+
__builtin_ieee_nearest = &
80+
__builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_NEAREST), &
81+
__builtin_ieee_up = &
82+
__builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_UP), &
83+
__builtin_ieee_down = &
84+
__builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_DOWN), &
85+
__builtin_ieee_away = &
86+
__builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_AWAY), &
87+
__builtin_ieee_other = &
88+
__builtin_ieee_round_type(_FORTRAN_RUNTIME_IEEE_OTHER)
89+
5290
type, public :: __builtin_team_type
5391
integer(kind=int64), private :: __id
5492
end type
@@ -74,8 +112,10 @@
74112
intrinsic :: __builtin_ieee_selected_real_kind
75113
intrinsic :: __builtin_ieee_support_datatype, &
76114
__builtin_ieee_support_denormal, __builtin_ieee_support_divide, &
115+
__builtin_ieee_support_flag, __builtin_ieee_support_halting, &
77116
__builtin_ieee_support_inf, __builtin_ieee_support_io, &
78-
__builtin_ieee_support_nan, __builtin_ieee_support_sqrt, &
117+
__builtin_ieee_support_nan, __builtin_ieee_support_rounding, &
118+
__builtin_ieee_support_sqrt, &
79119
__builtin_ieee_support_standard, __builtin_ieee_support_subnormal, &
80120
__builtin_ieee_support_underflow_control
81121
public :: __builtin_fma
@@ -87,8 +127,10 @@
87127
public :: __builtin_ieee_selected_real_kind
88128
public :: __builtin_ieee_support_datatype, &
89129
__builtin_ieee_support_denormal, __builtin_ieee_support_divide, &
130+
__builtin_ieee_support_flag, __builtin_ieee_support_halting, &
90131
__builtin_ieee_support_inf, __builtin_ieee_support_io, &
91-
__builtin_ieee_support_nan, __builtin_ieee_support_sqrt, &
132+
__builtin_ieee_support_nan, __builtin_ieee_support_rounding, &
133+
__builtin_ieee_support_sqrt, &
92134
__builtin_ieee_support_standard, __builtin_ieee_support_subnormal, &
93135
__builtin_ieee_support_underflow_control
94136

0 commit comments

Comments
 (0)