[flang-commits] [flang] 991a90a - [flang] Lower evaluate::Extremum

Jean Perier via flang-commits flang-commits at lists.llvm.org
Fri Dec 2 00:30:12 PST 2022


Author: Jean Perier
Date: 2022-12-02T09:29:39+01:00
New Revision: 991a90a00d571cfe3ed3da3f2ad766d4afce6c2b

URL: https://github.com/llvm/llvm-project/commit/991a90a00d571cfe3ed3da3f2ad766d4afce6c2b
DIFF: https://github.com/llvm/llvm-project/commit/991a90a00d571cfe3ed3da3f2ad766d4afce6c2b.diff

LOG: [flang] Lower evaluate::Extremum

Update BinaryOp<T>::gen so that const T& is threaded and some
operation knowledge that is not encoded by the type T or the arguments
can be used. For Extremum, it is the order (Greater or Lesser) that is
required, but this will also be required for evaluate::Relational.

Differential Revision: https://reviews.llvm.org/D139124

Added: 
    

Modified: 
    flang/lib/Lower/ConvertExprToHLFIR.cpp
    flang/test/Lower/HLFIR/binary-ops.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index a8860f639f609..284b1cc7ea674 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -252,7 +252,7 @@ class HlfirDesignatorBuilder {
 template <typename T>
 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 @@ struct BinaryOp {
   template <int KIND>                                                          \
   struct BinaryOp<Fortran::evaluate::GenBinEvOp<Fortran::evaluate::Type<       \
       Fortran::common::TypeCategory::GenBinTyCat, KIND>>> {                    \
+    using Op = Fortran::evaluate::GenBinEvOp<Fortran::evaluate::Type<          \
+        Fortran::common::TypeCategory::GenBinTyCat, KIND>>;                    \
     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<GenBinFirOp>(loc, lhs, rhs)};                         \
@@ -287,9 +289,11 @@ GENBIN(Divide, Complex, fir::DivcOp)
 
 template <Fortran::common::TypeCategory TC, int KIND>
 struct BinaryOp<Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>>> {
+  using Op = Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>>;
   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 @@ struct BinaryOp<Fortran::evaluate::Power<Fortran::evaluate::Type<TC, KIND>>> {
 template <Fortran::common::TypeCategory TC, int KIND>
 struct BinaryOp<
     Fortran::evaluate::RealToIntPower<Fortran::evaluate::Type<TC, KIND>>> {
+  using Op =
+      Fortran::evaluate::RealToIntPower<Fortran::evaluate::Type<TC, KIND>>;
   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 @@ struct BinaryOp<
   }
 };
 
+template <Fortran::common::TypeCategory TC, int KIND>
+struct BinaryOp<
+    Fortran::evaluate::Extremum<Fortran::evaluate::Type<TC, KIND>>> {
+  using Op = Fortran::evaluate::Extremum<Fortran::evaluate::Type<TC, KIND>>;
+  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<mlir::Value, 2> 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 @@ class HlfirBuilder {
       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<D>::gen(loc, builder, left, right);
+    return BinaryOp<D>::gen(loc, builder, op.derived(), left, right);
   }
 
   template <int KIND>

diff  --git a/flang/test/Lower/HLFIR/binary-ops.f90 b/flang/test/Lower/HLFIR/binary-ops.f90
index 0c3abbc554a01..678cd23bf5615 100644
--- a/flang/test/Lower/HLFIR/binary-ops.f90
+++ b/flang/test/Lower/HLFIR/binary-ops.f90
@@ -193,3 +193,17 @@ subroutine complex_to_int_power(x, y, z)
 ! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.complex<4>>
 ! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
 ! CHECK:  %[[VAL_8:.*]] = fir.call @_FortranAcpowi(%[[VAL_6]], %[[VAL_7]]) fastmath<contract> : (!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<i64>
+! CHECK:  %[[VAL_13:.*]] = arith.cmpi sgt, %[[VAL_11]], %[[VAL_12]] : i64
+! CHECK:  arith.select %[[VAL_13]], %[[VAL_11]], %[[VAL_12]] : i64


        


More information about the flang-commits mailing list