[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:
parent
6cc5bcc12d
commit
000de66649
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue