[llvm] [HashRecognize] Rewrite arePHIsIntertwined (PR #144878)
Piotr Fusik via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 30 09:06:56 PDT 2025
================
@@ -497,45 +497,29 @@ CRCTable HashRecognize::genSarwateTable(const APInt &GenPoly,
return Table;
}
-/// Checks if \p Reference is reachable from \p Needle on the use-def chain, and
-/// that there are no stray PHI nodes while digging the use-def chain. \p
-/// BOToMatch is a CRC peculiarity: at least one of the Users of Needle needs to
-/// match this OpCode, which is XOR for CRC.
-static bool arePHIsIntertwined(
- const PHINode *Needle, const PHINode *Reference, const Loop &L,
- Instruction::BinaryOps BOToMatch = Instruction::BinaryOpsEnd) {
- // Initialize the worklist with Users of the Needle.
- SmallVector<const Instruction *> Worklist;
- for (const User *U : Needle->users()) {
- if (auto *UI = dyn_cast<Instruction>(U))
- if (L.contains(UI))
- Worklist.push_back(UI);
- }
-
- // BOToMatch is usually XOR for CRC.
- if (BOToMatch != Instruction::BinaryOpsEnd) {
- if (count_if(Worklist, [BOToMatch](const Instruction *I) {
- return I->getOpcode() == BOToMatch;
- }) != 1)
- return false;
- }
-
- while (!Worklist.empty()) {
- const Instruction *I = Worklist.pop_back_val();
-
- // Since Needle is never pushed onto the Worklist, I must either be the
- // Reference PHI node (in which case we're done), or a stray PHI node (in
- // which case we abort).
- if (isa<PHINode>(I))
- return I == Reference;
+/// A small helper for arePHIsIntertwined that is asymmetric in \p L and \p R,
+/// and hence needs to be called twice.
+static bool isXoredWith(const Value *L, const Value *R) {
+ return count_if(L->users(), [L, R](const User *U) {
+ return match(U, m_c_Xor(m_Specific(L),
+ m_CombineOr(m_ZExtOrSelf(m_Specific(R)),
+ m_Trunc(m_Specific(R)))));
+ }) == 1;
+}
- for (const Use &U : I->operands())
- if (auto *UI = dyn_cast<Instruction>(U))
- // Don't push Needle back onto the Worklist.
- if (UI != Needle && L.contains(UI))
- Worklist.push_back(UI);
- }
- return false;
+/// Checks that \p L and \p R are used together in an XOR, which is a recurrence
+/// over both, ignoring zext and trunc. In other words, it checks for the
+/// following pattern:
+///
+/// loop:
+/// %L = phi [_, %entry], [%L.next, %loop]
+/// %R = phi [_, %entry], [%R.next, %loop]
+/// ...
+/// _ = xor ((trunc|zext|self) %L) ((trunc|zext|self) %R)
----------------
pfusik wrote:
```suggestion
/// _ = xor ((trunc|zext|self) %L), ((trunc|zext|self) %R)
```
https://github.com/llvm/llvm-project/pull/144878
More information about the llvm-commits
mailing list