Skip to content

Commit 6003be7

Browse files
authored
[flang] IEEE_GET_UNDERFLOW_MODE, IEEE_SET_UNDERFLOW_MODE (#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

0 commit comments

Comments
 (0)