[llvm] a695d6b - [HashRecognize] Check TC against bitwidth of LHSAux (#144881)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 3 10:07:18 PDT 2025


Author: Ramkumar Ramachandra
Date: 2025-07-03T18:07:15+01:00
New Revision: a695d6b9a726d0059d9bf80341ee567c1153286c

URL: https://github.com/llvm/llvm-project/commit/a695d6b9a726d0059d9bf80341ee567c1153286c
DIFF: https://github.com/llvm/llvm-project/commit/a695d6b9a726d0059d9bf80341ee567c1153286c.diff

LOG: [HashRecognize] Check TC against bitwidth of LHSAux (#144881)

The trip-count of a CRC algorithm can legitimately be greater than the
bitwidth of the result: what it cannot exceed is the bitwidth of the
data, or LHSAux. crc8.le.tc16 is now successfully recognized as a CRC
algorithm.

Added: 
    

Modified: 
    llvm/lib/Analysis/HashRecognize.cpp
    llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp
index be295a6d86a5c..2cc3ad5f18482 100644
--- a/llvm/lib/Analysis/HashRecognize.cpp
+++ b/llvm/lib/Analysis/HashRecognize.cpp
@@ -247,16 +247,10 @@ KnownBits ValueEvolution::compute(const Value *V) {
 }
 
 bool ValueEvolution::computeEvolutions(ArrayRef<PhiStepPair> PhiEvolutions) {
-  for (unsigned I = 0; I < TripCount; ++I) {
-    for (auto [Phi, Step] : PhiEvolutions) {
-      KnownBits KnownAtIter = computeInstr(Step);
-      if (KnownAtIter.getBitWidth() < I + 1) {
-        ErrStr = "Loop iterations exceed bitwidth of result";
-        return false;
-      }
-      KnownPhis.emplace_or_assign(Phi, KnownAtIter);
-    }
-  }
+  for (unsigned I = 0; I < TripCount; ++I)
+    for (auto [Phi, Step] : PhiEvolutions)
+      KnownPhis.emplace_or_assign(Phi, computeInstr(Step));
+
   return ErrStr.empty();
 }
 
@@ -605,6 +599,13 @@ HashRecognize::recognizeCRC() const {
       return "Recurrences not intertwined with XOR";
   }
 
+  // Make sure that the TC doesn't exceed the bitwidth of LHSAux, or LHS.
+  Value *LHS = ConditionalRecurrence.Start;
+  Value *LHSAux = SimpleRecurrence ? SimpleRecurrence.Start : nullptr;
+  if (TC > (LHSAux ? LHSAux->getType()->getIntegerBitWidth()
+                   : LHS->getType()->getIntegerBitWidth()))
+    return "Loop iterations exceed bitwidth of data";
+
   // Make sure that the computed value is used in the exit block: this should be
   // true even if it is only really used in an outer loop's exit block, since
   // the loop is in LCSSA form.
@@ -633,13 +634,13 @@ HashRecognize::recognizeCRC() const {
     return VE.getError();
   KnownBits ResultBits = VE.KnownPhis.at(ConditionalRecurrence.Phi);
 
+  unsigned N = std::min(TC, ResultBits.getBitWidth());
   auto IsZero = [](const KnownBits &K) { return K.isZero(); };
-  if (!checkExtractBits(ResultBits, TC, IsZero, *ByteOrderSwapped))
+  if (!checkExtractBits(ResultBits, N, IsZero, *ByteOrderSwapped))
     return ErrBits(ResultBits, TC, *ByteOrderSwapped);
 
-  Value *LHSAux = SimpleRecurrence ? SimpleRecurrence.Start : nullptr;
-  return PolynomialInfo(TC, ConditionalRecurrence.Start, GenPoly, ComputedValue,
-                        *ByteOrderSwapped, LHSAux);
+  return PolynomialInfo(TC, LHS, GenPoly, ComputedValue, *ByteOrderSwapped,
+                        LHSAux);
 }
 
 void CRCTable::print(raw_ostream &OS) const {

diff  --git a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
index 88fd8bf3c2487..247a105940e6e 100644
--- a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
+++ b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
@@ -146,8 +146,28 @@ exit:                                              ; preds = %loop
 
 define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) {
 ; CHECK-LABEL: 'crc8.le.tc16'
-; CHECK-NEXT:  Did not find a hash algorithm
-; CHECK-NEXT:  Reason: Loop iterations exceed bitwidth of result
+; CHECK-NEXT:  Found little-endian CRC-8 loop with trip count 16
+; CHECK-NEXT:    Initial CRC: i8 %checksum
+; CHECK-NEXT:    Generating polynomial: 29
+; CHECK-NEXT:    Computed CRC: %crc.next = select i1 %check.sb, i8 %crc.lshr, i8 %crc.xor
+; CHECK-NEXT:    Auxiliary data: i16 %msg
+; CHECK-NEXT:    Computed CRC lookup table:
+; CHECK-NEXT:  0 9 18 27 31 22 13 4 5 12 23 30 26 19 8 1
+; CHECK-NEXT:  10 3 24 17 21 28 7 14 15 6 29 20 16 25 2 11
+; CHECK-NEXT:  20 29 6 15 11 2 25 16 17 24 3 10 14 7 28 21
+; CHECK-NEXT:  30 23 12 5 1 8 19 26 27 18 9 0 4 13 22 31
+; CHECK-NEXT:  19 26 1 8 12 5 30 23 22 31 4 13 9 0 27 18
+; CHECK-NEXT:  25 16 11 2 6 15 20 29 28 21 14 7 3 10 17 24
+; CHECK-NEXT:  7 14 21 28 24 17 10 3 2 11 16 25 29 20 15 6
+; CHECK-NEXT:  13 4 31 22 18 27 0 9 8 1 26 19 23 30 5 12
+; CHECK-NEXT:  29 20 15 6 2 11 16 25 24 17 10 3 7 14 21 28
+; CHECK-NEXT:  23 30 5 12 8 1 26 19 18 27 0 9 13 4 31 22
+; CHECK-NEXT:  9 0 27 18 22 31 4 13 12 5 30 23 19 26 1 8
+; CHECK-NEXT:  3 10 17 24 28 21 14 7 6 15 20 29 25 16 11 2
+; CHECK-NEXT:  14 7 28 21 17 24 3 10 11 2 25 16 20 29 6 15
+; CHECK-NEXT:  4 13 22 31 27 18 9 0 1 8 19 26 30 23 12 5
+; CHECK-NEXT:  26 19 8 1 5 12 23 30 31 22 13 4 0 9 18 27
+; CHECK-NEXT:  16 25 2 11 15 6 29 20 21 28 7 14 10 3 24 17
 ;
 entry:
   br label %loop
@@ -676,10 +696,10 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i16 @not.crc.excess.tc(i16 %msg, i16 %checksum) {
+define i16 @not.crc.excess.tc(i8 %msg, i16 %checksum) {
 ; CHECK-LABEL: 'not.crc.excess.tc'
 ; CHECK-NEXT:  Did not find a hash algorithm
-; CHECK-NEXT:  Reason: Loop iterations exceed bitwidth of result
+; CHECK-NEXT:  Reason: Loop iterations exceed bitwidth of data
 ;
 entry:
   br label %loop
@@ -687,16 +707,40 @@ entry:
 loop:                                              ; preds = %loop, %entry
   %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
   %crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
-  %data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
-  %xor.crc.data = xor i16 %crc, %data
-  %and.crc.data = and i16 %xor.crc.data, 1
-  %data.next = lshr i16 %data, 1
-  %check.sb = icmp eq i16 %and.crc.data, 0
+  %data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
+  %crc.trunc = trunc i16 %crc to i8
+  %xor.crc.data = xor i8 %crc.trunc, %data
+  %and.crc.data = and i8 %xor.crc.data, 1
+  %data.next = lshr i8 %data, 1
+  %check.sb = icmp eq i8 %and.crc.data, 0
   %crc.lshr = lshr i16 %crc, 1
   %crc.xor = xor i16 %crc.lshr, -24575
   %crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %crc.xor
   %iv.next = add nuw nsw i8 %iv, 1
-  %exit.cond = icmp samesign ult i8 %iv, 31
+  %exit.cond = icmp samesign ult i8 %iv, 15
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i16 %crc.next
+}
+
+define i16 @not.crc.init.arg.excess.tc(i16 %crc.init) {
+; CHECK-LABEL: 'not.crc.init.arg.excess.tc'
+; CHECK-NEXT:  Did not find a hash algorithm
+; CHECK-NEXT:  Reason: Loop iterations exceed bitwidth of data
+;
+entry:
+  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, 31
   br i1 %exit.cond, label %loop, label %exit
 
 exit:                                              ; preds = %loop


        


More information about the llvm-commits mailing list