Skip to content

EarlyCSE: fix CmpPredicate duplicate-hashing #119902

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 2 commits into from
Dec 13, 2024

Conversation

artagnon
Copy link
Contributor

@artagnon artagnon commented Dec 13, 2024

Strip hash_value() for CmpPredicate, as different callers have different hashing use-cases. In this case, there is just one caller, namely EarlyCSE, which calls hash_combine() on a CmpPredicate, which used to call hash_combine() on a CmpInst::Predicate prior to 4a0d53a (PatternMatch: migrate to CmpPredicate). This has uncovered a bug where two icmp instructions differing in just the fact that one of them has the samesign flag on it are hashed differently, leading to divergent hashing, and a crash. Fix this crash by dropping samesign information on icmp instructions before hashing them, preserving the former behavior.

Fixes #119893.

@llvmbot
Copy link
Member

llvmbot commented Dec 13, 2024

@llvm/pr-subscribers-llvm-transforms

@llvm/pr-subscribers-llvm-ir

Author: Ramkumar Ramachandra (artagnon)

Changes

Fixes #119893.


Full diff: https://github.com/llvm/llvm-project/pull/119902.diff

3 Files Affected:

  • (modified) llvm/include/llvm/IR/CmpPredicate.h (-6)
  • (modified) llvm/lib/IR/Instructions.cpp (-4)
  • (modified) llvm/lib/Transforms/Scalar/EarlyCSE.cpp (+2-1)
diff --git a/llvm/include/llvm/IR/CmpPredicate.h b/llvm/include/llvm/IR/CmpPredicate.h
index ce78e4311f9f82..9aa1449465f5ff 100644
--- a/llvm/include/llvm/IR/CmpPredicate.h
+++ b/llvm/include/llvm/IR/CmpPredicate.h
@@ -71,13 +71,7 @@ class CmpPredicate {
 
   /// Get the swapped predicate of a CmpInst.
   static CmpPredicate getSwapped(const CmpInst *Cmp);
-
-  /// Provided to facilitate storing a CmpPredicate in data structures that
-  /// require hashing.
-  friend hash_code hash_value(const CmpPredicate &Arg); // NOLINT
 };
-
-[[nodiscard]] hash_code hash_value(const CmpPredicate &Arg);
 } // namespace llvm
 
 #endif
diff --git a/llvm/lib/IR/Instructions.cpp b/llvm/lib/IR/Instructions.cpp
index d1da02c744f18c..2d6fe40f4c1de0 100644
--- a/llvm/lib/IR/Instructions.cpp
+++ b/llvm/lib/IR/Instructions.cpp
@@ -3946,10 +3946,6 @@ CmpPredicate CmpPredicate::getSwapped(const CmpInst *Cmp) {
   return getSwapped(get(Cmp));
 }
 
-hash_code llvm::hash_value(const CmpPredicate &Arg) { // NOLINT
-  return hash_combine(Arg.Pred, Arg.HasSameSign);
-}
-
 //===----------------------------------------------------------------------===//
 //                        SwitchInst Implementation
 //===----------------------------------------------------------------------===//
diff --git a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
index 682c5c3d8c6340..3a0ae6b01a1144 100644
--- a/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
+++ b/llvm/lib/Transforms/Scalar/EarlyCSE.cpp
@@ -290,7 +290,8 @@ static unsigned getHashValueImpl(SimpleValue Val) {
       Pred = CmpInst::getInversePredicate(Pred);
       std::swap(A, B);
     }
-    return hash_combine(Inst->getOpcode(), Pred, X, Y, A, B);
+    return hash_combine(Inst->getOpcode(),
+                        static_cast<CmpInst::Predicate>(Pred), X, Y, A, B);
   }
 
   if (CastInst *CI = dyn_cast<CastInst>(Inst))

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

This looks good to me, but should add a test? You can probably use -earlycse-debug-hash to produce a minimal test case.

@artagnon
Copy link
Contributor Author

Sounds good, will work on a test if this is not super-urgent.

Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

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

LGTM

@artagnon artagnon merged commit 5528388 into llvm:main Dec 13, 2024
8 checks passed
@artagnon artagnon deleted the earlycse-cmppredicate-hash-fix branch December 13, 2024 22:06
searlmc1 pushed a commit to ROCm/llvm-project that referenced this pull request Dec 14, 2024
revert: SPIRV 2nd patch from llvm needed
5528388 EarlyCSE: fix CmpPredicate duplicate-hashing (llvm#119902)

Change-Id: Ib28de7b92a661965bc294313b117de96cd2e056a
searlmc1 pushed a commit to ROCm/llvm-project that referenced this pull request Dec 16, 2024
Strip hash_value() for CmpPredicate, as different callers have different
hashing use-cases. In this case, there is just one caller, namely
EarlyCSE, which calls hash_combine() on a CmpPredicate, which used to
call hash_combine() on a CmpInst::Predicate prior to 4a0d53a
(PatternMatch: migrate to CmpPredicate). This has uncovered a bug where
two icmp instructions differing in just the fact that one of them has
the samesign flag on it are hashed differently, leading to divergent
hashing, and a crash. Fix this crash by dropping samesign information on
icmp instructions before hashing them, preserving the former behavior.

Fixes llvm#119893.

Change-Id: Iaa84f654b5f0cbe9792a78a14ba92af2ebaf5c18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[EarlyCSE] Assertion `!FoundVal && "Key already in new map?"' failed.
3 participants