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 @@ -252,7 +252,7 @@ template struct BinaryOp { static hlfir::EntityWithAttributes gen(mlir::Location loc, - fir::FirOpBuilder &builder, + fir::FirOpBuilder &builder, const T &, hlfir::Entity lhs, hlfir::Entity rhs) { TODO(loc, "binary op implementation in HLFIR"); } @@ -263,9 +263,11 @@ template \ struct BinaryOp>> { \ + using Op = Fortran::evaluate::GenBinEvOp>; \ static hlfir::EntityWithAttributes gen(mlir::Location loc, \ fir::FirOpBuilder &builder, \ - hlfir::Entity lhs, \ + const Op &, hlfir::Entity lhs, \ hlfir::Entity rhs) { \ return hlfir::EntityWithAttributes{ \ builder.create(loc, lhs, rhs)}; \ @@ -287,9 +289,11 @@ template struct BinaryOp>> { + using Op = Fortran::evaluate::Power>; static hlfir::EntityWithAttributes gen(mlir::Location loc, fir::FirOpBuilder &builder, - hlfir::Entity lhs, hlfir::Entity rhs) { + const Op &op, hlfir::Entity lhs, + hlfir::Entity rhs) { mlir::Type ty = Fortran::lower::getFIRType(builder.getContext(), TC, KIND, /*params=*/llvm::None); return hlfir::EntityWithAttributes{ @@ -300,9 +304,12 @@ template struct BinaryOp< Fortran::evaluate::RealToIntPower>> { + using Op = + Fortran::evaluate::RealToIntPower>; static hlfir::EntityWithAttributes gen(mlir::Location loc, fir::FirOpBuilder &builder, - hlfir::Entity lhs, hlfir::Entity rhs) { + const Op &op, hlfir::Entity lhs, + hlfir::Entity rhs) { mlir::Type ty = Fortran::lower::getFIRType(builder.getContext(), TC, KIND, /*params=*/llvm::None); return hlfir::EntityWithAttributes{ @@ -310,6 +317,30 @@ } }; +template +struct BinaryOp< + Fortran::evaluate::Extremum>> { + using Op = Fortran::evaluate::Extremum>; + static hlfir::EntityWithAttributes gen(mlir::Location loc, + fir::FirOpBuilder &builder, + const Op &op, hlfir::Entity lhs, + hlfir::Entity rhs) { + // evaluate::Extremum is only created by the front-end when building + // compiler generated expressions (like when folding LEN() or shape/bounds + // inquiries). MIN and MAX are represented as evaluate::ProcedureRef and are + // not going through here. So far the frontend does not generate character + // Extremum so there is no way to test it. + if constexpr (TC == Fortran::common::TypeCategory::Character) { + fir::emitFatalError(loc, "Fortran::evaluate::Extremum are unexpected"); + } + llvm::SmallVector args{lhs, rhs}; + fir::ExtendedValue res = op.ordering == Fortran::evaluate::Ordering::Greater + ? Fortran::lower::genMax(builder, loc, args) + : Fortran::lower::genMin(builder, loc, args); + return hlfir::EntityWithAttributes{fir::getBase(res)}; + } +}; + /// Lower Expr to HLFIR. class HlfirBuilder { public: @@ -411,7 +442,7 @@ TODO(loc, "elemental operations in HLFIR"); auto left = hlfir::loadTrivialScalar(loc, builder, gen(op.left())); auto right = hlfir::loadTrivialScalar(loc, builder, gen(op.right())); - return BinaryOp::gen(loc, builder, left, right); + return BinaryOp::gen(loc, builder, op.derived(), left, right); } template 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 @@ -193,3 +193,17 @@ ! 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> + +subroutine extremum(c, n, l) + integer(8), intent(in) :: l + integer(8) :: n + character(l) :: c + ! evaluate::Extremum is created by semantics while analyzing LEN(). + n = len(c, 8) +end subroutine +! CHECK-LABEL: func.func @_QPextremum( +! CHECK: hlfir.declare {{.*}}c +! CHECK: %[[VAL_11:.*]] = arith.constant 0 : i64 +! CHECK: %[[VAL_12:.*]] = fir.load %{{.*}} : !fir.ref +! CHECK: %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : i64 +! CHECK: arith.select %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : i64