Skip to content

Commit 0b52aa1

Browse files
authored
[flang] Unsupported rounding modes (#128240)
Two new ieee_round_type values were added in f18 beyond the four values defined in f03 and f08: ieee_away and ieee_other. Contemporary hardware typically does not have support for these rounding modes, so flang does not support them. ieee_support_rounding calls for these values return false. Current generated code handles some attempts to set the rounding mode to one of these unsupported values by setting the mode to ieee_nearest. Update the code to explicitly do this in all cases.
1 parent 3a6108b commit 0b52aa1

File tree

4 files changed

+269
-199
lines changed

4 files changed

+269
-199
lines changed

flang/docs/Extensions.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,6 +815,14 @@ print *, [(j,j=1,10)]
815815
integer overflow never occurs in address calculations and increment of
816816
do-variable unless the option `-fwrapv` is enabled.
817817

818+
* Two new ieee_round_type values were added in f18 beyond the four values
819+
defined in f03 and f08: ieee_away and ieee_other. Contemporary hardware
820+
typically does not have support for these rounding modes;
821+
ieee_support_rounding calls for these values return false.
822+
ieee_set_rounding_mode calls that attempt to set the rounding mode to one
823+
of these values in violation of the restriction in f23 clause 17.11.42 set
824+
the mode to ieee_nearest.
825+
818826
## De Facto Standard Features
819827

820828
* `EXTENDS_TYPE_OF()` returns `.TRUE.` if both of its arguments have the

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5519,13 +5519,33 @@ void IntrinsicLibrary::genIeeeSetRoundingMode(
55195519
llvm::ArrayRef<fir::ExtendedValue> args) {
55205520
// Set the current floating point rounding mode to the value of arg
55215521
// ROUNDING_VALUE. Values are llvm.get.rounding encoding values.
5522-
// Generate an error if the value of optional arg RADIX is not 2.
5522+
// Modes ieee_to_zero, ieee_nearest, ieee_up, and ieee_down are supported.
5523+
// Modes ieee_away and ieee_other are not supported, and are treated as
5524+
// ieee_nearest. Generate an error if the optional RADIX arg is not 2.
55235525
assert(args.size() == 1 || args.size() == 2);
55245526
if (args.size() == 2)
55255527
checkRadix(builder, loc, fir::getBase(args[1]), "ieee_set_rounding_mode");
5526-
auto [fieldRef, ignore] = getFieldRef(builder, loc, fir::getBase(args[0]));
5528+
auto [fieldRef, fieldTy] = getFieldRef(builder, loc, fir::getBase(args[0]));
55275529
mlir::func::FuncOp setRound = fir::factory::getLlvmSetRounding(builder);
55285530
mlir::Value mode = builder.create<fir::LoadOp>(loc, fieldRef);
5531+
static_assert(
5532+
_FORTRAN_RUNTIME_IEEE_TO_ZERO >= 0 &&
5533+
_FORTRAN_RUNTIME_IEEE_TO_ZERO <= 3 &&
5534+
_FORTRAN_RUNTIME_IEEE_NEAREST >= 0 &&
5535+
_FORTRAN_RUNTIME_IEEE_NEAREST <= 3 && _FORTRAN_RUNTIME_IEEE_UP >= 0 &&
5536+
_FORTRAN_RUNTIME_IEEE_UP <= 3 && _FORTRAN_RUNTIME_IEEE_DOWN >= 0 &&
5537+
_FORTRAN_RUNTIME_IEEE_DOWN <= 3 && "unexpected rounding mode mapping");
5538+
mlir::Value mask = builder.create<mlir::arith::ShLIOp>(
5539+
loc, builder.createAllOnesInteger(loc, fieldTy),
5540+
builder.createIntegerConstant(loc, fieldTy, 2));
5541+
mlir::Value modeIsSupported = builder.create<mlir::arith::CmpIOp>(
5542+
loc, mlir::arith::CmpIPredicate::eq,
5543+
builder.create<mlir::arith::AndIOp>(loc, mode, mask),
5544+
builder.createIntegerConstant(loc, fieldTy, 0));
5545+
mlir::Value nearest = builder.createIntegerConstant(
5546+
loc, fieldTy, _FORTRAN_RUNTIME_IEEE_NEAREST);
5547+
mode = builder.create<mlir::arith::SelectOp>(loc, modeIsSupported, mode,
5548+
nearest);
55295549
mode = builder.create<fir::ConvertOp>(
55305550
loc, setRound.getFunctionType().getInput(0), mode);
55315551
builder.create<fir::CallOp>(loc, setRound, mode);

0 commit comments

Comments
 (0)