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 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