[flang-commits] [flang] ba45f63 - [flang] Lower complex part

Ethan Luis McDonough via flang-commits flang-commits at lists.llvm.org
Tue Mar 7 09:40:36 PST 2023


Author: Ethan Luis McDonough
Date: 2023-03-07T11:40:27-06:00
New Revision: ba45f63782fa04a530d451dedb3cd58ed6e99664

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

LOG: [flang] Lower complex part

Implements HLFIR lowering for %im and %re.

Reviewed By: jeanPerier

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

Added: 
    

Modified: 
    flang/lib/Lower/ConvertExprToHLFIR.cpp
    flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
    flang/test/Lower/HLFIR/designators.f90

Removed: 
    


################################################################################
diff  --git a/flang/lib/Lower/ConvertExprToHLFIR.cpp b/flang/lib/Lower/ConvertExprToHLFIR.cpp
index 68839bacd6ef..2dd61bb15833 100644
--- a/flang/lib/Lower/ConvertExprToHLFIR.cpp
+++ b/flang/lib/Lower/ConvertExprToHLFIR.cpp
@@ -88,6 +88,7 @@ class HlfirDesignatorBuilder {
     std::string componentName{};
     mlir::Value componentShape;
     hlfir::DesignateOp::Subscripts subscripts;
+    std::optional<bool> complexPart;
     mlir::Value resultShape;
     llvm::SmallVector<mlir::Value> typeParams;
     llvm::SmallVector<mlir::Value, 2> substring;
@@ -98,8 +99,14 @@ class HlfirDesignatorBuilder {
   // fir.box)...
   template <typename T>
   mlir::Type computeDesignatorType(mlir::Type resultValueType,
-                                   const PartInfo &partInfo,
+                                   PartInfo &partInfo,
                                    const T &designatorNode) {
+    // Get base's shape if its a sequence type with no previously computed
+    // result shape
+    if (partInfo.base && resultValueType.isa<fir::SequenceType>() &&
+        !partInfo.resultShape)
+      partInfo.resultShape =
+          hlfir::genShape(getLoc(), getBuilder(), *partInfo.base);
     // Dynamic type of polymorphic base must be kept if the designator is
     // polymorphic.
     if (isPolymorphic(designatorNode))
@@ -144,11 +151,10 @@ class HlfirDesignatorBuilder {
   fir::FortranVariableOpInterface
   genDesignate(mlir::Type designatorType, PartInfo &partInfo,
                fir::FortranVariableFlagsAttr attributes) {
-    std::optional<bool> complexPart;
     auto designate = getBuilder().create<hlfir::DesignateOp>(
         getLoc(), designatorType, partInfo.base.value().getBase(),
         partInfo.componentName, partInfo.componentShape, partInfo.subscripts,
-        partInfo.substring, complexPart, partInfo.resultShape,
+        partInfo.substring, partInfo.complexPart, partInfo.resultShape,
         partInfo.typeParams, attributes);
     return mlir::cast<fir::FortranVariableOpInterface>(
         designate.getOperation());
@@ -240,7 +246,21 @@ class HlfirDesignatorBuilder {
 
   fir::FortranVariableOpInterface
   gen(const Fortran::evaluate::ComplexPart &complexPart) {
-    TODO(getLoc(), "lowering complex part to HLFIR");
+    PartInfo partInfo;
+    fir::factory::Complex cmplxHelper(getBuilder(), getLoc());
+
+    bool complexBit =
+        complexPart.part() == Fortran::evaluate::ComplexPart::Part::IM;
+    partInfo.complexPart = {complexBit};
+
+    mlir::Type resultType = visit(complexPart.complex(), partInfo);
+
+    // Determine complex part type
+    mlir::Type base = hlfir::getFortranElementType(resultType);
+    mlir::Type cmplxValueType = cmplxHelper.getComplexPartType(base);
+    mlir::Type designatorType = changeElementType(resultType, cmplxValueType);
+
+    return genDesignate(designatorType, partInfo, complexPart);
   }
 
   fir::FortranVariableOpInterface

diff  --git a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
index 53259fe495ba..13103c50d0df 100644
--- a/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
+++ b/flang/lib/Optimizer/HLFIR/IR/HLFIROps.cpp
@@ -336,7 +336,9 @@ mlir::LogicalResult hlfir::DesignateOp::verify() {
   // length may 
diff er because of substrings.
   if (resultElementType != outputElementType &&
       !(resultElementType.isa<fir::CharacterType>() &&
-        outputElementType.isa<fir::CharacterType>()))
+        outputElementType.isa<fir::CharacterType>()) &&
+      !(resultElementType.isa<mlir::FloatType>() &&
+        outputElementType.isa<fir::RealType>()))
     return emitOpError(
                "result element type is not consistent with operands, expected ")
            << outputElementType;

diff  --git a/flang/test/Lower/HLFIR/designators.f90 b/flang/test/Lower/HLFIR/designators.f90
index a2aaad536e19..777d6ea5182e 100644
--- a/flang/test/Lower/HLFIR/designators.f90
+++ b/flang/test/Lower/HLFIR/designators.f90
@@ -112,3 +112,58 @@ subroutine char_array_section_cst_len(x, n)
 ! CHECK:  %[[VAL_19:.*]] = arith.select %[[VAL_18]], %[[VAL_17]], %[[VAL_14]] : index
 ! CHECK:  %[[VAL_20:.*]] = fir.shape %[[VAL_19]] : (index) -> !fir.shape<1>
 ! CHECK:  %[[VAL_21:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_10]]:%[[VAL_12]]#1:%[[VAL_13]])  shape %[[VAL_20]] typeparams %[[VAL_3]] : (!fir.box<!fir.array<?x!fir.char<1,5>>>, index, index, index, !fir.shape<1>, index) -> !fir.box<!fir.array<?x!fir.char<1,5>>>
+
+! Checks related to complex numbers
+
+subroutine complex_imag_ref(x)
+  complex :: x(:)
+  print *, x%im
+end subroutine
+! CHECK-LABEL: func.func @_QPcomplex_imag_ref(
+! CHECK:  %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_imag_refEx"} : (!fir.box<!fir.array<?x!fir.complex<4>>>) -> (!fir.box<!fir.array<?x!fir.complex<4>>>, !fir.box<!fir.array<?x!fir.complex<4>>>)
+! CHECK:  %[[VAL_3:.*]] = fir.shape %[[VAL_4:.*]]#1 : (index) -> !fir.shape<1>
+! CHECK:  %[[VAL_5:.*]] = hlfir.designate %[[VAL_2]]#0  imag shape %[[VAL_3]] : (!fir.box<!fir.array<?x!fir.complex<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
+
+subroutine complex_real_ref(x)
+  complex :: x(:)
+  print *, x%re
+end subroutine
+! CHECK-LABEL: func.func @_QPcomplex_real_ref(
+! CHECK:  %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_real_refEx"} : (!fir.box<!fir.array<?x!fir.complex<4>>>) -> (!fir.box<!fir.array<?x!fir.complex<4>>>, !fir.box<!fir.array<?x!fir.complex<4>>>)
+! CHECK:  %[[VAL_3:.*]] = fir.shape %[[VAL_4:.*]]#1 : (index) -> !fir.shape<1>
+! CHECK:  %[[VAL_5:.*]] = hlfir.designate %[[VAL_2]]#0  real shape %[[VAL_3]] : (!fir.box<!fir.array<?x!fir.complex<4>>>, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>
+
+subroutine complex_individual_ref(x, n)
+  complex :: x(:)
+  integer :: n
+  print *, x(n)%im
+end subroutine
+! CHECK-LABEL: func.func @_QPcomplex_individual_ref(
+! CHECK:  %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_individual_refEn"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_individual_refEx"} : (!fir.box<!fir.array<?x!fir.complex<4>>>) -> (!fir.box<!fir.array<?x!fir.complex<4>>>, !fir.box<!fir.array<?x!fir.complex<4>>>)
+! CHECK:  %[[VAL_4:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_5:.*]] = fir.convert %[[VAL_4]] : (i32) -> i64
+! CHECK:  %[[VAL_6:.*]] = hlfir.designate %1#0 (%[[VAL_5]]) imag : (!fir.box<!fir.array<?x!fir.complex<4>>>, i64) -> !fir.ref<f32>
+
+subroutine complex_slice_ref(x, start, end)
+  complex :: x(:)
+  integer :: start, end
+  print *, x(start:end)%re
+end subroutine
+! CHECK-LABEL: func.func @_QPcomplex_slice_ref(
+! CHECK:  %[[VAL_2:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_slice_refEend"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_3:.*]]:2 = hlfir.declare %{{.*}} {uniq_name = "_QFcomplex_slice_refEstart"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK:  %[[VAL_4:.*]]:2 = hlfir.declare %arg0 {uniq_name = "_QFcomplex_slice_refEx"} : (!fir.box<!fir.array<?x!fir.complex<4>>>) -> (!fir.box<!fir.array<?x!fir.complex<4>>>, !fir.box<!fir.array<?x!fir.complex<4>>>)
+! CHECK:  %[[VAL_5:.*]] = fir.load %[[VAL_3]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_6:.*]] = fir.convert %[[VAL_5]] : (i32) -> i64
+! CHECK:  %[[VAL_7:.*]] = fir.load %[[VAL_2]]#0 : !fir.ref<i32>
+! CHECK:  %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i32) -> i64
+! CHECK:  %[[VAL_9:.*]] = fir.convert %[[VAL_6]] : (i64) -> index
+! CHECK:  %[[VAL_10:.*]] = fir.convert %[[VAL_8]] : (i64) -> index
+! CHECK:  %[[VAL_11:.*]] = arith.subi %[[VAL_10]], %[[VAL_9]] : index
+! CHECK:  %[[VAL_12:.*]] = arith.addi %[[VAL_11]], %{{.*}} : index
+! CHECK:  %[[VAL_13:.*]] = arith.divsi %[[VAL_12]], %{{.*}} : index
+! CHECK:  %[[VAL_14:.*]] = arith.cmpi sgt, %[[VAL_13]], %{{.*}} : index
+! CHECK:  %[[VAL_15:.*]] = arith.select %[[VAL_14]], %[[VAL_13]], %{{.*}} : index
+! CHECK:  %[[VAL_16:.*]] = fir.shape %[[VAL_15]] : (index) -> !fir.shape<1>
+! CHECK:  %[[VAL_17:.*]] = hlfir.designate %[[VAL_4]]#0 (%[[VAL_9]]:%[[VAL_10]]:%{{.*}}) real shape %[[VAL_16]] : (!fir.box<!fir.array<?x!fir.complex<4>>>, index, index, index, !fir.shape<1>) -> !fir.box<!fir.array<?xf32>>


        


More information about the flang-commits mailing list