Skip to content

Commit bac3aed

Browse files
committed
[flang] Lower integer exponentiation into math::IPowI.
Differential Revision: https://reviews.llvm.org/D132770
1 parent 0044cb4 commit bac3aed

File tree

5 files changed

+60
-3
lines changed

5 files changed

+60
-3
lines changed

flang/lib/Lower/IntrinsicCall.cpp

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,12 @@ static mlir::FunctionType genF32IntF32FuncType(mlir::MLIRContext *context) {
11531153
return mlir::FunctionType::get(context, {itype, ftype}, {ftype});
11541154
}
11551155

1156+
template <int Bits>
1157+
static mlir::FunctionType genIntIntIntFuncType(mlir::MLIRContext *context) {
1158+
auto itype = mlir::IntegerType::get(context, Bits);
1159+
return mlir::FunctionType::get(context, {itype, itype}, {itype});
1160+
}
1161+
11561162
/// Callback type for generating lowering for a math operation.
11571163
using MathGeneratorTy = mlir::Value (*)(fir::FirOpBuilder &, mlir::Location,
11581164
llvm::StringRef, mlir::FunctionType,
@@ -1220,7 +1226,12 @@ static mlir::Value genMathOp(fir::FirOpBuilder &builder, mlir::Location loc,
12201226
// can be also lowered to libm calls for "fast" and "relaxed"
12211227
// modes.
12221228
mlir::Value result;
1223-
if (mathRuntimeVersion == preciseVersion) {
1229+
if (mathRuntimeVersion == preciseVersion &&
1230+
// Some operations do not have to be lowered as conservative
1231+
// calls, since they do not affect strict FP behavior.
1232+
// For example, purely integer operations like exponentiation
1233+
// with integer operands fall into this class.
1234+
!mathLibFuncName.empty()) {
12241235
result = genLibCall(builder, loc, mathLibFuncName, mathLibFuncType, args);
12251236
} else {
12261237
LLVM_DEBUG(llvm::dbgs() << "Generating '" << mathLibFuncName
@@ -1310,6 +1321,10 @@ static constexpr MathOperation mathOperations[] = {
13101321
{"nint", "llvm.lround.i64.f32", genIntF32FuncType<64>, genLibCall},
13111322
{"nint", "llvm.lround.i32.f64", genIntF64FuncType<32>, genLibCall},
13121323
{"nint", "llvm.lround.i32.f32", genIntF32FuncType<32>, genLibCall},
1324+
{"pow", {}, genIntIntIntFuncType<8>, genMathOp<mlir::math::IPowIOp>},
1325+
{"pow", {}, genIntIntIntFuncType<16>, genMathOp<mlir::math::IPowIOp>},
1326+
{"pow", {}, genIntIntIntFuncType<32>, genMathOp<mlir::math::IPowIOp>},
1327+
{"pow", {}, genIntIntIntFuncType<64>, genMathOp<mlir::math::IPowIOp>},
13131328
{"pow", "powf", genF32F32F32FuncType, genMathOp<mlir::math::PowFOp>},
13141329
{"pow", "pow", genF64F64F64FuncType, genMathOp<mlir::math::PowFOp>},
13151330
// TODO: add PowIOp in math and complex dialects.

flang/lib/Optimizer/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ add_flang_library(FIRCodeGen
1717
FIRBuilder
1818
FIRDialect
1919
FIRSupport
20+
MLIRMathToFuncs
2021
MLIRMathToLLVM
2122
MLIRMathToLibm
2223
MLIROpenMPToLLVM

flang/lib/Optimizer/CodeGen/CodeGen.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,14 @@
2323
#include "mlir/Conversion/ControlFlowToLLVM/ControlFlowToLLVM.h"
2424
#include "mlir/Conversion/FuncToLLVM/ConvertFuncToLLVM.h"
2525
#include "mlir/Conversion/LLVMCommon/Pattern.h"
26+
#include "mlir/Conversion/MathToFuncs/MathToFuncs.h"
2627
#include "mlir/Conversion/MathToLLVM/MathToLLVM.h"
2728
#include "mlir/Conversion/MathToLibm/MathToLibm.h"
2829
#include "mlir/Conversion/OpenMPToLLVM/ConvertOpenMPToLLVM.h"
2930
#include "mlir/IR/BuiltinTypes.h"
3031
#include "mlir/IR/Matchers.h"
3132
#include "mlir/Pass/Pass.h"
33+
#include "mlir/Pass/PassManager.h"
3234
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
3335
#include "llvm/ADT/ArrayRef.h"
3436

@@ -3291,6 +3293,18 @@ class FIRToLLVMLowering : public fir::FIRToLLVMLoweringBase<FIRToLLVMLowering> {
32913293
if (!forcedTargetTriple.empty())
32923294
fir::setTargetTriple(mod, forcedTargetTriple);
32933295

3296+
// Run dynamic pass pipeline for converting Math dialect
3297+
// operations into other dialects (llvm, func, etc.).
3298+
// Some conversions of Math operations cannot be done
3299+
// by just using conversion patterns. This is true for
3300+
// conversions that affect the ModuleOp, e.g. create new
3301+
// function operations in it. We have to run such conversions
3302+
// as passes here.
3303+
mlir::OpPassManager mathConvertionPM("builtin.module");
3304+
mathConvertionPM.addPass(mlir::createConvertMathToFuncsPass());
3305+
if (mlir::failed(runPipeline(mathConvertionPM, mod)))
3306+
return signalPassFailure();
3307+
32943308
auto *context = getModule().getContext();
32953309
fir::LLVMTypeConverter typeConverter{getModule()};
32963310
mlir::RewritePatternSet pattern(context);

flang/test/Intrinsics/math-codegen.fir

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1466,6 +1466,19 @@ func.func private @powf(f32, f32) -> f32
14661466
func.func private @llvm.powi.f64.i32(f64, i32) -> f64
14671467
func.func private @pow(f64, f64) -> f64
14681468

1469+
//--- exponentiation_integer.fir
1470+
// RUN: fir-opt %t/exponentiation_integer.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/exponentiation_integer.fir
1471+
// CHECK: @_QPtest_int4
1472+
// CHECK: llvm.call @__mlir_math_ipowi_i32({{%[A-Za-z0-9._]+}}, {{%[A-Za-z0-9._]+}}) : (i32, i32) -> i32
1473+
1474+
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"}) {
1475+
%0 = fir.load %arg0 : !fir.ref<i32>
1476+
%1 = fir.load %arg1 : !fir.ref<i32>
1477+
%2 = math.ipowi %0, %1 : i32
1478+
fir.store %2 to %arg2 : !fir.ref<i32>
1479+
return
1480+
}
1481+
14691482
//--- sign_fast.fir
14701483
// RUN: fir-opt %t/sign_fast.fir --fir-to-llvm-ir="target=x86_64-unknown-linux-gnu" | FileCheck %t/sign_fast.fir
14711484
// CHECK: @_QPtest_real4

flang/test/Lower/power-operator.f90

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,18 +57,32 @@ subroutine pow_r4_r8(x, y, z)
5757
! CHECK: math.powf %{{.*}}, %{{.*}} : f64
5858
end subroutine
5959

60+
! CHECK-LABEL: pow_i1_i1
61+
subroutine pow_i1_i1(x, y, z)
62+
integer(1) :: x, y, z
63+
z = x ** y
64+
! CHECK: math.ipowi %{{.*}}, %{{.*}} : i8
65+
end subroutine
66+
67+
! CHECK-LABEL: pow_i2_i2
68+
subroutine pow_i2_i2(x, y, z)
69+
integer(2) :: x, y, z
70+
z = x ** y
71+
! CHECK: math.ipowi %{{.*}}, %{{.*}} : i16
72+
end subroutine
73+
6074
! CHECK-LABEL: pow_i4_i4
6175
subroutine pow_i4_i4(x, y, z)
6276
integer(4) :: x, y, z
6377
z = x ** y
64-
! CHECK: call @__mth_i_ipowi
78+
! CHECK: math.ipowi %{{.*}}, %{{.*}} : i32
6579
end subroutine
6680

6781
! CHECK-LABEL: pow_i8_i8
6882
subroutine pow_i8_i8(x, y, z)
6983
integer(8) :: x, y, z
7084
z = x ** y
71-
! CHECK: call @__mth_i_kpowk
85+
! CHECK: math.ipowi %{{.*}}, %{{.*}} : i64
7286
end subroutine
7387

7488
! CHECK-LABEL: pow_c4_i4

0 commit comments

Comments
 (0)