diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md index 1dc0b65271b27..e70f40306c4e1 100644 --- a/flang/docs/Extensions.md +++ b/flang/docs/Extensions.md @@ -150,13 +150,15 @@ end have this capability. An Arm executable will run on either type of processor, so it is effectively unknown at compile time whether or not this support will be available at runtime. The standard requires - that a call to intrinsic module procedure `IEEE_SUPPORT_HALTING` with + that a call to intrinsic module procedure `ieee_support_halting` with a constant argument has a compile time constant result in `constant expression` and `specification expression` contexts. In compilations where this information is not known at compile time, f18 generates code to determine the absence or presence of this capability at runtime. - A call to `IEEE_SUPPORT_HALTING` in contexts that the standard requires - to be constant will generate a compilation error. + A call to `ieee_support_halting` in contexts that the standard requires + to be constant will generate a compilation error. `ieee_support_standard` + depends in part on `ieee_support_halting`, so this also applies to + `ieee_support_standard` calls. ## Extensions, deletions, and legacy features supported by default diff --git a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h index f5971610694f0..c82e5265970c5 100644 --- a/flang/include/flang/Optimizer/Builder/IntrinsicCall.h +++ b/flang/include/flang/Optimizer/Builder/IntrinsicCall.h @@ -313,7 +313,10 @@ struct IntrinsicLibrary { llvm::ArrayRef); fir::ExtendedValue genIeeeSupportHalting(mlir::Type, llvm::ArrayRef); - mlir::Value genIeeeSupportRounding(mlir::Type, llvm::ArrayRef); + fir::ExtendedValue genIeeeSupportRounding(mlir::Type, + llvm::ArrayRef); + fir::ExtendedValue genIeeeSupportStandard(mlir::Type, + llvm::ArrayRef); template mlir::Value genIeeeTypeCompare(mlir::Type, llvm::ArrayRef); mlir::Value genIeeeUnordered(mlir::Type, llvm::ArrayRef); diff --git a/flang/lib/Evaluate/fold-logical.cpp b/flang/lib/Evaluate/fold-logical.cpp index e3ec1a1af8881..77f8e0f616878 100644 --- a/flang/lib/Evaluate/fold-logical.cpp +++ b/flang/lib/Evaluate/fold-logical.cpp @@ -882,7 +882,7 @@ Expr> FoldIntrinsicFunction( IeeeFeature::Flags)}; } else if (name == "__builtin_ieee_support_halting") { if (!context.targetCharacteristics() - .haltingSupportIsUnknownAtCompileTime()) { + .haltingSupportIsUnknownAtCompileTime()) { return Expr{context.targetCharacteristics().ieeeFeatures().test( IeeeFeature::Halting)}; } @@ -906,8 +906,12 @@ Expr> FoldIntrinsicFunction( return Expr{ context.targetCharacteristics().ieeeFeatures().test(IeeeFeature::Sqrt)}; } else if (name == "__builtin_ieee_support_standard") { - return Expr{context.targetCharacteristics().ieeeFeatures().test( - IeeeFeature::Standard)}; + // ieee_support_standard depends in part on ieee_support_halting. + if (!context.targetCharacteristics() + .haltingSupportIsUnknownAtCompileTime()) { + return Expr{context.targetCharacteristics().ieeeFeatures().test( + IeeeFeature::Standard)}; + } } else if (name == "__builtin_ieee_support_subnormal") { return Expr{context.targetCharacteristics().ieeeFeatures().test( IeeeFeature::Subnormal)}; diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp index 5c9527cec2f69..6d8f19388d8b7 100644 --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -1022,45 +1022,35 @@ static const IntrinsicInterface genericIntrinsicFunction[]{ {"__builtin_ieee_next_up", {{"x", SameReal}}, SameReal}, {"__builtin_ieee_real", {{"a", AnyIntOrReal}, DefaultingKIND}, KINDReal}, {"__builtin_ieee_support_datatype", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_denormal", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_divide", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_flag", {{"flag", IeeeFlagType, Rank::scalar}, - {"x", AnyReal, Rank::elemental, Optionality::optional}}, + {"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_halting", {{"flag", IeeeFlagType, Rank::scalar}}, DefaultLogical}, {"__builtin_ieee_support_inf", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_io", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_nan", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_rounding", {{"round_value", IeeeRoundType, Rank::scalar}, - {"x", AnyReal, Rank::elemental, Optionality::optional}}, + {"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_sqrt", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_standard", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_subnormal", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_ieee_support_underflow_control", - {{"x", AnyReal, Rank::elemental, Optionality::optional}}, - DefaultLogical}, + {{"x", AnyReal, Rank::known, Optionality::optional}}, DefaultLogical}, {"__builtin_numeric_storage_size", {}, DefaultInt}, }; diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp index 537c817e32ad8..6e865a8bfb71b 100644 --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -456,8 +456,18 @@ static constexpr IntrinsicHandler handlers[]{ &I::genIeeeSupportFlag, {{{"flag", asValue}, {"x", asInquired, handleDynamicOptional}}}, /*isElemental=*/false}, - {"ieee_support_halting", &I::genIeeeSupportHalting}, - {"ieee_support_rounding", &I::genIeeeSupportRounding}, + {"ieee_support_halting", + &I::genIeeeSupportHalting, + {{{"flag", asValue}}}, + /*isElemental=*/false}, + {"ieee_support_rounding", + &I::genIeeeSupportRounding, + {{{"round_value", asValue}, {"x", asInquired, handleDynamicOptional}}}, + /*isElemental=*/false}, + {"ieee_support_standard", + &I::genIeeeSupportStandard, + {{{"flag", asValue}, {"x", asInquired, handleDynamicOptional}}}, + /*isElemental=*/false}, {"ieee_unordered", &I::genIeeeUnordered}, {"ieee_value", &I::genIeeeValue}, {"ieor", &I::genIeor}, @@ -5613,7 +5623,7 @@ IntrinsicLibrary::genIeeeSupportFlag(mlir::Type resultType, // is therefore ignored. Standard flags are all supported. The nonstandard // DENORM extension is not supported, at least for now. assert(args.size() == 1 || args.size() == 2); - auto [fieldRef, fieldTy] = getFieldRef(builder, loc, fir::getBase(args[0])); + auto [fieldRef, fieldTy] = getFieldRef(builder, loc, getBase(args[0])); mlir::Value flag = builder.create(loc, fieldRef); mlir::Value mask = builder.createIntegerConstant( // values are powers of 2 loc, fieldTy, @@ -5645,9 +5655,8 @@ fir::ExtendedValue IntrinsicLibrary::genIeeeSupportHalting( } // IEEE_SUPPORT_ROUNDING -mlir::Value -IntrinsicLibrary::genIeeeSupportRounding(mlir::Type resultType, - llvm::ArrayRef args) { +fir::ExtendedValue IntrinsicLibrary::genIeeeSupportRounding( + mlir::Type resultType, llvm::ArrayRef args) { // Check if floating point rounding mode ROUND_VALUE is supported. // Rounding is supported either for all type kinds or none. // An optional X kind argument is therefore ignored. @@ -5658,7 +5667,7 @@ IntrinsicLibrary::genIeeeSupportRounding(mlir::Type resultType, // 3 - toward negative infinity [supported] // 4 - to nearest, ties away from zero [not supported] assert(args.size() == 1 || args.size() == 2); - auto [fieldRef, fieldTy] = getFieldRef(builder, loc, args[0]); + auto [fieldRef, fieldTy] = getFieldRef(builder, loc, getBase(args[0])); mlir::Value mode = builder.create(loc, fieldRef); mlir::Value lbOk = builder.create( loc, mlir::arith::CmpIPredicate::sge, mode, @@ -5671,6 +5680,19 @@ IntrinsicLibrary::genIeeeSupportRounding(mlir::Type resultType, loc, resultType, builder.create(loc, lbOk, ubOk)); } +// IEEE_SUPPORT_STANDARD +fir::ExtendedValue IntrinsicLibrary::genIeeeSupportStandard( + mlir::Type resultType, llvm::ArrayRef args) { + // Check if IEEE standard support is available, which reduces to checking + // if halting control is supported, as that is the only support component + // that may not be available. + assert(args.size() <= 1); + mlir::Value nearest = builder.createIntegerConstant( + loc, builder.getIntegerType(32), _FORTRAN_RUNTIME_IEEE_NEAREST); + return builder.createConvert( + loc, resultType, fir::runtime::genSupportHalting(builder, loc, nearest)); +} + // IEEE_UNORDERED mlir::Value IntrinsicLibrary::genIeeeUnordered(mlir::Type resultType,