Skip to content

Commit 9bdde2d

Browse files
committed
[flang] Unsupported rounding modes
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 2ff80d2 commit 9bdde2d

File tree

3 files changed

+261
-199
lines changed

3 files changed

+261
-199
lines changed

flang/lib/Optimizer/Builder/IntrinsicCall.cpp

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5450,13 +5450,33 @@ void IntrinsicLibrary::genIeeeSetRoundingMode(
54505450
llvm::ArrayRef<fir::ExtendedValue> args) {
54515451
// Set the current floating point rounding mode to the value of arg
54525452
// ROUNDING_VALUE. Values are llvm.get.rounding encoding values.
5453-
// Generate an error if the value of optional arg RADIX is not 2.
5453+
// Modes ieee_to_zero, ieee_nearest, ieee_up, and ieee_down are supported.
5454+
// Modes ieee_away and ieee_other are not supported, and are treated as
5455+
// ieee_nearest. Generate an error if the optional RADIX arg is not 2.
54545456
assert(args.size() == 1 || args.size() == 2);
54555457
if (args.size() == 2)
54565458
checkRadix(builder, loc, fir::getBase(args[1]), "ieee_set_rounding_mode");
5457-
auto [fieldRef, ignore] = getFieldRef(builder, loc, fir::getBase(args[0]));
5459+
auto [fieldRef, fieldTy] = getFieldRef(builder, loc, fir::getBase(args[0]));
54585460
mlir::func::FuncOp setRound = fir::factory::getLlvmSetRounding(builder);
54595461
mlir::Value mode = builder.create<fir::LoadOp>(loc, fieldRef);
5462+
static_assert(
5463+
_FORTRAN_RUNTIME_IEEE_TO_ZERO >= 0 &&
5464+
_FORTRAN_RUNTIME_IEEE_TO_ZERO <= 3 &&
5465+
_FORTRAN_RUNTIME_IEEE_NEAREST >= 0 &&
5466+
_FORTRAN_RUNTIME_IEEE_NEAREST <= 3 && _FORTRAN_RUNTIME_IEEE_UP >= 0 &&
5467+
_FORTRAN_RUNTIME_IEEE_UP <= 3 && _FORTRAN_RUNTIME_IEEE_DOWN >= 0 &&
5468+
_FORTRAN_RUNTIME_IEEE_DOWN <= 3 && "unexpected rounding mode mapping");
5469+
mlir::Value mask = builder.create<mlir::arith::ShLIOp>(
5470+
loc, builder.createAllOnesInteger(loc, fieldTy),
5471+
builder.createIntegerConstant(loc, fieldTy, 2));
5472+
mlir::Value modeIsSupported = builder.create<mlir::arith::CmpIOp>(
5473+
loc, mlir::arith::CmpIPredicate::eq,
5474+
builder.create<mlir::arith::AndIOp>(loc, mode, mask),
5475+
builder.createIntegerConstant(loc, fieldTy, 0));
5476+
mlir::Value nearest = builder.createIntegerConstant(
5477+
loc, fieldTy, _FORTRAN_RUNTIME_IEEE_NEAREST);
5478+
mode = builder.create<mlir::arith::SelectOp>(loc, modeIsSupported, mode,
5479+
nearest);
54605480
mode = builder.create<fir::ConvertOp>(
54615481
loc, setRound.getFunctionType().getInput(0), mode);
54625482
builder.create<fir::CallOp>(loc, setRound, mode);

0 commit comments

Comments
 (0)