llvm-project/flang/test/Lower/llvm-math.f90
Slava Zakharin 9f35657983 [flang] Lower Fortran math intrinsic operations into MLIR ops or libm calls.
Added new -lower-math-early option that defaults to 'true' that matches
the current math lowering scheme. If set to 'false', the intrinsic math
operations will be lowered to MLIR operations, which should potentially
enable more MLIR optimizations, or libm calls, if there is no corresponding
MLIR operation exists or if "precise" mode is requested.
The generated math MLIR operations are then converted to LLVM dialect
during codegen phase.

The -lower-math-early option is not exposed to users currently. I plan to
get rid of the "early" lowering completely, when "late" lowering
is robust enough to support all math intrinsics that are currently
supported via pgmath. So "late" mode will become default and -lower-math-early
option will not be needed. This will effectively eliminate the mandatory
dependency on pgmath in Fortran lowering, but this is WIP.

Differential Revision: https://reviews.llvm.org/D128385
2022-06-28 13:32:19 -07:00

220 lines
5.9 KiB
Fortran

! RUN: bbc -emit-fir %s -o - --math-runtime=llvm --outline-intrinsics | FileCheck %s
! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=llvm -mllvm -outline-intrinsics %s -o - | FileCheck %s
SUBROUTINE POW_WRAPPER(IN, IN2, OUT)
DOUBLE PRECISION IN, IN2
OUT = IN ** IN2
RETURN
END
! CHECK-LABEL: func @_QPpow_wrapper(
! CHECK-SAME: %{{.*}}: !fir.ref<f64>{{.*}}, %{{.*}}: !fir.ref<f64>{{.*}}, %{{.*}}: !fir.ref<f32>{{.*}}) {
! CHECK-NEXT: %0 = fir.load %arg0 : !fir.ref<f64>
! CHECK-NEXT: %1 = fir.load %arg1 : !fir.ref<f64>
! CHECK-NEXT: %2 = fir.call @llvm.pow.f64(%0, %1) : (f64, f64) -> f64
SUBROUTINE POWF_WRAPPER(IN, IN2, OUT)
REAL IN, IN2
OUT = IN ** IN2
RETURN
END
! CHECK-LABEL: func @_QPpowf_wrapper(
! CHECK-SAME: %{{.*}}: !fir.ref<f32>{{.*}}, %{{.*}}: !fir.ref<f32>{{.*}}, %{{.*}}: !fir.ref<f32>{{.*}}) {
! CHECK-NEXT: %0 = fir.load %arg0 : !fir.ref<f32>
! 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)
RETURN
END
! 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)
DOUBLE PRECISION IN, OUT
OUT = DLOG(IN)
RETURN
END
! CHECK: func private @fir.log.f64.f64(%arg0: f64)
! CHECK-NEXT: %0 = fir.call @llvm.log.f64(%arg0) : (f64) -> f64
! CHECK-NEXT: return %0 : f64
! CHECK-NEXT: }
SUBROUTINE LOG10_WRAPPER(IN, OUT)
DOUBLE PRECISION IN, OUT
OUT = DLOG10(IN)
RETURN
END
! 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 LOGF_WRAPPER(IN, OUT)
REAL IN, OUT
OUT = LOG(IN)
RETURN
END
! CHECK: func private @fir.log.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @llvm.log.f32(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE LOG10F_WRAPPER(IN, OUT)
REAL IN, OUT
OUT = LOG10(IN)
RETURN
END
! CHECK: func private @fir.log10.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @llvm.log10.f32(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE SQRT_WRAPPER(IN, OUT)
REAL :: IN, OUT
OUT = SQRT(IN)
END SUBROUTINE
! CHECK-LABEL: func private @fir.sqrt.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @llvm.sqrt.f32(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE SQRTD_WRAPPER(IN, OUT)
REAL(KIND=8) :: IN, OUT
OUT = SQRT(IN)
END SUBROUTINE
! CHECK-LABEL: func private @fir.sqrt.f64.f64(%arg0: f64)
! CHECK-NEXT: %0 = fir.call @llvm.sqrt.f64(%arg0) : (f64) -> f64
! CHECK-NEXT: return %0 : f64
! CHECK-NEXT: }
SUBROUTINE COS_WRAPPER(IN, OUT)
REAL :: IN, OUT
OUT = COS(IN)
END SUBROUTINE
! CHECK-LABEL: func private @fir.cos.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @llvm.cos.f32(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE COSD_WRAPPER(IN, OUT)
REAL(KIND=8) :: IN, OUT
OUT = COS(IN)
END SUBROUTINE
! CHECK-LABEL: func private @fir.cos.f64.f64(%arg0: f64)
! CHECK-NEXT: %0 = fir.call @llvm.cos.f64(%arg0) : (f64) -> f64
! CHECK-NEXT: return %0 : f64
! CHECK-NEXT: }
SUBROUTINE SIN_WRAPPER(IN, OUT)
REAL :: IN, OUT
OUT = SIN(IN)
END SUBROUTINE
! CHECK-LABEL: func private @fir.sin.f32.f32(%arg0: f32)
! CHECK-NEXT: %0 = fir.call @llvm.sin.f32(%arg0) : (f32) -> f32
! CHECK-NEXT: return %0 : f32
! CHECK-NEXT: }
SUBROUTINE SIND_WRAPPER(IN, OUT)
REAL(KIND=8) :: IN, OUT
OUT = SIN(IN)
END SUBROUTINE
! CHECK-LABEL: func private @fir.sin.f64.f64(%arg0: f64)
! CHECK-NEXT: %0 = fir.call @llvm.sin.f64(%arg0) : (f64) -> f64
! CHECK-NEXT: return %0 : f64
! CHECK-NEXT: }