@@ -7593,12 +7593,46 @@ IntrinsicLibrary::genSameTypeAs(mlir::Type resultType,
7593
7593
mlir::Value IntrinsicLibrary::genScale (mlir::Type resultType,
7594
7594
llvm::ArrayRef<mlir::Value> args) {
7595
7595
assert (args.size () == 2 );
7596
+ mlir::FloatType floatTy = mlir::dyn_cast<mlir::FloatType>(resultType);
7597
+ if (!floatTy.isF16 () && !floatTy.isBF16 ()) // kind=4,8,10,16
7598
+ return builder.createConvert (
7599
+ loc, resultType,
7600
+ fir::runtime::genScale (builder, loc, args[0 ], args[1 ]));
7596
7601
7597
- mlir::Value realX = fir::getBase (args[0 ]);
7598
- mlir::Value intI = fir::getBase (args[1 ]);
7599
-
7600
- return builder.createConvert (
7601
- loc, resultType, fir::runtime::genScale (builder, loc, realX, intI));
7602
+ // Convert kind=2,3 arg X to kind=4. Convert kind=4 result back to kind=2,3.
7603
+ mlir::Type i1Ty = builder.getI1Type ();
7604
+ mlir::Type f32Ty = mlir::Float32Type::get (builder.getContext ());
7605
+ mlir::Value result = builder.createConvert (
7606
+ loc, resultType,
7607
+ fir::runtime::genScale (
7608
+ builder, loc, builder.createConvert (loc, f32Ty, args[0 ]), args[1 ]));
7609
+
7610
+ // kind=4 runtime::genScale call may not signal kind=2,3 exceptions.
7611
+ // If X is finite and result is infinite, signal IEEE_OVERFLOW
7612
+ // If X is finite and scale(result, -I) != X, signal IEEE_UNDERFLOW
7613
+ fir::IfOp outerIfOp =
7614
+ builder.create <fir::IfOp>(loc, genIsFPClass (i1Ty, args[0 ], finiteTest),
7615
+ /* withElseRegion=*/ false );
7616
+ builder.setInsertionPointToStart (&outerIfOp.getThenRegion ().front ());
7617
+ fir::IfOp innerIfOp =
7618
+ builder.create <fir::IfOp>(loc, genIsFPClass (i1Ty, result, infiniteTest),
7619
+ /* withElseRegion=*/ true );
7620
+ builder.setInsertionPointToStart (&innerIfOp.getThenRegion ().front ());
7621
+ genRaiseExcept (_FORTRAN_RUNTIME_IEEE_OVERFLOW |
7622
+ _FORTRAN_RUNTIME_IEEE_INEXACT);
7623
+ builder.setInsertionPointToStart (&innerIfOp.getElseRegion ().front ());
7624
+ mlir::Value minusI = builder.create <mlir::arith::MulIOp>(
7625
+ loc, args[1 ], builder.createAllOnesInteger (loc, args[1 ].getType ()));
7626
+ mlir::Value reverseResult = builder.createConvert (
7627
+ loc, resultType,
7628
+ fir::runtime::genScale (
7629
+ builder, loc, builder.createConvert (loc, f32Ty, result), minusI));
7630
+ genRaiseExcept (
7631
+ _FORTRAN_RUNTIME_IEEE_UNDERFLOW | _FORTRAN_RUNTIME_IEEE_INEXACT,
7632
+ builder.create <mlir::arith::CmpFOp>(loc, mlir::arith::CmpFPredicate::ONE,
7633
+ args[0 ], reverseResult));
7634
+ builder.setInsertionPointAfter (outerIfOp);
7635
+ return result;
7602
7636
}
7603
7637
7604
7638
// SCAN
0 commit comments