From f72c9754301e2a2edfd122aeb96861ea2a62f49b Mon Sep 17 00:00:00 2001 From: Eric Schweitz Date: Wed, 27 Oct 2021 11:22:22 -0700 Subject: [PATCH] Convert DenseMap to use value-based hashing and comparison. Add some more implementations. Second attempt to get rid of warning. --- flang/lib/Lower/IterationSpace.cpp | 39 ++++++++++++++++++++---------- flang/lib/Lower/IterationSpace.h | 28 +++++++++++++++++++-- 2 files changed, 52 insertions(+), 15 deletions(-) diff --git a/flang/lib/Lower/IterationSpace.cpp b/flang/lib/Lower/IterationSpace.cpp index 7739eb0fe7c5c8..b9bcbf1ece0ae0 100644 --- a/flang/lib/Lower/IterationSpace.cpp +++ b/flang/lib/Lower/IterationSpace.cpp @@ -208,7 +208,7 @@ class HashEvaluateExpr { unsigned args = 13u; for (const auto &v : x.arguments()) args -= getHashValue(v); - return getHashValue(x.proc()) * 101u; + return getHashValue(x.proc()) * 101u - args; } template static unsigned @@ -217,16 +217,15 @@ class HashEvaluateExpr { return 127u; } static unsigned getHashValue(const Fortran::evaluate::ImpliedDoIndex &x) { - // FIXME: hash the contents. - return 131u; + return llvm::hash_value(toStringRef(x.name).str()) * 131u; } static unsigned getHashValue(const Fortran::evaluate::TypeParamInquiry &x) { - // FIXME: hash the contents. - return 137u; + return getHashValue(x.base()) * 137u - getHashValue(x.parameter()) * 3u; } static unsigned getHashValue(const Fortran::evaluate::DescriptorInquiry &x) { - // FIXME: hash the contents. - return 139u; + return getHashValue(x.base()) * 139u - + static_cast(x.field()) * 13u + + static_cast(x.dimension()); } static unsigned getHashValue(const Fortran::evaluate::StructureConstructor &x) { @@ -280,6 +279,10 @@ unsigned Fortran::lower::getHashValue( [&](const auto *p) { return HashEvaluateExpr::getHashValue(*p); }, x); } +unsigned Fortran::lower::getHashValue(Fortran::lower::FrontEndExpr x) { + return HashEvaluateExpr::getHashValue(*x); +} + namespace { // Define the is equals test for using Fortran::evaluate::Expr values with // llvm::DenseMap. @@ -464,9 +467,8 @@ class IsEqualEvaluateExpr { return isEqual(*xs, *ys); return false; } - if ([[maybe_unused]] const auto *ys = y.GetAssumedTypeDummy()) - return false; - return isEqual(*x.UnwrapExpr(), *y.UnwrapExpr()); + return !y.GetAssumedTypeDummy() && + isEqual(*x.UnwrapExpr(), *y.UnwrapExpr()); } static bool isEqual(const Fortran::evaluate::ProcedureDesignator &x, const Fortran::evaluate::ProcedureDesignator &y) { @@ -484,15 +486,16 @@ class IsEqualEvaluateExpr { } static bool isEqual(const Fortran::evaluate::ImpliedDoIndex &x, const Fortran::evaluate::ImpliedDoIndex &y) { - llvm::report_fatal_error("not implemented"); + return toStringRef(x.name) == toStringRef(y.name); } static bool isEqual(const Fortran::evaluate::TypeParamInquiry &x, const Fortran::evaluate::TypeParamInquiry &y) { - llvm::report_fatal_error("not implemented"); + return isEqual(x.base(), y.base()) && isEqual(x.parameter(), y.parameter()); } static bool isEqual(const Fortran::evaluate::DescriptorInquiry &x, const Fortran::evaluate::DescriptorInquiry &y) { - llvm::report_fatal_error("not implemented"); + return isEqual(x.base(), y.base()) && x.field() == y.field() && + x.dimension() == y.dimension(); } static bool isEqual(const Fortran::evaluate::StructureConstructor &x, const Fortran::evaluate::StructureConstructor &y) { @@ -572,6 +575,16 @@ bool Fortran::lower::isEqual( x, y); } +bool Fortran::lower::isEqual(Fortran::lower::FrontEndExpr x, + Fortran::lower::FrontEndExpr y) { + auto empty = llvm::DenseMapInfo::getEmptyKey(); + auto tombstone = + llvm::DenseMapInfo::getTombstoneKey(); + if (x == empty || y == empty || x == tombstone || y == tombstone) + return x == y; + return x == y || IsEqualEvaluateExpr::isEqual(*x, *y); +} + namespace { /// This class can recover the base array in an expression that contains diff --git a/flang/lib/Lower/IterationSpace.h b/flang/lib/Lower/IterationSpace.h index befcbdb8c32340..eb3855f8a5445a 100644 --- a/flang/lib/Lower/IterationSpace.h +++ b/flang/lib/Lower/IterationSpace.h @@ -36,6 +36,31 @@ using FrontEndSymbol = const semantics::Symbol *; class AbstractConverter; +unsigned getHashValue(FrontEndExpr x); +bool isEqual(FrontEndExpr x, FrontEndExpr y); +} // namespace lower +} // namespace Fortran + +namespace llvm { +template <> +struct DenseMapInfo { + static inline Fortran::lower::FrontEndExpr getEmptyKey() { + return reinterpret_cast(~0); + } + static inline Fortran::lower::FrontEndExpr getTombstoneKey() { + return reinterpret_cast(~0 - 1); + } + static unsigned getHashValue(Fortran::lower::FrontEndExpr v) { + return Fortran::lower::getHashValue(v); + } + static bool isEqual(Fortran::lower::FrontEndExpr lhs, + Fortran::lower::FrontEndExpr rhs) { + return Fortran::lower::isEqual(lhs, rhs); + } +}; +} // namespace llvm + +namespace Fortran::lower { template class StackableConstructExpr { public: @@ -190,8 +215,7 @@ unsigned getHashValue(const ExplicitSpaceArrayBases &x); bool isEqual(const ExplicitSpaceArrayBases &x, const ExplicitSpaceArrayBases &y); -} // namespace lower -} // namespace Fortran +} // namespace Fortran::lower namespace llvm { template <>