Skip to content

Commit ed71a0b

Browse files
committed
[flang] When folding FINDLOC, convert operands to a common type
For example, FINDLOC(A,X) should convert both A and X to COMPLEX(8) if the operands are REAL(8) and COMPLEX(4), so that comparisons can be done without losing inforation. The current implementation unconditionally converts X to the type of the array A. Differential Revision: https://reviews.llvm.org/D127030
1 parent 9a163ff commit ed71a0b

File tree

3 files changed

+71
-0
lines changed

3 files changed

+71
-0
lines changed

flang/include/flang/Evaluate/type.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,12 @@ int SelectedIntKind(std::int64_t precision = 0);
452452
int SelectedRealKind(
453453
std::int64_t precision = 0, std::int64_t range = 0, std::int64_t radix = 2);
454454

455+
// Given the dynamic types and kinds of two operands, determine the common
456+
// type to which they must be converted in order to be compared with
457+
// intrinsic OPERATOR(==) or .EQV.
458+
std::optional<DynamicType> ComparisonType(
459+
const DynamicType &, const DynamicType &);
460+
455461
// For generating "[extern] template class", &c. boilerplate
456462
#define EXPAND_FOR_EACH_INTEGER_KIND(M, P, S) \
457463
M(P, S, 1) M(P, S, 2) M(P, S, 4) M(P, S, 8) M(P, S, 16)

flang/lib/Evaluate/fold-integer.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,17 @@ static std::optional<Constant<SubscriptInteger>> FoldLocationCall(
436436
ActualArguments &arg, FoldingContext &context) {
437437
if (arg[0]) {
438438
if (auto type{arg[0]->GetType()}) {
439+
if constexpr (which == WhichLocation::Findloc) {
440+
// Both ARRAY and VALUE are susceptible to conversion to a common
441+
// comparison type.
442+
if (arg[1]) {
443+
if (auto valType{arg[1]->GetType()}) {
444+
if (auto compareType{ComparisonType(*type, *valType)}) {
445+
type = compareType;
446+
}
447+
}
448+
}
449+
}
439450
return common::SearchTypes(
440451
LocationHelper<which>{std::move(*type), arg, context});
441452
}

flang/lib/Evaluate/type.cpp

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,4 +580,58 @@ int SelectedRealKind(
580580
}
581581
}
582582
}
583+
584+
std::optional<DynamicType> ComparisonType(
585+
const DynamicType &t1, const DynamicType &t2) {
586+
switch (t1.category()) {
587+
case TypeCategory::Integer:
588+
switch (t2.category()) {
589+
case TypeCategory::Integer:
590+
return DynamicType{TypeCategory::Integer, std::max(t1.kind(), t2.kind())};
591+
case TypeCategory::Real:
592+
case TypeCategory::Complex:
593+
return t2;
594+
default:
595+
return std::nullopt;
596+
}
597+
case TypeCategory::Real:
598+
switch (t2.category()) {
599+
case TypeCategory::Integer:
600+
return t1;
601+
case TypeCategory::Real:
602+
case TypeCategory::Complex:
603+
return DynamicType{t2.category(), std::max(t1.kind(), t2.kind())};
604+
default:
605+
return std::nullopt;
606+
}
607+
case TypeCategory::Complex:
608+
switch (t2.category()) {
609+
case TypeCategory::Integer:
610+
return t1;
611+
case TypeCategory::Real:
612+
case TypeCategory::Complex:
613+
return DynamicType{TypeCategory::Complex, std::max(t1.kind(), t2.kind())};
614+
default:
615+
return std::nullopt;
616+
}
617+
case TypeCategory::Character:
618+
switch (t2.category()) {
619+
case TypeCategory::Character:
620+
return DynamicType{
621+
TypeCategory::Character, std::max(t1.kind(), t2.kind())};
622+
default:
623+
return std::nullopt;
624+
}
625+
case TypeCategory::Logical:
626+
switch (t2.category()) {
627+
case TypeCategory::Logical:
628+
return DynamicType{TypeCategory::Logical, LogicalResult::kind};
629+
default:
630+
return std::nullopt;
631+
}
632+
default:
633+
return std::nullopt;
634+
}
635+
}
636+
583637
} // namespace Fortran::evaluate

0 commit comments

Comments
 (0)