[flang-commits] [flang] 440e9ba - [flang] Lower add, mul, div, and sub to HLFIR

Jean Perier via flang-commits flang-commits at lists.llvm.org
Thu Dec 1 08:40:57 PST 2022


Author: Jean Perier
Date: 2022-12-01T17:39:53+01:00
New Revision: 440e9baa6238dc6a58b694dd99b4c649a1ae7bd9

URL: https://github.com/llvm/llvm-project/commit/440e9baa6238dc6a58b694dd99b4c649a1ae7bd9
DIFF: https://github.com/llvm/llvm-project/commit/440e9baa6238dc6a58b694dd99b4c649a1ae7bd9.diff

LOG: [flang] Lower add, mul, div, and sub to HLFIR

Only lower operations when the operands are scalar for now.

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

Added: 
    flang/test/Lower/HLFIR/binary-ops.f90

Modified: 
    flang/lib/Lower/ConvertExprToHLFIR.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 81b4d63889729..d4c6f5358aff5 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -244,6 +244,46 @@ class HlfirDesignatorBuilder {
   mlir::Location loc;
 };
 
+//===--------------------------------------------------------------------===//
+// Binary Operation implementation
+//===--------------------------------------------------------------------===//
+
+template <typename T>
+struct BinaryOp {
+  static hlfir::EntityWithAttributes gen(mlir::Location loc,
+                                         fir::FirOpBuilder &builder,
+                                         hlfir::Entity lhs, hlfir::Entity rhs) {
+    TODO(loc, "binary op implementation in HLFIR");
+  }
+};
+
+#undef GENBIN
+#define GENBIN(GenBinEvOp, GenBinTyCat, GenBinFirOp)                           \
+  template <int KIND>                                                          \
+  struct BinaryOp<Fortran::evaluate::GenBinEvOp<Fortran::evaluate::Type<       \
+      Fortran::common::TypeCategory::GenBinTyCat, KIND>>> {                    \
+    static hlfir::EntityWithAttributes gen(mlir::Location loc,                 \
+                                           fir::FirOpBuilder &builder,         \
+                                           hlfir::Entity lhs,                  \
+                                           hlfir::Entity rhs) {                \
+      return hlfir::EntityWithAttributes{                                      \
+          builder.create<GenBinFirOp>(loc, lhs, rhs)};                         \
+    }                                                                          \
+  };
+
+GENBIN(Add, Integer, mlir::arith::AddIOp)
+GENBIN(Add, Real, mlir::arith::AddFOp)
+GENBIN(Add, Complex, fir::AddcOp)
+GENBIN(Subtract, Integer, mlir::arith::SubIOp)
+GENBIN(Subtract, Real, mlir::arith::SubFOp)
+GENBIN(Subtract, Complex, fir::SubcOp)
+GENBIN(Multiply, Integer, mlir::arith::MulIOp)
+GENBIN(Multiply, Real, mlir::arith::MulFOp)
+GENBIN(Multiply, Complex, fir::MulcOp)
+GENBIN(Divide, Integer, mlir::arith::DivSIOp)
+GENBIN(Divide, Real, mlir::arith::DivFOp)
+GENBIN(Divide, Complex, fir::DivcOp)
+
 /// Lower Expr to HLFIR.
 class HlfirBuilder {
 public:
@@ -339,7 +379,13 @@ class HlfirBuilder {
   template <typename D, typename R, typename LO, typename RO>
   hlfir::EntityWithAttributes
   gen(const Fortran::evaluate::Operation<D, R, LO, RO> &op) {
-    TODO(getLoc(), "lowering binary op to HLFIR");
+    auto &builder = getBuilder();
+    mlir::Location loc = getLoc();
+    if (op.Rank() != 0)
+      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);
   }
 
   template <int KIND>

diff  --git a/flang/test/Lower/HLFIR/binary-ops.f90 b/flang/test/Lower/HLFIR/binary-ops.f90
new file mode 100644
index 0000000000000..79c9ef6a31440
--- /dev/null
+++ b/flang/test/Lower/HLFIR/binary-ops.f90
@@ -0,0 +1,134 @@
+! Test lowering of binary intrinsic operations to HLFIR
+! RUN: bbc -emit-fir -hlfir -o - %s 2>&1 | FileCheck %s
+
+subroutine int_add(x, y, z)
+ integer :: x, y, z
+ x = y + z
+end subroutine
+! CHECK-LABEL: func.func @_QPint_add(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_8:.*]] = arith.addi %[[VAL_6]], %[[VAL_7]] : i32
+
+subroutine real_add(x, y, z)
+ real :: x, y, z
+ x = y + z
+end subroutine
+! CHECK-LABEL: func.func @_QPreal_add(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<f32>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<f32>
+! CHECK:  %[[VAL_8:.*]] = arith.addf %[[VAL_6]], %[[VAL_7]] fastmath<contract> : f32
+
+subroutine complex_add(x, y, z)
+ complex :: x, y, z
+ x = y + z
+end subroutine
+! CHECK-LABEL: func.func @_QPcomplex_add(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_8:.*]] = fir.addc %[[VAL_6]], %[[VAL_7]] : !fir.complex<4>
+
+subroutine int_sub(x, y, z)
+ integer :: x, y, z
+ x = y - z
+end subroutine
+! CHECK-LABEL: func.func @_QPint_sub(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_8:.*]] = arith.subi %[[VAL_6]], %[[VAL_7]] : i32
+
+subroutine real_sub(x, y, z)
+ real :: x, y, z
+ x = y - z
+end subroutine
+! CHECK-LABEL: func.func @_QPreal_sub(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<f32>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<f32>
+! CHECK:  %[[VAL_8:.*]] = arith.subf %[[VAL_6]], %[[VAL_7]] fastmath<contract> : f32
+
+subroutine complex_sub(x, y, z)
+ complex :: x, y, z
+ x = y - z
+end subroutine
+! CHECK-LABEL: func.func @_QPcomplex_sub(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_8:.*]] = fir.subc %[[VAL_6]], %[[VAL_7]] : !fir.complex<4>
+
+subroutine int_mul(x, y, z)
+ integer :: x, y, z
+ x = y * z
+end subroutine
+! CHECK-LABEL: func.func @_QPint_mul(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_8:.*]] = arith.muli %[[VAL_6]], %[[VAL_7]] : i32
+
+subroutine real_mul(x, y, z)
+ real :: x, y, z
+ x = y * z
+end subroutine
+! CHECK-LABEL: func.func @_QPreal_mul(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<f32>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<f32>
+! CHECK:  %[[VAL_8:.*]] = arith.mulf %[[VAL_6]], %[[VAL_7]] fastmath<contract> : f32
+
+subroutine complex_mul(x, y, z)
+ complex :: x, y, z
+ x = y * z
+end subroutine
+! CHECK-LABEL: func.func @_QPcomplex_mul(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_8:.*]] = fir.mulc %[[VAL_6]], %[[VAL_7]] : !fir.complex<4>
+
+subroutine int_div(x, y, z)
+ integer :: x, y, z
+ x = y / z
+end subroutine
+! CHECK-LABEL: func.func @_QPint_div(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_8:.*]] = arith.divsi %[[VAL_6]], %[[VAL_7]] : i32
+
+subroutine real_div(x, y, z)
+ real :: x, y, z
+ x = y / z
+end subroutine
+! CHECK-LABEL: func.func @_QPreal_div(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<f32>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<f32>
+! CHECK:  %[[VAL_8:.*]] = arith.divf %[[VAL_6]], %[[VAL_7]] fastmath<contract> : f32
+
+subroutine complex_div(x, y, z)
+ complex :: x, y, z
+ x = y / z
+end subroutine
+! CHECK-LABEL: func.func @_QPcomplex_div(
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %{{.*}}y"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_5:.*]]:2 = hlfir.declare %{{.*}}z"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_6:.*]] = fir.load %[[VAL_4]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_5]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_8:.*]] = fir.divc %[[VAL_6]], %[[VAL_7]] : !fir.complex<4>


        


More information about the flang-commits mailing list