@@ -4571,8 +4571,8 @@ void IntrinsicLibrary::genRaiseExcept(int excepts, mlir::Value cond) {
4571
4571
builder.setInsertionPointToStart (&ifOp.getThenRegion ().front ());
4572
4572
}
4573
4573
mlir::Type i32Ty = builder.getIntegerType (32 );
4574
- genRuntimeCall (
4575
- " feraiseexcept " , i32Ty ,
4574
+ fir::runtime::genFeraiseexcept (
4575
+ builder, loc ,
4576
4576
fir::runtime::genMapExcept (
4577
4577
builder, loc, builder.createIntegerConstant (loc, i32Ty, excepts)));
4578
4578
if (cond)
@@ -4939,8 +4939,8 @@ void IntrinsicLibrary::genIeeeGetFlag(llvm::ArrayRef<fir::ExtendedValue> args) {
4939
4939
mlir::Value zero = builder.createIntegerConstant (loc, i32Ty, 0 );
4940
4940
auto [fieldRef, ignore] = getFieldRef (builder, loc, flag);
4941
4941
mlir::Value field = builder.create <fir::LoadOp>(loc, fieldRef);
4942
- mlir::Value excepts = IntrinsicLibrary::genRuntimeCall (
4943
- " fetestexcept " , i32Ty ,
4942
+ mlir::Value excepts = fir::runtime::genFetestexcept (
4943
+ builder, loc ,
4944
4944
fir::runtime::genMapExcept (
4945
4945
builder, loc, builder.create <fir::ConvertOp>(loc, i32Ty, field)));
4946
4946
mlir::Value logicalResult = builder.create <fir::ConvertOp>(
@@ -4963,8 +4963,7 @@ void IntrinsicLibrary::genIeeeGetHaltingMode(
4963
4963
mlir::Value zero = builder.createIntegerConstant (loc, i32Ty, 0 );
4964
4964
auto [fieldRef, ignore] = getFieldRef (builder, loc, flag);
4965
4965
mlir::Value field = builder.create <fir::LoadOp>(loc, fieldRef);
4966
- mlir::Value haltSet =
4967
- IntrinsicLibrary::genRuntimeCall (" fegetexcept" , i32Ty, {});
4966
+ mlir::Value haltSet = fir::runtime::genFegetexcept (builder, loc);
4968
4967
mlir::Value intResult = builder.create <mlir::arith::AndIOp>(
4969
4968
loc, haltSet,
4970
4969
fir::runtime::genMapExcept (
@@ -5712,9 +5711,11 @@ void IntrinsicLibrary::genIeeeSetFlagOrHaltingMode(
5712
5711
loc, builder.create <fir::ConvertOp>(loc, i1Ty, getBase (args[1 ])),
5713
5712
/* withElseRegion=*/ true );
5714
5713
builder.setInsertionPointToStart (&ifOp.getThenRegion ().front ());
5715
- genRuntimeCall (isFlag ? " feraiseexcept" : " feenableexcept" , i32Ty, except);
5714
+ (isFlag ? fir::runtime::genFeraiseexcept : fir::runtime::genFeenableexcept)(
5715
+ builder, loc, builder.create <fir::ConvertOp>(loc, i32Ty, except));
5716
5716
builder.setInsertionPointToStart (&ifOp.getElseRegion ().front ());
5717
- genRuntimeCall (isFlag ? " feclearexcept" : " fedisableexcept" , i32Ty, except);
5717
+ (isFlag ? fir::runtime::genFeclearexcept : fir::runtime::genFedisableexcept)(
5718
+ builder, loc, builder.create <fir::ConvertOp>(loc, i32Ty, except));
5718
5719
builder.setInsertionPointAfter (ifOp);
5719
5720
}
5720
5721
@@ -5805,24 +5806,61 @@ mlir::Value IntrinsicLibrary::genIeeeSignbit(mlir::Type resultType,
5805
5806
fir::ExtendedValue
5806
5807
IntrinsicLibrary::genIeeeSupportFlag (mlir::Type resultType,
5807
5808
llvm::ArrayRef<fir::ExtendedValue> args) {
5808
- // Check if a floating point exception flag is supported. A flag is
5809
- // supported either for all type kinds or none. An optional kind argument X
5810
- // is therefore ignored. Standard flags are all supported. The nonstandard
5811
- // DENORM extension is not supported, at least for now.
5809
+ // Check if a floating point exception flag is supported.
5812
5810
assert (args.size () == 1 || args.size () == 2 );
5811
+ mlir::Type i1Ty = builder.getI1Type ();
5812
+ mlir::Type i32Ty = builder.getIntegerType (32 );
5813
5813
auto [fieldRef, fieldTy] = getFieldRef (builder, loc, getBase (args[0 ]));
5814
5814
mlir::Value flag = builder.create <fir::LoadOp>(loc, fieldRef);
5815
- mlir::Value mask = builder.createIntegerConstant ( // values are powers of 2
5815
+ mlir::Value standardFlagMask = builder.createIntegerConstant (
5816
5816
loc, fieldTy,
5817
5817
_FORTRAN_RUNTIME_IEEE_INVALID | _FORTRAN_RUNTIME_IEEE_DIVIDE_BY_ZERO |
5818
5818
_FORTRAN_RUNTIME_IEEE_OVERFLOW | _FORTRAN_RUNTIME_IEEE_UNDERFLOW |
5819
5819
_FORTRAN_RUNTIME_IEEE_INEXACT);
5820
- return builder.createConvert (
5821
- loc, resultType,
5822
- builder.create <mlir::arith::CmpIOp>(
5823
- loc, mlir::arith::CmpIPredicate::ne,
5824
- builder.create <mlir::arith::AndIOp>(loc, flag, mask),
5825
- builder.createIntegerConstant (loc, fieldTy, 0 )));
5820
+ mlir::Value isStandardFlag = builder.create <mlir::arith::CmpIOp>(
5821
+ loc, mlir::arith::CmpIPredicate::ne,
5822
+ builder.create <mlir::arith::AndIOp>(loc, flag, standardFlagMask),
5823
+ builder.createIntegerConstant (loc, fieldTy, 0 ));
5824
+ fir::IfOp ifOp = builder.create <fir::IfOp>(loc, i1Ty, isStandardFlag,
5825
+ /* withElseRegion=*/ true );
5826
+ // Standard flags are supported.
5827
+ builder.setInsertionPointToStart (&ifOp.getThenRegion ().front ());
5828
+ builder.create <fir::ResultOp>(loc, builder.createBool (loc, true ));
5829
+
5830
+ // TargetCharacteristics information for the nonstandard ieee_denorm flag
5831
+ // is not available here. So use a runtime check restricted to possibly
5832
+ // supported kinds.
5833
+ builder.setInsertionPointToStart (&ifOp.getElseRegion ().front ());
5834
+ bool mayBeSupported = false ;
5835
+ if (mlir::Value arg1 = getBase (args[1 ])) {
5836
+ mlir::Type arg1Ty = arg1.getType ();
5837
+ if (fir::ReferenceType refTy = mlir::dyn_cast<fir::ReferenceType>(arg1Ty))
5838
+ arg1Ty = refTy.getEleTy ();
5839
+ switch (mlir::dyn_cast<mlir::FloatType>(arg1Ty).getWidth ()) {
5840
+ case 16 :
5841
+ mayBeSupported = arg1Ty.isBF16 (); // kind=3
5842
+ break ;
5843
+ case 32 : // kind=4
5844
+ case 64 : // kind=8
5845
+ mayBeSupported = true ;
5846
+ break ;
5847
+ }
5848
+ }
5849
+ if (mayBeSupported) {
5850
+ mlir::Value isDenorm = builder.create <mlir::arith::CmpIOp>(
5851
+ loc, mlir::arith::CmpIPredicate::eq, flag,
5852
+ builder.createIntegerConstant (loc, fieldTy,
5853
+ _FORTRAN_RUNTIME_IEEE_DENORM));
5854
+ mlir::Value result = builder.create <mlir::arith::AndIOp>(
5855
+ loc, isDenorm,
5856
+ fir::runtime::genSupportHalting (
5857
+ builder, loc, builder.create <fir::ConvertOp>(loc, i32Ty, flag)));
5858
+ builder.create <fir::ResultOp>(loc, result);
5859
+ } else {
5860
+ builder.create <fir::ResultOp>(loc, builder.createBool (loc, false ));
5861
+ }
5862
+ builder.setInsertionPointAfter (ifOp);
5863
+ return builder.createConvert (loc, resultType, ifOp.getResult (0 ));
5826
5864
}
5827
5865
5828
5866
// IEEE_SUPPORT_HALTING
@@ -5838,7 +5876,7 @@ fir::ExtendedValue IntrinsicLibrary::genIeeeSupportHalting(
5838
5876
return builder.createConvert (
5839
5877
loc, resultType,
5840
5878
fir::runtime::genSupportHalting (
5841
- builder, loc, { builder.create <fir::ConvertOp>(loc, i32Ty, field)} ));
5879
+ builder, loc, builder.create <fir::ConvertOp>(loc, i32Ty, field)));
5842
5880
}
5843
5881
5844
5882
// IEEE_SUPPORT_ROUNDING
@@ -5874,10 +5912,10 @@ fir::ExtendedValue IntrinsicLibrary::genIeeeSupportStandard(
5874
5912
// if halting control is supported, as that is the only support component
5875
5913
// that may not be available.
5876
5914
assert (args.size () <= 1 );
5877
- mlir::Value nearest = builder.createIntegerConstant (
5878
- loc, builder.getIntegerType (32 ), _FORTRAN_RUNTIME_IEEE_NEAREST );
5915
+ mlir::Value overflow = builder.createIntegerConstant (
5916
+ loc, builder.getIntegerType (32 ), _FORTRAN_RUNTIME_IEEE_OVERFLOW );
5879
5917
return builder.createConvert (
5880
- loc, resultType, fir::runtime::genSupportHalting (builder, loc, nearest ));
5918
+ loc, resultType, fir::runtime::genSupportHalting (builder, loc, overflow ));
5881
5919
}
5882
5920
5883
5921
// IEEE_UNORDERED
0 commit comments