[flang-commits] [flang] 12c8797 - [flang] Lower unary operation to HLFIR

Jean Perier via flang-commits flang-commits at lists.llvm.org
Fri Dec 2 05:23:07 PST 2022


Author: Jean Perier
Date: 2022-12-02T14:22:41+01:00
New Revision: 12c8797fc4ed5a4068034c50af734f06d00c90ab

URL: https://github.com/llvm/llvm-project/commit/12c8797fc4ed5a4068034c50af734f06d00c90ab
DIFF: https://github.com/llvm/llvm-project/commit/12c8797fc4ed5a4068034c50af734f06d00c90ab.diff

LOG: [flang] Lower unary operation to HLFIR

Lower not, negate, and complex component to HLFIR.
Parentheses is the only remaining operation, but needs some
care/thinking to properly deal with character/derived variables.

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

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

Modified: 
    flang/lib/Lower/ConvertExprToHLFIR.cpp

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index f2e47ee96070..6eeafffe7942 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -506,6 +506,91 @@ struct BinaryOp<Fortran::evaluate::SetLength<KIND>> {
   }
 };
 
+//===--------------------------------------------------------------------===//
+// Unary Operation implementation
+//===--------------------------------------------------------------------===//
+
+template <typename T>
+struct UnaryOp {};
+
+template <int KIND>
+struct UnaryOp<Fortran::evaluate::Not<KIND>> {
+  using Op = Fortran::evaluate::Not<KIND>;
+  static hlfir::EntityWithAttributes gen(mlir::Location loc,
+                                         fir::FirOpBuilder &builder,
+                                         const Op &op, hlfir::Entity lhs) {
+    mlir::Value one = builder.createBool(loc, true);
+    mlir::Value val = builder.createConvert(loc, builder.getI1Type(), lhs);
+    return hlfir::EntityWithAttributes{
+        builder.create<mlir::arith::XOrIOp>(loc, val, one)};
+  }
+};
+
+template <int KIND>
+struct UnaryOp<Fortran::evaluate::Negate<
+    Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, KIND>>> {
+  using Op = Fortran::evaluate::Negate<
+      Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer, KIND>>;
+  static hlfir::EntityWithAttributes gen(mlir::Location loc,
+                                         fir::FirOpBuilder &builder,
+                                         const Op &op, hlfir::Entity lhs) {
+    // Like LLVM, integer negation is the binary op "0 - value"
+    mlir::Type type = Fortran::lower::getFIRType(
+        builder.getContext(), Fortran::common::TypeCategory::Integer, KIND,
+        /*params=*/llvm::None);
+    mlir::Value zero = builder.createIntegerConstant(loc, type, 0);
+    return hlfir::EntityWithAttributes{
+        builder.create<mlir::arith::SubIOp>(loc, zero, lhs)};
+  }
+};
+
+template <int KIND>
+struct UnaryOp<Fortran::evaluate::Negate<
+    Fortran::evaluate::Type<Fortran::common::TypeCategory::Real, KIND>>> {
+  using Op = Fortran::evaluate::Negate<
+      Fortran::evaluate::Type<Fortran::common::TypeCategory::Real, KIND>>;
+  static hlfir::EntityWithAttributes gen(mlir::Location loc,
+                                         fir::FirOpBuilder &builder,
+                                         const Op &op, hlfir::Entity lhs) {
+    return hlfir::EntityWithAttributes{
+        builder.create<mlir::arith::NegFOp>(loc, lhs)};
+  }
+};
+
+template <int KIND>
+struct UnaryOp<Fortran::evaluate::Negate<
+    Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>> {
+  using Op = Fortran::evaluate::Negate<
+      Fortran::evaluate::Type<Fortran::common::TypeCategory::Complex, KIND>>;
+  static hlfir::EntityWithAttributes gen(mlir::Location loc,
+                                         fir::FirOpBuilder &builder,
+                                         const Op &op, hlfir::Entity lhs) {
+    return hlfir::EntityWithAttributes{builder.create<fir::NegcOp>(loc, lhs)};
+  }
+};
+
+template <int KIND>
+struct UnaryOp<Fortran::evaluate::ComplexComponent<KIND>> {
+  using Op = Fortran::evaluate::ComplexComponent<KIND>;
+  static hlfir::EntityWithAttributes gen(mlir::Location loc,
+                                         fir::FirOpBuilder &builder,
+                                         const Op &op, hlfir::Entity lhs) {
+    mlir::Value res = fir::factory::Complex{builder, loc}.extractComplexPart(
+        lhs, op.isImaginaryPart);
+    return hlfir::EntityWithAttributes{res};
+  }
+};
+
+template <typename T>
+struct UnaryOp<Fortran::evaluate::Parentheses<T>> {
+  using Op = Fortran::evaluate::Parentheses<T>;
+  static hlfir::EntityWithAttributes gen(mlir::Location loc,
+                                         fir::FirOpBuilder &builder,
+                                         const Op &op, hlfir::Entity lhs) {
+    TODO(loc, "Parentheses lowering to HLFIR");
+  }
+};
+
 /// Lower Expr to HLFIR.
 class HlfirBuilder {
 public:
@@ -595,7 +680,12 @@ class HlfirBuilder {
   template <typename D, typename R, typename O>
   hlfir::EntityWithAttributes
   gen(const Fortran::evaluate::Operation<D, R, O> &op) {
-    TODO(getLoc(), "lowering unary 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()));
+    return UnaryOp<D>::gen(loc, builder, op.derived(), left);
   }
 
   template <typename D, typename R, typename LO, typename RO>

diff  --git a/flang/test/Lower/HLFIR/unary-ops.f90 b/flang/test/Lower/HLFIR/unary-ops.f90
new file mode 100644
index 000000000000..148491c6ebd9
--- /dev/null
+++ b/flang/test/Lower/HLFIR/unary-ops.f90
@@ -0,0 +1,61 @@
+! Test lowering of unary intrinsic operations to HLFIR
+! RUN: bbc -emit-fir -hlfir -o - %s 2>&1 | FileCheck %s
+
+subroutine test_not(l, x)
+  logical :: l, x
+  l = .not.x
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_not(
+! CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}x"} : (!fir.ref<!fir.logical<4>>) -> (!fir.ref<!fir.logical<4>>, !fir.ref<!fir.logical<4>>)
+! CHECK:  %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.logical<4>>
+! CHECK:  %[[VAL_5:.*]] = arith.constant true
+! CHECK:  %[[VAL_6:.*]] = fir.convert %[[VAL_4]] : (!fir.logical<4>) -> i1
+! CHECK:  %[[VAL_7:.*]] = arith.xori %[[VAL_6]], %[[VAL_5]] : i1
+
+subroutine test_negate_int(res, x)
+  integer :: res, x
+  res = -x
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_negate_int(
+! CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}x"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_5:.*]] = arith.constant 0 : i32
+! CHECK:  %[[VAL_6:.*]] = arith.subi %[[VAL_5]], %[[VAL_4]] : i32
+
+subroutine test_negate_real(res, x)
+  real :: res, x
+  res = -x
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_negate_real(
+! CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}x"} : (!fir.ref<f32>) -> (!fir.ref<f32>, !fir.ref<f32>)
+! CHECK:  %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<f32>
+! CHECK:  %[[VAL_5:.*]] = arith.negf %[[VAL_4]] fastmath<contract> : f32
+
+subroutine test_negate_complex(res, x)
+  complex :: res, x
+  res = -x
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_negate_complex(
+! CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}x"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_5:.*]] = fir.negc %[[VAL_4]] : !fir.complex<4>
+
+subroutine test_complex_component_real(res, x)
+  real :: res
+  complex :: x
+  res = real(x)
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_complex_component_real(
+! CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}x"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_5:.*]] = fir.extract_value %[[VAL_4]], [0 : index] : (!fir.complex<4>) -> f32
+
+subroutine test_complex_component_imag(res, x)
+  real :: res
+  complex :: x
+  res = aimag(x)
+end subroutine
+! CHECK-LABEL: func.func @_QPtest_complex_component_imag(
+! CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}}x"} : (!fir.ref<!fir.complex<4>>) -> (!fir.ref<!fir.complex<4>>, !fir.ref<!fir.complex<4>>)
+! CHECK:  %[[VAL_4:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<!fir.complex<4>>
+! CHECK:  %[[VAL_5:.*]] = fir.extract_value %[[VAL_4]], [1 : index] : (!fir.complex<4>) -> f32


        


More information about the flang-commits mailing list