[flang] Use mlir complex dialect for supported operations

This patch lowers the complex operations supported by the MLIR complex
dialect to those operations rather than libm. When the math runtime flag
is set to precise, libm lowering is used instead.

Differential Revision: https://reviews.llvm.org/D135882
This commit is contained in:
David Truby 2022-10-24 12:42:29 +00:00 committed by David Truby
parent 6cc5bcc12d
commit 000de66649
10 changed files with 195 additions and 69 deletions

View File

@ -17,6 +17,7 @@
#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
#include "mlir/Conversion/Passes.h"
#include "mlir/Dialect/Affine/Passes.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
#include "mlir/InitAllDialects.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Pass/PassRegistry.h"
@ -30,7 +31,8 @@ namespace fir::support {
mlir::acc::OpenACCDialect, mlir::omp::OpenMPDialect, \
mlir::scf::SCFDialect, mlir::arith::ArithDialect, \
mlir::cf::ControlFlowDialect, mlir::func::FuncDialect, \
mlir::vector::VectorDialect, mlir::math::MathDialect
mlir::vector::VectorDialect, mlir::math::MathDialect, \
mlir::complex::ComplexDialect
// The definitive list of dialects used by flang.
#define FLANG_DIALECT_LIST \

View File

@ -35,6 +35,7 @@
#include "flang/Optimizer/Dialect/FIROpsSupport.h"
#include "flang/Optimizer/Support/FatalError.h"
#include "flang/Runtime/entry-names.h"
#include "mlir/Dialect/Complex/IR/Complex.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/Math/IR/Math.h"
#include "llvm/Support/CommandLine.h"
@ -1084,6 +1085,12 @@ llvm::cl::opt<MathRuntimeVersion> mathRuntimeVersion(
clEnumValN(preciseVersion, "precise", "use precise runtime behavior")),
llvm::cl::init(fastVersion));
static llvm::cl::opt<bool>
disableMlirComplex("disable-mlir-complex",
llvm::cl::desc("Use libm instead of the MLIR complex "
"dialect to lower complex operations"),
llvm::cl::init(false));
struct RuntimeFunction {
// llvm::StringRef comparison operator are not constexpr, so use string_view.
using Key = std::string_view;
@ -1320,6 +1327,49 @@ static mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
return result;
}
template <typename T>
static mlir::Value genComplexMathOp(fir::FirOpBuilder &builder,
mlir::Location loc,
llvm::StringRef mathLibFuncName,
mlir::FunctionType mathLibFuncType,
llvm::ArrayRef<mlir::Value> args) {
mlir::Value result;
if (disableMlirComplex ||
(mathRuntimeVersion == preciseVersion && !mathLibFuncName.empty())) {
result = genLibCall(builder, loc, mathLibFuncName, mathLibFuncType, args);
LLVM_DEBUG(result.dump(); llvm::dbgs() << "\n");
return result;
}
LLVM_DEBUG(llvm::dbgs() << "Generating '" << mathLibFuncName
<< "' operation with type ";
mathLibFuncType.dump(); llvm::dbgs() << "\n");
auto type = mathLibFuncType.getInput(0).cast<fir::ComplexType>();
auto kind = type.getElementType().cast<fir::RealType>().getFKind();
auto realTy = builder.getRealType(kind);
auto mComplexTy = mlir::ComplexType::get(realTy);
llvm::SmallVector<mlir::Value, 2> cargs;
for (const mlir::Value &arg : args) {
// Convert the fir.complex to a mlir::complex
cargs.push_back(builder.createConvert(loc, mComplexTy, arg));
}
// Builder expects an extra return type to be provided if different to
// the argument types for an operation
if constexpr (T::template hasTrait<
mlir::OpTrait::SameOperandsAndResultType>()) {
result = builder.create<T>(loc, cargs);
result = builder.createConvert(loc, mathLibFuncType.getResult(0), result);
} else {
result = builder.create<T>(loc, realTy, cargs);
result = builder.createConvert(loc, mathLibFuncType.getResult(0), result);
}
LLVM_DEBUG(result.dump(); llvm::dbgs() << "\n");
return result;
}
/// Mapping between mathematical intrinsic operations and MLIR operations
/// of some appropriate dialect (math, complex, etc.) or libm calls.
/// TODO: support remaining Fortran math intrinsics.
@ -1330,8 +1380,10 @@ static constexpr MathOperation mathOperations[] = {
{"abs", "fabs", genF64F64FuncType, genMathOp<mlir::math::AbsFOp>},
{"abs", "llvm.fabs.f128", genF128F128FuncType,
genMathOp<mlir::math::AbsFOp>},
{"abs", "cabsf", genF32ComplexFuncType, genLibCall},
{"abs", "cabs", genF64ComplexFuncType, genLibCall},
{"abs", "cabsf", genF32ComplexFuncType,
genComplexMathOp<mlir::complex::AbsOp>},
{"abs", "cabs", genF64ComplexFuncType,
genComplexMathOp<mlir::complex::AbsOp>},
{"acos", "acosf", genF32F32FuncType, genLibCall},
{"acos", "acos", genF64F64FuncType, genLibCall},
{"acos", "cacosf", genComplexComplexFuncType<4>, genLibCall},
@ -1386,8 +1438,10 @@ static constexpr MathOperation mathOperations[] = {
{"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},
{"cos", "ccosf", genComplexComplexFuncType<4>,
genComplexMathOp<mlir::complex::CosOp>},
{"cos", "ccos", genComplexComplexFuncType<8>,
genComplexMathOp<mlir::complex::CosOp>},
{"cosh", "coshf", genF32F32FuncType, genLibCall},
{"cosh", "cosh", genF64F64FuncType, genLibCall},
{"cosh", "ccoshf", genComplexComplexFuncType<4>, genLibCall},
@ -1398,8 +1452,10 @@ static constexpr MathOperation mathOperations[] = {
{"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},
{"exp", "cexpf", genComplexComplexFuncType<4>,
genComplexMathOp<mlir::complex::ExpOp>},
{"exp", "cexp", genComplexComplexFuncType<8>,
genComplexMathOp<mlir::complex::ExpOp>},
// math::FloorOp returns a real, while Fortran FLOOR returns integer.
{"floor", "floorf", genF32F32FuncType, genMathOp<mlir::math::FloorOp>},
{"floor", "floor", genF64F64FuncType, genMathOp<mlir::math::FloorOp>},
@ -1409,8 +1465,10 @@ static constexpr MathOperation mathOperations[] = {
{"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},
{"log", "clogf", genComplexComplexFuncType<4>,
genComplexMathOp<mlir::complex::LogOp>},
{"log", "clog", genComplexComplexFuncType<8>,
genComplexMathOp<mlir::complex::LogOp>},
{"log10", "log10f", genF32F32FuncType, genMathOp<mlir::math::Log10Op>},
{"log10", "log10", genF64F64FuncType, genMathOp<mlir::math::Log10Op>},
{"log_gamma", "lgammaf", genF32F32FuncType, genLibCall},
@ -1426,8 +1484,10 @@ static constexpr MathOperation mathOperations[] = {
{"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},
{"pow", "cpowf", genComplexComplexComplexFuncType<4>,
genComplexMathOp<mlir::complex::PowOp>},
{"pow", "cpow", genComplexComplexComplexFuncType<8>,
genComplexMathOp<mlir::complex::PowOp>},
// TODO: add PowIOp in math and complex dialects.
{"pow", "llvm.powi.f32.i32", genF32F32IntFuncType<32>, genLibCall},
{"pow", "llvm.powi.f64.i32", genF64F64IntFuncType<32>, genLibCall},
@ -1449,24 +1509,32 @@ static constexpr MathOperation mathOperations[] = {
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},
{"sin", "csinf", genComplexComplexFuncType<4>,
genComplexMathOp<mlir::complex::SinOp>},
{"sin", "csin", genComplexComplexFuncType<8>,
genComplexMathOp<mlir::complex::SinOp>},
{"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},
{"sqrt", "csqrtf", genComplexComplexFuncType<4>,
genComplexMathOp<mlir::complex::SqrtOp>},
{"sqrt", "csqrt", genComplexComplexFuncType<8>,
genComplexMathOp<mlir::complex::SqrtOp>},
{"tan", "tanf", genF32F32FuncType, genMathOp<mlir::math::TanOp>},
{"tan", "tan", genF64F64FuncType, genMathOp<mlir::math::TanOp>},
{"tan", "ctanf", genComplexComplexFuncType<4>, genLibCall},
{"tan", "ctan", genComplexComplexFuncType<8>, genLibCall},
{"tan", "ctanf", genComplexComplexFuncType<4>,
genComplexMathOp<mlir::complex::TanOp>},
{"tan", "ctan", genComplexComplexFuncType<8>,
genComplexMathOp<mlir::complex::TanOp>},
{"tanh", "tanhf", genF32F32FuncType, genMathOp<mlir::math::TanhOp>},
{"tanh", "tanh", genF64F64FuncType, genMathOp<mlir::math::TanhOp>},
{"tanh", "ctanhf", genComplexComplexFuncType<4>, genLibCall},
{"tanh", "ctanh", genComplexComplexFuncType<8>, genLibCall},
{"tanh", "ctanhf", genComplexComplexFuncType<4>,
genComplexMathOp<mlir::complex::TanhOp>},
{"tanh", "ctanh", genComplexComplexFuncType<8>,
genComplexMathOp<mlir::complex::TanhOp>},
};
// This helper class computes a "distance" between two function types.

View File

@ -20,6 +20,8 @@
#include "flang/Optimizer/Support/TypeCode.h"
#include "flang/Semantics/runtime-type-info.h"
#include "mlir/Conversion/ArithToLLVM/ArithToLLVM.h"
#include "mlir/Conversion/ComplexToLLVM/ComplexToLLVM.h"
#include "mlir/Conversion/ComplexToStandard/ComplexToStandard.h"
#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
#include "mlir/Conversion/LLVMCommon/Pattern.h"
@ -3535,6 +3537,7 @@ public:
// as passes here.
mlir::OpPassManager mathConvertionPM("builtin.module");
mathConvertionPM.addPass(mlir::createConvertMathToFuncsPass());
mathConvertionPM.addPass(mlir::createConvertComplexToStandardPass());
if (mlir::failed(runPipeline(mathConvertionPM, mod)))
return signalPassFailure();
@ -3599,6 +3602,7 @@ public:
// when late math lowering mode is used, into llvm dialect.
mlir::populateMathToLLVMConversionPatterns(typeConverter, pattern);
mlir::populateMathToLibmConversionPatterns(pattern, /*benefit=*/0);
mlir::populateComplexToLLVMConversionPatterns(typeConverter, pattern);
mlir::ConversionTarget target{*context};
target.addLegalDialect<mlir::LLVM::LLVMDialect>();
// The OpenMP dialect is legal for Operations without regions, for those

View File

@ -1,5 +1,9 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s
! RUN: bbc -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX,CMPLX-FAST"
! RUN: bbc -emit-fir --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! RUN: bbc --disable-mlir-complex -emit-fir %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX,CMPLX-FAST"
! RUN: %flang_fc1 -emit-fir -mllvm --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir -mllvm --disable-mlir-complex %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! Test abs intrinsic for various types (int, float, complex)
@ -90,25 +94,29 @@ subroutine abs_testr16(a, b)
b = abs(a)
end subroutine
! CHECK-LABEL: func @_QPabs_testzr(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.complex<4>>{{.*}}, %[[VAL_1:.*]]: !fir.ref<f32>{{.*}}) {
! CMPLX-LABEL: func @_QPabs_testzr(
! CMPLX-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.complex<4>>{{.*}}, %[[VAL_1:.*]]: !fir.ref<f32>{{.*}}) {
subroutine abs_testzr(a, b)
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.complex<4>>
! CHECK: %[[VAL_3:.*]] = fir.call @cabsf(%[[VAL_2]]) : (!fir.complex<4>) -> f32
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f32>
! CHECK: return
! CMPLX: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.complex<4>>
! CMPLX-FAST: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.complex<4>) -> complex<f32>
! CMPLX-FAST: %[[VAL_4:.*]] = complex.abs %[[VAL_3]] : complex<f32>
! CMPLX-PRECISE: %[[VAL_4:.*]] = fir.call @cabsf(%[[VAL_2]]) : (!fir.complex<4>) -> f32
! CMPLX: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref<f32>
! CMPLX: return
complex :: a
real :: b
b = abs(a)
end subroutine abs_testzr
! CHECK-LABEL: func @_QPabs_testzd(
! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.complex<8>>{{.*}}, %[[VAL_1:.*]]: !fir.ref<f64>{{.*}}) {
! CMPLX-LABEL: func @_QPabs_testzd(
! CMPLX-SAME: %[[VAL_0:.*]]: !fir.ref<!fir.complex<8>>{{.*}}, %[[VAL_1:.*]]: !fir.ref<f64>{{.*}}) {
subroutine abs_testzd(a, b)
! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.complex<8>>
! CHECK: %[[VAL_3:.*]] = fir.call @cabs(%[[VAL_2]]) : (!fir.complex<8>) -> f64
! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref<f64>
! CHECK: return
! CMPLX: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<!fir.complex<8>>
! CMPLX-FAST: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.complex<8>) -> complex<f64>
! CMPLX-FAST: %[[VAL_4:.*]] = complex.abs %[[VAL_3]] : complex<f64>
! CMPLX-PRECISE: %[[VAL_4:.*]] = fir.call @cabs(%[[VAL_2]]) : (!fir.complex<8>) -> f64
! CMPLX: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref<f64>
! CMPLX: return
complex(kind=8) :: a
real(kind=8) :: b
b = abs(a)

View File

@ -1,5 +1,9 @@
! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s
! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX,CMPLX-FAST"
! RUN: bbc -emit-fir --math-runtime=precise -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! RUN: bbc -emit-fir --disable-mlir-complex -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX,CMPLX-FAST"
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics -mllvm --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics -mllvm --disable-mlir-complex %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! CHECK-LABEL: exp_testr
! CHECK-SAME: (%[[AREF:.*]]: !fir.ref<f32> {{.*}}, %[[BREF:.*]]: !fir.ref<f32> {{.*}})
@ -51,12 +55,18 @@ end subroutine
! CHECK: %[[RESULT64_OUTLINE:.*]] = math.exp %[[ARG64_OUTLINE]] : f64
! CHECK: return %[[RESULT64_OUTLINE]] : f64
! CHECK-LABEL: private @fir.exp.z4.z4
! CHECK-SAME: (%[[ARG32_OUTLINE]]: !fir.complex<4>) -> !fir.complex<4>
! CHECK: %[[RESULT32_OUTLINE]] = fir.call @cexpf(%[[ARG32_OUTLINE]]) : (!fir.complex<4>) -> !fir.complex<4>
! CHECK: return %[[RESULT32_OUTLINE]] : !fir.complex<4>
! CMPLX-LABEL: private @fir.exp.z4.z4
! CMPLX-SAME: (%[[ARG32_OUTLINE:.*]]: !fir.complex<4>) -> !fir.complex<4>
! CMPLX-FAST: %[[C:.*]] = fir.convert %[[ARG32_OUTLINE]] : (!fir.complex<4>) -> complex<f32>
! CMPLX-FAST: %[[E:.*]] = complex.exp %[[C]] : complex<f32>
! CMPLX-FAST: %[[RESULT32_OUTLINE:.*]] = fir.convert %[[E]] : (complex<f32>) -> !fir.complex<4>
! CMPLX-PRECISE: %[[RESULT32_OUTLINE:.*]] = fir.call @cexpf(%[[ARG32_OUTLINE]]) : (!fir.complex<4>) -> !fir.complex<4>
! CMPLX: return %[[RESULT32_OUTLINE]] : !fir.complex<4>
! CHECK-LABEL: private @fir.exp.z8.z8
! CHECK-SAME: (%[[ARG64_OUTLINE]]: !fir.complex<8>) -> !fir.complex<8>
! CHECK: %[[RESULT64_OUTLINE]] = fir.call @cexp(%[[ARG64_OUTLINE]]) : (!fir.complex<8>) -> !fir.complex<8>
! CHECK: return %[[RESULT64_OUTLINE]] : !fir.complex<8>
! CMPLX-LABEL: private @fir.exp.z8.z8
! CMPLX-SAME: (%[[ARG64_OUTLINE:.*]]: !fir.complex<8>) -> !fir.complex<8>
! CMPLX-FAST: %[[C:.*]] = fir.convert %[[ARG64_OUTLINE]] : (!fir.complex<8>) -> complex<f64>
! CMPLX-FAST: %[[E:.*]] = complex.exp %[[C]] : complex<f64>
! CMPLX-FAST: %[[RESULT64_OUTLINE:.*]] = fir.convert %[[E]] : (complex<f64>) -> !fir.complex<8>
! CMPLX-PRECISE: %[[RESULT64_OUTLINE:.*]] = fir.call @cexp(%[[ARG64_OUTLINE]]) : (!fir.complex<8>) -> !fir.complex<8>
! CMPLX: return %[[RESULT64_OUTLINE]] : !fir.complex<8>

View File

@ -1,5 +1,9 @@
! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s
! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX,CMPLX-FAST"
! RUN: bbc -emit-fir --math-runtime=precise -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! RUN: bbc -emit-fir --disable-mlir-complex -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX,CMPLX-FAST"
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics -mllvm --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics -mllvm --disable-mlir-complex %s -o - | FileCheck %s --check-prefixes="CMPLX,CMPLX-PRECISE"
! CHECK-LABEL: log_testr
! CHECK-SAME: (%[[AREF:.*]]: !fir.ref<f32> {{.*}}, %[[BREF:.*]]: !fir.ref<f32> {{.*}})
@ -71,15 +75,21 @@ end subroutine
! CHECK: %[[RESULT64_OUTLINE:.*]] = math.log %[[ARG64_OUTLINE]] : f64
! CHECK: return %[[RESULT64_OUTLINE]] : f64
! CHECK-LABEL: private @fir.log.z4.z4
! CHECK-SAME: (%[[ARG32_OUTLINE]]: !fir.complex<4>) -> !fir.complex<4>
! CHECK: %[[RESULT32_OUTLINE]] = fir.call @clogf(%[[ARG32_OUTLINE]]) : (!fir.complex<4>) -> !fir.complex<4>
! CHECK: return %[[RESULT32_OUTLINE]] : !fir.complex<4>
! CMPLX-LABEL: private @fir.log.z4.z4
! CMPLX-SAME: (%[[ARG32_OUTLINE:.*]]: !fir.complex<4>) -> !fir.complex<4>
! CMPLX-FAST: %[[C:.*]] = fir.convert %[[ARG32_OUTLINE]] : (!fir.complex<4>) -> complex<f32>
! CMPLX-FAST: %[[E:.*]] = complex.log %[[C]] : complex<f32>
! CMPLX-FAST: %[[RESULT32_OUTLINE:.*]] = fir.convert %[[E]] : (complex<f32>) -> !fir.complex<4>
! CMPLX-PRECISE: %[[RESULT32_OUTLINE:.*]] = fir.call @clogf(%[[ARG32_OUTLINE]]) : (!fir.complex<4>) -> !fir.complex<4>
! CMPLX: return %[[RESULT32_OUTLINE]] : !fir.complex<4>
! CHECK-LABEL: private @fir.log.z8.z8
! CHECK-SAME: (%[[ARG64_OUTLINE]]: !fir.complex<8>) -> !fir.complex<8>
! CHECK: %[[RESULT64_OUTLINE]] = fir.call @clog(%[[ARG64_OUTLINE]]) : (!fir.complex<8>) -> !fir.complex<8>
! CHECK: return %[[RESULT64_OUTLINE]] : !fir.complex<8>
! CMPLX-LABEL: private @fir.log.z8.z8
! CMPLX-SAME: (%[[ARG64_OUTLINE:.*]]: !fir.complex<8>) -> !fir.complex<8>
! CMPLX-FAST: %[[C:.*]] = fir.convert %[[ARG64_OUTLINE]] : (!fir.complex<8>) -> complex<f64>
! CMPLX-FAST: %[[E:.*]] = complex.log %[[C]] : complex<f64>
! CMPLX-FAST: %[[RESULT64_OUTLINE:.*]] = fir.convert %[[E]] : (complex<f64>) -> !fir.complex<8>
! CMPLX-PRECISE: %[[RESULT64_OUTLINE:.*]] = fir.call @clog(%[[ARG64_OUTLINE]]) : (!fir.complex<8>) -> !fir.complex<8>
! CMPLX: return %[[RESULT64_OUTLINE]] : !fir.complex<8>
! CHECK-LABEL: private @fir.log10.f32.f32
! CHECK-SAME: (%[[ARG32_OUTLINE:.*]]: f32) -> f32

View File

@ -43,7 +43,9 @@ function test_complex4(c)
end function
! ALL-LABEL: @_QPtest_complex4
! ALL: {{%[A-Za-z0-9._]+}} = fir.call @cabsf({{%[A-Za-z0-9._]+}}) : (!fir.complex<4>) -> f32
! FAST: {{%[A-Za-z0-9._]+}} = complex.abs {{%[A-Za-z0-9._]+}} : complex<f32>
! RELAXED: {{%[A-Za-z0-9._]+}} = complex.abs {{%[A-Za-z0-9._]+}} : complex<f32>
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @cabsf({{%[A-Za-z0-9._]+}}) : (!fir.complex<4>) -> f32
function test_complex8(c)
complex(8) :: c, test_complex8
@ -51,7 +53,9 @@ function test_complex8(c)
end function
! ALL-LABEL: @_QPtest_complex8
! ALL: {{%[A-Za-z0-9._]+}} = fir.call @cabs({{%[A-Za-z0-9._]+}}) : (!fir.complex<8>) -> f64
! FAST: {{%[A-Za-z0-9._]+}} = complex.abs {{%[A-Za-z0-9._]+}} : complex<f64>
! RELAXED: {{%[A-Za-z0-9._]+}} = complex.abs {{%[A-Za-z0-9._]+}} : complex<f64>
! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @cabs({{%[A-Za-z0-9._]+}}) : (!fir.complex<8>) -> f64
//--- aint.f90
! RUN: bbc -emit-fir %t/aint.f90 -o - --math-runtime=fast | FileCheck --check-prefixes=ALL %t/aint.f90

View File

@ -1,4 +1,9 @@
! RUN: bbc -emit-fir %s -o - | FileCheck %s
! RUN: bbc -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX-FAST"
! RUN: bbc --math-runtime=precise -emit-fir %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
! RUN: bbc --disable-mlir-complex -emit-fir %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX-FAST"
! RUN: %flang_fc1 -emit-fir -mllvm --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir -mllvm --disable-mlir-complex %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
! Test power operation lowering
@ -121,13 +126,15 @@ end subroutine
subroutine pow_c4_c4(x, y, z)
complex :: x, y, z
z = x ** y
! CHECK: call @cpowf
! CMPLX-FAST: complex.pow %{{.*}}, %{{.*}} : complex<f32>
! CMPLX-PRECISE: call @cpowf
end subroutine
! CHECK-LABEL: pow_c8_c8
subroutine pow_c8_c8(x, y, z)
complex(8) :: x, y, z
z = x ** y
! CHECK: call @cpow
! CMPLX-FAST: complex.pow %{{.*}}, %{{.*}} : complex<f64>
! CMPLX-PRECISE: call @cpow
end subroutine

View File

@ -1,5 +1,9 @@
! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s
! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX-FAST"
! RUN: bbc --math-runtime=precise -emit-fir -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
! RUN: bbc --disable-mlir-complex -emit-fir -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX-FAST"
! RUN: %flang_fc1 -emit-fir -mllvm --math-runtime=precise -mllvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir -mllvm --disable-mlir-complex -mllvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
! CHECK-LABEL: sqrt_testr
subroutine sqrt_testr(a, b)
@ -36,7 +40,9 @@ end subroutine
! CHECK: math.sqrt %{{.*}} : f64
! CHECK-LABEL: func private @fir.sqrt.z4.z4
! CHECK: fir.call @csqrtf
! CMPLX-FAST: complex.sqrt %{{.*}} : complex<f32>
! CMPLX-PRECISE: fir.call @csqrtf
! CHECK-LABEL: @fir.sqrt.z8.z8
! CHECK: fir.call @csqrt
! CMPLX-FAST: complex.sqrt %{{.*}} : complex<f64>
! CMPLX-PRECISE: fir.call @csqrt

View File

@ -1,4 +1,5 @@
! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s
! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CHECK,CMPLX-FAST"
! RUN: bbc --math-runtime=precise -emit-fir -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="CMPLX-PRECISE"
! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s
! CHECK-LABEL: tan_testr
@ -176,10 +177,12 @@ end subroutine
! CHECK: math.tan %{{.*}} : f64
! CHECK-LABEL: @fir.tan.z4.z4
! CHECK: fir.call @ctanf
! CMPLX-FAST: complex.tan %{{.*}} : complex<f32>
! CMPLX-PRECISE: fir.call @ctanf
! CHECK-LABEL: @fir.tan.z8.z8
! CHECK: fir.call @ctan
! CMPLX-FAST: complex.tan %{{.*}} : complex<f64>
! CMPLX-PRECISE: fir.call @ctan
! CHECK-LABEL: @fir.atan.f32.f32
! CHECK: math.atan %{{.*}} : f32
@ -200,10 +203,12 @@ end subroutine
! CHECK: math.cos %{{.*}} : f64
! CHECK-LABEL: @fir.cos.z4.z4
! CHECK: fir.call @ccosf
! CMPLX-FAST: complex.cos %{{.*}} : complex<f32>
! CMPLX-PRECISE: fir.call @ccosf
! CHECK-LABEL: @fir.cos.z8.z8
! CHECK: fir.call @ccos
! CMPLX-FAST: complex.cos %{{.*}} : complex<f64>
! CMPLX-PRECISE: fir.call @ccos
! CHECK-LABEL: @fir.cosh.f32.f32
! CHECK: fir.call {{.*}}cosh
@ -224,10 +229,12 @@ end subroutine
! CHECK: math.sin %{{.*}} : f64
! CHECK-LABEL: @fir.sin.z4.z4
! CHECK: fir.call @csinf
! CMPLX-FAST: complex.sin %{{.*}} : complex<f32>
! CMPLX-PRECISE: fir.call @csinf
! CHECK-LABEL: @fir.sin.z8.z8
! CHECK: fir.call @csin
! CMPLX-FAST: complex.sin %{{.*}} : complex<f64>
! CMPLX-PRECISE: fir.call @csin
! CHECK-LABEL: @fir.sinh.f32.f32
! CHECK: fir.call {{.*}}sinh