[flang] IEEE_SCALB and SCALE - kind=2, kind=3 (#135374)

Implement the kind=2,3 variants of language intrinsic SCALE and
intrinsic module procedure IEEE_SCALB, including exception signaling.
This commit is contained in:
vdonaldson 2025-04-11 16:38:45 -04:00 committed by GitHub
parent ee801cdd6e
commit a8da4834f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -7593,12 +7593,46 @@ IntrinsicLibrary::genSameTypeAs(mlir::Type resultType,
mlir::Value IntrinsicLibrary::genScale(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args) {
assert(args.size() == 2);
mlir::FloatType floatTy = mlir::dyn_cast<mlir::FloatType>(resultType);
if (!floatTy.isF16() && !floatTy.isBF16()) // kind=4,8,10,16
return builder.createConvert(
loc, resultType,
fir::runtime::genScale(builder, loc, args[0], args[1]));
mlir::Value realX = fir::getBase(args[0]);
mlir::Value intI = fir::getBase(args[1]);
// Convert kind=2,3 arg X to kind=4. Convert kind=4 result back to kind=2,3.
mlir::Type i1Ty = builder.getI1Type();
mlir::Type f32Ty = mlir::Float32Type::get(builder.getContext());
mlir::Value result = builder.createConvert(
loc, resultType,
fir::runtime::genScale(
builder, loc, builder.createConvert(loc, f32Ty, args[0]), args[1]));
return builder.createConvert(
loc, resultType, fir::runtime::genScale(builder, loc, realX, intI));
// kind=4 runtime::genScale call may not signal kind=2,3 exceptions.
// If X is finite and result is infinite, signal IEEE_OVERFLOW
// If X is finite and scale(result, -I) != X, signal IEEE_UNDERFLOW
fir::IfOp outerIfOp =
builder.create<fir::IfOp>(loc, genIsFPClass(i1Ty, args[0], finiteTest),
/*withElseRegion=*/false);
builder.setInsertionPointToStart(&outerIfOp.getThenRegion().front());
fir::IfOp innerIfOp =
builder.create<fir::IfOp>(loc, genIsFPClass(i1Ty, result, infiniteTest),
/*withElseRegion=*/true);
builder.setInsertionPointToStart(&innerIfOp.getThenRegion().front());
genRaiseExcept(_FORTRAN_RUNTIME_IEEE_OVERFLOW |
_FORTRAN_RUNTIME_IEEE_INEXACT);
builder.setInsertionPointToStart(&innerIfOp.getElseRegion().front());
mlir::Value minusI = builder.create<mlir::arith::MulIOp>(
loc, args[1], builder.createAllOnesInteger(loc, args[1].getType()));
mlir::Value reverseResult = builder.createConvert(
loc, resultType,
fir::runtime::genScale(
builder, loc, builder.createConvert(loc, f32Ty, result), minusI));
genRaiseExcept(
_FORTRAN_RUNTIME_IEEE_UNDERFLOW | _FORTRAN_RUNTIME_IEEE_INEXACT,
builder.create<mlir::arith::CmpFOp>(loc, mlir::arith::CmpFPredicate::ONE,
args[0], reverseResult));
builder.setInsertionPointAfter(outerIfOp);
return result;
}
// SCAN