return mlir::FunctionType::get(context, {itype, ftype}, {ftype});
}
+template <int Bits>
+static mlir::FunctionType genIntIntIntFuncType(mlir::MLIRContext *context) {
+ auto itype = mlir::IntegerType::get(context, Bits);
+ return mlir::FunctionType::get(context, {itype, itype}, {itype});
+}
+
/// Callback type for generating lowering for a math operation.
using MathGeneratorTy = mlir::Value (*)(fir::FirOpBuilder &, mlir::Location,
llvm::StringRef, mlir::FunctionType,
// can be also lowered to libm calls for "fast" and "relaxed"
// modes.
mlir::Value result;
- if (mathRuntimeVersion == preciseVersion) {
+ if (mathRuntimeVersion == preciseVersion &&
+ // Some operations do not have to be lowered as conservative
+ // calls, since they do not affect strict FP behavior.
+ // For example, purely integer operations like exponentiation
+ // with integer operands fall into this class.
+ !mathLibFuncName.empty()) {
result = genLibCall(builder, loc, mathLibFuncName, mathLibFuncType, args);
} else {
LLVM_DEBUG(llvm::dbgs() << "Generating '" << mathLibFuncName
{"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", {}, genIntIntIntFuncType<8>, genMathOp<mlir::math::IPowIOp>},
+ {"pow", {}, genIntIntIntFuncType<16>, genMathOp<mlir::math::IPowIOp>},
+ {"pow", {}, genIntIntIntFuncType<32>, genMathOp<mlir::math::IPowIOp>},
+ {"pow", {}, genIntIntIntFuncType<64>, genMathOp<mlir::math::IPowIOp>},
{"pow", "powf", genF32F32F32FuncType, genMathOp<mlir::math::PowFOp>},
{"pow", "pow", genF64F64F64FuncType, genMathOp<mlir::math::PowFOp>},
// TODO: add PowIOp in math and complex dialects.
FIRBuilder
FIRDialect
FIRSupport
+ MLIRMathToFuncs
MLIRMathToLLVM
MLIRMathToLibm
MLIROpenMPToLLVM
#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
#include "mlir/Conversion/LLVMCommon/Pattern.h"
+#include "mlir/Conversion/MathToFuncs/MathToFuncs.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"
#include "mlir/Pass/Pass.h"
+#include "mlir/Pass/PassManager.h"
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
#include "llvm/ADT/ArrayRef.h"
if (!forcedTargetTriple.empty())
fir::setTargetTriple(mod, forcedTargetTriple);
+ // Run dynamic pass pipeline for converting Math dialect
+ // operations into other dialects (llvm, func, etc.).
+ // Some conversions of Math operations cannot be done
+ // by just using conversion patterns. This is true for
+ // conversions that affect the ModuleOp, e.g. create new
+ // function operations in it. We have to run such conversions
+ // as passes here.
+ mlir::OpPassManager mathConvertionPM("builtin.module");
+ mathConvertionPM.addPass(mlir::createConvertMathToFuncsPass());
+ if (mlir::failed(runPipeline(mathConvertionPM, mod)))
+ return signalPassFailure();
+
auto *context = getModule().getContext();
fir::LLVMTypeConverter typeConverter{getModule()};
mlir::RewritePatternSet pattern(context);
func.func private @llvm.powi.f64.i32(f64, i32) -> f64
func.func private @pow(f64, f64) -> f64
+//--- exponentiation_integer.fir
+// RUN: fir-opt %t/exponentiation_integer.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exponentiation_integer.fir
+// CHECK: @_QPtest_int4
+// CHECK: llvm.call @__mlir_math_ipowi_i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (i32, i32) -> i32
+
+func.func @_QPtest_int4(%arg0: !fir.ref<i32> {fir.bindc_name = "x"}, %arg1: !fir.ref<i32> {fir.bindc_name = "y"}, %arg2: !fir.ref<i32> {fir.bindc_name = "z"}) {
+ %0 = fir.load %arg0 : !fir.ref<i32>
+ %1 = fir.load %arg1 : !fir.ref<i32>
+ %2 = math.ipowi %0, %1 : i32
+ fir.store %2 to %arg2 : !fir.ref<i32>
+ return
+}
+
//--- 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: math.powf %{{.*}}, %{{.*}} : f64
end subroutine
+! CHECK-LABEL: pow_i1_i1
+subroutine pow_i1_i1(x, y, z)
+ integer(1) :: x, y, z
+ z = x ** y
+ ! CHECK: math.ipowi %{{.*}}, %{{.*}} : i8
+end subroutine
+
+! CHECK-LABEL: pow_i2_i2
+subroutine pow_i2_i2(x, y, z)
+ integer(2) :: x, y, z
+ z = x ** y
+ ! CHECK: math.ipowi %{{.*}}, %{{.*}} : i16
+end subroutine
+
! CHECK-LABEL: pow_i4_i4
subroutine pow_i4_i4(x, y, z)
integer(4) :: x, y, z
z = x ** y
- ! CHECK: call @__mth_i_ipowi
+ ! CHECK: math.ipowi %{{.*}}, %{{.*}} : i32
end subroutine
! CHECK-LABEL: pow_i8_i8
subroutine pow_i8_i8(x, y, z)
integer(8) :: x, y, z
z = x ** y
- ! CHECK: call @__mth_i_kpowk
+ ! CHECK: math.ipowi %{{.*}}, %{{.*}} : i64
end subroutine
! CHECK-LABEL: pow_c4_i4