Skip to content

[Flang] Check if two ArrayConstructor's are Equal #121181

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Feb 19, 2025
Merged
36 changes: 35 additions & 1 deletion flang/include/flang/Lower/Support/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -545,9 +545,43 @@ class IsEqualEvaluateExpr {
return isEqual(x.proc(), y.proc()) && isEqual(x.arguments(), y.arguments());
}
template <typename A>
static bool isEqual(const Fortran::evaluate::ImpliedDo<A> &x,
const Fortran::evaluate::ImpliedDo<A> &y) {
return isEqual(x.values(), y.values()) && isEqual(x.lower(), y.lower()) &&
isEqual(x.upper(), y.upper()) && isEqual(x.stride(), y.stride());
}
template <typename A>
static bool isEqual(const Fortran::evaluate::ArrayConstructorValues<A> &x,
const Fortran::evaluate::ArrayConstructorValues<A> &y) {
using Expr = Fortran::evaluate::Expr<A>;
using ImpliedDo = Fortran::evaluate::ImpliedDo<A>;
for (const auto &[xValue, yValue] : llvm::zip(x, y)) {
bool checkElement = Fortran::common::visit(
common::visitors{
[&](const Expr &v, const Expr &w) { return isEqual(v, w); },
[&](const ImpliedDo &v, const ImpliedDo &w) {
return isEqual(v, w);
},
[&](const Expr &, const ImpliedDo &) { return false; },
[&](const ImpliedDo &, const Expr &) { return false; },
},
xValue.u, yValue.u);
if (!checkElement) {
return false;
}
}
return true;
}
template <typename A>
static bool isEqual(const Fortran::evaluate::ArrayConstructor<A> &x,
const Fortran::evaluate::ArrayConstructor<A> &y) {
llvm::report_fatal_error("not implemented");
bool checkCharacterType = true;
if constexpr (A::category == Fortran::common::TypeCategory::Character) {
checkCharacterType = x.LEN() == y.LEN();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: should use isEqual.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little confused, sorry about that.

Are you suggesting the following

Suggested change
checkCharacterType = x.LEN() == y.LEN();
checkCharacterType = isEqual(x.LEN(), y.LEN());

or Should I add a isEqual for the Fortran::common::TypeCategory::Character category?

Copy link
Member Author

@Thirumalai-Shaktivel Thirumalai-Shaktivel Jan 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took the first approach and implemented it: 6442b33, please let me know this works

}
using Base = Fortran::evaluate::ArrayConstructorValues<A>;
return isEqual((Base)x, (Base)y) &&
(x.GetType() == y.GetType() && checkCharacterType);
}
static bool isEqual(const Fortran::evaluate::ImpliedDoIndex &x,
const Fortran::evaluate::ImpliedDoIndex &y) {
Expand Down
15 changes: 15 additions & 0 deletions flang/test/Lower/OpenMP/atomic-update.f90
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,19 @@ program OmpAtomicUpdate
!$omp atomic update
w = max(w,x,y,z)

!CHECK: %[[IMP_DO:.*]] = hlfir.elemental %{{.*}} unordered : (!fir.shape<1>) -> !hlfir.expr<?xi32> {
!CHECK: ^bb0(%{{.*}}: index):
! [...]
!CHECK: %[[ADD_I1:.*]] = arith.addi {{.*}} : i32
!CHECK: hlfir.yield_element %[[ADD_I1]] : i32
!CHECK: }
! [...]
!CHECK: %[[SUM:.*]] = hlfir.sum %[[IMP_DO]]
!CHECK: omp.atomic.update %[[VAL_X_DECLARE]]#1 : !fir.ref<i32> {
!CHECK: ^bb0(%[[ARG0:.*]]: i32):
!CHECK: %[[ADD_I2:.*]] = arith.addi %[[ARG0]], %[[SUM]] : i32
!CHECK: omp.yield(%[[ADD_I2]] : i32)
!CHECK: }
!$omp atomic update
x = x + sum([ (y+2, y=1, z) ])
end program OmpAtomicUpdate
Loading