diff --git a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp index d98288419d68f..c13064a284d12 100644 --- a/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp +++ b/flang/lib/Optimizer/Builder/Runtime/Numeric.cpp @@ -625,7 +625,11 @@ mlir::Value fir::runtime::genSpacing(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Value x) { mlir::func::FuncOp func; mlir::Type fltTy = x.getType(); - + // TODO: for f16/bf16, there are better alternatives that do not require + // casting the argument (resp. result) to (resp. from) f32, but this requires + // knowing that the target runtime has been compiled with std::float16_t or + // std::bfloat16_t support, which is not an information available here for + // now. if (fltTy.isF32()) func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF64()) @@ -634,6 +638,10 @@ mlir::Value fir::runtime::genSpacing(fir::FirOpBuilder &builder, func = fir::runtime::getRuntimeFunc(loc, builder); else if (fltTy.isF128()) func = fir::runtime::getRuntimeFunc(loc, builder); + else if (fltTy.isF16()) + func = fir::runtime::getRuntimeFunc(loc, builder); + else if (fltTy.isBF16()) + func = fir::runtime::getRuntimeFunc(loc, builder); else fir::intrinsicTypeTODO(builder, fltTy, loc, "SPACING"); @@ -641,5 +649,6 @@ mlir::Value fir::runtime::genSpacing(fir::FirOpBuilder &builder, llvm::SmallVector args = { builder.createConvert(loc, funcTy.getInput(0), x)}; - return builder.create(loc, func, args).getResult(0); + mlir::Value res = builder.create(loc, func, args).getResult(0); + return builder.createConvert(loc, fltTy, res); } diff --git a/flang/test/Lower/Intrinsics/spacing.f90 b/flang/test/Lower/Intrinsics/spacing.f90 index 39b35ebd533ab..151f4e2a6d236 100644 --- a/flang/test/Lower/Intrinsics/spacing.f90 +++ b/flang/test/Lower/Intrinsics/spacing.f90 @@ -1,20 +1,36 @@ -! RUN: bbc -emit-fir -hlfir=false %s -o - | FileCheck %s -! RUN: %flang_fc1 -emit-fir -flang-deprecated-no-hlfir %s -o - | FileCheck %s +! RUN: bbc -emit-fir %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s ! CHECK-LABEL: func @_QPspacing_test( -! CHECK-SAME: %[[x:[^:]+]]: !fir.ref{{.*}}) -> f32 real*4 function spacing_test(x) real*4 :: x spacing_test = spacing(x) -! CHECK: %[[a1:.*]] = fir.load %[[x]] : !fir.ref +! CHECK: %[[a1:.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: %{{.*}} = fir.call @_FortranASpacing4(%[[a1]]) {{.*}}: (f32) -> f32 end function ! CHECK-LABEL: func @_QPspacing_test2( -! CHECK-SAME: %[[x:[^:]+]]: !fir.ref{{.*}}) -> f80 real*10 function spacing_test2(x) real*10 :: x spacing_test2 = spacing(x) -! CHECK: %[[a1:.*]] = fir.load %[[x]] : !fir.ref +! CHECK: %[[a1:.*]] = fir.load %{{.*}} : !fir.ref ! CHECK: %{{.*}} = fir.call @_FortranASpacing10(%[[a1]]) {{.*}}: (f80) -> f80 end function + +! CHECK-LABEL: test_real2 +subroutine test_real2(x, y) + real(2) :: x, y + y = spacing(x) +! CHECK: %[[CAST_ARG:.*]] = fir.convert %{{.*}} : (f16) -> f32 +! CHECK: %[[RT_RES:.*]] = fir.call @_FortranASpacing2By4(%[[CAST_ARG]]){{.*}}: (f32) -> f32 +! CHECK: fir.convert %[[RT_RES]] : (f32) -> f16 +end subroutine + +! CHECK-LABEL: test_real3 +subroutine test_real3(x, y) + real(3) :: x, y + y = spacing(x) +! CHECK: %[[CAST_ARG:.*]] = fir.convert %{{.*}} : (bf16) -> f32 +! CHECK: %[[RT_RES:.*]] = fir.call @_FortranASpacing3By4(%[[CAST_ARG]]){{.*}}: (f32) -> f32 +! CHECK: fir.convert %[[RT_RES]] : (f32) -> bf16 +end subroutine