diff --git a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp --- a/flang/lib/Optimizer/Builder/IntrinsicCall.cpp +++ b/flang/lib/Optimizer/Builder/IntrinsicCall.cpp @@ -250,6 +250,7 @@ fir::ExtendedValue genIparity(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genIsContiguous(mlir::Type, llvm::ArrayRef); + mlir::Value genIsNan(mlir::Type, llvm::ArrayRef); mlir::Value genIshft(mlir::Type, llvm::ArrayRef); mlir::Value genIshftc(mlir::Type, llvm::ArrayRef); fir::ExtendedValue genLbound(mlir::Type, llvm::ArrayRef); @@ -621,6 +622,7 @@ {"ieee_class_eq", &I::genIeeeTypeCompare}, {"ieee_class_ne", &I::genIeeeTypeCompare}, {"ieee_is_finite", &I::genIeeeIsFinite}, + {"ieee_is_nan", &I::genIsNan}, {"ieee_round_eq", &I::genIeeeTypeCompare}, {"ieee_round_ne", &I::genIeeeTypeCompare}, {"ieor", &I::genIeor}, @@ -643,6 +645,7 @@ /*isElemental=*/false}, {"ishft", &I::genIshft}, {"ishftc", &I::genIshftc}, + {"isnan", &I::genIsNan}, {"lbound", &I::genLbound, {{{"array", asInquired}, {"dim", asValue}, {"kind", asValue}}}, @@ -3690,6 +3693,22 @@ fir::runtime::genIsContiguous(builder, loc, fir::getBase(args[0]))); } +mlir::Value IntrinsicLibrary::genIsNan(mlir::Type resultType, + llvm::ArrayRef args) { + assert(args.size() == 1); + mlir::MLIRContext *context = builder.getContext(); + mlir::IntegerType i1ty = mlir::IntegerType::get(context, 1); + mlir::IntegerType i32ty = mlir::IntegerType::get(context, 32); + mlir::FunctionType funtype = + mlir::FunctionType::get(context, {args[0].getType(), i32ty}, {i1ty}); + // The last two bits indicate we are checking for signalling or quiet nan. + mlir::Value nan = builder.createIntegerConstant(loc, i32ty, 0b11); + + mlir::Value call = + genLibCall(builder, loc, "llvm.is.fpclass.f32", funtype, {args[0], nan}); + return builder.createConvert(loc, resultType, call); +} + // ISHFT mlir::Value IntrinsicLibrary::genIshft(mlir::Type resultType, llvm::ArrayRef args) { diff --git a/flang/test/Lower/Intrinsics/isnan.f90 b/flang/test/Lower/Intrinsics/isnan.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/Intrinsics/isnan.f90 @@ -0,0 +1,40 @@ +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: flang-new -fc1 -emit-fir %s -o - | FileCheck %s + +! CHECK-LABEL: isnan_f32 +subroutine isnan_f32(r) + real :: r + i = isnan(r) + ! CHECK: %[[test:.*]] = arith.constant 3 : i32 + ! CHECK: %[[l:.*]] = fir.call @llvm.is.fpclass.f32(%{{.*}}, %[[test]]) {{.*}} (f32, i32) -> i1 + ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4> +end subroutine isnan_f32 + +! CHECK-LABEL: ieee_is_nan_f32 +subroutine ieee_is_nan_f32(r) + use ieee_arithmetic + real :: r + i = ieee_is_nan(r) + ! CHECK: %[[test:.*]] = arith.constant 3 : i32 + ! CHECK: %[[l:.*]] = fir.call @llvm.is.fpclass.f32(%{{.*}}, %[[test]]) {{.*}} (f32, i32) -> i1 + ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4> +end subroutine ieee_is_nan_f32 + +! CHECK-LABEL: isnan_f64 +subroutine isnan_f64(r) + real(KIND=8) :: r + i = isnan(r) + ! CHECK: %[[test:.*]] = arith.constant 3 : i32 + ! CHECK: %[[l:.*]] = fir.call @llvm.is.fpclass.f32(%{{.*}}, %[[test]]) {{.*}} (f32, i32) -> i1 + ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4> +end subroutine isnan_f64 + +! CHECK-LABEL: ieee_is_nan_f64 +subroutine ieee_is_nan_f64(r) + use ieee_arithmetic + real(KIND=8) :: r + i = ieee_is_nan(r) + ! CHECK: %[[test:.*]] = arith.constant 3 : i32 + ! CHECK: %[[l:.*]] = fir.call @llvm.is.fpclass.f32(%{{.*}}, %[[test]]) {{.*}} (f32, i32) -> i1 + ! CHECK: fir.convert %[[l]] : (i1) -> !fir.logical<4> +end subroutine ieee_is_nan_f64