Index: flang/include/flang/Optimizer/Support/InitFIR.h =================================================================== --- flang/include/flang/Optimizer/Support/InitFIR.h +++ flang/include/flang/Optimizer/Support/InitFIR.h @@ -28,7 +28,8 @@ mlir::AffineDialect, FIROpsDialect, mlir::acc::OpenACCDialect, \ mlir::omp::OpenMPDialect, mlir::scf::SCFDialect, \ mlir::arith::ArithmeticDialect, mlir::cf::ControlFlowDialect, \ - mlir::func::FuncDialect, mlir::vector::VectorDialect + mlir::func::FuncDialect, mlir::vector::VectorDialect, \ + mlir::math::MathDialect // The definitive list of dialects used by flang. #define FLANG_DIALECT_LIST \ Index: flang/lib/Lower/IntrinsicCall.cpp =================================================================== --- flang/lib/Lower/IntrinsicCall.cpp +++ flang/lib/Lower/IntrinsicCall.cpp @@ -35,6 +35,7 @@ #include "flang/Optimizer/Dialect/FIROpsSupport.h" #include "flang/Optimizer/Support/FatalError.h" #include "mlir/Dialect/LLVMIR/LLVMDialect.h" +#include "mlir/Dialect/Math/IR/Math.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" @@ -960,8 +961,23 @@ // Math runtime description and matching utility //===----------------------------------------------------------------------===// -/// Command line option to modify math runtime version used to implement -/// intrinsics. +/// Command line option to control how math operations are lowered +/// into MLIR. +/// Going forward, most of the math operations have to be lowered +/// to some MLIR dialect operations or libm calls, if the corresponding +/// MLIR operation is not available or not reasonable to create +/// (e.g. there are no know optimization opportunities for the math +/// operation in MLIR). +/// +/// In general, exposing MLIR operations early can potentially enable more +/// MLIR optimizations. +llvm::cl::opt lowerEarlyToLibCall( + "lower-math-early", + llvm::cl::desc("Controls when to lower Math intrinsics to library calls"), + llvm::cl::init(true)); + +/// Command line option to modify math runtime behavior used to implement +/// intrinsics. This option applies both to early and late math-lowering modes. enum MathRuntimeVersion { fastVersion, relaxedVersion, @@ -969,11 +985,11 @@ llvmOnly }; llvm::cl::opt mathRuntimeVersion( - "math-runtime", llvm::cl::desc("Select math runtime version:"), + "math-runtime", llvm::cl::desc("Select math operations' runtime behavior:"), llvm::cl::values( - clEnumValN(fastVersion, "fast", "use pgmath fast runtime"), - clEnumValN(relaxedVersion, "relaxed", "use pgmath relaxed runtime"), - clEnumValN(preciseVersion, "precise", "use pgmath precise runtime"), + clEnumValN(fastVersion, "fast", "use fast runtime behavior"), + clEnumValN(relaxedVersion, "relaxed", "use relaxed runtime behavior"), + clEnumValN(preciseVersion, "precise", "use precise runtime behavior"), clEnumValN(llvmOnly, "llvm", "only use LLVM intrinsics (may be incomplete)")), llvm::cl::init(fastVersion)); @@ -984,6 +1000,8 @@ // Needed for implicit compare with keys. constexpr operator Key() const { return key; } Key key; // intrinsic name + + // Name of a runtime function that implements the operation. llvm::StringRef symbol; fir::runtime::FuncTypeBuilderFunc typeGenerator; }; @@ -1050,9 +1068,168 @@ return mlir::FunctionType::get(context, {t}, {r}); } -// TODO : Fill-up this table with more intrinsic. +template +static mlir::FunctionType genF64F64IntFuncType(mlir::MLIRContext *context) { + auto ftype = mlir::FloatType::getF64(context); + auto itype = mlir::IntegerType::get(context, Bits); + return mlir::FunctionType::get(context, {ftype, itype}, {ftype}); +} + +template +static mlir::FunctionType genF32F32IntFuncType(mlir::MLIRContext *context) { + auto ftype = mlir::FloatType::getF32(context); + auto itype = mlir::IntegerType::get(context, Bits); + return mlir::FunctionType::get(context, {ftype, itype}, {ftype}); +} + +/// Callback type for generating lowering for a math operation. +using MathGeneratorTy = mlir::Value (*)(fir::FirOpBuilder &, mlir::Location, + llvm::StringRef, mlir::FunctionType, + llvm::ArrayRef); + +struct MathOperation { + // llvm::StringRef comparison operator are not constexpr, so use string_view. + using Key = std::string_view; + // Needed for implicit compare with keys. + constexpr operator Key() const { return key; } + // Intrinsic name. + Key key; + + // Name of a runtime function that implements the operation. + llvm::StringRef runtimeFunc; + fir::runtime::FuncTypeBuilderFunc typeGenerator; + + // A callback to generate FIR for the intrinsic defined by 'name'. + // A callback may generate either dedicated MLIR operation(s) or + // a function call to a runtime function with name defined by + // 'symbol'. + MathGeneratorTy funcGenerator; +}; + +static mlir::Value genLibCall(fir::FirOpBuilder &builder, mlir::Location loc, + llvm::StringRef libFuncName, + mlir::FunctionType libFuncType, + llvm::ArrayRef args) { + LLVM_DEBUG(llvm::dbgs() << "Generating '" << libFuncName + << "' call with type "; + libFuncType.dump(); llvm::dbgs() << "\n"); + mlir::func::FuncOp funcOp = + builder.addNamedFunction(loc, libFuncName, libFuncType); + // TODO: ensure 'strictfp' setting on the call for "precise/strict" + // FP mode. Set appropriate Fast-Math Flags otherwise. + // TODO: we should also mark as many libm function as possible + // with 'pure' attribute (of course, not in strict FP mode). + auto libCall = builder.create(loc, funcOp, args); + LLVM_DEBUG(libCall.dump(); llvm::dbgs() << "\n"); + return libCall.getResult(0); +} + +template +static mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc, + llvm::StringRef mathLibFuncName, + mlir::FunctionType mathLibFuncType, + llvm::ArrayRef args) { + // TODO: we have to annotate the math operations with flags + // that will allow to define FP accuracy/exception + // behavior per operation, so that after early multi-module + // MLIR inlining we can distiguish operation that were + // compiled with different settings. + // Suggestion: + // * For "relaxed" FP mode set all Fast-Math Flags + // (see "[RFC] FastMath flags support in MLIR (arith dialect)" + // topic at discourse.llvm.org). + // * For "fast" FP mode set all Fast-Math Flags except 'afn'. + // * For "precise/strict" FP mode generate fir.calls to libm + // entries and annotate them with an attribute that will + // end up transformed into 'strictfp' LLVM attribute (TBD). + // Elsewhere, "precise/strict" FP mode should also set + // 'strictfp' for all user functions and calls so that + // LLVM backend does the right job. + // * Operations that cannot be reasonably optimized in MLIR + // can be also lowered to libm calls for "fast" and "relaxed" + // modes. + mlir::Value result; + if (mathRuntimeVersion == preciseVersion) { + result = genLibCall(builder, loc, mathLibFuncName, mathLibFuncType, args); + } else { + LLVM_DEBUG(llvm::dbgs() << "Generating '" << mathLibFuncName + << "' operation with type "; + mathLibFuncType.dump(); llvm::dbgs() << "\n"); + result = builder.create(loc, args); + } + 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. +/// See https://gcc.gnu.org/onlinedocs/gcc-12.1.0/gfortran/\ +/// Intrinsic-Procedures.html for a reference. +static constexpr MathOperation mathOperations[] = { + {"abs", "fabsf", genF32F32FuncType, genMathOp}, + {"abs", "fabs", genF64F64FuncType, genMathOp}, + // llvm.trunc behaves the same way as libm's trunc. + {"aint", "llvm.trunc.f32", genF32F32FuncType, genLibCall}, + {"aint", "llvm.trunc.f64", genF64F64FuncType, genLibCall}, + // llvm.round behaves the same way as libm's round. + {"anint", "llvm.round.f32", genF32F32FuncType, + genMathOp}, + {"anint", "llvm.round.f64", genF64F64FuncType, + genMathOp}, + {"atan", "atanf", genF32F32FuncType, genMathOp}, + {"atan", "atan", genF64F64FuncType, genMathOp}, + {"atan2", "atan2f", genF32F32F32FuncType, genMathOp}, + {"atan2", "atan2", genF64F64F64FuncType, genMathOp}, + // math::CeilOp returns a real, while Fortran CEILING returns integer. + {"ceil", "ceilf", genF32F32FuncType, genMathOp}, + {"ceil", "ceil", genF64F64FuncType, genMathOp}, + {"cos", "cosf", genF32F32FuncType, genMathOp}, + {"cos", "cos", genF64F64FuncType, genMathOp}, + {"erf", "erff", genF32F32FuncType, genMathOp}, + {"erf", "erf", genF64F64FuncType, genMathOp}, + {"exp", "expf", genF32F32FuncType, genMathOp}, + {"exp", "exp", genF64F64FuncType, genMathOp}, + // math::FloorOp returns a real, while Fortran FLOOR returns integer. + {"floor", "floorf", genF32F32FuncType, genMathOp}, + {"floor", "floor", genF64F64FuncType, genMathOp}, + {"hypot", "hypotf", genF32F32F32FuncType, genLibCall}, + {"hypot", "hypot", genF64F64F64FuncType, genLibCall}, + {"log", "logf", genF32F32FuncType, genMathOp}, + {"log", "log", genF64F64FuncType, genMathOp}, + {"log10", "log10f", genF32F32FuncType, genMathOp}, + {"log10", "log10", genF64F64FuncType, genMathOp}, + // llvm.lround behaves the same way as libm's lround. + {"nint", "llvm.lround.i64.f64", genIntF64FuncType<64>, genLibCall}, + {"nint", "llvm.lround.i64.f32", genIntF32FuncType<64>, genLibCall}, + {"nint", "llvm.lround.i32.f64", genIntF64FuncType<32>, genLibCall}, + {"nint", "llvm.lround.i32.f32", genIntF32FuncType<32>, genLibCall}, + {"pow", "powf", genF32F32F32FuncType, genMathOp}, + {"pow", "pow", genF64F64F64FuncType, genMathOp}, + // TODO: add PowIOp in math and complex dialects. + {"pow", "llvm.powi.f32.i32", genF32F32IntFuncType<32>, genLibCall}, + {"pow", "llvm.powi.f64.i32", genF64F64IntFuncType<32>, genLibCall}, + {"sign", "copysignf", genF32F32F32FuncType, + genMathOp}, + {"sign", "copysign", genF64F64F64FuncType, + genMathOp}, + {"sin", "sinf", genF32F32FuncType, genMathOp}, + {"sin", "sin", genF64F64FuncType, genMathOp}, + {"sqrt", "sqrtf", genF32F32FuncType, genMathOp}, + {"sqrt", "sqrt", genF64F64FuncType, genMathOp}, + {"tanh", "tanhf", genF32F32FuncType, genMathOp}, + {"tanh", "tanh", genF64F64FuncType, genMathOp}, +}; + // Note: These are also defined as operations in LLVM dialect. See if this // can be use and has advantages. +// TODO: remove this table, since the late math lowering should +// replace it and generate proper MLIR operations rather +// than llvm intrinsic calls, which still look like generic +// calls to MLIR and do not enable many optimizations. +// When late math lowering is able to handle all math operations +// described in pgmath.h.inc and in the table below, we can +// switch to it by default. static constexpr RuntimeFunction llvmIntrinsics[] = { {"abs", "llvm.fabs.f32", genF32F32FuncType}, {"abs", "llvm.fabs.f64", genF64F64FuncType}, @@ -1251,7 +1428,7 @@ /// function type and that will not imply narrowing arguments or extending the /// result. /// If nothing is found, the mlir::func::FuncOp will contain a nullptr. -mlir::func::FuncOp searchFunctionInLibrary( +static mlir::func::FuncOp searchFunctionInLibrary( mlir::Location loc, fir::FirOpBuilder &builder, const Fortran::common::StaticMultimapView &lib, llvm::StringRef name, mlir::FunctionType funcType, @@ -1274,6 +1451,77 @@ return {}; } +using RtMap = Fortran::common::StaticMultimapView; +static constexpr RtMap mathOps(mathOperations); +static_assert(mathOps.Verify() && "map must be sorted"); + +/// Look for a MathOperation entry specifying how to lower a mathematical +/// operation defined by \p name with its result' and operands' types +/// specified in the form of a FunctionType \p funcType. +/// If exact match for the given types is found, then the function +/// returns a pointer to the corresponding MathOperation. +/// Otherwise, the function returns nullptr. +/// If there is a MathOperation that can be used with additional +/// type casts for the operands or/and result (non-exact match), +/// then it is returned via \p bestNearMatch argument, and +/// \p bestMatchDistance specifies the FunctionDistance between +/// the requested operation and the non-exact match. +static const MathOperation * +searchMathOperation(fir::FirOpBuilder &builder, llvm::StringRef name, + mlir::FunctionType funcType, + const MathOperation **bestNearMatch, + FunctionDistance &bestMatchDistance) { + auto range = mathOps.equal_range(name); + for (auto iter = range.first; iter != range.second && iter; ++iter) { + const auto &impl = *iter; + auto implType = impl.typeGenerator(builder.getContext()); + if (funcType == implType) + return &impl; // exact match + + FunctionDistance distance(funcType, implType); + if (distance.isSmallerThan(bestMatchDistance)) { + *bestNearMatch = &impl; + bestMatchDistance = std::move(distance); + } + } + return nullptr; +} + +/// Implementation of the operation defined by \p name with type +/// \p funcType is not precise, and the actual available implementation +/// is \p distance away from the requested. If using the available +/// implementation results in a precision loss, emit an error message +/// with the given code location \p loc. +static void checkPrecisionLoss(llvm::StringRef name, + mlir::FunctionType funcType, + const FunctionDistance &distance, + mlir::Location loc) { + if (!distance.isLosingPrecision()) + return; + + // Using this runtime version requires narrowing the arguments + // or extending the result. It is not numerically safe. There + // is currently no quad math library that was described in + // lowering and could be used here. Emit an error and continue + // generating the code with the narrowing cast so that the user + // can get a complete list of the problematic intrinsic calls. + std::string message("TODO: no math runtime available for '"); + llvm::raw_string_ostream sstream(message); + if (name == "pow") { + assert(funcType.getNumInputs() == 2 && "power operator has two arguments"); + sstream << funcType.getInput(0) << " ** " << funcType.getInput(1); + } else { + sstream << name << "("; + if (funcType.getNumInputs() > 0) + sstream << funcType.getInput(0); + for (mlir::Type argType : funcType.getInputs().drop_front()) + sstream << ", " << argType; + sstream << ")"; + } + sstream << "'"; + mlir::emitError(loc, message); +} + /// Search runtime for the best runtime function given an intrinsic name /// and interface. The interface may not be a perfect match in which case /// the caller is responsible to insert argument and return value conversions. @@ -1292,6 +1540,7 @@ static_assert(pgmathR.Verify() && "map must be sorted"); static constexpr RtMap pgmathP(pgmathPrecise); static_assert(pgmathP.Verify() && "map must be sorted"); + if (mathRuntimeVersion == fastVersion) { match = searchFunctionInLibrary(loc, builder, pgmathF, name, funcType, &bestNearMatch, bestMatchDistance); @@ -1317,30 +1566,7 @@ return exactMatch; if (bestNearMatch != nullptr) { - if (bestMatchDistance.isLosingPrecision()) { - // Using this runtime version requires narrowing the arguments - // or extending the result. It is not numerically safe. There - // is currently no quad math library that was described in - // lowering and could be used here. Emit an error and continue - // generating the code with the narrowing cast so that the user - // can get a complete list of the problematic intrinsic calls. - std::string message("TODO: no math runtime available for '"); - llvm::raw_string_ostream sstream(message); - if (name == "pow") { - assert(funcType.getNumInputs() == 2 && - "power operator has two arguments"); - sstream << funcType.getInput(0) << " ** " << funcType.getInput(1); - } else { - sstream << name << "("; - if (funcType.getNumInputs() > 0) - sstream << funcType.getInput(0); - for (mlir::Type argType : funcType.getInputs().drop_front()) - sstream << ", " << argType; - sstream << ")"; - } - sstream << "'"; - mlir::emitError(loc, message); - } + checkPrecisionLoss(name, funcType, bestMatchDistance, loc); return getFuncOp(loc, builder, *bestNearMatch); } return {}; @@ -1578,7 +1804,7 @@ IntrinsicLibrary::RuntimeCallGenerator runtimeCallGenerator = getRuntimeCallGenerator(name, soughtFuncType); return genElementalCall(runtimeCallGenerator, name, *resultType, args, - /* outline */ true); + /*outline=*/outlineAllIntrinsics); } mlir::Value @@ -1730,29 +1956,58 @@ IntrinsicLibrary::RuntimeCallGenerator IntrinsicLibrary::getRuntimeCallGenerator(llvm::StringRef name, mlir::FunctionType soughtFuncType) { - mlir::func::FuncOp funcOp = - getRuntimeFunction(loc, builder, name, soughtFuncType); - if (!funcOp) { + mlir::func::FuncOp funcOp; + mlir::FunctionType actualFuncType; + const MathOperation *mathOp = nullptr; + if (!lowerEarlyToLibCall) { + // Look for a dedicated math operation generator, which + // normally produces a single MLIR operation implementing + // the math operation. + // If not found fall back to a runtime function lookup. + const MathOperation *bestNearMatch = nullptr; + FunctionDistance bestMatchDistance; + mathOp = searchMathOperation(builder, name, soughtFuncType, &bestNearMatch, + bestMatchDistance); + if (!mathOp && bestNearMatch) { + // Use the best near match, optionally issuing an error, + // if types conversions cause precision loss. + checkPrecisionLoss(name, soughtFuncType, bestMatchDistance, loc); + mathOp = bestNearMatch; + } + if (mathOp) + actualFuncType = mathOp->typeGenerator(builder.getContext()); + } + if (!mathOp) + if ((funcOp = getRuntimeFunction(loc, builder, name, soughtFuncType))) + actualFuncType = funcOp.getFunctionType(); + + if (!mathOp && !funcOp) { std::string nameAndType; llvm::raw_string_ostream sstream(nameAndType); sstream << name << "\nrequested type: " << soughtFuncType; crashOnMissingIntrinsic(loc, nameAndType); } - mlir::FunctionType actualFuncType = funcOp.getFunctionType(); assert(actualFuncType.getNumResults() == soughtFuncType.getNumResults() && actualFuncType.getNumInputs() == soughtFuncType.getNumInputs() && actualFuncType.getNumResults() == 1 && "Bad intrinsic match"); - return [funcOp, actualFuncType, + return [funcOp, actualFuncType, mathOp, soughtFuncType](fir::FirOpBuilder &builder, mlir::Location loc, llvm::ArrayRef args) { llvm::SmallVector convertedArguments; for (auto [fst, snd] : llvm::zip(actualFuncType.getInputs(), args)) convertedArguments.push_back(builder.createConvert(loc, fst, snd)); - auto call = builder.create(loc, funcOp, convertedArguments); + mlir::Value result; + // Use math operation generator, if available. + if (mathOp) + result = mathOp->funcGenerator(builder, loc, mathOp->runtimeFunc, + actualFuncType, convertedArguments); + else + result = builder.create(loc, funcOp, convertedArguments) + .getResult(0); mlir::Type soughtType = soughtFuncType.getResult(0); - return builder.createConvert(loc, soughtType, call.getResult(0)); + return builder.createConvert(loc, soughtType, result); }; } @@ -1918,7 +2173,7 @@ llvm::ArrayRef args) { assert(args.size() == 1); return fir::factory::Complex{builder, loc}.extractComplexPart( - args[0], true /* isImagPart */); + args[0], /*isImagPart=*/true); } // AINT @@ -4032,6 +4287,13 @@ mlir::Value Fortran::lower::genPow(fir::FirOpBuilder &builder, mlir::Location loc, mlir::Type type, mlir::Value x, mlir::Value y) { + // TODO: since there is no libm version of pow with integer exponent, + // we have to provide an alternative implementation for + // "precise/strict" FP mode and (!lowerEarlyToLibCall). + // One option is to generate internal function with inlined + // implementation and mark it 'strictfp'. + // Another option is to implement it in Fortran runtime library + // (just like matmul). return IntrinsicLibrary{builder, loc}.genRuntimeCall("pow", type, {x, y}); } Index: flang/lib/Optimizer/CodeGen/CMakeLists.txt =================================================================== --- flang/lib/Optimizer/CodeGen/CMakeLists.txt +++ flang/lib/Optimizer/CodeGen/CMakeLists.txt @@ -17,6 +17,8 @@ FIRBuilder FIRDialect FIRSupport + MLIRMathToLLVM + MLIRMathToLibm MLIROpenMPToLLVM MLIRLLVMToLLVMIRTranslation MLIRTargetLLVMIRExport Index: flang/lib/Optimizer/CodeGen/CodeGen.cpp =================================================================== --- flang/lib/Optimizer/CodeGen/CodeGen.cpp +++ flang/lib/Optimizer/CodeGen/CodeGen.cpp @@ -23,6 +23,8 @@ #include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h" #include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h" #include "mlir/Conversion/LLVMCommon/Pattern.h" +#include "mlir/Conversion/MathToLLVM/MathToLLVM.h" +#include "mlir/Conversion/MathToLibm/MathToLibm.h" #include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h" #include "mlir/IR/BuiltinTypes.h" #include "mlir/IR/Matchers.h" @@ -3380,6 +3382,10 @@ pattern); mlir::cf::populateControlFlowToLLVMConversionPatterns(typeConverter, pattern); + // Convert math-like dialect operations, which can be produced + // when late math lowering mode is used, into llvm dialect. + mlir::populateMathToLLVMConversionPatterns(typeConverter, pattern); + mlir::populateMathToLibmConversionPatterns(pattern, /*benefit=*/0); mlir::ConversionTarget target{*context}; target.addLegalDialect(); // The OpenMP dialect is legal for Operations without regions, for those Index: flang/test/Intrinsics/late-math-codegen.fir =================================================================== --- /dev/null +++ flang/test/Intrinsics/late-math-codegen.fir @@ -0,0 +1,1523 @@ +// RUN: split-file %s %t +// TODO: verify that Fast-Math Flags and 'strictfp' are properly set. + +//--- abs_fast.fir +// RUN: fir-opt %t/abs_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/abs_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.fabs"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @hypotf({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.fabs"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @hypot({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.abs %1 : f32 + %3 = fir.load %arg2 : !fir.ref> + %4 = fir.extract_value %3, [0 : index] : (!fir.complex<4>) -> f32 + %5 = fir.extract_value %3, [1 : index] : (!fir.complex<4>) -> f32 + %6 = fir.call @hypotf(%4, %5) : (f32, f32) -> f32 + %7 = arith.addf %2, %6 : f32 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.abs %1 : f64 + %3 = fir.load %arg2 : !fir.ref> + %4 = fir.extract_value %3, [0 : index] : (!fir.complex<8>) -> f64 + %5 = fir.extract_value %3, [1 : index] : (!fir.complex<8>) -> f64 + %6 = fir.call @hypot(%4, %5) : (f64, f64) -> f64 + %7 = arith.addf %2, %6 : f64 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f64 +} +func.func private @hypotf(f32, f32) -> f32 +func.func private @hypot(f64, f64) -> f64 + +//--- abs_relaxed.fir +// RUN: fir-opt %t/abs_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/abs_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.fabs"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @hypotf({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.fabs"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @hypot({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.abs %1 : f32 + %3 = fir.load %arg2 : !fir.ref> + %4 = fir.extract_value %3, [0 : index] : (!fir.complex<4>) -> f32 + %5 = fir.extract_value %3, [1 : index] : (!fir.complex<4>) -> f32 + %6 = fir.call @hypotf(%4, %5) : (f32, f32) -> f32 + %7 = arith.addf %2, %6 : f32 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.abs %1 : f64 + %3 = fir.load %arg2 : !fir.ref> + %4 = fir.extract_value %3, [0 : index] : (!fir.complex<8>) -> f64 + %5 = fir.extract_value %3, [1 : index] : (!fir.complex<8>) -> f64 + %6 = fir.call @hypot(%4, %5) : (f64, f64) -> f64 + %7 = arith.addf %2, %6 : f64 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f64 +} +func.func private @hypotf(f32, f32) -> f32 +func.func private @hypot(f64, f64) -> f64 + +//--- abs_precise.fir +// RUN: fir-opt %t/abs_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/abs_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @fabsf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @hypotf({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @fabs({{%[A-Za-z0-9._]+}}) : (f64) -> f64 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @hypot({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @fabsf(%1) : (f32) -> f32 + %3 = fir.load %arg2 : !fir.ref> + %4 = fir.extract_value %3, [0 : index] : (!fir.complex<4>) -> f32 + %5 = fir.extract_value %3, [1 : index] : (!fir.complex<4>) -> f32 + %6 = fir.call @hypotf(%4, %5) : (f32, f32) -> f32 + %7 = arith.addf %2, %6 : f32 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @fabs(%1) : (f64) -> f64 + %3 = fir.load %arg2 : !fir.ref> + %4 = fir.extract_value %3, [0 : index] : (!fir.complex<8>) -> f64 + %5 = fir.extract_value %3, [1 : index] : (!fir.complex<8>) -> f64 + %6 = fir.call @hypot(%4, %5) : (f64, f64) -> f64 + %7 = arith.addf %2, %6 : f64 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f64 +} +func.func private @fabsf(f32) -> f32 +func.func private @hypotf(f32, f32) -> f32 +func.func private @fabs(f64) -> f64 +func.func private @hypot(f64, f64) -> f64 + +//--- aint_fast.fir +// RUN: fir-opt %t/aint_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/aint_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.trunc.f32({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.trunc.f64({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.trunc.f32(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.trunc.f64(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @llvm.trunc.f32(f32) -> f32 +func.func private @llvm.trunc.f64(f64) -> f64 + +//--- aint_relaxed.fir +// RUN: fir-opt %t/aint_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/aint_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.trunc.f32({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.trunc.f64({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.trunc.f32(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.trunc.f64(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @llvm.trunc.f32(f32) -> f32 +func.func private @llvm.trunc.f64(f64) -> f64 + +//--- aint_precise.fir +// RUN: fir-opt %t/aint_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/aint_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.trunc.f32({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.trunc.f64({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.trunc.f32(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.trunc.f64(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @llvm.trunc.f32(f32) -> f32 +func.func private @llvm.trunc.f64(f64) -> f64 + +//--- anint_fast.fir +// RUN: fir-opt %t/anint_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/anint_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = "llvm.intr.round"(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = "llvm.intr.round"(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- anint_relaxed.fir +// RUN: fir-opt %t/anint_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/anint_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = "llvm.intr.round"(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = "llvm.intr.round"(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- anint_precise.fir +// RUN: fir-opt %t/anint_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/anint_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.round.f32({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.round.f64({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.round.f32(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.round.f64(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @llvm.round.f32(f32) -> f32 +func.func private @llvm.round.f64(f64) -> f64 + +//--- atan_fast.fir +// RUN: fir-opt %t/atan_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/atan_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atanf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atan({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.atan %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.atan %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- atan_relaxed.fir +// RUN: fir-opt %t/atan_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/atan_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atanf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atan({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.atan %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.atan %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- atan_precise.fir +// RUN: fir-opt %t/atan_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/atan_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atanf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atan({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @atanf(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @atan(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @atanf(f32) -> f32 +func.func private @atan(f64) -> f64 + +//--- atan2_fast.fir +// RUN: fir-opt %t/atan2_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/atan2_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atan2f({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atan2({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = math.atan2 %1, %2 : f32 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = math.atan2 %1, %2 : f64 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f64 +} + +//--- atan2_relaxed.fir +// RUN: fir-opt %t/atan2_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/atan2_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atan2f({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atan2({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = math.atan2 %1, %2 : f32 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = math.atan2 %1, %2 : f64 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f64 +} + +//--- atan2_precise.fir +// RUN: fir-opt %t/atan2_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/atan2_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atan2f({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @atan2({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = fir.call @atan2f(%1, %2) : (f32, f32) -> f32 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = fir.call @atan2(%1, %2) : (f64, f64) -> f64 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f64 +} +func.func private @atan2f(f32, f32) -> f32 +func.func private @atan2(f64, f64) -> f64 + +//--- ceiling_fast.fir +// RUN: fir-opt %t/ceiling_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/ceiling_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.ceil"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.ceil"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.ceil %1 : f32 + %3 = fir.convert %2 : (f32) -> i32 + %4 = fir.convert %3 : (i32) -> f32 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.ceil %1 : f64 + %3 = fir.convert %2 : (f64) -> i32 + %4 = fir.convert %3 : (i32) -> f64 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f64 +} + +//--- ceiling_relaxed.fir +// RUN: fir-opt %t/ceiling_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/ceiling_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.ceil"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.ceil"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.ceil %1 : f32 + %3 = fir.convert %2 : (f32) -> i32 + %4 = fir.convert %3 : (i32) -> f32 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.ceil %1 : f64 + %3 = fir.convert %2 : (f64) -> i32 + %4 = fir.convert %3 : (i32) -> f64 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f64 +} + +//--- ceiling_precise.fir +// RUN: fir-opt %t/ceiling_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/ceiling_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @ceilf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @ceil({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @ceilf(%1) : (f32) -> f32 + %3 = fir.convert %2 : (f32) -> i32 + %4 = fir.convert %3 : (i32) -> f32 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @ceil(%1) : (f64) -> f64 + %3 = fir.convert %2 : (f64) -> i32 + %4 = fir.convert %3 : (i32) -> f64 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f64 +} +func.func private @ceilf(f32) -> f32 +func.func private @ceil(f64) -> f64 + +//--- cos_fast.fir +// RUN: fir-opt %t/cos_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/cos_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.cos"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.cos"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.cos %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.cos %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- cos_relaxed.fir +// RUN: fir-opt %t/cos_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/cos_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.cos"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.cos"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.cos %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.cos %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- cos_precise.fir +// RUN: fir-opt %t/cos_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/cos_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @cosf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @cos({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @cosf(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @cos(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @cosf(f32) -> f32 +func.func private @cos(f64) -> f64 + +//--- erf_fast.fir +// RUN: fir-opt %t/erf_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/erf_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erff({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erf({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.erf %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.erf %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- erf_relaxed.fir +// RUN: fir-opt %t/erf_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/erf_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erff({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erf({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.erf %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.erf %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- erf_precise.fir +// RUN: fir-opt %t/erf_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/erf_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erff({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @erf({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @erff(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @erf(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @erff(f32) -> f32 +func.func private @erf(f64) -> f64 + +//--- exp_fast.fir +// RUN: fir-opt %t/exp_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exp_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.exp"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.exp"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.exp %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.exp %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- exp_relaxed.fir +// RUN: fir-opt %t/exp_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exp_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.exp"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.exp"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.exp %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.exp %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- exp_precise.fir +// RUN: fir-opt %t/exp_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exp_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @expf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @exp({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @expf(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @exp(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @expf(f32) -> f32 +func.func private @exp(f64) -> f64 + +//--- floor_fast.fir +// RUN: fir-opt %t/floor_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/floor_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.floor"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.floor"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.floor %1 : f32 + %3 = fir.convert %2 : (f32) -> i32 + %4 = fir.convert %3 : (i32) -> f32 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.floor %1 : f64 + %3 = fir.convert %2 : (f64) -> i32 + %4 = fir.convert %3 : (i32) -> f64 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f64 +} + +//--- floor_relaxed.fir +// RUN: fir-opt %t/floor_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/floor_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.floor"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.floor"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.floor %1 : f32 + %3 = fir.convert %2 : (f32) -> i32 + %4 = fir.convert %3 : (i32) -> f32 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.floor %1 : f64 + %3 = fir.convert %2 : (f64) -> i32 + %4 = fir.convert %3 : (i32) -> f64 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f64 +} + +//--- floor_precise.fir +// RUN: fir-opt %t/floor_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/floor_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @floorf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @floor({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @floorf(%1) : (f32) -> f32 + %3 = fir.convert %2 : (f32) -> i32 + %4 = fir.convert %3 : (i32) -> f32 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @floor(%1) : (f64) -> f64 + %3 = fir.convert %2 : (f64) -> i32 + %4 = fir.convert %3 : (i32) -> f64 + fir.store %4 to %0 : !fir.ref + %5 = fir.load %0 : !fir.ref + return %5 : f64 +} +func.func private @floorf(f32) -> f32 +func.func private @floor(f64) -> f64 + +//--- log_fast.fir +// RUN: fir-opt %t/log_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/log_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.log"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.log"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.log %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.log %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- log_relaxed.fir +// RUN: fir-opt %t/log_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/log_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.log"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.log"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.log %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.log %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- log_precise.fir +// RUN: fir-opt %t/log_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/log_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @logf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @log({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @logf(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @log(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @logf(f32) -> f32 +func.func private @log(f64) -> f64 + +//--- log10_fast.fir +// RUN: fir-opt %t/log10_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/log10_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.log10"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.log10"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.log10 %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.log10 %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- log10_relaxed.fir +// RUN: fir-opt %t/log10_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/log10_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.log10"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.log10"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.log10 %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.log10 %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- log10_precise.fir +// RUN: fir-opt %t/log10_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/log10_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @log10f({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @log10({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @log10f(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @log10(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @log10f(f32) -> f32 +func.func private @log10(f64) -> f64 + +//--- nint_fast.fir +// RUN: fir-opt %t/nint_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/nint_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i32.f32({{%[A-Za-z0-9._]+}}) : (f32) -> i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i64.f32({{%[A-Za-z0-9._]+}}) : (f32) -> i64 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i32.f64({{%[A-Za-z0-9._]+}}) : (f64) -> i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i64.f64({{%[A-Za-z0-9._]+}}) : (f64) -> i64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.lround.i32.f32(%1) : (f32) -> i32 + %3 = fir.convert %2 : (i32) -> i64 + %4 = fir.load %arg0 : !fir.ref + %5 = fir.call @llvm.lround.i64.f32(%4) : (f32) -> i64 + %6 = arith.addi %3, %5 : i64 + %7 = fir.convert %6 : (i64) -> f32 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.lround.i32.f64(%1) : (f64) -> i32 + %3 = fir.convert %2 : (i32) -> i64 + %4 = fir.load %arg0 : !fir.ref + %5 = fir.call @llvm.lround.i64.f64(%4) : (f64) -> i64 + %6 = arith.addi %3, %5 : i64 + %7 = fir.convert %6 : (i64) -> f64 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f64 +} +func.func private @llvm.lround.i32.f32(f32) -> i32 +func.func private @llvm.lround.i64.f32(f32) -> i64 +func.func private @llvm.lround.i32.f64(f64) -> i32 +func.func private @llvm.lround.i64.f64(f64) -> i64 + +//--- nint_relaxed.fir +// RUN: fir-opt %t/nint_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/nint_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i32.f32({{%[A-Za-z0-9._]+}}) : (f32) -> i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i64.f32({{%[A-Za-z0-9._]+}}) : (f32) -> i64 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i32.f64({{%[A-Za-z0-9._]+}}) : (f64) -> i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i64.f64({{%[A-Za-z0-9._]+}}) : (f64) -> i64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.lround.i32.f32(%1) : (f32) -> i32 + %3 = fir.convert %2 : (i32) -> i64 + %4 = fir.load %arg0 : !fir.ref + %5 = fir.call @llvm.lround.i64.f32(%4) : (f32) -> i64 + %6 = arith.addi %3, %5 : i64 + %7 = fir.convert %6 : (i64) -> f32 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.lround.i32.f64(%1) : (f64) -> i32 + %3 = fir.convert %2 : (i32) -> i64 + %4 = fir.load %arg0 : !fir.ref + %5 = fir.call @llvm.lround.i64.f64(%4) : (f64) -> i64 + %6 = arith.addi %3, %5 : i64 + %7 = fir.convert %6 : (i64) -> f64 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f64 +} +func.func private @llvm.lround.i32.f32(f32) -> i32 +func.func private @llvm.lround.i64.f32(f32) -> i64 +func.func private @llvm.lround.i32.f64(f64) -> i32 +func.func private @llvm.lround.i64.f64(f64) -> i64 + +//--- nint_precise.fir +// RUN: fir-opt %t/nint_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/nint_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i32.f32({{%[A-Za-z0-9._]+}}) : (f32) -> i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i64.f32({{%[A-Za-z0-9._]+}}) : (f32) -> i64 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i32.f64({{%[A-Za-z0-9._]+}}) : (f64) -> i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.lround.i64.f64({{%[A-Za-z0-9._]+}}) : (f64) -> i64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.lround.i32.f32(%1) : (f32) -> i32 + %3 = fir.convert %2 : (i32) -> i64 + %4 = fir.load %arg0 : !fir.ref + %5 = fir.call @llvm.lround.i64.f32(%4) : (f32) -> i64 + %6 = arith.addi %3, %5 : i64 + %7 = fir.convert %6 : (i64) -> f32 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @llvm.lround.i32.f64(%1) : (f64) -> i32 + %3 = fir.convert %2 : (i32) -> i64 + %4 = fir.load %arg0 : !fir.ref + %5 = fir.call @llvm.lround.i64.f64(%4) : (f64) -> i64 + %6 = arith.addi %3, %5 : i64 + %7 = fir.convert %6 : (i64) -> f64 + fir.store %7 to %0 : !fir.ref + %8 = fir.load %0 : !fir.ref + return %8 : f64 +} +func.func private @llvm.lround.i32.f32(f32) -> i32 +func.func private @llvm.lround.i64.f32(f32) -> i64 +func.func private @llvm.lround.i32.f64(f64) -> i32 +func.func private @llvm.lround.i64.f64(f64) -> i64 + +//--- exponentiation_fast.fir +// RUN: fir-opt %t/exponentiation_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exponentiation_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: [[STOI:%[A-Za-z0-9._]+]] = llvm.sext {{%[A-Za-z0-9._]+}} : i16 to i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) : (f32, i32) -> f32 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.pow"({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, i32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: [[STOI:%[A-Za-z0-9._]+]] = llvm.sext {{%[A-Za-z0-9._]+}} : i16 to i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) : (f64, i32) -> f64 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.pow"({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, i32) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg3 : !fir.ref + %3 = fir.convert %2 : (i16) -> i32 + %4 = fir.call @llvm.powi.f32.i32(%1, %3) : (f32, i32) -> f32 + %5 = fir.load %arg0 : !fir.ref + %6 = fir.load %arg1 : !fir.ref + %7 = math.powf %5, %6 : f32 + %8 = arith.addf %4, %7 : f32 + %9 = fir.load %arg0 : !fir.ref + %10 = fir.load %arg4 : !fir.ref + %11 = fir.call @llvm.powi.f32.i32(%9, %10) : (f32, i32) -> f32 + %12 = arith.addf %8, %11 : f32 + fir.store %12 to %0 : !fir.ref + %13 = fir.load %0 : !fir.ref + return %13 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg3 : !fir.ref + %3 = fir.convert %2 : (i16) -> i32 + %4 = fir.call @llvm.powi.f64.i32(%1, %3) : (f64, i32) -> f64 + %5 = fir.load %arg0 : !fir.ref + %6 = fir.load %arg1 : !fir.ref + %7 = math.powf %5, %6 : f64 + %8 = arith.addf %4, %7 : f64 + %9 = fir.load %arg0 : !fir.ref + %10 = fir.load %arg4 : !fir.ref + %11 = fir.call @llvm.powi.f64.i32(%9, %10) : (f64, i32) -> f64 + %12 = arith.addf %8, %11 : f64 + fir.store %12 to %0 : !fir.ref + %13 = fir.load %0 : !fir.ref + return %13 : f64 +} +func.func private @llvm.powi.f32.i32(f32, i32) -> f32 +func.func private @llvm.powi.f64.i32(f64, i32) -> f64 + +//--- exponentiation_relaxed.fir +// RUN: fir-opt %t/exponentiation_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exponentiation_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: [[STOI:%[A-Za-z0-9._]+]] = llvm.sext {{%[A-Za-z0-9._]+}} : i16 to i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) : (f32, i32) -> f32 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.pow"({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, i32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: [[STOI:%[A-Za-z0-9._]+]] = llvm.sext {{%[A-Za-z0-9._]+}} : i16 to i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) : (f64, i32) -> f64 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.pow"({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, i32) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg3 : !fir.ref + %3 = fir.convert %2 : (i16) -> i32 + %4 = fir.call @llvm.powi.f32.i32(%1, %3) : (f32, i32) -> f32 + %5 = fir.load %arg0 : !fir.ref + %6 = fir.load %arg1 : !fir.ref + %7 = math.powf %5, %6 : f32 + %8 = arith.addf %4, %7 : f32 + %9 = fir.load %arg0 : !fir.ref + %10 = fir.load %arg4 : !fir.ref + %11 = fir.call @llvm.powi.f32.i32(%9, %10) : (f32, i32) -> f32 + %12 = arith.addf %8, %11 : f32 + fir.store %12 to %0 : !fir.ref + %13 = fir.load %0 : !fir.ref + return %13 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg3 : !fir.ref + %3 = fir.convert %2 : (i16) -> i32 + %4 = fir.call @llvm.powi.f64.i32(%1, %3) : (f64, i32) -> f64 + %5 = fir.load %arg0 : !fir.ref + %6 = fir.load %arg1 : !fir.ref + %7 = math.powf %5, %6 : f64 + %8 = arith.addf %4, %7 : f64 + %9 = fir.load %arg0 : !fir.ref + %10 = fir.load %arg4 : !fir.ref + %11 = fir.call @llvm.powi.f64.i32(%9, %10) : (f64, i32) -> f64 + %12 = arith.addf %8, %11 : f64 + fir.store %12 to %0 : !fir.ref + %13 = fir.load %0 : !fir.ref + return %13 : f64 +} +func.func private @llvm.powi.f32.i32(f32, i32) -> f32 +func.func private @llvm.powi.f64.i32(f64, i32) -> f64 + +//--- exponentiation_precise.fir +// RUN: fir-opt %t/exponentiation_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exponentiation_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: [[STOI:%[A-Za-z0-9._]+]] = llvm.sext {{%[A-Za-z0-9._]+}} : i16 to i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) : (f32, i32) -> f32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @powf({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, i32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: [[STOI:%[A-Za-z0-9._]+]] = llvm.sext {{%[A-Za-z0-9._]+}} : i16 to i32 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) : (f64, i32) -> f64 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @pow({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, i32) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg3 : !fir.ref + %3 = fir.convert %2 : (i16) -> i32 + %4 = fir.call @llvm.powi.f32.i32(%1, %3) : (f32, i32) -> f32 + %5 = fir.load %arg0 : !fir.ref + %6 = fir.load %arg1 : !fir.ref + %7 = fir.call @powf(%5, %6) : (f32, f32) -> f32 + %8 = arith.addf %4, %7 : f32 + %9 = fir.load %arg0 : !fir.ref + %10 = fir.load %arg4 : !fir.ref + %11 = fir.call @llvm.powi.f32.i32(%9, %10) : (f32, i32) -> f32 + %12 = arith.addf %8, %11 : f32 + fir.store %12 to %0 : !fir.ref + %13 = fir.load %0 : !fir.ref + return %13 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg3 : !fir.ref + %3 = fir.convert %2 : (i16) -> i32 + %4 = fir.call @llvm.powi.f64.i32(%1, %3) : (f64, i32) -> f64 + %5 = fir.load %arg0 : !fir.ref + %6 = fir.load %arg1 : !fir.ref + %7 = fir.call @pow(%5, %6) : (f64, f64) -> f64 + %8 = arith.addf %4, %7 : f64 + %9 = fir.load %arg0 : !fir.ref + %10 = fir.load %arg4 : !fir.ref + %11 = fir.call @llvm.powi.f64.i32(%9, %10) : (f64, i32) -> f64 + %12 = arith.addf %8, %11 : f64 + fir.store %12 to %0 : !fir.ref + %13 = fir.load %0 : !fir.ref + return %13 : f64 +} +func.func private @llvm.powi.f32.i32(f32, i32) -> f32 +func.func private @powf(f32, f32) -> f32 +func.func private @llvm.powi.f64.i32(f64, i32) -> f64 +func.func private @pow(f64, f64) -> f64 + +//--- sign_fast.fir +// RUN: fir-opt %t/sign_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/sign_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.copysign"({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.copysign"({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = math.copysign %1, %2 : f32 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = math.copysign %1, %2 : f64 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f64 +} + +//--- sign_relaxed.fir +// RUN: fir-opt %t/sign_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/sign_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.copysign"({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.copysign"({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = math.copysign %1, %2 : f32 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = math.copysign %1, %2 : f64 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f64 +} + +//--- sign_precise.fir +// RUN: fir-opt %t/sign_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/sign_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @copysignf({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @copysign({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = fir.call @copysignf(%1, %2) : (f32, f32) -> f32 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.load %arg1 : !fir.ref + %3 = fir.call @copysign(%1, %2) : (f64, f64) -> f64 + fir.store %3 to %0 : !fir.ref + %4 = fir.load %0 : !fir.ref + return %4 : f64 +} +func.func private @copysignf(f32, f32) -> f32 +func.func private @copysign(f64, f64) -> f64 + +//--- sin_fast.fir +// RUN: fir-opt %t/sin_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/sin_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.sin"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.sin"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.sin %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.sin %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- sin_relaxed.fir +// RUN: fir-opt %t/sin_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/sin_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.sin"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = "llvm.intr.sin"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.sin %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.sin %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- sin_precise.fir +// RUN: fir-opt %t/sin_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/sin_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @sinf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @sin({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @sinf(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @sin(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @sinf(f32) -> f32 +func.func private @sin(f64) -> f64 + +//--- tanh_fast.fir +// RUN: fir-opt %t/tanh_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/tanh_fast.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @tanhf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @tanh({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.tanh %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.tanh %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- tanh_relaxed.fir +// RUN: fir-opt %t/tanh_relaxed.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/tanh_relaxed.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @tanhf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @tanh({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.tanh %1 : f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = math.tanh %1 : f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} + +//--- tanh_precise.fir +// RUN: fir-opt %t/tanh_precise.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/tanh_precise.fir +// CHECK: @_QPtest_real4 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @tanhf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +// CHECK: @_QPtest_real8 +// CHECK: {{%[A-Za-z0-9._]+}} = llvm.call @tanh({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +func.func @_QPtest_real4(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f32 { + %0 = fir.alloca f32 {bindc_name = "test_real4", uniq_name = "_QFtest_real4Etest_real4"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @tanhf(%1) : (f32) -> f32 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f32 +} +func.func @_QPtest_real8(%arg0: !fir.ref {fir.bindc_name = "x"}, %arg1: !fir.ref {fir.bindc_name = "y"}, %arg2: !fir.ref> {fir.bindc_name = "c"}, %arg3: !fir.ref {fir.bindc_name = "s"}, %arg4: !fir.ref {fir.bindc_name = "i"}) -> f64 { + %0 = fir.alloca f64 {bindc_name = "test_real8", uniq_name = "_QFtest_real8Etest_real8"} + %1 = fir.load %arg0 : !fir.ref + %2 = fir.call @tanh(%1) : (f64) -> f64 + fir.store %2 to %0 : !fir.ref + %3 = fir.load %0 : !fir.ref + return %3 : f64 +} +func.func private @tanhf(f32) -> f32 +func.func private @tanh(f64) -> f64 Index: flang/test/Lower/Intrinsics/exp.f90 =================================================================== --- flang/test/Lower/Intrinsics/exp.f90 +++ flang/test/Lower/Intrinsics/exp.f90 @@ -1,5 +1,5 @@ -! RUN: bbc -emit-fir %s -o - | FileCheck %s -! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s +! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s ! CHECK-LABEL: exp_testr ! CHECK-SAME: (%[[AREF:.*]]: !fir.ref {{.*}}, %[[BREF:.*]]: !fir.ref {{.*}}) Index: flang/test/Lower/Intrinsics/log.f90 =================================================================== --- flang/test/Lower/Intrinsics/log.f90 +++ flang/test/Lower/Intrinsics/log.f90 @@ -1,5 +1,5 @@ -! RUN: bbc -emit-fir %s -o - | FileCheck %s -! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s +! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s ! CHECK-LABEL: log_testr ! CHECK-SAME: (%[[AREF:.*]]: !fir.ref {{.*}}, %[[BREF:.*]]: !fir.ref {{.*}}) Index: flang/test/Lower/Intrinsics/math-runtime-options.f90 =================================================================== --- flang/test/Lower/Intrinsics/math-runtime-options.f90 +++ flang/test/Lower/Intrinsics/math-runtime-options.f90 @@ -1,7 +1,11 @@ -! RUN: bbc -emit-fir --math-runtime=fast %s -o - | FileCheck %s --check-prefixes="FIR,FAST" -! RUN: bbc -emit-fir --math-runtime=relaxed %s -o - | FileCheck %s --check-prefixes="FIR,RELAXED" -! RUN: bbc -emit-fir --math-runtime=precise %s -o - | FileCheck %s --check-prefixes="FIR,PRECISE" -! RUN: bbc -emit-fir --math-runtime=llvm %s -o - | FileCheck %s --check-prefixes="FIR,LLVM" +! RUN: bbc -emit-fir --math-runtime=fast -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="FIR,FAST" +! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=fast -mllvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="FIR,FAST" +! RUN: bbc -emit-fir --math-runtime=relaxed -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="FIR,RELAXED" +! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=relaxed -mllvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="FIR,RELAXED" +! RUN: bbc -emit-fir --math-runtime=precise -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="FIR,PRECISE" +! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=precise -mllvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="FIR,PRECISE" +! RUN: bbc -emit-fir --math-runtime=llvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="FIR,LLVM" +! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=llvm -mllvm -outline-intrinsics %s -o - | FileCheck %s --check-prefixes="FIR,LLVM" ! CHECK-LABEL: cos_testr subroutine cos_testr(a, b) Index: flang/test/Lower/array-expression-slice-1.f90 =================================================================== --- flang/test/Lower/array-expression-slice-1.f90 +++ flang/test/Lower/array-expression-slice-1.f90 @@ -1,4 +1,4 @@ -! RUN: bbc -o - %s | FileCheck %s +! RUN: bbc -o - --outline-intrinsics %s | FileCheck %s ! CHECK-LABEL: func @_QQmain() { ! CHECK-DAG: %[[VAL_0:.*]] = arith.constant 10 : index Index: flang/test/Lower/late-math-lowering.f90 =================================================================== --- /dev/null +++ flang/test/Lower/late-math-lowering.f90 @@ -0,0 +1,581 @@ +! RUN: split-file %s %t + +//--- abs.f90 +! RUN: bbc -emit-fir %t/abs.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/abs.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/abs.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/abs.f90 +! RUN: bbc -emit-fir %t/abs.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/abs.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/abs.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/abs.f90 +! RUN: bbc -emit-fir %t/abs.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/abs.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/abs.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/abs.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = abs(x) + abs(c) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.abs {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.abs {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @fabsf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @hypotf({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = abs(x) + abs(c) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.abs {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.abs {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @fabs({{%[A-Za-z0-9._]+}}) : (f64) -> f64 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @hypot({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +//--- aint.f90 +! RUN: bbc -emit-fir %t/aint.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL %t/aint.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/aint.f90 -o - | FileCheck --check-prefixes=ALL %t/aint.f90 +! RUN: bbc -emit-fir %t/aint.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL %t/aint.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/aint.f90 -o - | FileCheck --check-prefixes=ALL %t/aint.f90 +! RUN: bbc -emit-fir %t/aint.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL %t/aint.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/aint.f90 -o - | FileCheck --check-prefixes=ALL %t/aint.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = aint(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.trunc.f32({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = aint(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.trunc.f64({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- anint.f90 +! RUN: bbc -emit-fir %t/anint.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/anint.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/anint.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/anint.f90 +! RUN: bbc -emit-fir %t/anint.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/anint.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/anint.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/anint.f90 +! RUN: bbc -emit-fir %t/anint.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/anint.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/anint.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/anint.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = anint(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f32) -> f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @llvm.round.f32({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = anint(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = "llvm.intr.round"({{%[A-Za-z0-9._]+}}) : (f64) -> f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @llvm.round.f64({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- atan.f90 +! RUN: bbc -emit-fir %t/atan.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/atan.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/atan.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/atan.f90 +! RUN: bbc -emit-fir %t/atan.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/atan.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/atan.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/atan.f90 +! RUN: bbc -emit-fir %t/atan.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/atan.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/atan.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/atan.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = atan(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.atan {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.atan {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @atanf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = atan(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.atan {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.atan {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @atan({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- atan2.f90 +! RUN: bbc -emit-fir %t/atan2.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/atan2.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/atan2.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/atan2.f90 +! RUN: bbc -emit-fir %t/atan2.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/atan2.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/atan2.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/atan2.f90 +! RUN: bbc -emit-fir %t/atan2.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/atan2.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/atan2.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/atan2.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = atan2(x, y) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.atan2 {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.atan2 {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @atan2f({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = atan2(x, y) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.atan2 {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.atan2 {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @atan2({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +//--- ceiling.f90 +! RUN: bbc -emit-fir %t/ceiling.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/ceiling.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/ceiling.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/ceiling.f90 +! RUN: bbc -emit-fir %t/ceiling.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/ceiling.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/ceiling.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/ceiling.f90 +! RUN: bbc -emit-fir %t/ceiling.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/ceiling.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/ceiling.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/ceiling.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = ceiling(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.ceil {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.ceil {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @ceilf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = ceiling(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.ceil {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.ceil {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @ceil({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- cos.f90 +! RUN: bbc -emit-fir %t/cos.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/cos.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/cos.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/cos.f90 +! RUN: bbc -emit-fir %t/cos.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/cos.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/cos.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/cos.f90 +! RUN: bbc -emit-fir %t/cos.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/cos.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/cos.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/cos.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = cos(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.cos {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.cos {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @cosf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = cos(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.cos {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.cos {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @cos({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- erf.f90 +! RUN: bbc -emit-fir %t/erf.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/erf.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/erf.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/erf.f90 +! RUN: bbc -emit-fir %t/erf.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/erf.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/erf.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/erf.f90 +! RUN: bbc -emit-fir %t/erf.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/erf.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/erf.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/erf.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = erf(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.erf {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.erf {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @erff({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = erf(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.erf {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.erf {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @erf({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- exp.f90 +! RUN: bbc -emit-fir %t/exp.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/exp.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/exp.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/exp.f90 +! RUN: bbc -emit-fir %t/exp.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/exp.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/exp.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/exp.f90 +! RUN: bbc -emit-fir %t/exp.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/exp.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/exp.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/exp.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = exp(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.exp {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.exp {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @expf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = exp(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.exp {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.exp {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @exp({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- floor.f90 +! RUN: bbc -emit-fir %t/floor.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/floor.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/floor.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/floor.f90 +! RUN: bbc -emit-fir %t/floor.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/floor.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/floor.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/floor.f90 +! RUN: bbc -emit-fir %t/floor.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/floor.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/floor.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/floor.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = floor(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.floor {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.floor {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @floorf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = floor(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.floor {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.floor {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @floor({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- log.f90 +! RUN: bbc -emit-fir %t/log.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/log.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/log.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/log.f90 +! RUN: bbc -emit-fir %t/log.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/log.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/log.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/log.f90 +! RUN: bbc -emit-fir %t/log.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/log.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/log.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/log.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = log(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.log {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.log {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @logf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = log(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.log {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.log {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @log({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- log10.f90 +! RUN: bbc -emit-fir %t/log10.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/log10.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/log10.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/log10.f90 +! RUN: bbc -emit-fir %t/log10.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/log10.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/log10.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/log10.f90 +! RUN: bbc -emit-fir %t/log10.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/log10.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/log10.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/log10.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = log10(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.log10 {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.log10 {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @log10f({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = log10(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.log10 {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.log10 {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @log10({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- nint.f90 +! RUN: bbc -emit-fir %t/nint.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL %t/nint.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/nint.f90 -o - | FileCheck --check-prefixes=ALL %t/nint.f90 +! RUN: bbc -emit-fir %t/nint.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL %t/nint.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/nint.f90 -o - | FileCheck --check-prefixes=ALL %t/nint.f90 +! RUN: bbc -emit-fir %t/nint.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL %t/nint.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/nint.f90 -o - | FileCheck --check-prefixes=ALL %t/nint.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = nint(x, 4) + nint(x, 8) +end function + +! ALL-LABEL: @_QPtest_real4 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.lround.i32.f32({{%[A-Za-z0-9._]+}}) : (f32) -> i32 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.lround.i64.f32({{%[A-Za-z0-9._]+}}) : (f32) -> i64 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = nint(x, 4) + nint(x, 8) +end function + +! ALL-LABEL: @_QPtest_real8 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.lround.i32.f64({{%[A-Za-z0-9._]+}}) : (f64) -> i32 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.lround.i64.f64({{%[A-Za-z0-9._]+}}) : (f64) -> i64 + +//--- exponentiation.f90 +! RUN: bbc -emit-fir %t/exponentiation.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/exponentiation.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/exponentiation.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/exponentiation.f90 +! RUN: bbc -emit-fir %t/exponentiation.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/exponentiation.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/exponentiation.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/exponentiation.f90 +! RUN: bbc -emit-fir %t/exponentiation.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/exponentiation.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/exponentiation.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/exponentiation.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = x ** s + x ** y + x ** i +end function + +! ALL-LABEL: @_QPtest_real4 +! ALL: [[STOI:%[A-Za-z0-9._]+]] = fir.convert {{%[A-Za-z0-9._]+}} : (i16) -> i32 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) : (f32, i32) -> f32 +! FAST: {{%[A-Za-z0-9._]+}} = math.powf {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.powf {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @powf({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.powi.f32.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, i32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = x ** s + x ** y + x ** i +end function + +! ALL-LABEL: @_QPtest_real8 +! ALL: [[STOI:%[A-Za-z0-9._]+]] = fir.convert {{%[A-Za-z0-9._]+}} : (i16) -> i32 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, [[STOI]]) : (f64, i32) -> f64 +! FAST: {{%[A-Za-z0-9._]+}} = math.powf {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.powf {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @pow({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 +! ALL: {{%[A-Za-z0-9._]+}} = fir.call @llvm.powi.f64.i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, i32) -> f64 + +//--- sign.f90 +! RUN: bbc -emit-fir %t/sign.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/sign.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/sign.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/sign.f90 +! RUN: bbc -emit-fir %t/sign.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/sign.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/sign.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/sign.f90 +! RUN: bbc -emit-fir %t/sign.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/sign.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/sign.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/sign.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = sign(x, y) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.copysign {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.copysign {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @copysignf({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f32, f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = sign(x, y) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.copysign {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.copysign {{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @copysign({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (f64, f64) -> f64 + +//--- sin.f90 +! RUN: bbc -emit-fir %t/sin.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/sin.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/sin.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/sin.f90 +! RUN: bbc -emit-fir %t/sin.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/sin.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/sin.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/sin.f90 +! RUN: bbc -emit-fir %t/sin.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/sin.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/sin.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/sin.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = sin(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.sin {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.sin {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @sinf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = sin(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.sin {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.sin {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @sin({{%[A-Za-z0-9._]+}}) : (f64) -> f64 + +//--- tanh.f90 +! RUN: bbc -emit-fir %t/tanh.f90 -o - --lower-math-early=false --math-runtime=fast | FileCheck --check-prefixes=ALL,FAST %t/tanh.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=fast %t/tanh.f90 -o - | FileCheck --check-prefixes=ALL,FAST %t/tanh.f90 +! RUN: bbc -emit-fir %t/tanh.f90 -o - --lower-math-early=false --math-runtime=relaxed | FileCheck --check-prefixes=ALL,RELAXED %t/tanh.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=relaxed %t/tanh.f90 -o - | FileCheck --check-prefixes=ALL,RELAXED %t/tanh.f90 +! RUN: bbc -emit-fir %t/tanh.f90 -o - --lower-math-early=false --math-runtime=precise | FileCheck --check-prefixes=ALL,PRECISE %t/tanh.f90 +! RUN: %flang_fc1 -emit-fir -mllvm -lower-math-early=false -mllvm -math-runtime=precise %t/tanh.f90 -o - | FileCheck --check-prefixes=ALL,PRECISE %t/tanh.f90 + +function test_real4(x, y, c, s, i) + real :: x, y, test_real4 + complex(4) :: c + integer(2) :: s + integer(4) :: i + test_real4 = tanh(x) +end function + +! ALL-LABEL: @_QPtest_real4 +! FAST: {{%[A-Za-z0-9._]+}} = math.tanh {{%[A-Za-z0-9._]+}} : f32 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.tanh {{%[A-Za-z0-9._]+}} : f32 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @tanhf({{%[A-Za-z0-9._]+}}) : (f32) -> f32 + +function test_real8(x, y, c, s, i) + real(8) :: x, y, test_real8 + complex(8) :: c + integer(2) :: s + integer(4) :: i + test_real8 = tanh(x) +end function + +! ALL-LABEL: @_QPtest_real8 +! FAST: {{%[A-Za-z0-9._]+}} = math.tanh {{%[A-Za-z0-9._]+}} : f64 +! RELAXED: {{%[A-Za-z0-9._]+}} = math.tanh {{%[A-Za-z0-9._]+}} : f64 +! PRECISE: {{%[A-Za-z0-9._]+}} = fir.call @tanh({{%[A-Za-z0-9._]+}}) : (f64) -> f64 Index: flang/test/Lower/llvm-math.f90 =================================================================== --- flang/test/Lower/llvm-math.f90 +++ flang/test/Lower/llvm-math.f90 @@ -1,4 +1,5 @@ -! RUN: bbc -emit-fir %s -o - --math-runtime=llvm | FileCheck %s +! RUN: bbc -emit-fir %s -o - --math-runtime=llvm --outline-intrinsics | FileCheck %s +! RUN: %flang_fc1 -emit-fir -mllvm -math-runtime=llvm -mllvm -outline-intrinsics %s -o - | FileCheck %s SUBROUTINE POW_WRAPPER(IN, IN2, OUT) DOUBLE PRECISION IN, IN2 Index: flang/test/Lower/sqrt.f90 =================================================================== --- flang/test/Lower/sqrt.f90 +++ flang/test/Lower/sqrt.f90 @@ -1,5 +1,5 @@ -! RUN: bbc -emit-fir %s -o - | FileCheck %s -! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s +! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s ! CHECK-LABEL: sqrt_testr subroutine sqrt_testr(a, b) Index: flang/test/Lower/trigonometric-intrinsics.f90 =================================================================== --- flang/test/Lower/trigonometric-intrinsics.f90 +++ flang/test/Lower/trigonometric-intrinsics.f90 @@ -1,5 +1,5 @@ -! RUN: bbc -emit-fir %s -o - | FileCheck %s -! RUN: %flang_fc1 -emit-fir %s -o - | FileCheck %s +! RUN: bbc -emit-fir -outline-intrinsics %s -o - | FileCheck %s +! RUN: %flang_fc1 -emit-fir -mllvm -outline-intrinsics %s -o - | FileCheck %s ! CHECK-LABEL: atan_testr subroutine atan_testr(a, b)