Skip to content

Commit 6003be7

Browse files
authored
[flang] IEEE_GET_UNDERFLOW_MODE, IEEE_SET_UNDERFLOW_MODE (llvm#118551)
Implement IEEE_GET_UNDERFLOW_MODE and IEEE_SET_UNDERFLOW_MODE. Update IEEE_SUPPORT_UNDERFLOW_CONTROL to enable support for indvidual REAL kinds.
1 parent ac5dd45 commit 6003be7

File tree

16 files changed

+184
-35
lines changed

16 files changed

+184
-35
lines changed

flang/include/flang/Evaluate/target.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,12 @@ class TargetCharacteristics {
5252
}
5353
void set_areSubnormalsFlushedToZero(bool yes = true);
5454

55+
// Check if a given real kind has flushing control.
56+
bool hasSubnormalFlushingControl(int kind) const;
57+
// Check if any or all real kinds have flushing control.
58+
bool hasSubnormalFlushingControl(bool any = false) const;
59+
void set_hasSubnormalFlushingControl(int kind, bool yes = true);
60+
5561
Rounding roundingMode() const { return roundingMode_; }
5662
void set_roundingMode(Rounding);
5763

@@ -111,13 +117,14 @@ class TargetCharacteristics {
111117
const IeeeFeatures &ieeeFeatures() const { return ieeeFeatures_; }
112118

113119
private:
114-
static constexpr int maxKind{32};
115-
std::uint8_t byteSize_[common::TypeCategory_enumSize][maxKind]{};
116-
std::uint8_t align_[common::TypeCategory_enumSize][maxKind]{};
120+
static constexpr int maxKind{16};
121+
std::uint8_t byteSize_[common::TypeCategory_enumSize][maxKind + 1]{};
122+
std::uint8_t align_[common::TypeCategory_enumSize][maxKind + 1]{};
117123
bool isBigEndian_{false};
118124
bool isPPC_{false};
119125
bool isOSWindows_{false};
120126
bool areSubnormalsFlushedToZero_{false};
127+
bool hasSubnormalFlushingControl_[maxKind + 1]{};
121128
Rounding roundingMode_{defaultRounding};
122129
std::size_t procedurePointerByteSize_{8};
123130
std::size_t procedurePointerAlignment_{8};

flang/include/flang/Lower/PFTBuilder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,7 @@ struct FunctionLikeUnit : public ProgramUnit {
723723
bool hasIeeeAccess{false};
724724
bool mayModifyHaltingMode{false};
725725
bool mayModifyRoundingMode{false};
726+
bool mayModifyUnderflowMode{false};
726727
/// Terminal basic block (if any)
727728
mlir::Block *finalBlock{};
728729
HostAssociations hostAssociations;

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -166,11 +166,6 @@ struct IntrinsicLibrary {
166166
getRuntimeCallGenerator(llvm::StringRef name,
167167
mlir::FunctionType soughtFuncType);
168168

169-
/// Helper to generate TODOs for module procedures that must be intercepted in
170-
/// lowering and are not yet implemented.
171-
template <const char *intrinsicName>
172-
void genModuleProcTODO(llvm::ArrayRef<fir::ExtendedValue>);
173-
174169
void genAbort(llvm::ArrayRef<fir::ExtendedValue>);
175170
/// Lowering for the ABS intrinsic. The ABS intrinsic expects one argument in
176171
/// the llvm::ArrayRef. The ABS intrinsic is lowered into MLIR/FIR operation
@@ -278,6 +273,7 @@ struct IntrinsicLibrary {
278273
template <bool isGet>
279274
void genIeeeGetOrSetStatus(llvm::ArrayRef<fir::ExtendedValue>);
280275
void genIeeeGetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
276+
void genIeeeGetUnderflowMode(llvm::ArrayRef<fir::ExtendedValue>);
281277
mlir::Value genIeeeInt(mlir::Type, llvm::ArrayRef<mlir::Value>);
282278
mlir::Value genIeeeIsFinite(mlir::Type, llvm::ArrayRef<mlir::Value>);
283279
mlir::Value genIeeeIsNan(mlir::Type, llvm::ArrayRef<mlir::Value>);
@@ -295,6 +291,7 @@ struct IntrinsicLibrary {
295291
template <bool isFlag>
296292
void genIeeeSetFlagOrHaltingMode(llvm::ArrayRef<fir::ExtendedValue>);
297293
void genIeeeSetRoundingMode(llvm::ArrayRef<fir::ExtendedValue>);
294+
void genIeeeSetUnderflowMode(llvm::ArrayRef<fir::ExtendedValue>);
298295
template <mlir::arith::CmpFPredicate pred>
299296
mlir::Value genIeeeSignalingCompare(mlir::Type resultType,
300297
llvm::ArrayRef<mlir::Value>);

flang/include/flang/Optimizer/Builder/Runtime/Exceptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,9 @@ namespace fir::runtime {
2626
mlir::Value genMapExcept(fir::FirOpBuilder &builder, mlir::Location loc,
2727
mlir::Value excepts);
2828

29+
mlir::Value genGetUnderflowMode(fir::FirOpBuilder &builder, mlir::Location loc);
30+
void genSetUnderflowMode(fir::FirOpBuilder &builder, mlir::Location loc,
31+
mlir::Value bit);
32+
2933
} // namespace fir::runtime
3034
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_EXCEPTIONS_H

flang/include/flang/Runtime/exceptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ extern "C" {
2424
// This mapping is done at runtime to support cross compilation.
2525
std::uint32_t RTNAME(MapException)(std::uint32_t excepts);
2626

27+
// Get and set the ieee underflow mode if supported; otherwise nops.
28+
bool RTNAME(GetUnderflowMode)(void);
29+
void RTNAME(SetUnderflowMode)(bool flag);
30+
2731
} // extern "C"
2832
} // namespace Fortran::runtime
2933
#endif // FORTRAN_RUNTIME_EXCEPTIONS_H_

flang/include/flang/Tools/TargetSetup.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ namespace Fortran::tools {
2929
targetCharacteristics.DisableType(
3030
Fortran::common::TypeCategory::Real, /*kind=*/10);
3131
}
32+
if (targetTriple.getArch() == llvm::Triple::ArchType::x86_64) {
33+
targetCharacteristics.set_hasSubnormalFlushingControl(/*kind=*/3);
34+
targetCharacteristics.set_hasSubnormalFlushingControl(/*kind=*/4);
35+
targetCharacteristics.set_hasSubnormalFlushingControl(/*kind=*/8);
36+
}
3237

3338
// Figure out if we can support F128: see
3439
// flang/runtime/Float128Math/math-entries.h

flang/lib/Evaluate/fold-logical.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -890,8 +890,16 @@ Expr<Type<TypeCategory::Logical, KIND>> FoldIntrinsicFunction(
890890
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
891891
IeeeFeature::Subnormal)};
892892
} else if (name == "__builtin_ieee_support_underflow_control") {
893-
return Expr<T>{context.targetCharacteristics().ieeeFeatures().test(
894-
IeeeFeature::UnderflowControl)};
893+
// Setting kind=0 checks subnormal flushing control across all type kinds.
894+
if (args[0]) {
895+
return Expr<T>{
896+
context.targetCharacteristics().hasSubnormalFlushingControl(
897+
args[0]->GetType().value().kind())};
898+
} else {
899+
return Expr<T>{
900+
context.targetCharacteristics().hasSubnormalFlushingControl(
901+
/*any=*/false)};
902+
}
895903
}
896904
return Expr<T>{std::move(funcRef)};
897905
}

flang/lib/Evaluate/target.cpp

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Rounding TargetCharacteristics::defaultRounding;
1717

1818
TargetCharacteristics::TargetCharacteristics() {
1919
auto enableCategoryKinds{[this](TypeCategory category) {
20-
for (int kind{0}; kind < maxKind; ++kind) {
20+
for (int kind{1}; kind <= maxKind; ++kind) {
2121
if (CanSupportType(category, kind)) {
2222
auto byteSize{static_cast<std::size_t>(kind)};
2323
if (category == TypeCategory::Real ||
@@ -70,14 +70,14 @@ bool TargetCharacteristics::EnableType(common::TypeCategory category,
7070

7171
void TargetCharacteristics::DisableType(
7272
common::TypeCategory category, std::int64_t kind) {
73-
if (kind >= 0 && kind < maxKind) {
73+
if (kind > 0 && kind <= maxKind) {
7474
align_[static_cast<int>(category)][kind] = 0;
7575
}
7676
}
7777

7878
std::size_t TargetCharacteristics::GetByteSize(
7979
common::TypeCategory category, std::int64_t kind) const {
80-
if (kind >= 0 && kind < maxKind) {
80+
if (kind > 0 && kind <= maxKind) {
8181
return byteSize_[static_cast<int>(category)][kind];
8282
} else {
8383
return 0;
@@ -86,7 +86,7 @@ std::size_t TargetCharacteristics::GetByteSize(
8686

8787
std::size_t TargetCharacteristics::GetAlignment(
8888
common::TypeCategory category, std::int64_t kind) const {
89-
if (kind >= 0 && kind < maxKind) {
89+
if (kind > 0 && kind <= maxKind) {
9090
return align_[static_cast<int>(category)][kind];
9191
} else {
9292
return 0;
@@ -108,6 +108,30 @@ void TargetCharacteristics::set_areSubnormalsFlushedToZero(bool yes) {
108108
areSubnormalsFlushedToZero_ = yes;
109109
}
110110

111+
// Check if a given real kind has flushing control.
112+
bool TargetCharacteristics::hasSubnormalFlushingControl(int kind) const {
113+
CHECK(kind > 0 && kind <= maxKind);
114+
CHECK(CanSupportType(TypeCategory::Real, kind));
115+
return hasSubnormalFlushingControl_[kind];
116+
}
117+
118+
// Check if any or all real kinds have flushing control.
119+
bool TargetCharacteristics::hasSubnormalFlushingControl(bool any) const {
120+
for (int kind{1}; kind <= maxKind; ++kind) {
121+
if (CanSupportType(TypeCategory::Real, kind) &&
122+
hasSubnormalFlushingControl_[kind] == any) {
123+
return any;
124+
}
125+
}
126+
return !any;
127+
}
128+
129+
void TargetCharacteristics::set_hasSubnormalFlushingControl(
130+
int kind, bool yes) {
131+
CHECK(kind > 0 && kind <= maxKind);
132+
hasSubnormalFlushingControl_[kind] = yes;
133+
}
134+
111135
void TargetCharacteristics::set_roundingMode(Rounding rounding) {
112136
roundingMode_ = rounding;
113137
}

flang/lib/Lower/Bridge.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "flang/Optimizer/Builder/Runtime/Character.h"
4040
#include "flang/Optimizer/Builder/Runtime/Derived.h"
4141
#include "flang/Optimizer/Builder/Runtime/EnvironmentDefaults.h"
42+
#include "flang/Optimizer/Builder/Runtime/Exceptions.h"
4243
#include "flang/Optimizer/Builder/Runtime/Main.h"
4344
#include "flang/Optimizer/Builder/Runtime/Ragged.h"
4445
#include "flang/Optimizer/Builder/Runtime/Stop.h"
@@ -5181,8 +5182,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
51815182
genOpenMPSymbolProperties(*this, var);
51825183
}
51835184

5184-
/// Where applicable, save the exception state and halting and rounding
5185-
/// modes at function entry and restore them at function exits.
5185+
/// Where applicable, save the exception state and halting, rounding, and
5186+
/// underflow modes at function entry, and restore them at function exits.
51865187
void manageFPEnvironment(Fortran::lower::pft::FunctionLikeUnit &funit) {
51875188
mlir::Location loc = toLocation();
51885189
mlir::Location endLoc =
@@ -5224,7 +5225,7 @@ class FirConverter : public Fortran::lower::AbstractConverter {
52245225
});
52255226
}
52265227
if (funit.mayModifyRoundingMode) {
5227-
// F18 Clause 17.4.5: In a procedure [...], the processor shall not
5228+
// F18 Clause 17.4p5: In a procedure [...], the processor shall not
52285229
// change the rounding modes on entry, and on return shall ensure that
52295230
// the rounding modes are the same as they were on entry.
52305231
mlir::func::FuncOp getRounding =
@@ -5237,6 +5238,18 @@ class FirConverter : public Fortran::lower::AbstractConverter {
52375238
builder->create<fir::CallOp>(endLoc, setRounding, roundingMode);
52385239
});
52395240
}
5241+
if ((funit.mayModifyUnderflowMode) &&
5242+
(bridge.getTargetCharacteristics().hasSubnormalFlushingControl(
5243+
/*any=*/true))) {
5244+
// F18 Clause 17.5p2: In a procedure [...], the processor shall not
5245+
// change the underflow mode on entry, and on return shall ensure that
5246+
// the underflow mode is the same as it was on entry.
5247+
mlir::Value underflowMode =
5248+
fir::runtime::genGetUnderflowMode(*builder, loc);
5249+
bridge.fctCtx().attachCleanup([=]() {
5250+
fir::runtime::genSetUnderflowMode(*builder, loc, {underflowMode});
5251+
});
5252+
}
52405253
}
52415254

52425255
/// Start translation of a function.

flang/lib/Lower/PFTBuilder.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,14 @@ class PFTBuilder {
161161
return;
162162
if (procName.starts_with("ieee_set_modes_") ||
163163
procName.starts_with("ieee_set_status_"))
164-
proc->mayModifyHaltingMode = proc->mayModifyRoundingMode = true;
164+
proc->mayModifyHaltingMode = proc->mayModifyRoundingMode =
165+
proc->mayModifyUnderflowMode = true;
165166
else if (procName.starts_with("ieee_set_halting_mode_"))
166167
proc->mayModifyHaltingMode = true;
167168
else if (procName.starts_with("ieee_set_rounding_mode_"))
168169
proc->mayModifyRoundingMode = true;
170+
else if (procName.starts_with("ieee_set_underflow_mode_"))
171+
proc->mayModifyUnderflowMode = true;
169172
}
170173

171174
/// Convert an IfStmt into an IfConstruct, retaining the IfStmt as the

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,6 @@ static bool isStaticallyPresent(const fir::ExtendedValue &exv) {
9595
return !isStaticallyAbsent(exv);
9696
}
9797

98-
/// IEEE module procedure names not yet implemented for genModuleProcTODO.
99-
static constexpr char ieee_get_underflow_mode[] = "ieee_get_underflow_mode";
100-
static constexpr char ieee_set_underflow_mode[] = "ieee_set_underflow_mode";
101-
10298
using I = IntrinsicLibrary;
10399

104100
/// Flag to indicate that an intrinsic argument has to be handled as
@@ -328,7 +324,10 @@ static constexpr IntrinsicHandler handlers[]{
328324
{"radix", asValue, handleDynamicOptional}}},
329325
/*isElemental=*/false},
330326
{"ieee_get_status", &I::genIeeeGetOrSetStatus</*isGet=*/true>},
331-
{"ieee_get_underflow_mode", &I::genModuleProcTODO<ieee_get_underflow_mode>},
327+
{"ieee_get_underflow_mode",
328+
&I::genIeeeGetUnderflowMode,
329+
{{{"gradual", asAddr}}},
330+
/*isElemental=*/false},
332331
{"ieee_int", &I::genIeeeInt},
333332
{"ieee_is_finite", &I::genIeeeIsFinite},
334333
{"ieee_is_nan", &I::genIeeeIsNan},
@@ -375,7 +374,7 @@ static constexpr IntrinsicHandler handlers[]{
375374
{"radix", asValue, handleDynamicOptional}}},
376375
/*isElemental=*/false},
377376
{"ieee_set_status", &I::genIeeeGetOrSetStatus</*isGet=*/false>},
378-
{"ieee_set_underflow_mode", &I::genModuleProcTODO<ieee_set_underflow_mode>},
377+
{"ieee_set_underflow_mode", &I::genIeeeSetUnderflowMode},
379378
{"ieee_signaling_eq",
380379
&I::genIeeeSignalingCompare<mlir::arith::CmpFPredicate::OEQ>},
381380
{"ieee_signaling_ge",
@@ -2295,12 +2294,6 @@ mlir::Value IntrinsicLibrary::genConversion(mlir::Type resultType,
22952294
return builder.convertWithSemantics(loc, resultType, args[0]);
22962295
}
22972296

2298-
template <const char *intrinsicName>
2299-
void IntrinsicLibrary::genModuleProcTODO(
2300-
llvm::ArrayRef<fir::ExtendedValue> args) {
2301-
crashOnMissingIntrinsic(loc, intrinsicName);
2302-
}
2303-
23042297
// ABORT
23052298
void IntrinsicLibrary::genAbort(llvm::ArrayRef<fir::ExtendedValue> args) {
23062299
assert(args.size() == 0);
@@ -4471,6 +4464,14 @@ void IntrinsicLibrary::genIeeeGetOrSetStatus(
44714464
genRuntimeCall(isGet ? "fegetenv" : "fesetenv", i32Ty, addr);
44724465
}
44734466

4467+
// IEEE_GET_UNDERFLOW_MODE
4468+
void IntrinsicLibrary::genIeeeGetUnderflowMode(
4469+
llvm::ArrayRef<fir::ExtendedValue> args) {
4470+
assert(args.size() == 1);
4471+
mlir::Value flag = fir::runtime::genGetUnderflowMode(builder, loc);
4472+
builder.createStoreWithConvert(loc, flag, fir::getBase(args[0]));
4473+
}
4474+
44744475
// IEEE_INT
44754476
mlir::Value IntrinsicLibrary::genIeeeInt(mlir::Type resultType,
44764477
llvm::ArrayRef<mlir::Value> args) {
@@ -5135,6 +5136,15 @@ void IntrinsicLibrary::genIeeeSetRoundingMode(
51355136
builder.create<fir::CallOp>(loc, setRound, mode);
51365137
}
51375138

5139+
// IEEE_SET_UNDERFLOW_MODE
5140+
void IntrinsicLibrary::genIeeeSetUnderflowMode(
5141+
llvm::ArrayRef<fir::ExtendedValue> args) {
5142+
assert(args.size() == 1);
5143+
mlir::Value gradual = builder.create<fir::ConvertOp>(loc, builder.getI1Type(),
5144+
getBase(args[0]));
5145+
fir::runtime::genSetUnderflowMode(builder, loc, {gradual});
5146+
}
5147+
51385148
// IEEE_SIGNALING_EQ, IEEE_SIGNALING_GE, IEEE_SIGNALING_GT,
51395149
// IEEE_SIGNALING_LE, IEEE_SIGNALING_LT, IEEE_SIGNALING_NE
51405150
template <mlir::arith::CmpFPredicate pred>

flang/lib/Optimizer/Builder/Runtime/Exceptions.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,17 @@ mlir::Value fir::runtime::genMapExcept(fir::FirOpBuilder &builder,
2020
fir::runtime::getRuntimeFunc<mkRTKey(MapException)>(loc, builder)};
2121
return builder.create<fir::CallOp>(loc, func, excepts).getResult(0);
2222
}
23+
24+
mlir::Value fir::runtime::genGetUnderflowMode(fir::FirOpBuilder &builder,
25+
mlir::Location loc) {
26+
mlir::func::FuncOp func{
27+
fir::runtime::getRuntimeFunc<mkRTKey(GetUnderflowMode)>(loc, builder)};
28+
return builder.create<fir::CallOp>(loc, func).getResult(0);
29+
}
30+
31+
void fir::runtime::genSetUnderflowMode(fir::FirOpBuilder &builder,
32+
mlir::Location loc, mlir::Value flag) {
33+
mlir::func::FuncOp func{
34+
fir::runtime::getRuntimeFunc<mkRTKey(SetUnderflowMode)>(loc, builder)};
35+
builder.create<fir::CallOp>(loc, func, flag);
36+
}

flang/runtime/exceptions.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include "flang/Runtime/exceptions.h"
1212
#include "terminator.h"
1313
#include <cfenv>
14+
#if __x86_64__
15+
#include <xmmintrin.h>
16+
#endif
1417

1518
// When not supported, these macro are undefined in cfenv.h,
1619
// set them to zero in that case.
@@ -78,5 +81,22 @@ uint32_t RTNAME(MapException)(uint32_t excepts) {
7881
// on some systems, e.g. Solaris, so omit object size comparison for now.
7982
// TODO: consider femode_t object size comparison once its more mature.
8083

84+
bool RTNAME(GetUnderflowMode)(void) {
85+
#if __x86_64__
86+
// The MXCSR Flush to Zero flag is the negation of the ieee_get_underflow_mode
87+
// GRADUAL argument. It affects real computations of kinds 3, 4, and 8.
88+
return _MM_GET_FLUSH_ZERO_MODE() == _MM_FLUSH_ZERO_OFF;
89+
#else
90+
return false;
91+
#endif
92+
}
93+
void RTNAME(SetUnderflowMode)(bool flag) {
94+
#if __x86_64__
95+
// The MXCSR Flush to Zero flag is the negation of the ieee_set_underflow_mode
96+
// GRADUAL argument. It affects real computations of kinds 3, 4, and 8.
97+
_MM_SET_FLUSH_ZERO_MODE(flag ? _MM_FLUSH_ZERO_OFF : _MM_FLUSH_ZERO_ON);
98+
#endif
99+
}
100+
81101
} // extern "C"
82102
} // namespace Fortran::runtime

flang/test/Evaluate/fold-ieee.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ module m
5858
logical, parameter :: test_sn_all = ieee_support_subnormal()
5959
logical, parameter :: test_sn_4 = ieee_support_subnormal(1.)
6060
logical, parameter :: test_sn_8 = ieee_support_subnormal(1.d0)
61-
logical, parameter :: test_uc_all = ieee_support_underflow_control()
61+
logical, parameter :: test_uc_all = .not. ieee_support_underflow_control()
6262
logical, parameter :: test_uc_4 = ieee_support_underflow_control(1.)
6363
logical, parameter :: test_uc_8 = ieee_support_underflow_control(1.d0)
6464
end

flang/test/Evaluate/folding18.f90

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,11 @@ module m
6565
.and. ieee_support_subnormal(1.0_8) &
6666
.and. ieee_support_subnormal(1.0_10) &
6767
.and. ieee_support_subnormal(1.0_16)
68-
logical, parameter :: test_ieee_support_underflow_control = ieee_support_underflow_control() &
69-
.and. ieee_support_underflow_control(1.0_2) &
68+
logical, parameter :: test_ieee_support_underflow_control = .not. ieee_support_underflow_control() &
69+
.and. .not. ieee_support_underflow_control(1.0_2) &
7070
.and. ieee_support_underflow_control(1.0_3) &
7171
.and. ieee_support_underflow_control(1.0_4) &
7272
.and. ieee_support_underflow_control(1.0_8) &
73-
.and. ieee_support_underflow_control(1.0_10) &
74-
.and. ieee_support_underflow_control(1.0_16)
73+
.and. .not. ieee_support_underflow_control(1.0_10) &
74+
.and. .not. ieee_support_underflow_control(1.0_16)
7575
end module

0 commit comments

Comments
 (0)