[flang-commits] [flang] [flang][Lower] Add alternative real expression lowering (PR #207371)
Tom Eccles via flang-commits
flang-commits at lists.llvm.org
Mon Jul 6 09:50:48 PDT 2026
================
@@ -51,6 +57,113 @@ static bool isParenthesized(const Fortran::evaluate::Expr<T> &expr) {
}
}
+template <int KIND>
+using Real = Fortran::evaluate::Type<Fortran::common::TypeCategory::Real, KIND>;
+
+template <int KIND>
+using RealExpr = Fortran::evaluate::Expr<Real<KIND>>;
+
+template <int KIND>
+static void flattenTopLevelAdds(const RealExpr<KIND> &expr,
+ llvm::SmallVectorImpl<RealExpr<KIND>> &terms) {
+ if (const auto *add =
+ std::get_if<Fortran::evaluate::Add<Real<KIND>>>(&expr.u)) {
+ flattenTopLevelAdds(add->left(), terms);
+ flattenTopLevelAdds(add->right(), terms);
+ return;
+ }
+ terms.push_back(expr);
+}
+
+template <int KIND>
+static RealExpr<KIND>
+buildRightAssociatedAddFold(llvm::ArrayRef<RealExpr<KIND>> terms) {
+ assert(!terms.empty() && "cannot build empty add fold");
+ if (terms.size() == 1)
+ return terms.front();
+ RealExpr<KIND> result{terms.back()};
+ for (const RealExpr<KIND> &term : llvm::reverse(terms.drop_back()))
+ result = RealExpr<KIND>{Fortran::evaluate::Add<Real<KIND>>{term, result}};
+ return result;
+}
+
+template <typename L, typename R>
+static std::optional<Fortran::lower::SomeExpr>
+tryBuildSplitSumExpressionTree(const L &, const R &) {
+ return std::nullopt;
+}
+
+template <int KIND>
+static std::optional<Fortran::lower::SomeExpr>
+tryBuildSplitSumExpressionTree(const RealExpr<KIND> &lhs,
+ const RealExpr<KIND> &rhs) {
+ if (!std::get_if<Fortran::evaluate::Add<Real<KIND>>>(&rhs.u))
+ return std::nullopt;
+
+ llvm::SmallVector<RealExpr<KIND>, 8> terms;
+ flattenTopLevelAdds(rhs, terms);
+ if (terms.size() <= 2)
+ return std::nullopt;
+
+ llvm::SmallVector<RealExpr<KIND>, 2> head{terms[0], terms[1]};
+ llvm::SmallVector<RealExpr<KIND>, 8> tail(terms.begin() + 2, terms.end());
+ RealExpr<KIND> headExpr = buildRightAssociatedAddFold<KIND>(head);
+ RealExpr<KIND> tailExpr = buildRightAssociatedAddFold<KIND>(tail);
+ return Fortran::lower::SomeExpr{RealExpr<KIND>{
+ Fortran::evaluate::Add<Real<KIND>>{std::move(tailExpr), headExpr}}};
+}
+
+template <Fortran::common::TypeCategory CAT>
+static std::optional<Fortran::lower::SomeExpr> tryBuildSplitSumExpressionTree(
+ const Fortran::evaluate::Expr<Fortran::evaluate::SomeKind<CAT>> &lhs,
+ const Fortran::evaluate::Expr<Fortran::evaluate::SomeKind<CAT>> &rhs) {
+ if constexpr (CAT == Fortran::common::TypeCategory::Real) {
+ return Fortran::common::visit(
+ [&](const auto &typedLhs) -> std::optional<Fortran::lower::SomeExpr> {
+ return Fortran::common::visit(
+ [&](const auto &typedRhs)
+ -> std::optional<Fortran::lower::SomeExpr> {
+ return tryBuildSplitSumExpressionTree(typedLhs, typedRhs);
+ },
+ rhs.u);
+ },
+ lhs.u);
+ }
+ return std::nullopt;
+}
+
+static bool
+canBuildSplitSumExpressionTree(const Fortran::lower::SomeExpr &lhs,
+ const Fortran::lower::SomeExpr &rhs) {
+ // The split rewrites a top-level addition chain. Subtraction would need to
+ // be carried as signed terms; division is safe here because it remains inside
+ // an individual term rather than changing the additive chain.
----------------
tblah wrote:
Yes you are correct.
The patch doesn't currently support any situations when nested subtraction terms can exist (e.g. parentheses). The intention was to merge something conservative and then extend if other useful cases were found. Would you like support for this in a follow up patch?
https://github.com/llvm/llvm-project/pull/207371
More information about the flang-commits
mailing list