return mlir::FunctionType::get(context, {itype, itype}, {itype});
}
+template <int Kind>
+static mlir::FunctionType
+genComplexComplexFuncType(mlir::MLIRContext *context) {
+ auto ctype = fir::ComplexType::get(context, Kind);
+ return mlir::FunctionType::get(context, {ctype}, {ctype});
+}
+
+template <int Kind>
+static mlir::FunctionType
+genComplexComplexComplexFuncType(mlir::MLIRContext *context) {
+ auto ctype = fir::ComplexType::get(context, Kind);
+ return mlir::FunctionType::get(context, {ctype, ctype}, {ctype});
+}
+
+static mlir::FunctionType genF32ComplexFuncType(mlir::MLIRContext *context) {
+ auto ctype = fir::ComplexType::get(context, 4);
+ auto ftype = mlir::FloatType::getF32(context);
+ return mlir::FunctionType::get(context, {ctype}, {ftype});
+}
+
+static mlir::FunctionType genF64ComplexFuncType(mlir::MLIRContext *context) {
+ auto ctype = fir::ComplexType::get(context, 8);
+ auto ftype = mlir::FloatType::getF64(context);
+ return mlir::FunctionType::get(context, {ctype}, {ftype});
+}
+
/// Callback type for generating lowering for a math operation.
using MathGeneratorTy = mlir::Value (*)(fir::FirOpBuilder &, mlir::Location,
llvm::StringRef, mlir::FunctionType,
{"abs", "fabs", genF64F64FuncType, genMathOp<mlir::math::AbsFOp>},
{"abs", "llvm.fabs.f128", genF128F128FuncType,
genMathOp<mlir::math::AbsFOp>},
+ {"abs", "cabsf", genF32ComplexFuncType, genLibCall},
+ {"abs", "cabs", genF64ComplexFuncType, genLibCall},
{"acos", "acosf", genF32F32FuncType, genLibCall},
{"acos", "acos", genF64F64FuncType, genLibCall},
+ {"acos", "cacosf", genComplexComplexFuncType<4>, genLibCall},
+ {"acos", "cacos", genComplexComplexFuncType<8>, genLibCall},
{"acosh", "acoshf", genF32F32FuncType, genLibCall},
{"acosh", "acosh", genF64F64FuncType, genLibCall},
+ {"acosh", "cacoshf", genComplexComplexFuncType<4>, genLibCall},
+ {"acosh", "cacosh", genComplexComplexFuncType<8>, genLibCall},
// llvm.trunc behaves the same way as libm's trunc.
{"aint", "llvm.trunc.f32", genF32F32FuncType, genLibCall},
{"aint", "llvm.trunc.f64", genF64F64FuncType, genLibCall},
genMathOp<mlir::LLVM::RoundOp>},
{"asin", "asinf", genF32F32FuncType, genLibCall},
{"asin", "asin", genF64F64FuncType, genLibCall},
+ {"asin", "casinf", genComplexComplexFuncType<4>, genLibCall},
+ {"asin", "casin", genComplexComplexFuncType<8>, genLibCall},
{"asinh", "asinhf", genF32F32FuncType, genLibCall},
{"asinh", "asinh", genF64F64FuncType, genLibCall},
+ {"asinh", "casinhf", genComplexComplexFuncType<4>, genLibCall},
+ {"asinh", "casinh", genComplexComplexFuncType<8>, genLibCall},
{"atan", "atanf", genF32F32FuncType, genMathOp<mlir::math::AtanOp>},
{"atan", "atan", genF64F64FuncType, genMathOp<mlir::math::AtanOp>},
+ {"atan", "catanf", genComplexComplexFuncType<4>, genLibCall},
+ {"atan", "catan", genComplexComplexFuncType<8>, genLibCall},
{"atan2", "atan2f", genF32F32F32FuncType, genMathOp<mlir::math::Atan2Op>},
{"atan2", "atan2", genF64F64F64FuncType, genMathOp<mlir::math::Atan2Op>},
{"atanh", "atanhf", genF32F32FuncType, genLibCall},
{"atanh", "atanh", genF64F64FuncType, genLibCall},
+ {"atanh", "catanhf", genComplexComplexFuncType<4>, genLibCall},
+ {"atanh", "catanh", genComplexComplexFuncType<8>, genLibCall},
{"bessel_j0", "j0f", genF32F32FuncType, genLibCall},
{"bessel_j0", "j0", genF64F64FuncType, genLibCall},
{"bessel_j1", "j1f", genF32F32FuncType, genLibCall},
{"ceil", "ceil", genF64F64FuncType, genMathOp<mlir::math::CeilOp>},
{"cos", "cosf", genF32F32FuncType, genMathOp<mlir::math::CosOp>},
{"cos", "cos", genF64F64FuncType, genMathOp<mlir::math::CosOp>},
+ {"cos", "ccosf", genComplexComplexFuncType<4>, genLibCall},
+ {"cos", "ccos", genComplexComplexFuncType<8>, genLibCall},
{"cosh", "coshf", genF32F32FuncType, genLibCall},
{"cosh", "cosh", genF64F64FuncType, genLibCall},
+ {"cosh", "ccoshf", genComplexComplexFuncType<4>, genLibCall},
+ {"cosh", "ccosh", genComplexComplexFuncType<8>, genLibCall},
{"erf", "erff", genF32F32FuncType, genMathOp<mlir::math::ErfOp>},
{"erf", "erf", genF64F64FuncType, genMathOp<mlir::math::ErfOp>},
{"erfc", "erfcf", genF32F32FuncType, genLibCall},
{"erfc", "erfc", genF64F64FuncType, genLibCall},
{"exp", "expf", genF32F32FuncType, genMathOp<mlir::math::ExpOp>},
{"exp", "exp", genF64F64FuncType, genMathOp<mlir::math::ExpOp>},
+ {"exp", "cexpf", genComplexComplexFuncType<4>, genLibCall},
+ {"exp", "cexp", genComplexComplexFuncType<8>, genLibCall},
// math::FloorOp returns a real, while Fortran FLOOR returns integer.
{"floor", "floorf", genF32F32FuncType, genMathOp<mlir::math::FloorOp>},
{"floor", "floor", genF64F64FuncType, genMathOp<mlir::math::FloorOp>},
{"hypot", "hypot", genF64F64F64FuncType, genLibCall},
{"log", "logf", genF32F32FuncType, genMathOp<mlir::math::LogOp>},
{"log", "log", genF64F64FuncType, genMathOp<mlir::math::LogOp>},
+ {"log", "clogf", genComplexComplexFuncType<4>, genLibCall},
+ {"log", "clog", genComplexComplexFuncType<8>, genLibCall},
{"log10", "log10f", genF32F32FuncType, genMathOp<mlir::math::Log10Op>},
{"log10", "log10", genF64F64FuncType, genMathOp<mlir::math::Log10Op>},
{"log_gamma", "lgammaf", genF32F32FuncType, genLibCall},
{"pow", {}, genIntIntIntFuncType<64>, genMathOp<mlir::math::IPowIOp>},
{"pow", "powf", genF32F32F32FuncType, genMathOp<mlir::math::PowFOp>},
{"pow", "pow", genF64F64F64FuncType, genMathOp<mlir::math::PowFOp>},
+ {"pow", "cpowf", genComplexComplexComplexFuncType<4>, genLibCall},
+ {"pow", "cpow", genComplexComplexComplexFuncType<8>, genLibCall},
// TODO: add PowIOp in math and complex dialects.
{"pow", "llvm.powi.f32.i32", genF32F32IntFuncType<32>, genLibCall},
{"pow", "llvm.powi.f64.i32", genF64F64IntFuncType<32>, genLibCall},
genMathOp<mlir::math::CopySignOp>},
{"sin", "sinf", genF32F32FuncType, genMathOp<mlir::math::SinOp>},
{"sin", "sin", genF64F64FuncType, genMathOp<mlir::math::SinOp>},
+ {"sin", "csinf", genComplexComplexFuncType<4>, genLibCall},
+ {"sin", "csin", genComplexComplexFuncType<8>, genLibCall},
{"sinh", "sinhf", genF32F32FuncType, genLibCall},
{"sinh", "sinh", genF64F64FuncType, genLibCall},
+ {"sinh", "csinhf", genComplexComplexFuncType<4>, genLibCall},
+ {"sinh", "csinh", genComplexComplexFuncType<8>, genLibCall},
{"sqrt", "sqrtf", genF32F32FuncType, genMathOp<mlir::math::SqrtOp>},
{"sqrt", "sqrt", genF64F64FuncType, genMathOp<mlir::math::SqrtOp>},
+ {"sqrt", "csqrtf", genComplexComplexFuncType<4>, genLibCall},
+ {"sqrt", "csqrt", genComplexComplexFuncType<8>, genLibCall},
{"tan", "tanf", genF32F32FuncType, genMathOp<mlir::math::TanOp>},
{"tan", "tan", genF64F64FuncType, genMathOp<mlir::math::TanOp>},
+ {"tan", "ctanf", genComplexComplexFuncType<4>, genLibCall},
+ {"tan", "ctan", genComplexComplexFuncType<8>, genLibCall},
{"tanh", "tanhf", genF32F32FuncType, genMathOp<mlir::math::TanhOp>},
{"tanh", "tanh", genF64F64FuncType, genMathOp<mlir::math::TanhOp>},
+ {"tanh", "ctanhf", genComplexComplexFuncType<4>, genLibCall},
+ {"tanh", "ctanh", genComplexComplexFuncType<8>, genLibCall},
};
// This helper class computes a "distance" between two function types.
assert(args.size() == 1);
mlir::Value arg = args[0];
mlir::Type type = arg.getType();
- if (fir::isa_real(type)) {
+ if (fir::isa_real(type) || fir::isa_complex(type)) {
// Runtime call to fp abs. An alternative would be to use mlir
// math::AbsFOp but it does not support all fir floating point types.
return genRuntimeCall("abs", resultType, args);
auto xored = builder.create<mlir::arith::XOrIOp>(loc, arg, mask);
return builder.create<mlir::arith::SubIOp>(loc, xored, mask);
}
- if (fir::isa_complex(type)) {
- // Use HYPOT to fulfill the no underflow/overflow requirement.
- auto parts = fir::factory::Complex{builder, loc}.extractParts(arg);
- llvm::SmallVector<mlir::Value> args = {parts.first, parts.second};
- return genRuntimeCall("hypot", resultType, args);
- }
llvm_unreachable("unexpected type in ABS argument");
}
! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s
+! CHECK-LABEL: tan_testr
+subroutine tan_testr(a, b)
+ real :: a, b
+! CHECK: fir.call @fir.tan.f32.f32
+ b = tan(a)
+end subroutine
+
+! CHECK-LABEL: tan_testd
+subroutine tan_testd(a, b)
+ real(kind=8) :: a, b
+! CHECK: fir.call @fir.tan.f64.f64
+ b = tan(a)
+end subroutine
+
+! CHECK-LABEL: tan_testc
+subroutine tan_testc(z)
+ complex :: z
+! CHECK: fir.call @fir.tan.z4.z4
+ z = tan(z)
+end subroutine
+
+! CHECK-LABEL: tan_testcd
+subroutine tan_testcd(z)
+ complex(kind=8) :: z
+! CHECK: fir.call @fir.tan.z8.z8
+ z = tan(z)
+end subroutine
+
! CHECK-LABEL: atan_testr
subroutine atan_testr(a, b)
real :: a, b
z = sinh(z)
end subroutine
+! CHECK-LABEL: @fir.tan.f32.f32
+! CHECK: math.tan %{{.*}} : f32
+
+! CHECK-LABEL: @fir.tan.f64.f64
+! CHECK: math.tan %{{.*}} : f64
+
+! CHECK-LABEL: @fir.tan.z4.z4
+! CHECK: fir.call @ctanf
+
+! CHECK-LABEL: @fir.tan.z8.z8
+! CHECK: fir.call @ctan
+
! CHECK-LABEL: @fir.atan.f32.f32
! CHECK: math.atan %{{.*}} : f32
! CHECK: math.atan %{{.*}} : f64
! CHECK-LABEL: @fir.atan.z4.z4
-! CHECK: fir.call {{.*}}atan
+! CHECK: fir.call @catanf
! CHECK-LABEL: @fir.atan.z8.z8
-! CHECK: fir.call {{.*}}atan
+! CHECK: fir.call @catan
! CHECK-LABEL: @fir.cos.f32.f32
! CHECK: math.cos %{{.*}} : f32
! CHECK: math.cos %{{.*}} : f64
! CHECK-LABEL: @fir.cos.z4.z4
-! CHECK: fir.call {{.*}}cos
+! CHECK: fir.call @ccosf
! CHECK-LABEL: @fir.cos.z8.z8
-! CHECK: fir.call {{.*}}cos
+! CHECK: fir.call @ccos
! CHECK-LABEL: @fir.cosh.f32.f32
! CHECK: fir.call {{.*}}cosh
! CHECK: fir.call {{.*}}cosh
! CHECK-LABEL: @fir.cosh.z4.z4
-! CHECK: fir.call {{.*}}cosh
+! CHECK: fir.call @ccoshf
! CHECK-LABEL: @fir.cosh.z8.z8
-! CHECK: fir.call {{.*}}cosh
+! CHECK: fir.call @ccosh
! CHECK-LABEL: @fir.sin.f32.f32
! CHECK: math.sin %{{.*}} : f32
! CHECK: math.sin %{{.*}} : f64
! CHECK-LABEL: @fir.sin.z4.z4
-! CHECK: fir.call {{.*}}sin
+! CHECK: fir.call @csinf
! CHECK-LABEL: @fir.sin.z8.z8
-! CHECK: fir.call {{.*}}sin
+! CHECK: fir.call @csin
! CHECK-LABEL: @fir.sinh.f32.f32
! CHECK: fir.call {{.*}}sinh
! CHECK: fir.call {{.*}}sinh
! CHECK-LABEL: @fir.sinh.z4.z4
-! CHECK: fir.call {{.*}}sinh
+! CHECK: fir.call @csinhf
! CHECK-LABEL: @fir.sinh.z8.z8
-! CHECK: fir.call {{.*}}sinh
+! CHECK: fir.call @csinh