diff --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp --- a/flang/lib/Lower/ConvertExprToHLFIR.cpp +++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp @@ -17,6 +17,7 @@ #include "flang/Lower/ConvertCall.h" #include "flang/Lower/ConvertConstant.h" #include "flang/Lower/ConvertType.h" +#include "flang/Lower/IntrinsicCall.h" #include "flang/Lower/StatementContext.h" #include "flang/Lower/SymbolMap.h" #include "flang/Optimizer/Builder/Todo.h" @@ -284,6 +285,31 @@ GENBIN(Divide, Real, mlir::arith::DivFOp) GENBIN(Divide, Complex, fir::DivcOp) +template +struct BinaryOp>> { + static hlfir::EntityWithAttributes gen(mlir::Location loc, + fir::FirOpBuilder &builder, + hlfir::Entity lhs, hlfir::Entity rhs) { + mlir::Type ty = Fortran::lower::getFIRType(builder.getContext(), TC, KIND, + /*params=*/llvm::None); + return hlfir::EntityWithAttributes{ + Fortran::lower::genPow(builder, loc, ty, lhs, rhs)}; + } +}; + +template +struct BinaryOp< + Fortran::evaluate::RealToIntPower>> { + static hlfir::EntityWithAttributes gen(mlir::Location loc, + fir::FirOpBuilder &builder, + hlfir::Entity lhs, hlfir::Entity rhs) { + mlir::Type ty = Fortran::lower::getFIRType(builder.getContext(), TC, KIND, + /*params=*/llvm::None); + return hlfir::EntityWithAttributes{ + Fortran::lower::genPow(builder, loc, ty, lhs, rhs)}; + } +}; + /// Lower Expr to HLFIR. class HlfirBuilder { public: diff --git a/flang/test/Lower/HLFIR/binary-ops.f90 b/flang/test/Lower/HLFIR/binary-ops.f90 --- a/flang/test/Lower/HLFIR/binary-ops.f90 +++ b/flang/test/Lower/HLFIR/binary-ops.f90 @@ -132,3 +132,64 @@ ! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref> ! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref> ! CHECK: %[[VAL_8:.*]] = fir.divc %[[VAL_6]], %[[VAL_7]] : !fir.complex<4> + + +subroutine int_power(x, y, z) + integer :: x, y, z + x = y**z +end subroutine +! CHECK-LABEL: func.func @_QPint_power( +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! CHECK: %[[VAL_8:.*]] = math.ipowi %[[VAL_6]], %[[VAL_7]] : i32 + +subroutine real_power(x, y, z) + real :: x, y, z + x = y**z +end subroutine +! CHECK-LABEL: func.func @_QPreal_power( +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! CHECK: %[[VAL_8:.*]] = math.powf %[[VAL_6]], %[[VAL_7]] fastmath : f32 + +subroutine complex_power(x, y, z) + complex :: x, y, z + x = y**z +end subroutine +! CHECK-LABEL: func.func @_QPcomplex_power( +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref> +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref> +! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_6]] : (!fir.complex<4>) -> complex +! CHECK: %[[VAL_9:.*]] = fir.convert %[[VAL_7]] : (!fir.complex<4>) -> complex +! CHECK: %[[VAL_10:.*]] = complex.pow %[[VAL_8]], %[[VAL_9]] : complex +! CHECK: %[[VAL_11:.*]] = fir.convert %[[VAL_10]] : (complex) -> !fir.complex<4> + +subroutine real_to_int_power(x, y, z) + real :: x, y + integer :: z + x = y**z +end subroutine +! CHECK-LABEL: func.func @_QPreal_to_int_power( +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! CHECK: %[[VAL_8:.*]] = fir.call @llvm.powi.f32.i32(%[[VAL_6]], %[[VAL_7]]) fastmath : (f32, i32) -> f32 + +subroutine complex_to_int_power(x, y, z) + complex :: x, y + integer :: z + x = y**z +end subroutine +! CHECK-LABEL: func.func @_QPcomplex_to_int_power( +! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref>) -> (!fir.ref>, !fir.ref>) +! CHECK: %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref) -> (!fir.ref, !fir.ref) +! CHECK: %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref> +! CHECK: %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref +! CHECK: %[[VAL_8:.*]] = fir.call @_FortranAcpowi(%[[VAL_6]], %[[VAL_7]]) fastmath : (!fir.complex<4>, i32) -> !fir.complex<4>