[llvm] [DenseMap] Fix constness issues with lookup_or (PR #139247)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Fri May 9 04:53:38 PDT 2025


https://github.com/artagnon created https://github.com/llvm/llvm-project/pull/139247

Also demonstrate its use in ScalarEvolution.

>From 8e8f0595d4f66577b06c4380c41b682d40ed124d Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Fri, 9 May 2025 12:46:26 +0100
Subject: [PATCH] [DenseMap] Fix constness issues with lookup_or

Also demonstrate its use in ScalarEvolution.
---
 llvm/include/llvm/ADT/DenseMap.h      |  9 ++++++--
 llvm/lib/Analysis/ScalarEvolution.cpp | 32 +++++++++------------------
 llvm/unittests/ADT/DenseMapTest.cpp   |  4 +++-
 3 files changed, 21 insertions(+), 24 deletions(-)

diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index 4df50e03de94b..acc81f069a5aa 100644
--- a/llvm/include/llvm/ADT/DenseMap.h
+++ b/llvm/include/llvm/ADT/DenseMap.h
@@ -220,8 +220,13 @@ class DenseMapBase : public DebugEpochBase {
   // Return the entry with the specified key, or \p Default. This variant is
   // useful, because `lookup` cannot be used with non-default-constructible
   // values.
-  ValueT lookup_or(const_arg_type_t<KeyT> Val,
-                   const_arg_type_t<ValueT> Default) const {
+  ValueT lookup_or(const_arg_type_t<KeyT> Val, const ValueT &Default) const {
+    if (const BucketT *Bucket = doFind(Val))
+      return Bucket->getSecond();
+    return Default;
+  }
+
+  ValueT lookup_or(const_arg_type_t<KeyT> Val, ValueT &&Default) const {
     if (const BucketT *Bucket = doFind(Val))
       return Bucket->getSecond();
     return Default;
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 3f9614254ae7a..0b0748b7ffe78 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -9571,15 +9571,14 @@ getConstantEvolvingPHIOperands(Instruction *UseInst, const Loop *L,
     if (!OpInst || !canConstantEvolve(OpInst, L)) return nullptr;
 
     PHINode *P = dyn_cast<PHINode>(OpInst);
-    if (!P)
+    if (!P) {
       // If this operand is already visited, reuse the prior result.
       // We may have P != PHI if this is the deepest point at which the
       // inconsistent paths meet.
-      P = PHIMap.lookup(OpInst);
-    if (!P) {
       // Recurse and memoize the results, whether a phi is found or not.
       // This recursive call invalidates pointers into PHIMap.
-      P = getConstantEvolvingPHIOperands(OpInst, L, PHIMap, Depth + 1);
+      P = PHIMap.lookup_or(
+          OpInst, getConstantEvolvingPHIOperands(OpInst, L, PHIMap, Depth + 1));
       PHIMap[OpInst] = P;
     }
     if (!P)
@@ -15860,10 +15859,7 @@ const SCEV *ScalarEvolution::LoopGuards::rewrite(const SCEV *Expr) const {
     const SCEV *visitAddRecExpr(const SCEVAddRecExpr *Expr) { return Expr; }
 
     const SCEV *visitUnknown(const SCEVUnknown *Expr) {
-      auto I = Map.find(Expr);
-      if (I == Map.end())
-        return Expr;
-      return I->second;
+      return Map.lookup_or(Expr, Expr);
     }
 
     const SCEV *visitZeroExtendExpr(const SCEVZeroExtendExpr *Expr) {
@@ -15891,25 +15887,19 @@ const SCEV *ScalarEvolution::LoopGuards::rewrite(const SCEV *Expr) const {
     }
 
     const SCEV *visitSignExtendExpr(const SCEVSignExtendExpr *Expr) {
-      auto I = Map.find(Expr);
-      if (I == Map.end())
-        return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitSignExtendExpr(
-            Expr);
-      return I->second;
+      return Map.lookup_or(
+          Expr,
+          SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitSignExtendExpr(Expr));
     }
 
     const SCEV *visitUMinExpr(const SCEVUMinExpr *Expr) {
-      auto I = Map.find(Expr);
-      if (I == Map.end())
-        return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitUMinExpr(Expr);
-      return I->second;
+      return Map.lookup_or(
+          Expr, SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitUMinExpr(Expr));
     }
 
     const SCEV *visitSMinExpr(const SCEVSMinExpr *Expr) {
-      auto I = Map.find(Expr);
-      if (I == Map.end())
-        return SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitSMinExpr(Expr);
-      return I->second;
+      return Map.lookup_or(
+          Expr, SCEVRewriteVisitor<SCEVLoopGuardRewriter>::visitSMinExpr(Expr));
     }
 
     const SCEV *visitAddExpr(const SCEVAddExpr *Expr) {
diff --git a/llvm/unittests/ADT/DenseMapTest.cpp b/llvm/unittests/ADT/DenseMapTest.cpp
index d002a3c15cf52..cf90b10495a14 100644
--- a/llvm/unittests/ADT/DenseMapTest.cpp
+++ b/llvm/unittests/ADT/DenseMapTest.cpp
@@ -668,7 +668,9 @@ TEST(DenseMapCustomTest, LookupOr) {
 
   EXPECT_EQ(M.lookup_or(0, 4u), 3u);
   EXPECT_EQ(M.lookup_or(1, 4u), 0u);
-  EXPECT_EQ(M.lookup_or(2, 4u), 4u);
+
+  NonDefaultConstructible DefaultV = M.lookup_or(2, 4u);
+  EXPECT_EQ(DefaultV, 4u);
 }
 
 // Key traits that allows lookup with either an unsigned or char* key;



More information about the llvm-commits mailing list