[Flang] Lower atan, sinh, cosh intrinsics

The intrinsic computes the tan and hyperbolic sin, cosine values. By
default they are lowered to runtime calls to the math library. Not all
types are supported currently. The generic and llvm lowering does not
lower floating point types with kind greater than 8, the llvm lowering
does not support the complex types.

Note: tanh is not present in fir-dev hence ignoring for now. We can add
support after upstreaming is complete. sin and cos will come in separate
patches since they have llvm intrinsic lowering.

This is part of the upstreaming effort from the fir-dev branch in [1].
[1] https://github.com/flang-compiler/f18-llvm-project

Reviewed By: PeteSteinfeld

Differential Revision: https://reviews.llvm.org/D122264

Co-authored-by: Eric Schweitz <eschweitz@nvidia.com>
Co-authored-by: William Moses <gh@wsmoses.com>
This commit is contained in:
Kiran Chandramohan 2022-03-23 14:39:11 +00:00
parent 30cb49b44e
commit 3d94851735
3 changed files with 206 additions and 11 deletions

View File

@ -1014,9 +1014,13 @@ static constexpr RuntimeFunction llvmIntrinsics[] = {
{"aint", "llvm.trunc.f64", genF64F64FuncType},
{"anint", "llvm.round.f32", genF32F32FuncType},
{"anint", "llvm.round.f64", genF64F64FuncType},
{"atan", "atanf", genF32F32FuncType},
{"atan", "atan", genF64F64FuncType},
// ceil is used for CEILING but is different, it returns a real.
{"ceil", "llvm.ceil.f32", genF32F32FuncType},
{"ceil", "llvm.ceil.f64", genF64F64FuncType},
{"cosh", "coshf", genF32F32FuncType},
{"cosh", "cosh", genF64F64FuncType},
{"exp", "llvm.exp.f32", genF32F32FuncType},
{"exp", "llvm.exp.f64", genF64F64FuncType},
// llvm.floor is used for FLOOR, but returns real.
@ -1036,6 +1040,8 @@ static constexpr RuntimeFunction llvmIntrinsics[] = {
{"sign", "llvm.copysign.f64", genF64F64F64FuncType},
{"sign", "llvm.copysign.f80", genF80F80F80FuncType},
{"sign", "llvm.copysign.f128", genF128F128F128FuncType},
{"sinh", "sinhf", genF32F32FuncType},
{"sinh", "sinh", genF64F64FuncType},
{"sqrt", "llvm.sqrt.f32", genF32F32FuncType},
{"sqrt", "llvm.sqrt.f64", genF64F64FuncType},
};

View File

@ -24,6 +24,17 @@
! CHECK-NEXT: %1 = fir.load %arg1 : !fir.ref<f32>
! CHECK-NEXT: %2 = fir.call @llvm.pow.f32(%0, %1) : (f32, f32) -> f32
SUBROUTINE ATAN_WRAPPER(IN, OUT)
DOUBLE PRECISION IN
OUT = DATAN(IN)
RETURN
END
! CHECK: func private @fir.atan.f64.f64(%arg0: f64)
! CHECK-NEXT: %0 = fir.call @atan(%arg0) : (f64) -> f64
! CHECK-NEXT: return %0 : f64
! CHECK-NEXT: }
SUBROUTINE EXP_WRAPPER(IN, OUT)
DOUBLE PRECISION IN
OUT = DEXP(IN)
@ -33,6 +44,73 @@
! CHECK: func private @fir.exp.f64.f64(%arg0: f64)
! CHECK-NEXT: %0 = fir.call @llvm.exp.f64(%arg0) : (f64) -> f64
! CHECK-NEXT: return %0 : f64
! CHECK-NEXT: }
SUBROUTINE SINH_WRAPPER(IN, OUT)
DOUBLE PRECISION IN
OUT = DSINH(IN)
RETURN
END
! CHECK: func private @fir.sinh.f64.f64(%arg0: f64)
! CHECK-NEXT: %0 = fir.call @sinh(%arg0) : (f64) -> f64
! CHECK-NEXT: return %0 : f64
! CHECK-NEXT: }
SUBROUTINE COSH_WRAPPER(IN, OUT)
DOUBLE PRECISION IN
OUT = DCOSH(IN)
RETURN
END
! CHECK: func private @fir.cosh.f64.f64(%arg0: f64)
! CHECK-NEXT: %0 = fir.call @cosh(%arg0) : (f64) -> f64
! CHECK-NEXT: return %0 : f64
! CHECK-NEXT: }
SUBROUTINE ATANF_WRAPPER(IN, OUT)
REAL IN
OUT = ATAN(IN)
RETURN
END
! CHECK: func private @fir.atan.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @atanf(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE EXPF_WRAPPER(IN, OUT)
REAL IN
OUT = EXP(IN)
RETURN
END
! CHECK: func private @fir.exp.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @llvm.exp.f32(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE SINHF_WRAPPER(IN, OUT)
REAL IN
OUT = SINH(IN)
RETURN
END
! CHECK: func private @fir.sinh.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @sinhf(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE COSHF_WRAPPER(IN, OUT)
REAL IN
OUT = COSH(IN)
RETURN
END
! CHECK: func private @fir.cosh.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @coshf(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE LOG_WRAPPER(IN, OUT)
@ -55,17 +133,6 @@
! CHECK: func private @fir.log10.f64.f64(%arg0: f64)
! CHECK-NEXT: %0 = fir.call @llvm.log10.f64(%arg0) : (f64) -> f64
! CHECK-NEXT: return %0 : f64
! CHECK-NEXT: }
SUBROUTINE EXPF_WRAPPER(IN, OUT)
REAL IN
OUT = EXP(IN)
RETURN
END
! CHECK: func private @fir.exp.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @llvm.exp.f32(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE LOGF_WRAPPER(IN, OUT)

View File

@ -0,0 +1,122 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
! CHECK-LABEL: atan_testr
subroutine atan_testr(a, b)
real :: a, b
! CHECK: fir.call @fir.atan.f32.f32
b = atan(a)
end subroutine
! CHECK-LABEL: atan_testd
subroutine atan_testd(a, b)
real(kind=8) :: a, b
! CHECK: fir.call @fir.atan.f64.f64
b = atan(a)
end subroutine
! CHECK-LABEL: atan_testc
subroutine atan_testc(z)
complex :: z
! CHECK: fir.call @fir.atan.z4.z4
z = atan(z)
end subroutine
! CHECK-LABEL: atan_testcd
subroutine atan_testcd(z)
complex(kind=8) :: z
! CHECK: fir.call @fir.atan.z8.z8
z = atan(z)
end subroutine
! CHECK-LABEL: cosh_testr
subroutine cosh_testr(a, b)
real :: a, b
! CHECK: fir.call @fir.cosh.f32.f32
b = cosh(a)
end subroutine
! CHECK-LABEL: cosh_testd
subroutine cosh_testd(a, b)
real(kind=8) :: a, b
! CHECK: fir.call @fir.cosh.f64.f64
b = cosh(a)
end subroutine
! CHECK-LABEL: cosh_testc
subroutine cosh_testc(z)
complex :: z
! CHECK: fir.call @fir.cosh.z4.z4
z = cosh(z)
end subroutine
! CHECK-LABEL: cosh_testcd
subroutine cosh_testcd(z)
complex(kind=8) :: z
! CHECK: fir.call @fir.cosh.z8.z8
z = cosh(z)
end subroutine
! CHECK-LABEL: sinh_testr
subroutine sinh_testr(a, b)
real :: a, b
! CHECK: fir.call @fir.sinh.f32.f32
b = sinh(a)
end subroutine
! CHECK-LABEL: sinh_testd
subroutine sinh_testd(a, b)
real(kind=8) :: a, b
! CHECK: fir.call @fir.sinh.f64.f64
b = sinh(a)
end subroutine
! CHECK-LABEL: sinh_testc
subroutine sinh_testc(z)
complex :: z
! CHECK: fir.call @fir.sinh.z4.z4
z = sinh(z)
end subroutine
! CHECK-LABEL: sinh_testcd
subroutine sinh_testcd(z)
complex(kind=8) :: z
! CHECK: fir.call @fir.sinh.z8.z8
z = sinh(z)
end subroutine
! CHECK-LABEL: @fir.atan.f32.f32
! CHECK: fir.call {{.*}}atan
! CHECK-LABEL: @fir.atan.f64.f64
! CHECK: fir.call {{.*}}atan
! CHECK-LABEL: @fir.atan.z4.z4
! CHECK: fir.call {{.*}}atan
! CHECK-LABEL: @fir.atan.z8.z8
! CHECK: fir.call {{.*}}atan
! CHECK-LABEL: @fir.cosh.f32.f32
! CHECK: fir.call {{.*}}cosh
! CHECK-LABEL: @fir.cosh.f64.f64
! CHECK: fir.call {{.*}}cosh
! CHECK-LABEL: @fir.cosh.z4.z4
! CHECK: fir.call {{.*}}cosh
! CHECK-LABEL: @fir.cosh.z8.z8
! CHECK: fir.call {{.*}}cosh
! CHECK-LABEL: @fir.sinh.f32.f32
! CHECK: fir.call {{.*}}sinh
! CHECK-LABEL: @fir.sinh.f64.f64
! CHECK: fir.call {{.*}}sinh
! CHECK-LABEL: @fir.sinh.z4.z4
! CHECK: fir.call {{.*}}sinh
! CHECK-LABEL: @fir.sinh.z8.z8
! CHECK: fir.call {{.*}}sinh