[flang] Use mlir complex dialect for supported operations
authorDavid Truby <david.truby@arm.com>
Mon, 24 Oct 2022 12:42:29 +0000 (12:42 +0000)
committerDavid Truby <David.Truby@arm.com>
Wed, 26 Oct 2022 12:37:15 +0000 (12:37 +0000)
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
flang/lib/Lower/IntrinsicCall.cpp
flang/lib/Optimizer/CodeGen/CodeGen.cpp
flang/test/Lower/Intrinsics/abs.f90
flang/test/Lower/Intrinsics/exp.f90
flang/test/Lower/Intrinsics/log.f90
flang/test/Lower/math-lowering.f90
flang/test/Lower/power-operator.f90
flang/test/Lower/sqrt.f90
flang/test/Lower/trigonometric-intrinsics.f90

index 434556e..bbc50dc 100644 (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                                                     \
index c45270d..0184352 100644 (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.
index 126f688..23745a7 100644 (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
index 52b5ff4..11db7c6 100644 (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)
index 6ddd56c..9fb1557 100644 (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>
index 3c35a3a..80376a9 100644 (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
index 558c44c..7d9bf7c 100644 (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
index a92f2b3..867830f 100644 (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
 
index e4537c5..4b4bc9e 100644 (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
index 99b1812..e1e690c 100644 (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