[llvm] [HashRecognize] Use loop latch to determine step/start for conditional recurrence (PR #211916)
Sean Clarke via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 27 07:16:31 PDT 2026
https://github.com/xarkenz updated https://github.com/llvm/llvm-project/pull/211916
>From 88ae6d344f3959e3a94820a139cabaeed94b194d Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 24 Jul 2026 13:26:37 -0500
Subject: [PATCH 1/4] Add baseline test
---
.../HashRecognize/cyclic-redundancy-check.ll | 27 +++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
index b7139a7367829..4c0e51b67dd59 100644
--- a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
+++ b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
@@ -335,6 +335,33 @@ exit: ; preds = %loop
ret i16 %crc.next
}
+define i16 @crc16.be.tc8.crc.init.select(i16 %a, i16 %b) {
+; CHECK-LABEL: 'crc16.be.tc8.crc.init.select'
+; CHECK-NEXT: Did not find a hash algorithm
+; CHECK-NEXT: Reason: Unable to find conditional recurrence
+;
+entry:
+ %a.inc = add i16 %a, 1
+ %b.inc = add i16 %b, 2
+ %init.cond = icmp ult i16 %a, %b
+ %crc.init = select i1 %init.cond, i16 %a.inc, i16 %b.inc
+ br label %loop
+
+loop: ; preds = %loop, %entry
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
+ %crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
+ %crc.shl = shl i16 %crc, 1
+ %crc.xor = xor i16 %crc.shl, 4129
+ %check.sb = icmp slt i16 %crc, 0
+ %crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
+ %iv.next = add nuw nsw i32 %iv, 1
+ %exit.cond = icmp samesign ult i32 %iv, 7
+ br i1 %exit.cond, label %loop, label %exit
+
+exit: ; preds = %loop
+ ret i16 %crc.next
+}
+
define i8 @crc8.be.tc8.ptr.nested.loop(ptr %msg, i32 %loop.limit) {
; CHECK-LABEL: 'crc8.be.tc8.ptr.nested.loop'
; CHECK-NEXT: Found big-endian CRC-8 loop with trip count 8
>From 731245e267806c320413b323be741140439ff1ff Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 24 Jul 2026 19:51:57 -0500
Subject: [PATCH 2/4] Dedent loop for diff purposes
---
llvm/lib/Analysis/HashRecognize.cpp | 44 ++++++++++++++---------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp
index 1b6a2acc1a584..560e5566f5c9d 100644
--- a/llvm/lib/Analysis/HashRecognize.cpp
+++ b/llvm/lib/Analysis/HashRecognize.cpp
@@ -291,31 +291,31 @@ bool RecurrenceInfo::matchConditionalRecurrence(
return false;
for (unsigned Idx = 0; Idx != 2; ++Idx) {
- Value *FoundStep = Phi->getIncomingValue(Idx);
- Value *FoundStart = Phi->getIncomingValue(!Idx);
+ Value *FoundStep = Phi->getIncomingValue(Idx);
+ Value *FoundStart = Phi->getIncomingValue(!Idx);
- Instruction *TV, *FV;
- if (!match(FoundStep,
- m_Select(m_Cmp(), m_Instruction(TV), m_Instruction(FV))))
- continue;
+ Instruction *TV, *FV;
+ if (!match(FoundStep,
+ m_Select(m_Cmp(), m_Instruction(TV), m_Instruction(FV))))
+ continue;
+
+ // For a conditional recurrence, both the true and false values of the
+ // select must ultimately end up in the same recurrent BinOp.
+ BinaryOperator *FoundBO = digRecurrence(TV, BOWithConstOpToMatch);
+ BinaryOperator *AltBO = digRecurrence(FV, BOWithConstOpToMatch);
+ if (!FoundBO || FoundBO != AltBO)
+ return false;
- // For a conditional recurrence, both the true and false values of the
- // select must ultimately end up in the same recurrent BinOp.
- BinaryOperator *FoundBO = digRecurrence(TV, BOWithConstOpToMatch);
- BinaryOperator *AltBO = digRecurrence(FV, BOWithConstOpToMatch);
- if (!FoundBO || FoundBO != AltBO)
- return false;
-
- if (BOWithConstOpToMatch != Instruction::BinaryOpsEnd && !ExtraConst) {
- LLVM_DEBUG(dbgs() << "HashRecognize: Unable to match single BinaryOp "
- "with constant in conditional recurrence\n");
- return false;
- }
+ if (BOWithConstOpToMatch != Instruction::BinaryOpsEnd && !ExtraConst) {
+ LLVM_DEBUG(dbgs() << "HashRecognize: Unable to match single BinaryOp "
+ "with constant in conditional recurrence\n");
+ return false;
+ }
- BO = FoundBO;
- Start = FoundStart;
- Step = FoundStep;
- return true;
+ BO = FoundBO;
+ Start = FoundStart;
+ Step = FoundStep;
+ return true;
}
return false;
}
>From 9da27b03c36820bcbbb59c6ccfc6921f4e955428 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Fri, 24 Jul 2026 13:27:12 -0500
Subject: [PATCH 3/4] Use loop latch to determine step/start rather than
iterating
---
llvm/lib/Analysis/HashRecognize.cpp | 11 ++++----
.../HashRecognize/cyclic-redundancy-check.ll | 25 +++++++++++++++++--
2 files changed, 28 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp
index 560e5566f5c9d..7357c9c21a1f9 100644
--- a/llvm/lib/Analysis/HashRecognize.cpp
+++ b/llvm/lib/Analysis/HashRecognize.cpp
@@ -290,14 +290,15 @@ bool RecurrenceInfo::matchConditionalRecurrence(
if (Phi->getNumIncomingValues() != 2)
return false;
- for (unsigned Idx = 0; Idx != 2; ++Idx) {
- Value *FoundStep = Phi->getIncomingValue(Idx);
- Value *FoundStart = Phi->getIncomingValue(!Idx);
+ // Step comes from the loop latch, start comes from the other incoming value.
+ int LatchIdx = Phi->getBasicBlockIndex(L.getLoopLatch());
+ Value *FoundStep = Phi->getIncomingValue(LatchIdx);
+ Value *FoundStart = Phi->getIncomingValue(!LatchIdx);
Instruction *TV, *FV;
if (!match(FoundStep,
m_Select(m_Cmp(), m_Instruction(TV), m_Instruction(FV))))
- continue;
+ return false;
// For a conditional recurrence, both the true and false values of the
// select must ultimately end up in the same recurrent BinOp.
@@ -316,8 +317,6 @@ bool RecurrenceInfo::matchConditionalRecurrence(
Start = FoundStart;
Step = FoundStep;
return true;
- }
- return false;
}
/// Iterates over all the phis in \p LoopLatch, and attempts to extract a
diff --git a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
index 4c0e51b67dd59..1f9bd52425455 100644
--- a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
+++ b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
@@ -337,8 +337,29 @@ exit: ; preds = %loop
define i16 @crc16.be.tc8.crc.init.select(i16 %a, i16 %b) {
; CHECK-LABEL: 'crc16.be.tc8.crc.init.select'
-; CHECK-NEXT: Did not find a hash algorithm
-; CHECK-NEXT: Reason: Unable to find conditional recurrence
+; CHECK-NEXT: Found big-endian CRC-16 loop with trip count 8
+; CHECK-NEXT: Initial CRC: %crc.init = select i1 %init.cond, i16 %a.inc, i16 %b.inc
+; CHECK-NEXT: Generating polynomial: 4129
+; CHECK-NEXT: Computed CRC: %crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
+; CHECK-NEXT: Computed CRC lookup table:
+; CHECK-NEXT: 0 4129 8258 12387 16516 20645 24774 28903 33032 37161 41290 45419 49548 53677 57806 61935
+; CHECK-NEXT: 4657 528 12915 8786 21173 17044 29431 25302 37689 33560 45947 41818 54205 50076 62463 58334
+; CHECK-NEXT: 9314 13379 1056 5121 25830 29895 17572 21637 42346 46411 34088 38153 58862 62927 50604 54669
+; CHECK-NEXT: 13907 9842 5649 1584 30423 26358 22165 18100 46939 42874 38681 34616 63455 59390 55197 51132
+; CHECK-NEXT: 18628 22757 26758 30887 2112 6241 10242 14371 51660 55789 59790 63919 35144 39273 43274 47403
+; CHECK-NEXT: 23285 19156 31415 27286 6769 2640 14899 10770 56317 52188 64447 60318 39801 35672 47931 43802
+; CHECK-NEXT: 27814 31879 19684 23749 11298 15363 3168 7233 60846 64911 52716 56781 44330 48395 36200 40265
+; CHECK-NEXT: 32407 28342 24277 20212 15891 11826 7761 3696 65439 61374 57309 53244 48923 44858 40793 36728
+; CHECK-NEXT: 37256 33193 45514 41451 53516 49453 61774 57711 4224 161 12482 8419 20484 16421 28742 24679
+; CHECK-NEXT: 33721 37784 41979 46042 49981 54044 58239 62302 689 4752 8947 13010 16949 21012 25207 29270
+; CHECK-NEXT: 46570 42443 38312 34185 62830 58703 54572 50445 13538 9411 5280 1153 29798 25671 21540 17413
+; CHECK-NEXT: 42971 47098 34713 38840 59231 63358 50973 55100 9939 14066 1681 5808 26199 30326 17941 22068
+; CHECK-NEXT: 55628 51565 63758 59695 39368 35305 47498 43435 22596 18533 30726 26663 6336 2273 14466 10403
+; CHECK-NEXT: 52093 56156 60223 64286 35833 39896 43963 48026 19061 23124 27191 31254 2801 6864 10931 14994
+; CHECK-NEXT: 64814 60687 56684 52557 48554 44427 40424 36297 31782 27655 23652 19525 15522 11395 7392 3265
+; CHECK-NEXT: 61215 65342 53085 57212 44955 49082 36825 40952 28183 32310 20053 24180 11923 16050 3793 7920
+; CHECK-NEXT: Computed CRC Barrett constants:
+; CHECK-NEXT: Mu = 273, FullGenPoly = 69665
;
entry:
%a.inc = add i16 %a, 1
>From ee013c36efc04c1978da7a2d4cefd82faf1e5721 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Mon, 27 Jul 2026 09:16:09 -0500
Subject: [PATCH 4/4] Add guard for invalid LatchIdx
---
llvm/lib/Analysis/HashRecognize.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp
index 7357c9c21a1f9..c2cb6c44763a2 100644
--- a/llvm/lib/Analysis/HashRecognize.cpp
+++ b/llvm/lib/Analysis/HashRecognize.cpp
@@ -292,6 +292,8 @@ bool RecurrenceInfo::matchConditionalRecurrence(
// Step comes from the loop latch, start comes from the other incoming value.
int LatchIdx = Phi->getBasicBlockIndex(L.getLoopLatch());
+ if (LatchIdx < 0)
+ return false;
Value *FoundStep = Phi->getIncomingValue(LatchIdx);
Value *FoundStart = Phi->getIncomingValue(!LatchIdx);
More information about the llvm-commits
mailing list