From 000de66649110bc3e0e7cc7d353f3d30c656bcb2 Mon Sep 17 00:00:00 2001 From: David Truby Date: Mon, 24 Oct 2022 12:42:29 +0000 Subject: [PATCH] [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 --- flang/include/flang/Optimizer/Support/InitFIR.h | 4 +- flang/lib/Lower/IntrinsicCall.cpp | 104 ++++++++++++++++++++---- flang/lib/Optimizer/CodeGen/CodeGen.cpp | 4 + flang/test/Lower/Intrinsics/abs.f90 | 36 ++++---- flang/test/Lower/Intrinsics/exp.f90 | 30 ++++--- flang/test/Lower/Intrinsics/log.f90 | 30 ++++--- flang/test/Lower/math-lowering.f90 | 8 +- flang/test/Lower/power-operator.f90 | 13 ++- flang/test/Lower/sqrt.f90 | 14 +++- flang/test/Lower/trigonometric-intrinsics.f90 | 21 +++-- 10 files changed, 195 insertions(+), 69 deletions(-) diff --git a/flang/include/flang/Optimizer/Support/InitFIR.h b/flang/include/flang/Optimizer/Support/InitFIR.h index 434556e..bbc50dc 100644 --- a/flang/include/flang/Optimizer/Support/InitFIR.h +++ b/flang/include/flang/Optimizer/Support/InitFIR.h @@ -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 \ diff --git a/flang/lib/Lower/IntrinsicCall.cpp b/flang/lib/Lower/IntrinsicCall.cpp index c45270d..0184352 100644 --- a/flang/lib/Lower/IntrinsicCall.cpp +++ b/flang/lib/Lower/IntrinsicCall.cpp @@ -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( clEnumValN(preciseVersion, "precise", "use precise runtime behavior")), llvm::cl::init(fastVersion)); +static llvm::cl::opt + 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 +static mlir::Value genComplexMathOp(fir::FirOpBuilder &builder, + mlir::Location loc, + llvm::StringRef mathLibFuncName, + mlir::FunctionType mathLibFuncType, + llvm::ArrayRef 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(); + auto kind = type.getElementType().cast().getFKind(); + auto realTy = builder.getRealType(kind); + auto mComplexTy = mlir::ComplexType::get(realTy); + + llvm::SmallVector 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(loc, cargs); + result = builder.createConvert(loc, mathLibFuncType.getResult(0), result); + } else { + result = builder.create(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}, {"abs", "llvm.fabs.f128", genF128F128FuncType, genMathOp}, - {"abs", "cabsf", genF32ComplexFuncType, genLibCall}, - {"abs", "cabs", genF64ComplexFuncType, genLibCall}, + {"abs", "cabsf", genF32ComplexFuncType, + genComplexMathOp}, + {"abs", "cabs", genF64ComplexFuncType, + genComplexMathOp}, {"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}, {"cos", "cosf", genF32F32FuncType, genMathOp}, {"cos", "cos", genF64F64FuncType, genMathOp}, - {"cos", "ccosf", genComplexComplexFuncType<4>, genLibCall}, - {"cos", "ccos", genComplexComplexFuncType<8>, genLibCall}, + {"cos", "ccosf", genComplexComplexFuncType<4>, + genComplexMathOp}, + {"cos", "ccos", genComplexComplexFuncType<8>, + genComplexMathOp}, {"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}, {"exp", "exp", genF64F64FuncType, genMathOp}, - {"exp", "cexpf", genComplexComplexFuncType<4>, genLibCall}, - {"exp", "cexp", genComplexComplexFuncType<8>, genLibCall}, + {"exp", "cexpf", genComplexComplexFuncType<4>, + genComplexMathOp}, + {"exp", "cexp", genComplexComplexFuncType<8>, + genComplexMathOp}, // math::FloorOp returns a real, while Fortran FLOOR returns integer. {"floor", "floorf", genF32F32FuncType, genMathOp}, {"floor", "floor", genF64F64FuncType, genMathOp}, @@ -1409,8 +1465,10 @@ static constexpr MathOperation mathOperations[] = { {"hypot", "hypot", genF64F64F64FuncType, genLibCall}, {"log", "logf", genF32F32FuncType, genMathOp}, {"log", "log", genF64F64FuncType, genMathOp}, - {"log", "clogf", genComplexComplexFuncType<4>, genLibCall}, - {"log", "clog", genComplexComplexFuncType<8>, genLibCall}, + {"log", "clogf", genComplexComplexFuncType<4>, + genComplexMathOp}, + {"log", "clog", genComplexComplexFuncType<8>, + genComplexMathOp}, {"log10", "log10f", genF32F32FuncType, genMathOp}, {"log10", "log10", genF64F64FuncType, genMathOp}, {"log_gamma", "lgammaf", genF32F32FuncType, genLibCall}, @@ -1426,8 +1484,10 @@ static constexpr MathOperation mathOperations[] = { {"pow", {}, genIntIntIntFuncType<64>, genMathOp}, {"pow", "powf", genF32F32F32FuncType, genMathOp}, {"pow", "pow", genF64F64F64FuncType, genMathOp}, - {"pow", "cpowf", genComplexComplexComplexFuncType<4>, genLibCall}, - {"pow", "cpow", genComplexComplexComplexFuncType<8>, genLibCall}, + {"pow", "cpowf", genComplexComplexComplexFuncType<4>, + genComplexMathOp}, + {"pow", "cpow", genComplexComplexComplexFuncType<8>, + genComplexMathOp}, // 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}, {"sin", "sinf", genF32F32FuncType, genMathOp}, {"sin", "sin", genF64F64FuncType, genMathOp}, - {"sin", "csinf", genComplexComplexFuncType<4>, genLibCall}, - {"sin", "csin", genComplexComplexFuncType<8>, genLibCall}, + {"sin", "csinf", genComplexComplexFuncType<4>, + genComplexMathOp}, + {"sin", "csin", genComplexComplexFuncType<8>, + genComplexMathOp}, {"sinh", "sinhf", genF32F32FuncType, genLibCall}, {"sinh", "sinh", genF64F64FuncType, genLibCall}, {"sinh", "csinhf", genComplexComplexFuncType<4>, genLibCall}, {"sinh", "csinh", genComplexComplexFuncType<8>, genLibCall}, {"sqrt", "sqrtf", genF32F32FuncType, genMathOp}, {"sqrt", "sqrt", genF64F64FuncType, genMathOp}, - {"sqrt", "csqrtf", genComplexComplexFuncType<4>, genLibCall}, - {"sqrt", "csqrt", genComplexComplexFuncType<8>, genLibCall}, + {"sqrt", "csqrtf", genComplexComplexFuncType<4>, + genComplexMathOp}, + {"sqrt", "csqrt", genComplexComplexFuncType<8>, + genComplexMathOp}, {"tan", "tanf", genF32F32FuncType, genMathOp}, {"tan", "tan", genF64F64FuncType, genMathOp}, - {"tan", "ctanf", genComplexComplexFuncType<4>, genLibCall}, - {"tan", "ctan", genComplexComplexFuncType<8>, genLibCall}, + {"tan", "ctanf", genComplexComplexFuncType<4>, + genComplexMathOp}, + {"tan", "ctan", genComplexComplexFuncType<8>, + genComplexMathOp}, {"tanh", "tanhf", genF32F32FuncType, genMathOp}, {"tanh", "tanh", genF64F64FuncType, genMathOp}, - {"tanh", "ctanhf", genComplexComplexFuncType<4>, genLibCall}, - {"tanh", "ctanh", genComplexComplexFuncType<8>, genLibCall}, + {"tanh", "ctanhf", genComplexComplexFuncType<4>, + genComplexMathOp}, + {"tanh", "ctanh", genComplexComplexFuncType<8>, + genComplexMathOp}, }; // This helper class computes a "distance" between two function types. diff --git a/flang/lib/Optimizer/CodeGen/CodeGen.cpp b/flang/lib/Optimizer/CodeGen/CodeGen.cpp index 126f688..23745a7 100644 --- a/flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ b/flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -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(); // The OpenMP dialect is legal for Operations without regions, for those diff --git a/flang/test/Lower/Intrinsics/abs.f90 b/flang/test/Lower/Intrinsics/abs.f90 index 52b5ff4..11db7c6 100644 --- a/flang/test/Lower/Intrinsics/abs.f90 +++ b/flang/test/Lower/Intrinsics/abs.f90 @@ -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>{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { +! CMPLX-LABEL: func @_QPabs_testzr( +! CMPLX-SAME: %[[VAL_0:.*]]: !fir.ref>{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { subroutine abs_testzr(a, b) -! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref> -! CHECK: %[[VAL_3:.*]] = fir.call @cabsf(%[[VAL_2]]) : (!fir.complex<4>) -> f32 -! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref -! CHECK: return +! CMPLX: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref> +! CMPLX-FAST: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.complex<4>) -> complex +! CMPLX-FAST: %[[VAL_4:.*]] = complex.abs %[[VAL_3]] : complex +! CMPLX-PRECISE: %[[VAL_4:.*]] = fir.call @cabsf(%[[VAL_2]]) : (!fir.complex<4>) -> f32 +! CMPLX: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref +! CMPLX: return complex :: a real :: b b = abs(a) end subroutine abs_testzr -! CHECK-LABEL: func @_QPabs_testzd( -! CHECK-SAME: %[[VAL_0:.*]]: !fir.ref>{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { +! CMPLX-LABEL: func @_QPabs_testzd( +! CMPLX-SAME: %[[VAL_0:.*]]: !fir.ref>{{.*}}, %[[VAL_1:.*]]: !fir.ref{{.*}}) { subroutine abs_testzd(a, b) -! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref> -! CHECK: %[[VAL_3:.*]] = fir.call @cabs(%[[VAL_2]]) : (!fir.complex<8>) -> f64 -! CHECK: fir.store %[[VAL_3]] to %[[VAL_1]] : !fir.ref -! CHECK: return +! CMPLX: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref> +! CMPLX-FAST: %[[VAL_3:.*]] = fir.convert %[[VAL_2]] : (!fir.complex<8>) -> complex +! CMPLX-FAST: %[[VAL_4:.*]] = complex.abs %[[VAL_3]] : complex +! CMPLX-PRECISE: %[[VAL_4:.*]] = fir.call @cabs(%[[VAL_2]]) : (!fir.complex<8>) -> f64 +! CMPLX: fir.store %[[VAL_4]] to %[[VAL_1]] : !fir.ref +! CMPLX: return complex(kind=8) :: a real(kind=8) :: b b = abs(a) diff --git a/flang/test/Lower/Intrinsics/exp.f90 b/flang/test/Lower/Intrinsics/exp.f90 index 6ddd56c..9fb1557 100644 --- a/flang/test/Lower/Intrinsics/exp.f90 +++ b/flang/test/Lower/Intrinsics/exp.f90 @@ -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 {{.*}}, %[[BREF:.*]]: !fir.ref {{.*}}) @@ -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 +! CMPLX-FAST: %[[E:.*]] = complex.exp %[[C]] : complex +! CMPLX-FAST: %[[RESULT32_OUTLINE:.*]] = fir.convert %[[E]] : (complex) -> !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 +! CMPLX-FAST: %[[E:.*]] = complex.exp %[[C]] : complex +! CMPLX-FAST: %[[RESULT64_OUTLINE:.*]] = fir.convert %[[E]] : (complex) -> !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> diff --git a/flang/test/Lower/Intrinsics/log.f90 b/flang/test/Lower/Intrinsics/log.f90 index 3c35a3a..80376a9 100644 --- a/flang/test/Lower/Intrinsics/log.f90 +++ b/flang/test/Lower/Intrinsics/log.f90 @@ -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 {{.*}}, %[[BREF:.*]]: !fir.ref {{.*}}) @@ -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 +! CMPLX-FAST: %[[E:.*]] = complex.log %[[C]] : complex +! CMPLX-FAST: %[[RESULT32_OUTLINE:.*]] = fir.convert %[[E]] : (complex) -> !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 +! CMPLX-FAST: %[[E:.*]] = complex.log %[[C]] : complex +! CMPLX-FAST: %[[RESULT64_OUTLINE:.*]] = fir.convert %[[E]] : (complex) -> !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 diff --git a/flang/test/Lower/math-lowering.f90 b/flang/test/Lower/math-lowering.f90 index 558c44c..7d9bf7c 100644 --- a/flang/test/Lower/math-lowering.f90 +++ b/flang/test/Lower/math-lowering.f90 @@ -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 +! RELAXED: {{%[A-Za-z0-9._]+}} = complex.abs {{%[A-Za-z0-9._]+}} : complex +! 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 +! RELAXED: {{%[A-Za-z0-9._]+}} = complex.abs {{%[A-Za-z0-9._]+}} : complex +! 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 diff --git a/flang/test/Lower/power-operator.f90 b/flang/test/Lower/power-operator.f90 index a92f2b3..867830f 100644 --- a/flang/test/Lower/power-operator.f90 +++ b/flang/test/Lower/power-operator.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 + ! 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 + ! CMPLX-PRECISE: call @cpow end subroutine diff --git a/flang/test/Lower/sqrt.f90 b/flang/test/Lower/sqrt.f90 index e4537c5..4b4bc9e 100644 --- a/flang/test/Lower/sqrt.f90 +++ b/flang/test/Lower/sqrt.f90 @@ -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 +! CMPLX-PRECISE: fir.call @csqrtf ! CHECK-LABEL: @fir.sqrt.z8.z8 -! CHECK: fir.call @csqrt +! CMPLX-FAST: complex.sqrt %{{.*}} : complex +! CMPLX-PRECISE: fir.call @csqrt diff --git a/flang/test/Lower/trigonometric-intrinsics.f90 b/flang/test/Lower/trigonometric-intrinsics.f90 index 99b1812..e1e690c 100644 --- a/flang/test/Lower/trigonometric-intrinsics.f90 +++ b/flang/test/Lower/trigonometric-intrinsics.f90 @@ -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 +! CMPLX-PRECISE: fir.call @ctanf ! CHECK-LABEL: @fir.tan.z8.z8 -! CHECK: fir.call @ctan +! CMPLX-FAST: complex.tan %{{.*}} : complex +! 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 +! CMPLX-PRECISE: fir.call @ccosf ! CHECK-LABEL: @fir.cos.z8.z8 -! CHECK: fir.call @ccos +! CMPLX-FAST: complex.cos %{{.*}} : complex +! 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 +! CMPLX-PRECISE: fir.call @csinf ! CHECK-LABEL: @fir.sin.z8.z8 -! CHECK: fir.call @csin +! CMPLX-FAST: complex.sin %{{.*}} : complex +! CMPLX-PRECISE: fir.call @csin ! CHECK-LABEL: @fir.sinh.f32.f32 ! CHECK: fir.call {{.*}}sinh -- 2.7.4