[flang] Lower complex part

Implements HLFIR lowering for %im and %re.

Reviewed By: jeanPerier

Differential Revision: https://reviews.llvm.org/D145005
This commit is contained in:
Ethan Luis McDonough
2023-03-07 11:38:50 -06:00
parent 8fa1e5e673
commit ba45f63782
3 changed files with 82 additions and 5 deletions

View File

@@ -88,6 +88,7 @@ private:
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 @@ private:
// 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 @@ private:
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 @@ private:
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

View File

@@ -336,7 +336,9 @@ mlir::LogicalResult hlfir::DesignateOp::verify() {
// length may differ 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;

View File

@@ -112,3 +112,58 @@ end subroutine
! 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>>