[llvm] [LoopIdiom] Use HashRecognize to optimize CRC (PR #143208)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Sun Jun 8 03:21:18 PDT 2025


https://github.com/artagnon updated https://github.com/llvm/llvm-project/pull/143208

>From 966d3a12ebe5e41fe5410718f1f8e318ce22d885 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Fri, 6 Jun 2025 16:50:57 +0100
Subject: [PATCH 1/2] [LoopIdiom] Use HashRecognize to optimize CRC

---
 llvm/include/llvm/Analysis/HashRecognize.h    |  12 +-
 .../Transforms/Scalar/LoopIdiomRecognize.h    |   3 +
 llvm/lib/Analysis/HashRecognize.cpp           |  10 +-
 .../Transforms/Scalar/LoopIdiomRecognize.cpp  | 140 ++++++-
 .../LoopIdiom/cyclic-redundancy-check.ll      | 388 ++++++++++++++++++
 5 files changed, 538 insertions(+), 15 deletions(-)
 create mode 100644 llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll

diff --git a/llvm/include/llvm/Analysis/HashRecognize.h b/llvm/include/llvm/Analysis/HashRecognize.h
index 8ab68a5dc2cb1..c169383bf7b08 100644
--- a/llvm/include/llvm/Analysis/HashRecognize.h
+++ b/llvm/include/llvm/Analysis/HashRecognize.h
@@ -53,7 +53,7 @@ struct PolynomialInfo {
   // division in the case of CRC. Since polynomial division is an XOR in
   // GF(2^m), this variable must be XOR'ed with RHS in a loop to yield the
   // ComputedValue.
-  const Value *LHS;
+  Value *LHS;
 
   // The generating polynomial, or the RHS of the polynomial division in the
   // case of CRC.
@@ -61,7 +61,7 @@ struct PolynomialInfo {
 
   // The final computed value. This is a remainder of a polynomial division in
   // the case of CRC, which must be zero.
-  const Value *ComputedValue;
+  Value *ComputedValue;
 
   // Set to true in the case of big-endian.
   bool ByteOrderSwapped;
@@ -69,11 +69,11 @@ struct PolynomialInfo {
   // An optional auxiliary checksum that augments the LHS. In the case of CRC,
   // it is XOR'ed with the LHS, so that the computation's final remainder is
   // zero.
-  const Value *LHSAux;
+  Value *LHSAux;
 
-  PolynomialInfo(unsigned TripCount, const Value *LHS, const APInt &RHS,
-                 const Value *ComputedValue, bool ByteOrderSwapped,
-                 const Value *LHSAux = nullptr);
+  PolynomialInfo(unsigned TripCount, Value *LHS, const APInt &RHS,
+                 Value *ComputedValue, bool ByteOrderSwapped,
+                 Value *LHSAux = nullptr);
 };
 
 /// The analysis.
diff --git a/llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h b/llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
index 241a3fc109360..109b4520878cb 100644
--- a/llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
+++ b/llvm/include/llvm/Transforms/Scalar/LoopIdiomRecognize.h
@@ -40,6 +40,9 @@ struct DisableLIRP {
 
   /// When true, Wcslen is disabled.
   static bool Wcslen;
+
+  /// When true, HashRecognize is disabled.
+  static bool HashRecognize;
 };
 
 /// Performs Loop Idiom Recognize Pass.
diff --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp
index b245548dea6d5..92c1191bd71b1 100644
--- a/llvm/lib/Analysis/HashRecognize.cpp
+++ b/llvm/lib/Analysis/HashRecognize.cpp
@@ -442,9 +442,9 @@ getRecurrences(BasicBlock *LoopLatch, const PHINode *IndVar, const Loop &L) {
   return std::make_pair(SimpleRecurrence, ConditionalRecurrence);
 }
 
-PolynomialInfo::PolynomialInfo(unsigned TripCount, const Value *LHS,
-                               const APInt &RHS, const Value *ComputedValue,
-                               bool ByteOrderSwapped, const Value *LHSAux)
+PolynomialInfo::PolynomialInfo(unsigned TripCount, Value *LHS, const APInt &RHS,
+                               Value *ComputedValue, bool ByteOrderSwapped,
+                               Value *LHSAux)
     : TripCount(TripCount), LHS(LHS), RHS(RHS), ComputedValue(ComputedValue),
       ByteOrderSwapped(ByteOrderSwapped), LHSAux(LHSAux) {}
 
@@ -563,7 +563,7 @@ HashRecognize::recognizeCRC() const {
   BasicBlock *Latch = L.getLoopLatch();
   BasicBlock *Exit = L.getExitBlock();
   const PHINode *IndVar = L.getCanonicalInductionVariable();
-  if (!Latch || !Exit || !IndVar)
+  if (!Latch || !Exit || !IndVar || L.getNumBlocks() != 1)
     return "Loop not in canonical form";
 
   auto R = getRecurrences(Latch, IndVar, L);
@@ -620,7 +620,7 @@ HashRecognize::recognizeCRC() const {
   if (!checkExtractBits(ResultBits, TC, IsZero, *ByteOrderSwapped))
     return ErrBits(ResultBits, TC, *ByteOrderSwapped);
 
-  const Value *LHSAux = SimpleRecurrence ? SimpleRecurrence.Start : nullptr;
+  Value *LHSAux = SimpleRecurrence ? SimpleRecurrence.Start : nullptr;
   return PolynomialInfo(TC, ConditionalRecurrence.Start, GenPoly, ComputedValue,
                         *ByteOrderSwapped, LHSAux);
 }
diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index 0967e90e24c5f..756836e1db686 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -39,6 +39,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Analysis/AliasAnalysis.h"
 #include "llvm/Analysis/CmpInstAnalysis.h"
+#include "llvm/Analysis/HashRecognize.h"
 #include "llvm/Analysis/LoopInfo.h"
 #include "llvm/Analysis/LoopPass.h"
 #include "llvm/Analysis/MemoryLocation.h"
@@ -144,6 +145,14 @@ static cl::opt<bool, true>
                      cl::location(DisableLIRP::Wcslen), cl::init(false),
                      cl::ReallyHidden);
 
+bool DisableLIRP::HashRecognize;
+static cl::opt<bool, true> DisableLIRPHashRecognize(
+    "disable-" DEBUG_TYPE "-hashrecognize",
+    cl::desc("Proceed with loop idiom recognize pass, "
+             "enable conversion of loop(s) to wcslen."),
+    cl::location(DisableLIRP::HashRecognize), cl::init(false),
+    cl::ReallyHidden);
+
 static cl::opt<bool> UseLIRCodeSizeHeurs(
     "use-lir-code-size-heurs",
     cl::desc("Use loop idiom recognition code size heuristics when compiling "
@@ -158,6 +167,7 @@ class LoopIdiomRecognize {
   DominatorTree *DT;
   LoopInfo *LI;
   ScalarEvolution *SE;
+  const HashRecognize *HR;
   TargetLibraryInfo *TLI;
   const TargetTransformInfo *TTI;
   const DataLayout *DL;
@@ -168,11 +178,12 @@ class LoopIdiomRecognize {
 public:
   explicit LoopIdiomRecognize(AliasAnalysis *AA, DominatorTree *DT,
                               LoopInfo *LI, ScalarEvolution *SE,
-                              TargetLibraryInfo *TLI,
+                              const HashRecognize *HR, TargetLibraryInfo *TLI,
                               const TargetTransformInfo *TTI, MemorySSA *MSSA,
                               const DataLayout *DL,
                               OptimizationRemarkEmitter &ORE)
-      : AA(AA), DT(DT), LI(LI), SE(SE), TLI(TLI), TTI(TTI), DL(DL), ORE(ORE) {
+      : AA(AA), DT(DT), LI(LI), SE(SE), HR(HR), TLI(TLI), TTI(TTI), DL(DL),
+        ORE(ORE) {
     if (MSSA)
       MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
   }
@@ -238,6 +249,7 @@ class LoopIdiomRecognize {
                                   const SCEV *BECount);
   bool avoidLIRForMultiBlockLoop(bool IsMemset = false,
                                  bool IsLoopMemset = false);
+  bool optimizeCRCLoop(const PolynomialInfo &Info);
 
   /// @}
   /// \name Noncountable Loop Idiom Handling
@@ -283,7 +295,9 @@ PreservedAnalyses LoopIdiomRecognizePass::run(Loop &L, LoopAnalysisManager &AM,
   // but ORE cannot be preserved (see comment before the pass definition).
   OptimizationRemarkEmitter ORE(L.getHeader()->getParent());
 
-  LoopIdiomRecognize LIR(&AR.AA, &AR.DT, &AR.LI, &AR.SE, &AR.TLI, &AR.TTI,
+  const HashRecognize &HR = AM.getResult<HashRecognizeAnalysis>(L, AR);
+
+  LoopIdiomRecognize LIR(&AR.AA, &AR.DT, &AR.LI, &AR.SE, &HR, &AR.TLI, &AR.TTI,
                          AR.MSSA, DL, ORE);
   if (!LIR.runOnLoop(&L))
     return PreservedAnalyses::all();
@@ -326,7 +340,7 @@ bool LoopIdiomRecognize::runOnLoop(Loop *L) {
   HasMemsetPattern = TLI->has(LibFunc_memset_pattern16);
   HasMemcpy = TLI->has(LibFunc_memcpy);
 
-  if (HasMemset || HasMemsetPattern || HasMemcpy)
+  if (HasMemset || HasMemsetPattern || HasMemcpy || !DisableLIRP::HashRecognize)
     if (SE->hasLoopInvariantBackedgeTakenCount(L))
       return runOnCountableLoop();
 
@@ -369,6 +383,13 @@ bool LoopIdiomRecognize::runOnCountableLoop() {
 
     MadeChange |= runOnLoopBlock(BB, BECount, ExitBlocks);
   }
+
+  if (!DisableLIRP::HashRecognize) {
+    auto Result = HR->recognizeCRC();
+    if (std::holds_alternative<PolynomialInfo>(Result))
+      MadeChange |= optimizeCRCLoop(std::get<PolynomialInfo>(Result));
+  }
+
   return MadeChange;
 }
 
@@ -1473,6 +1494,117 @@ bool LoopIdiomRecognize::avoidLIRForMultiBlockLoop(bool IsMemset,
   return false;
 }
 
+bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
+  // We currently only optimize CRC loops with TC a multiple of 8 with a table
+  // lookup: the table-lookup can be improved using target-specific
+  // instructions.
+  if (Info.TripCount % 8 != 0)
+    return false;
+
+  // First, create a new GlobalVariable corresponding to the
+  // Sarwate-lookup-table.
+  Type *CRCTy = Info.LHS->getType();
+  unsigned CRCBW = CRCTy->getIntegerBitWidth();
+  const APInt &GenPoly = Info.RHS;
+  std::array<APInt, 256> CRCTable =
+      HR->genSarwateTable(GenPoly, Info.ByteOrderSwapped);
+  std::array<Constant *, 256> CRCConstants;
+  transform(CRCTable, CRCConstants.begin(),
+            [CRCTy](const APInt &E) { return ConstantInt::get(CRCTy, E); });
+  Constant *ConstArray =
+      ConstantArray::get(ArrayType::get(CRCTy, 256), CRCConstants);
+  Module &M = *CurLoop->getHeader()->getModule();
+  GlobalVariable *GV =
+      new GlobalVariable(M, ConstArray->getType(), true,
+                         GlobalValue::PrivateLinkage, ConstArray, ".crctable");
+
+  PHINode *IV = CurLoop->getCanonicalInductionVariable();
+  Type *IVTy = IV->getType();
+  SmallVector<PHINode *, 2> Cleanup;
+
+  // Next, mark all PHIs for removal except IV.
+  {
+    for (PHINode &PN : CurLoop->getHeader()->phis()) {
+      if (&PN == IV)
+        continue;
+      PN.replaceAllUsesWith(PoisonValue::get(PN.getType()));
+      Cleanup.push_back(&PN);
+    }
+  }
+
+  // Next, fix up the trip count.
+  {
+    unsigned NewBTC = (Info.TripCount / 8) - 1;
+    BasicBlock *LoopBlk = CurLoop->getLoopLatch();
+    BranchInst *BrInst = cast<BranchInst>(LoopBlk->getTerminator());
+    CmpPredicate ExitPred = BrInst->getSuccessor(0) == LoopBlk
+                                ? ICmpInst::Predicate::ICMP_ULT
+                                : ICmpInst::Predicate::ICMP_EQ;
+    Instruction *ExitCond = CurLoop->getLatchCmpInst();
+    IRBuilder<> Builder(ExitCond);
+    Value *NewExitCond = Builder.CreateICmp(
+        ExitPred, IV, ConstantInt::get(IVTy, NewBTC), "exit.cond");
+    ExitCond->replaceAllUsesWith(NewExitCond);
+    deleteDeadInstruction(ExitCond);
+  }
+
+  // Finally, fill the loop with the Sarwate-table-lookup logic, and replace all
+  // uses of ComputedValue.
+  //
+  // Little-endian:
+  //   crc = (crc >> 8) ^ tbl[data[iv] ^ (crc & 0xFF)]
+  // Big-Endian:
+  //   crc = (crc << 8) ^ tbl[data[iv] ^ (crc >> (crc.bw - 8))]
+  {
+    // Compute the top 8 bits of Op.
+    auto GetHiByte = [CRCBW](IRBuilderBase &Builder, Value *Op,
+                             StringRef Name) {
+      return Builder.CreateAShr(Op, ConstantInt::get(Op->getType(), CRCBW - 8),
+                                Name);
+    };
+
+    Constant *AllOnes = ConstantInt::get(CRCTy, APInt::getAllOnes(CRCBW));
+    Constant *LoByteMask = ConstantInt::get(CRCTy, 0xFF);
+    IRBuilder<> Builder(CurLoop->getHeader(),
+                        CurLoop->getHeader()->getFirstNonPHIIt());
+    Value *CRC = Info.LHSAux ? AllOnes : Info.LHS;
+    if (Info.LHSAux) {
+      // Compute Info.LHSAux[iv], when Info.LHSAux is an integer.
+      Value *IVLo = Builder.CreateZExtOrTrunc(
+          Builder.CreateMul(IV, ConstantInt::get(IVTy, 8), "iv.bits"),
+          Info.LHSAux->getType(), "iv.indexer");
+      Value *DataIndexer = GetHiByte(
+          Builder, Builder.CreateShl(Info.LHSAux, IVLo, "data.lo.indexer"),
+          "data.hi.indexer");
+      CRC = Builder.CreateXor(
+          CRC, Builder.CreateZExtOrTrunc(DataIndexer, CRCTy, "data.indexer"),
+          "xor.crc.data");
+    }
+    Value *CRCShift = Info.ByteOrderSwapped
+                          ? Builder.CreateShl(CRC, LoByteMask, "crc.be.shift")
+                          : Builder.CreateAShr(CRC, LoByteMask, "crc.le.shift");
+
+    // Compute either top 8 or bottom 8 bits of CRC.
+    Value *CRCIndexer = Info.ByteOrderSwapped
+                            ? GetHiByte(Builder, CRC, "crc.hi.indexer")
+                            : Builder.CreateAnd(CRC, LoByteMask, "crc.indexer");
+    Value *CRCTableGEP = Builder.CreatePtrAdd(GV, CRCIndexer, "crc.tbl.indexer",
+                                              GEPNoWrapFlags::inBounds());
+    Value *CRCTableLd = Builder.CreateLoad(CRCTy, CRCTableGEP, "crc.tbl.index");
+    CRC = Builder.CreateXor(CRCShift, CRCTableLd, "xor.crcshift.tbl");
+    CRC = Info.LHSAux ? Builder.CreateXor(CRC, AllOnes, "finalize.crc") : CRC;
+    Info.ComputedValue->replaceUsesOutsideBlock(CRC, CurLoop->getLoopLatch());
+  }
+
+  // Cleanup.
+  {
+    for (PHINode *PN : Cleanup)
+      RecursivelyDeleteDeadPHINode(PN);
+    SE->forgetLoop(CurLoop);
+  }
+  return true;
+}
+
 bool LoopIdiomRecognize::runOnNoncountableLoop() {
   LLVM_DEBUG(dbgs() << DEBUG_TYPE " Scanning: F["
                     << CurLoop->getHeader()->getParent()->getName()
diff --git a/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll
new file mode 100644
index 0000000000000..143813ab2bf70
--- /dev/null
+++ b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll
@@ -0,0 +1,388 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
+; RUN: opt -passes=loop-idiom < %s -S | FileCheck %s
+
+;.
+; CHECK: @.crctable = private constant [256 x i16] [i16 0, i16 -16191, i16 -15999, i16 320, i16 -15615, i16 960, i16 640, i16 -15807, i16 -14847, i16 1728, i16 1920, i16 -14527, i16 1280, i16 -14911, i16 -15231, i16 1088, i16 -13311, i16 3264, i16 3456, i16 -12991, i16 3840, i16 -12351, i16 -12671, i16 3648, i16 2560, i16 -13631, i16 -13439, i16 2880, i16 -14079, i16 2496, i16 2176, i16 -14271, i16 -10239, i16 6336, i16 6528, i16 -9919, i16 6912, i16 -9279, i16 -9599, i16 6720, i16 7680, i16 -8511, i16 -8319, i16 8000, i16 -8959, i16 7616, i16 7296, i16 -9151, i16 5120, i16 -11071, i16 -10879, i16 5440, i16 -10495, i16 6080, i16 5760, i16 -10687, i16 -11775, i16 4800, i16 4992, i16 -11455, i16 4352, i16 -11839, i16 -12159, i16 4160, i16 -4095, i16 12480, i16 12672, i16 -3775, i16 13056, i16 -3135, i16 -3455, i16 12864, i16 13824, i16 -2367, i16 -2175, i16 14144, i16 -2815, i16 13760, i16 13440, i16 -3007, i16 15360, i16 -831, i16 -639, i16 15680, i16 -255, i16 16320, i16 16000, i16 -447, i16 -1535, i16 15040, i16 15232, i16 -1215, i16 14592, i16 -1599, i16 -1919, i16 14400, i16 10240, i16 -5951, i16 -5759, i16 10560, i16 -5375, i16 11200, i16 10880, i16 -5567, i16 -4607, i16 11968, i16 12160, i16 -4287, i16 11520, i16 -4671, i16 -4991, i16 11328, i16 -7167, i16 9408, i16 9600, i16 -6847, i16 9984, i16 -6207, i16 -6527, i16 9792, i16 8704, i16 -7487, i16 -7295, i16 9024, i16 -7935, i16 8640, i16 8320, i16 -8127, i16 -24575, i16 24768, i16 24960, i16 -24255, i16 25344, i16 -23615, i16 -23935, i16 25152, i16 26112, i16 -22847, i16 -22655, i16 26432, i16 -23295, i16 26048, i16 25728, i16 -23487, i16 27648, i16 -21311, i16 -21119, i16 27968, i16 -20735, i16 28608, i16 28288, i16 -20927, i16 -22015, i16 27328, i16 27520, i16 -21695, i16 26880, i16 -22079, i16 -22399, i16 26688, i16 30720, i16 -18239, i16 -18047, i16 31040, i16 -17663, i16 31680, i16 31360, i16 -17855, i16 -16895, i16 32448, i16 32640, i16 -16575, i16 32000, i16 -16959, i16 -17279, i16 31808, i16 -19455, i16 29888, i16 30080, i16 -19135, i16 30464, i16 -18495, i16 -18815, i16 30272, i16 29184, i16 -19775, i16 -19583, i16 29504, i16 -20223, i16 29120, i16 28800, i16 -20415, i16 20480, i16 -28479, i16 -28287, i16 20800, i16 -27903, i16 21440, i16 21120, i16 -28095, i16 -27135, i16 22208, i16 22400, i16 -26815, i16 21760, i16 -27199, i16 -27519, i16 21568, i16 -25599, i16 23744, i16 23936, i16 -25279, i16 24320, i16 -24639, i16 -24959, i16 24128, i16 23040, i16 -25919, i16 -25727, i16 23360, i16 -26367, i16 22976, i16 22656, i16 -26559, i16 -30719, i16 18624, i16 18816, i16 -30399, i16 19200, i16 -29759, i16 -30079, i16 19008, i16 19968, i16 -28991, i16 -28799, i16 20288, i16 -29439, i16 19904, i16 19584, i16 -29631, i16 17408, i16 -31551, i16 -31359, i16 17728, i16 -30975, i16 18368, i16 18048, i16 -31167, i16 -32255, i16 17088, i16 17280, i16 -31935, i16 16640, i16 -32319, i16 -32639, i16 16448]
+; CHECK: @.crctable.1 = private constant [256 x i16] [i16 0, i16 -16191, i16 -15999, i16 320, i16 -15615, i16 960, i16 640, i16 -15807, i16 -14847, i16 1728, i16 1920, i16 -14527, i16 1280, i16 -14911, i16 -15231, i16 1088, i16 -13311, i16 3264, i16 3456, i16 -12991, i16 3840, i16 -12351, i16 -12671, i16 3648, i16 2560, i16 -13631, i16 -13439, i16 2880, i16 -14079, i16 2496, i16 2176, i16 -14271, i16 -10239, i16 6336, i16 6528, i16 -9919, i16 6912, i16 -9279, i16 -9599, i16 6720, i16 7680, i16 -8511, i16 -8319, i16 8000, i16 -8959, i16 7616, i16 7296, i16 -9151, i16 5120, i16 -11071, i16 -10879, i16 5440, i16 -10495, i16 6080, i16 5760, i16 -10687, i16 -11775, i16 4800, i16 4992, i16 -11455, i16 4352, i16 -11839, i16 -12159, i16 4160, i16 -4095, i16 12480, i16 12672, i16 -3775, i16 13056, i16 -3135, i16 -3455, i16 12864, i16 13824, i16 -2367, i16 -2175, i16 14144, i16 -2815, i16 13760, i16 13440, i16 -3007, i16 15360, i16 -831, i16 -639, i16 15680, i16 -255, i16 16320, i16 16000, i16 -447, i16 -1535, i16 15040, i16 15232, i16 -1215, i16 14592, i16 -1599, i16 -1919, i16 14400, i16 10240, i16 -5951, i16 -5759, i16 10560, i16 -5375, i16 11200, i16 10880, i16 -5567, i16 -4607, i16 11968, i16 12160, i16 -4287, i16 11520, i16 -4671, i16 -4991, i16 11328, i16 -7167, i16 9408, i16 9600, i16 -6847, i16 9984, i16 -6207, i16 -6527, i16 9792, i16 8704, i16 -7487, i16 -7295, i16 9024, i16 -7935, i16 8640, i16 8320, i16 -8127, i16 -24575, i16 24768, i16 24960, i16 -24255, i16 25344, i16 -23615, i16 -23935, i16 25152, i16 26112, i16 -22847, i16 -22655, i16 26432, i16 -23295, i16 26048, i16 25728, i16 -23487, i16 27648, i16 -21311, i16 -21119, i16 27968, i16 -20735, i16 28608, i16 28288, i16 -20927, i16 -22015, i16 27328, i16 27520, i16 -21695, i16 26880, i16 -22079, i16 -22399, i16 26688, i16 30720, i16 -18239, i16 -18047, i16 31040, i16 -17663, i16 31680, i16 31360, i16 -17855, i16 -16895, i16 32448, i16 32640, i16 -16575, i16 32000, i16 -16959, i16 -17279, i16 31808, i16 -19455, i16 29888, i16 30080, i16 -19135, i16 30464, i16 -18495, i16 -18815, i16 30272, i16 29184, i16 -19775, i16 -19583, i16 29504, i16 -20223, i16 29120, i16 28800, i16 -20415, i16 20480, i16 -28479, i16 -28287, i16 20800, i16 -27903, i16 21440, i16 21120, i16 -28095, i16 -27135, i16 22208, i16 22400, i16 -26815, i16 21760, i16 -27199, i16 -27519, i16 21568, i16 -25599, i16 23744, i16 23936, i16 -25279, i16 24320, i16 -24639, i16 -24959, i16 24128, i16 23040, i16 -25919, i16 -25727, i16 23360, i16 -26367, i16 22976, i16 22656, i16 -26559, i16 -30719, i16 18624, i16 18816, i16 -30399, i16 19200, i16 -29759, i16 -30079, i16 19008, i16 19968, i16 -28991, i16 -28799, i16 20288, i16 -29439, i16 19904, i16 19584, i16 -29631, i16 17408, i16 -31551, i16 -31359, i16 17728, i16 -30975, i16 18368, i16 18048, i16 -31167, i16 -32255, i16 17088, i16 17280, i16 -31935, i16 16640, i16 -32319, i16 -32639, i16 16448]
+; CHECK: @.crctable.2 = private constant [256 x i16] [i16 0, i16 -16191, i16 -15999, i16 320, i16 -15615, i16 960, i16 640, i16 -15807, i16 -14847, i16 1728, i16 1920, i16 -14527, i16 1280, i16 -14911, i16 -15231, i16 1088, i16 -13311, i16 3264, i16 3456, i16 -12991, i16 3840, i16 -12351, i16 -12671, i16 3648, i16 2560, i16 -13631, i16 -13439, i16 2880, i16 -14079, i16 2496, i16 2176, i16 -14271, i16 -10239, i16 6336, i16 6528, i16 -9919, i16 6912, i16 -9279, i16 -9599, i16 6720, i16 7680, i16 -8511, i16 -8319, i16 8000, i16 -8959, i16 7616, i16 7296, i16 -9151, i16 5120, i16 -11071, i16 -10879, i16 5440, i16 -10495, i16 6080, i16 5760, i16 -10687, i16 -11775, i16 4800, i16 4992, i16 -11455, i16 4352, i16 -11839, i16 -12159, i16 4160, i16 -4095, i16 12480, i16 12672, i16 -3775, i16 13056, i16 -3135, i16 -3455, i16 12864, i16 13824, i16 -2367, i16 -2175, i16 14144, i16 -2815, i16 13760, i16 13440, i16 -3007, i16 15360, i16 -831, i16 -639, i16 15680, i16 -255, i16 16320, i16 16000, i16 -447, i16 -1535, i16 15040, i16 15232, i16 -1215, i16 14592, i16 -1599, i16 -1919, i16 14400, i16 10240, i16 -5951, i16 -5759, i16 10560, i16 -5375, i16 11200, i16 10880, i16 -5567, i16 -4607, i16 11968, i16 12160, i16 -4287, i16 11520, i16 -4671, i16 -4991, i16 11328, i16 -7167, i16 9408, i16 9600, i16 -6847, i16 9984, i16 -6207, i16 -6527, i16 9792, i16 8704, i16 -7487, i16 -7295, i16 9024, i16 -7935, i16 8640, i16 8320, i16 -8127, i16 -24575, i16 24768, i16 24960, i16 -24255, i16 25344, i16 -23615, i16 -23935, i16 25152, i16 26112, i16 -22847, i16 -22655, i16 26432, i16 -23295, i16 26048, i16 25728, i16 -23487, i16 27648, i16 -21311, i16 -21119, i16 27968, i16 -20735, i16 28608, i16 28288, i16 -20927, i16 -22015, i16 27328, i16 27520, i16 -21695, i16 26880, i16 -22079, i16 -22399, i16 26688, i16 30720, i16 -18239, i16 -18047, i16 31040, i16 -17663, i16 31680, i16 31360, i16 -17855, i16 -16895, i16 32448, i16 32640, i16 -16575, i16 32000, i16 -16959, i16 -17279, i16 31808, i16 -19455, i16 29888, i16 30080, i16 -19135, i16 30464, i16 -18495, i16 -18815, i16 30272, i16 29184, i16 -19775, i16 -19583, i16 29504, i16 -20223, i16 29120, i16 28800, i16 -20415, i16 20480, i16 -28479, i16 -28287, i16 20800, i16 -27903, i16 21440, i16 21120, i16 -28095, i16 -27135, i16 22208, i16 22400, i16 -26815, i16 21760, i16 -27199, i16 -27519, i16 21568, i16 -25599, i16 23744, i16 23936, i16 -25279, i16 24320, i16 -24639, i16 -24959, i16 24128, i16 23040, i16 -25919, i16 -25727, i16 23360, i16 -26367, i16 22976, i16 22656, i16 -26559, i16 -30719, i16 18624, i16 18816, i16 -30399, i16 19200, i16 -29759, i16 -30079, i16 19008, i16 19968, i16 -28991, i16 -28799, i16 20288, i16 -29439, i16 19904, i16 19584, i16 -29631, i16 17408, i16 -31551, i16 -31359, i16 17728, i16 -30975, i16 18368, i16 18048, i16 -31167, i16 -32255, i16 17088, i16 17280, i16 -31935, i16 16640, i16 -32319, i16 -32639, i16 16448]
+; CHECK: @.crctable.3 = private constant [256 x i16] [i16 0, i16 256, i16 512, i16 768, i16 1024, i16 1280, i16 1536, i16 1792, i16 2048, i16 2304, i16 2560, i16 2816, i16 3072, i16 3328, i16 3584, i16 3840, i16 4096, i16 4352, i16 4608, i16 4864, i16 5120, i16 5376, i16 5632, i16 5888, i16 6144, i16 6400, i16 6656, i16 6912, i16 7168, i16 7424, i16 7680, i16 7936, i16 8192, i16 8448, i16 8704, i16 8960, i16 9216, i16 9472, i16 9728, i16 9984, i16 10240, i16 10496, i16 10752, i16 11008, i16 11264, i16 11520, i16 11776, i16 12032, i16 12288, i16 12544, i16 12800, i16 13056, i16 13312, i16 13568, i16 13824, i16 14080, i16 14336, i16 14592, i16 14848, i16 15104, i16 15360, i16 15616, i16 15872, i16 16128, i16 16384, i16 16640, i16 16896, i16 17152, i16 17408, i16 17664, i16 17920, i16 18176, i16 18432, i16 18688, i16 18944, i16 19200, i16 19456, i16 19712, i16 19968, i16 20224, i16 20480, i16 20736, i16 20992, i16 21248, i16 21504, i16 21760, i16 22016, i16 22272, i16 22528, i16 22784, i16 23040, i16 23296, i16 23552, i16 23808, i16 24064, i16 24320, i16 24576, i16 24832, i16 25088, i16 25344, i16 25600, i16 25856, i16 26112, i16 26368, i16 26624, i16 26880, i16 27136, i16 27392, i16 27648, i16 27904, i16 28160, i16 28416, i16 28672, i16 28928, i16 29184, i16 29440, i16 29696, i16 29952, i16 30208, i16 30464, i16 30720, i16 30976, i16 31232, i16 31488, i16 31744, i16 32000, i16 32256, i16 32512, i16 -32768, i16 -32512, i16 -32256, i16 -32000, i16 -31744, i16 -31488, i16 -31232, i16 -30976, i16 -30720, i16 -30464, i16 -30208, i16 -29952, i16 -29696, i16 -29440, i16 -29184, i16 -28928, i16 -28672, i16 -28416, i16 -28160, i16 -27904, i16 -27648, i16 -27392, i16 -27136, i16 -26880, i16 -26624, i16 -26368, i16 -26112, i16 -25856, i16 -25600, i16 -25344, i16 -25088, i16 -24832, i16 -24576, i16 -24320, i16 -24064, i16 -23808, i16 -23552, i16 -23296, i16 -23040, i16 -22784, i16 -22528, i16 -22272, i16 -22016, i16 -21760, i16 -21504, i16 -21248, i16 -20992, i16 -20736, i16 -20480, i16 -20224, i16 -19968, i16 -19712, i16 -19456, i16 -19200, i16 -18944, i16 -18688, i16 -18432, i16 -18176, i16 -17920, i16 -17664, i16 -17408, i16 -17152, i16 -16896, i16 -16640, i16 -16384, i16 -16128, i16 -15872, i16 -15616, i16 -15360, i16 -15104, i16 -14848, i16 -14592, i16 -14336, i16 -14080, i16 -13824, i16 -13568, i16 -13312, i16 -13056, i16 -12800, i16 -12544, i16 -12288, i16 -12032, i16 -11776, i16 -11520, i16 -11264, i16 -11008, i16 -10752, i16 -10496, i16 -10240, i16 -9984, i16 -9728, i16 -9472, i16 -9216, i16 -8960, i16 -8704, i16 -8448, i16 -8192, i16 -7936, i16 -7680, i16 -7424, i16 -7168, i16 -6912, i16 -6656, i16 -6400, i16 -6144, i16 -5888, i16 -5632, i16 -5376, i16 -5120, i16 -4864, i16 -4608, i16 -4352, i16 -4096, i16 -3840, i16 -3584, i16 -3328, i16 -3072, i16 -2816, i16 -2560, i16 -2304, i16 -2048, i16 -1792, i16 -1536, i16 -1280, i16 -1024, i16 -768, i16 -512, i16 -256]
+; CHECK: @.crctable.4 = private constant [256 x i16] [i16 0, i16 256, i16 512, i16 768, i16 1024, i16 1280, i16 1536, i16 1792, i16 2048, i16 2304, i16 2560, i16 2816, i16 3072, i16 3328, i16 3584, i16 3840, i16 4096, i16 4352, i16 4608, i16 4864, i16 5120, i16 5376, i16 5632, i16 5888, i16 6144, i16 6400, i16 6656, i16 6912, i16 7168, i16 7424, i16 7680, i16 7936, i16 8192, i16 8448, i16 8704, i16 8960, i16 9216, i16 9472, i16 9728, i16 9984, i16 10240, i16 10496, i16 10752, i16 11008, i16 11264, i16 11520, i16 11776, i16 12032, i16 12288, i16 12544, i16 12800, i16 13056, i16 13312, i16 13568, i16 13824, i16 14080, i16 14336, i16 14592, i16 14848, i16 15104, i16 15360, i16 15616, i16 15872, i16 16128, i16 16384, i16 16640, i16 16896, i16 17152, i16 17408, i16 17664, i16 17920, i16 18176, i16 18432, i16 18688, i16 18944, i16 19200, i16 19456, i16 19712, i16 19968, i16 20224, i16 20480, i16 20736, i16 20992, i16 21248, i16 21504, i16 21760, i16 22016, i16 22272, i16 22528, i16 22784, i16 23040, i16 23296, i16 23552, i16 23808, i16 24064, i16 24320, i16 24576, i16 24832, i16 25088, i16 25344, i16 25600, i16 25856, i16 26112, i16 26368, i16 26624, i16 26880, i16 27136, i16 27392, i16 27648, i16 27904, i16 28160, i16 28416, i16 28672, i16 28928, i16 29184, i16 29440, i16 29696, i16 29952, i16 30208, i16 30464, i16 30720, i16 30976, i16 31232, i16 31488, i16 31744, i16 32000, i16 32256, i16 32512, i16 -32768, i16 -32512, i16 -32256, i16 -32000, i16 -31744, i16 -31488, i16 -31232, i16 -30976, i16 -30720, i16 -30464, i16 -30208, i16 -29952, i16 -29696, i16 -29440, i16 -29184, i16 -28928, i16 -28672, i16 -28416, i16 -28160, i16 -27904, i16 -27648, i16 -27392, i16 -27136, i16 -26880, i16 -26624, i16 -26368, i16 -26112, i16 -25856, i16 -25600, i16 -25344, i16 -25088, i16 -24832, i16 -24576, i16 -24320, i16 -24064, i16 -23808, i16 -23552, i16 -23296, i16 -23040, i16 -22784, i16 -22528, i16 -22272, i16 -22016, i16 -21760, i16 -21504, i16 -21248, i16 -20992, i16 -20736, i16 -20480, i16 -20224, i16 -19968, i16 -19712, i16 -19456, i16 -19200, i16 -18944, i16 -18688, i16 -18432, i16 -18176, i16 -17920, i16 -17664, i16 -17408, i16 -17152, i16 -16896, i16 -16640, i16 -16384, i16 -16128, i16 -15872, i16 -15616, i16 -15360, i16 -15104, i16 -14848, i16 -14592, i16 -14336, i16 -14080, i16 -13824, i16 -13568, i16 -13312, i16 -13056, i16 -12800, i16 -12544, i16 -12288, i16 -12032, i16 -11776, i16 -11520, i16 -11264, i16 -11008, i16 -10752, i16 -10496, i16 -10240, i16 -9984, i16 -9728, i16 -9472, i16 -9216, i16 -8960, i16 -8704, i16 -8448, i16 -8192, i16 -7936, i16 -7680, i16 -7424, i16 -7168, i16 -6912, i16 -6656, i16 -6400, i16 -6144, i16 -5888, i16 -5632, i16 -5376, i16 -5120, i16 -4864, i16 -4608, i16 -4352, i16 -4096, i16 -3840, i16 -3584, i16 -3328, i16 -3072, i16 -2816, i16 -2560, i16 -2304, i16 -2048, i16 -1792, i16 -1536, i16 -1280, i16 -1024, i16 -768, i16 -512, i16 -256]
+; CHECK: @.crctable.5 = private constant [256 x i16] [i16 0, i16 256, i16 512, i16 768, i16 1024, i16 1280, i16 1536, i16 1792, i16 2048, i16 2304, i16 2560, i16 2816, i16 3072, i16 3328, i16 3584, i16 3840, i16 4096, i16 4352, i16 4608, i16 4864, i16 5120, i16 5376, i16 5632, i16 5888, i16 6144, i16 6400, i16 6656, i16 6912, i16 7168, i16 7424, i16 7680, i16 7936, i16 8192, i16 8448, i16 8704, i16 8960, i16 9216, i16 9472, i16 9728, i16 9984, i16 10240, i16 10496, i16 10752, i16 11008, i16 11264, i16 11520, i16 11776, i16 12032, i16 12288, i16 12544, i16 12800, i16 13056, i16 13312, i16 13568, i16 13824, i16 14080, i16 14336, i16 14592, i16 14848, i16 15104, i16 15360, i16 15616, i16 15872, i16 16128, i16 16384, i16 16640, i16 16896, i16 17152, i16 17408, i16 17664, i16 17920, i16 18176, i16 18432, i16 18688, i16 18944, i16 19200, i16 19456, i16 19712, i16 19968, i16 20224, i16 20480, i16 20736, i16 20992, i16 21248, i16 21504, i16 21760, i16 22016, i16 22272, i16 22528, i16 22784, i16 23040, i16 23296, i16 23552, i16 23808, i16 24064, i16 24320, i16 24576, i16 24832, i16 25088, i16 25344, i16 25600, i16 25856, i16 26112, i16 26368, i16 26624, i16 26880, i16 27136, i16 27392, i16 27648, i16 27904, i16 28160, i16 28416, i16 28672, i16 28928, i16 29184, i16 29440, i16 29696, i16 29952, i16 30208, i16 30464, i16 30720, i16 30976, i16 31232, i16 31488, i16 31744, i16 32000, i16 32256, i16 32512, i16 -32768, i16 -32512, i16 -32256, i16 -32000, i16 -31744, i16 -31488, i16 -31232, i16 -30976, i16 -30720, i16 -30464, i16 -30208, i16 -29952, i16 -29696, i16 -29440, i16 -29184, i16 -28928, i16 -28672, i16 -28416, i16 -28160, i16 -27904, i16 -27648, i16 -27392, i16 -27136, i16 -26880, i16 -26624, i16 -26368, i16 -26112, i16 -25856, i16 -25600, i16 -25344, i16 -25088, i16 -24832, i16 -24576, i16 -24320, i16 -24064, i16 -23808, i16 -23552, i16 -23296, i16 -23040, i16 -22784, i16 -22528, i16 -22272, i16 -22016, i16 -21760, i16 -21504, i16 -21248, i16 -20992, i16 -20736, i16 -20480, i16 -20224, i16 -19968, i16 -19712, i16 -19456, i16 -19200, i16 -18944, i16 -18688, i16 -18432, i16 -18176, i16 -17920, i16 -17664, i16 -17408, i16 -17152, i16 -16896, i16 -16640, i16 -16384, i16 -16128, i16 -15872, i16 -15616, i16 -15360, i16 -15104, i16 -14848, i16 -14592, i16 -14336, i16 -14080, i16 -13824, i16 -13568, i16 -13312, i16 -13056, i16 -12800, i16 -12544, i16 -12288, i16 -12032, i16 -11776, i16 -11520, i16 -11264, i16 -11008, i16 -10752, i16 -10496, i16 -10240, i16 -9984, i16 -9728, i16 -9472, i16 -9216, i16 -8960, i16 -8704, i16 -8448, i16 -8192, i16 -7936, i16 -7680, i16 -7424, i16 -7168, i16 -6912, i16 -6656, i16 -6400, i16 -6144, i16 -5888, i16 -5632, i16 -5376, i16 -5120, i16 -4864, i16 -4608, i16 -4352, i16 -4096, i16 -3840, i16 -3584, i16 -3328, i16 -3072, i16 -2816, i16 -2560, i16 -2304, i16 -2048, i16 -1792, i16 -1536, i16 -1280, i16 -1024, i16 -768, i16 -512, i16 -256]
+; CHECK: @.crctable.6 = private constant [256 x i8] c"\00\1D:'tiNS\E8\F5\D2\CF\9C\81\A6\BB\CD\D0\F7\EA\B9\A4\83\9E%8\1F\02QLkv\87\9A\BD\A0\F3\EE\C9\D4orUH\1B\06!<JWpm>#\04\19\A2\BF\98\85\D6\CB\EC\F1\13\0E)4gz]@\FB\E6\C1\DC\8F\92\B5\A8\DE\C3\E4\F9\AA\B7\90\8D6+\0C\11B_xe\94\89\AE\B3\E0\FD\DA\C7|aF[\08\152/YDc~-0\17\0A\B1\AC\8B\96\C5\D8\FF\E2&
+; CHECK: @.crctable.7 = private constant [256 x i32] [i32 0, i32 4489, i32 8978, i32 12955, i32 17956, i32 22445, i32 25910, i32 29887, i32 35912, i32 40385, i32 44890, i32 48851, i32 51820, i32 56293, i32 59774, i32 63735, i32 4225, i32 264, i32 13203, i32 8730, i32 22181, i32 18220, i32 30135, i32 25662, i32 40137, i32 36160, i32 49115, i32 44626, i32 56045, i32 52068, i32 63999, i32 59510, i32 8450, i32 12427, i32 528, i32 5017, i32 26406, i32 30383, i32 17460, i32 21949, i32 44362, i32 48323, i32 36440, i32 40913, i32 60270, i32 64231, i32 51324, i32 55797, i32 12675, i32 8202, i32 4753, i32 792, i32 30631, i32 26158, i32 21685, i32 17724, i32 48587, i32 44098, i32 40665, i32 36688, i32 64495, i32 60006, i32 55549, i32 51572, i32 16900, i32 21389, i32 24854, i32 28831, i32 1056, i32 5545, i32 10034, i32 14011, i32 52812, i32 57285, i32 60766, i32 64727, i32 34920, i32 39393, i32 43898, i32 47859, i32 21125, i32 17164, i32 29079, i32 24606, i32 5281, i32 1320, i32 14259, i32 9786, i32 57037, i32 53060, i32 64991, i32 60502, i32 39145, i32 35168, i32 48123, i32 43634, i32 25350, i32 29327, i32 16404, i32 20893, i32 9506, i32 13483, i32 1584, i32 6073, i32 61262, i32 65223, i32 52316, i32 56789, i32 43370, i32 47331, i32 35448, i32 39921, i32 29575, i32 25102, i32 20629, i32 16668, i32 13731, i32 9258, i32 5809, i32 1848, i32 65487, i32 60998, i32 56541, i32 52564, i32 47595, i32 43106, i32 39673, i32 35696, i32 33800, i32 38273, i32 42778, i32 46739, i32 49708, i32 54181, i32 57662, i32 61623, i32 2112, i32 6601, i32 11090, i32 15067, i32 20068, i32 24557, i32 28022, i32 31999, i32 38025, i32 34048, i32 47003, i32 42514, i32 53933, i32 49956, i32 61887, i32 57398, i32 6337, i32 2376, i32 15315, i32 10842, i32 24293, i32 20332, i32 32247, i32 27774, i32 42250, i32 46211, i32 34328, i32 38801, i32 58158, i32 62119, i32 49212, i32 53685, i32 10562, i32 14539, i32 2640, i32 7129, i32 28518, i32 32495, i32 19572, i32 24061, i32 46475, i32 41986, i32 38553, i32 34576, i32 62383, i32 57894, i32 53437, i32 49460, i32 14787, i32 10314, i32 6865, i32 2904, i32 32743, i32 28270, i32 23797, i32 19836, i32 50700, i32 55173, i32 58654, i32 62615, i32 32808, i32 37281, i32 41786, i32 45747, i32 19012, i32 23501, i32 26966, i32 30943, i32 3168, i32 7657, i32 12146, i32 16123, i32 54925, i32 50948, i32 62879, i32 58390, i32 37033, i32 33056, i32 46011, i32 41522, i32 23237, i32 19276, i32 31191, i32 26718, i32 7393, i32 3432, i32 16371, i32 11898, i32 59150, i32 63111, i32 50204, i32 54677, i32 41258, i32 45219, i32 33336, i32 37809, i32 27462, i32 31439, i32 18516, i32 23005, i32 11618, i32 15595, i32 3696, i32 8185, i32 63375, i32 58886, i32 54429, i32 50452, i32 45483, i32 40994, i32 37561, i32 33584, i32 31687, i32 27214, i32 22741, i32 18780, i32 15843, i32 11370, i32 7921, i32 3960]
+;.
+define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) {
+; CHECK-LABEL: define i16 @crc16.le.tc8(
+; CHECK-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[IV_BITS:%.*]] = mul i8 [[IV]], 8
+; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i8 [[MSG]], [[IV_BITS]]
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i8 [[DATA_LO_INDEXER]], 8
+; CHECK-NEXT:    [[DATA_INDEXER:%.*]] = zext i8 [[DATA_HI_INDEXER]] to i16
+; CHECK-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 -1, [[DATA_INDEXER]]
+; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i16 [[XOR_CRC_DATA]], 255
+; CHECK-NEXT:    [[CRC_INDEXER:%.*]] = and i16 [[XOR_CRC_DATA]], 255
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable, i16 [[CRC_INDEXER]]
+; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
+; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_LE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i16 [[XOR_CRCSHIFT_TBL]], -1
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i8 [[IV]], 0
+; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[FINALIZE_CRC]], %[[LOOP]] ]
+; CHECK-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+entry:
+  br label %loop
+
+loop:                                              ; preds = %loop, %entry
+  %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
+  %crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
+  %data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
+  %crc.trunc = trunc i16 %crc to i8
+  %xor.data.crc = xor i8 %data, %crc.trunc
+  %and.data.crc = and i8 %xor.data.crc, 1
+  %data.next = lshr i8 %data, 1
+  %check.sb = icmp eq i8 %and.data.crc, 0
+  %crc.lshr = lshr i16 %crc, 1
+  %xor = xor i16 %crc.lshr, -24575
+  %crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %xor
+  %iv.next = add nuw nsw i8 %iv, 1
+  %exit.cond = icmp samesign ult i8 %iv, 7
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i16 %crc.next
+}
+
+define i16 @crc16.le.tc8.udiv(i8 %msg, i16 %checksum) {
+; CHECK-LABEL: define i16 @crc16.le.tc8.udiv(
+; CHECK-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[IV_BITS:%.*]] = mul i8 [[IV]], 8
+; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i8 [[MSG]], [[IV_BITS]]
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i8 [[DATA_LO_INDEXER]], 8
+; CHECK-NEXT:    [[DATA_INDEXER:%.*]] = zext i8 [[DATA_HI_INDEXER]] to i16
+; CHECK-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 -1, [[DATA_INDEXER]]
+; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i16 [[XOR_CRC_DATA]], 255
+; CHECK-NEXT:    [[CRC_INDEXER:%.*]] = and i16 [[XOR_CRC_DATA]], 255
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.1, i16 [[CRC_INDEXER]]
+; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
+; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_LE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i16 [[XOR_CRCSHIFT_TBL]], -1
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i8 [[IV]], 0
+; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[FINALIZE_CRC]], %[[LOOP]] ]
+; CHECK-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+entry:
+  br label %loop
+
+loop:                                              ; preds = %loop, %entry
+  %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
+  %crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
+  %data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
+  %crc.trunc = trunc i16 %crc to i8
+  %xor.data.crc = xor i8 %data, %crc.trunc
+  %and.data.crc = and i8 %xor.data.crc, 1
+  %data.next = udiv i8 %data, 2
+  %check.sb = icmp eq i8 %and.data.crc, 0
+  %crc.lshr = udiv i16 %crc, 2
+  %xor = xor i16 %crc.lshr, -24575
+  %crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %xor
+  %iv.next = add nuw nsw i8 %iv, 1
+  %exit.cond = icmp samesign ult i8 %iv, 7
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i16 %crc.next
+}
+
+define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) {
+; CHECK-LABEL: define i16 @crc16.le.tc16(
+; CHECK-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[IV_BITS:%.*]] = mul i8 [[IV]], 8
+; CHECK-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i16 [[DATA_LO_INDEXER]], 8
+; CHECK-NEXT:    [[XOR_CRC_DATA2:%.*]] = xor i16 -1, [[DATA_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i16 [[XOR_CRC_DATA2]], 255
+; CHECK-NEXT:    [[CRC_INDEXER:%.*]] = and i16 [[XOR_CRC_DATA2]], 255
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.2, i16 [[CRC_INDEXER]]
+; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
+; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_LE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i16 [[XOR_CRCSHIFT_TBL]], -1
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i8 [[IV]], 1
+; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[FINALIZE_CRC]], %[[LOOP]] ]
+; CHECK-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+entry:
+  br label %loop
+
+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
+  %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, 15
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i16 %crc.next
+}
+
+define i16 @crc16.be.tc8.crc.init.li(i16 %checksum, i8 %msg) {
+; CHECK-LABEL: define i16 @crc16.be.tc8.crc.init.li(
+; CHECK-SAME: i16 [[CHECKSUM:%.*]], i8 [[MSG:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    [[MSG_EXT:%.*]] = zext i8 [[MSG]] to i16
+; CHECK-NEXT:    [[MSG_SHL:%.*]] = shl nuw i16 [[MSG_EXT]], 8
+; CHECK-NEXT:    [[CRC_INIT:%.*]] = xor i16 [[MSG_SHL]], [[CHECKSUM]]
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC_INIT]], 255
+; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i16 [[CRC_INIT]], 8
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.3, i16 [[CRC_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
+; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_BE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i32 [[IV]], 0
+; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[XOR_CRCSHIFT_TBL]], %[[LOOP]] ]
+; CHECK-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+entry:
+  %msg.ext = zext i8 %msg to i16
+  %msg.shl = shl nuw i16 %msg.ext, 8
+  %crc.init = xor i16 %msg.shl, %checksum
+  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 i16 @crc16.be.tc8.crc.init.arg(i16 %crc.init) {
+; CHECK-LABEL: define i16 @crc16.be.tc8.crc.init.arg(
+; CHECK-SAME: i16 [[CRC_INIT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC_INIT]], 255
+; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i16 [[CRC_INIT]], 8
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.4, i16 [[CRC_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
+; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_BE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i32 [[IV]], 0
+; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[XOR_CRCSHIFT_TBL]], %[[LOOP]] ]
+; CHECK-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+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, 7
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i16 %crc.next
+}
+
+define i16 @crc16.be.tc8.crc.init.arg.flipped.sb.check(i16 %crc.init) {
+; CHECK-LABEL: define i16 @crc16.be.tc8.crc.init.arg.flipped.sb.check(
+; CHECK-SAME: i16 [[CRC_INIT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC_INIT]], 255
+; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i16 [[CRC_INIT]], 8
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.5, i16 [[CRC_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
+; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_BE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i32 [[IV]], 0
+; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[XOR_CRCSHIFT_TBL]], %[[LOOP]] ]
+; CHECK-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+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 sge i16 %crc, 0
+  %crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor
+  %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: define i8 @crc8.be.tc8.ptr.nested.loop(
+; CHECK-SAME: ptr [[MSG:%.*]], i32 [[LOOP_LIMIT:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[OUTER_LOOP:.*]]
+; CHECK:       [[OUTER_LOOP]]:
+; CHECK-NEXT:    [[CRC_OUTER:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[CRC_NEXT_LCSSA:%.*]], %[[INNER_EXIT:.*]] ]
+; CHECK-NEXT:    [[OUTER_IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[OUTER_IV_NEXT:%.*]], %[[INNER_EXIT]] ]
+; CHECK-NEXT:    [[OUTER_EXIT_COND:%.*]] = icmp ult i32 [[OUTER_IV]], [[LOOP_LIMIT]]
+; CHECK-NEXT:    br i1 [[OUTER_EXIT_COND]], label %[[PH:.*]], label %[[EXIT:.*]]
+; CHECK:       [[PH]]:
+; CHECK-NEXT:    [[OUTER_IV_EXT:%.*]] = sext i32 [[OUTER_IV]] to i64
+; CHECK-NEXT:    [[MSG_OUTER_IV:%.*]] = getelementptr inbounds i8, ptr [[MSG]], i64 [[OUTER_IV_EXT]]
+; CHECK-NEXT:    [[MSG_LOAD:%.*]] = load i8, ptr [[MSG_OUTER_IV]], align 1
+; CHECK-NEXT:    [[CRC_INIT:%.*]] = xor i8 [[MSG_LOAD]], [[CRC_OUTER]]
+; CHECK-NEXT:    br label %[[INNER_LOOP:.*]]
+; CHECK:       [[INNER_LOOP]]:
+; CHECK-NEXT:    [[INNER_IV:%.*]] = phi i32 [ 0, %[[PH]] ], [ [[INNER_IV_NEXT:%.*]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i8 [[CRC_INIT]], -1
+; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i8 [[CRC_INIT]], 0
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.6, i8 [[CRC_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i8, ptr [[CRC_TBL_INDEXER]], align 1
+; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i8 [[CRC_BE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[INNER_IV_NEXT]] = add nuw nsw i32 [[INNER_IV]], 1
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i32 [[INNER_IV]], 0
+; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[INNER_LOOP]], label %[[INNER_EXIT]]
+; CHECK:       [[INNER_EXIT]]:
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA]] = phi i8 [ [[XOR_CRCSHIFT_TBL]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[OUTER_IV_NEXT]] = add i32 [[OUTER_IV]], 1
+; CHECK-NEXT:    br label %[[OUTER_LOOP]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[CRC_OUTER_LCSSA:%.*]] = phi i8 [ [[CRC_OUTER]], %[[OUTER_LOOP]] ]
+; CHECK-NEXT:    ret i8 [[CRC_OUTER_LCSSA]]
+;
+entry:
+  br label %outer.loop
+
+outer.loop:                                        ; preds = %inner.exit, %entry
+  %crc.outer = phi i8 [ 0, %entry ], [ %crc.next, %inner.exit ]
+  %outer.iv = phi i32 [ 0, %entry ], [ %outer.iv.next, %inner.exit ]
+  %outer.exit.cond = icmp ult i32 %outer.iv, %loop.limit
+  br i1 %outer.exit.cond, label %ph, label %exit
+
+ph:                                                ; preds = %outer.loop
+  %outer.iv.ext = sext i32 %outer.iv to i64
+  %msg.outer.iv = getelementptr inbounds i8, ptr %msg, i64 %outer.iv.ext
+  %msg.load = load i8, ptr %msg.outer.iv, align 1
+  %crc.init = xor i8 %msg.load, %crc.outer
+  br label %inner.loop
+
+inner.loop:                                        ; preds = %inner.loop, %ph
+  %inner.iv = phi i32 [ 0, %ph ], [ %inner.iv.next, %inner.loop ]
+  %crc = phi i8 [ %crc.init, %ph ], [ %crc.next, %inner.loop ]
+  %crc.shl = shl i8 %crc, 1
+  %crc.xor = xor i8 %crc.shl, 29
+  %check.sb = icmp slt i8 %crc, 0
+  %crc.next = select i1 %check.sb, i8 %crc.xor, i8 %crc.shl
+  %inner.iv.next = add nuw nsw i32 %inner.iv, 1
+  %exit.cond = icmp samesign ult i32 %inner.iv, 7
+  br i1 %exit.cond, label %inner.loop, label %inner.exit
+
+inner.exit:                                        ; preds = %inner.loop
+  %outer.iv.next = add i32 %outer.iv, 1
+  br label %outer.loop
+
+exit:                                              ; preds = %outer.loop
+  ret i8 %crc.outer
+}
+
+define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) {
+; CHECK-LABEL: define i32 @crc32.le.tc8.data32(
+; CHECK-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) {
+; CHECK-NEXT:  [[ENTRY:.*]]:
+; CHECK-NEXT:    br label %[[LOOP:.*]]
+; CHECK:       [[LOOP]]:
+; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; CHECK-NEXT:    [[IV_BITS:%.*]] = mul i8 [[IV]], 8
+; CHECK-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i32 [[MSG]], [[IV_INDEXER]]
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i32 [[DATA_LO_INDEXER]], 24
+; CHECK-NEXT:    [[XOR_CRC_DATA2:%.*]] = xor i32 -1, [[DATA_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i32 [[XOR_CRC_DATA2]], 255
+; CHECK-NEXT:    [[CRC_INDEXER:%.*]] = and i32 [[XOR_CRC_DATA2]], 255
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.7, i32 [[CRC_INDEXER]]
+; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i32, ptr [[CRC_TBL_INDEXER]], align 4
+; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i32 [[CRC_LE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i32 [[XOR_CRCSHIFT_TBL]], -1
+; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i8 [[IV]], 0
+; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; CHECK:       [[EXIT]]:
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[FINALIZE_CRC]], %[[LOOP]] ]
+; CHECK-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
+;
+entry:
+  br label %loop
+
+loop:                                              ; preds = %loop, %entry
+  %crc = phi i32 [ %checksum, %entry ], [ %crc.next, %loop ]
+  %data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
+  %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
+  %xor.crc.data = xor i32 %crc, %data
+  %sb.crc.data = and i32 %xor.crc.data, 1
+  %check.sb = icmp eq i32 %sb.crc.data, 0
+  %crc.lshr = lshr i32 %crc, 1
+  %crc.xor = xor i32 %crc.lshr, 33800
+  %crc.next = select i1 %check.sb, i32 %crc.lshr, i32 %crc.xor
+  %iv.next = add nuw nsw i8 %iv, 1
+  %data.next = lshr i32 %data, 1
+  %exit.cond = icmp samesign ult i8 %iv, 7
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i32 %crc.next
+}

>From 6d1c6c981d5c1728ddb260b3db7edfb14e6eace2 Mon Sep 17 00:00:00 2001
From: Ramkumar Ramachandra <ramkumar.ramachandra at codasip.com>
Date: Sat, 7 Jun 2025 08:36:49 +0100
Subject: [PATCH 2/2] [LoopIdiom] Fix some issues

---
 llvm/include/llvm/Analysis/HashRecognize.h    |  13 +-
 llvm/lib/Analysis/HashRecognize.cpp           |  41 +++---
 .../Transforms/Scalar/LoopIdiomRecognize.cpp  | 119 +++++++++++-------
 .../LoopIdiom/cyclic-redundancy-check.ll      | 100 +++++++++------
 4 files changed, 170 insertions(+), 103 deletions(-)

diff --git a/llvm/include/llvm/Analysis/HashRecognize.h b/llvm/include/llvm/Analysis/HashRecognize.h
index c169383bf7b08..e8a05593442db 100644
--- a/llvm/include/llvm/Analysis/HashRecognize.h
+++ b/llvm/include/llvm/Analysis/HashRecognize.h
@@ -63,17 +63,24 @@ struct PolynomialInfo {
   // the case of CRC, which must be zero.
   Value *ComputedValue;
 
+  // The LCSSA PHI node in the exit block of the loop that uses ComputedValue.
+  PHINode *LCSSAPhi;
+
   // Set to true in the case of big-endian.
   bool ByteOrderSwapped;
 
+  // The generated Sarwate lookup-table, which can be used to optimize CRC in
+  // the absence of target-specific instructions.
+  CRCTable SarwateTable;
+
   // An optional auxiliary checksum that augments the LHS. In the case of CRC,
   // it is XOR'ed with the LHS, so that the computation's final remainder is
   // zero.
   Value *LHSAux;
 
   PolynomialInfo(unsigned TripCount, Value *LHS, const APInt &RHS,
-                 Value *ComputedValue, bool ByteOrderSwapped,
-                 Value *LHSAux = nullptr);
+                 Value *ComputedValue, PHINode *LCSSAPhi, bool ByteOrderSwapped,
+                 const CRCTable &SarwateTable, Value *LHSAux = nullptr);
 };
 
 /// The analysis.
@@ -113,7 +120,7 @@ class HashRecognizeAnalysis : public AnalysisInfoMixin<HashRecognizeAnalysis> {
   static AnalysisKey Key;
 
 public:
-  using Result = HashRecognize;
+  using Result = std::optional<PolynomialInfo>;
   Result run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR);
 };
 } // namespace llvm
diff --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp
index 92c1191bd71b1..70c359c01a642 100644
--- a/llvm/lib/Analysis/HashRecognize.cpp
+++ b/llvm/lib/Analysis/HashRecognize.cpp
@@ -443,10 +443,12 @@ getRecurrences(BasicBlock *LoopLatch, const PHINode *IndVar, const Loop &L) {
 }
 
 PolynomialInfo::PolynomialInfo(unsigned TripCount, Value *LHS, const APInt &RHS,
-                               Value *ComputedValue, bool ByteOrderSwapped,
-                               Value *LHSAux)
+                               Value *ComputedValue, PHINode *LCSSAPhi,
+                               bool ByteOrderSwapped,
+                               const CRCTable &SarwateTable, Value *LHSAux)
     : TripCount(TripCount), LHS(LHS), RHS(RHS), ComputedValue(ComputedValue),
-      ByteOrderSwapped(ByteOrderSwapped), LHSAux(LHSAux) {}
+      LCSSAPhi(LCSSAPhi), ByteOrderSwapped(ByteOrderSwapped),
+      SarwateTable(SarwateTable), LHSAux(LHSAux) {}
 
 /// In the big-endian case, checks the bottom N bits against CheckFn, and that
 /// the rest are unknown. In the little-endian case, checks the top N bits
@@ -557,14 +559,14 @@ std::variant<PolynomialInfo, ErrBits, StringRef>
 HashRecognize::recognizeCRC() const {
   if (!L.isInnermost())
     return "Loop is not innermost";
-  unsigned TC = SE.getSmallConstantMaxTripCount(&L);
-  if (!TC || TC > 256)
-    return "Unable to find a small constant trip count";
   BasicBlock *Latch = L.getLoopLatch();
   BasicBlock *Exit = L.getExitBlock();
   const PHINode *IndVar = L.getCanonicalInductionVariable();
   if (!Latch || !Exit || !IndVar || L.getNumBlocks() != 1)
     return "Loop not in canonical form";
+  unsigned TC = SE.getSmallConstantTripCount(&L);
+  if (!TC || TC > 256)
+    return "Unable to find a small constant trip count";
 
   auto R = getRecurrences(Latch, IndVar, L);
   if (!R)
@@ -592,11 +594,13 @@ HashRecognize::recognizeCRC() const {
   // true even if it is only really used in an outer loop's exit block, since
   // the loop is in LCSSA form.
   auto *ComputedValue = cast<SelectInst>(ConditionalRecurrence.Step);
-  if (none_of(ComputedValue->users(), [Exit](User *U) {
-        auto *UI = dyn_cast<Instruction>(U);
-        return UI && UI->getParent() == Exit;
-      }))
+  auto LCSSAIt = find_if(ComputedValue->users(), [Exit](User *U) {
+    auto *UI = dyn_cast<PHINode>(U);
+    return UI && UI->getNumIncomingValues() == 1 && UI->getParent() == Exit;
+  });
+  if (LCSSAIt == ComputedValue->user_end())
     return "Unable to find use of computed value in loop exit block";
+  PHINode *LCSSAPhi = cast<PHINode>(*LCSSAIt);
 
   assert(ConditionalRecurrence.ExtraConst &&
          "Expected ExtraConst in conditional recurrence");
@@ -621,8 +625,9 @@ HashRecognize::recognizeCRC() const {
     return ErrBits(ResultBits, TC, *ByteOrderSwapped);
 
   Value *LHSAux = SimpleRecurrence ? SimpleRecurrence.Start : nullptr;
+  const CRCTable &SarwateTable = genSarwateTable(GenPoly, *ByteOrderSwapped);
   return PolynomialInfo(TC, ConditionalRecurrence.Start, GenPoly, ComputedValue,
-                        *ByteOrderSwapped, LHSAux);
+                        LCSSAPhi, *ByteOrderSwapped, SarwateTable, LHSAux);
 }
 
 void CRCTable::print(raw_ostream &OS) const {
@@ -676,7 +681,7 @@ void HashRecognize::print(raw_ostream &OS) const {
     OS << "\n";
   }
   OS.indent(2) << "Computed CRC lookup table:\n";
-  genSarwateTable(Info.RHS, Info.ByteOrderSwapped).print(OS);
+  Info.SarwateTable.print(OS);
 }
 
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
@@ -690,13 +695,17 @@ PreservedAnalyses HashRecognizePrinterPass::run(Loop &L,
                                                 LoopAnalysisManager &AM,
                                                 LoopStandardAnalysisResults &AR,
                                                 LPMUpdater &) {
-  AM.getResult<HashRecognizeAnalysis>(L, AR).print(OS);
+  HashRecognize(L, AR.SE).print(OS);
   return PreservedAnalyses::all();
 }
 
-HashRecognize HashRecognizeAnalysis::run(Loop &L, LoopAnalysisManager &AM,
-                                         LoopStandardAnalysisResults &AR) {
-  return {L, AR.SE};
+std::optional<PolynomialInfo>
+HashRecognizeAnalysis::run(Loop &L, LoopAnalysisManager &AM,
+                           LoopStandardAnalysisResults &AR) {
+  auto Res = HashRecognize(L, AR.SE).recognizeCRC();
+  if (std::holds_alternative<PolynomialInfo>(Res))
+    return std::get<PolynomialInfo>(Res);
+  return std::nullopt;
 }
 
 AnalysisKey HashRecognizeAnalysis::Key;
diff --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index 756836e1db686..7ab8f6c75e17a 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -146,12 +146,12 @@ static cl::opt<bool, true>
                      cl::ReallyHidden);
 
 bool DisableLIRP::HashRecognize;
-static cl::opt<bool, true> DisableLIRPHashRecognize(
-    "disable-" DEBUG_TYPE "-hashrecognize",
-    cl::desc("Proceed with loop idiom recognize pass, "
-             "enable conversion of loop(s) to wcslen."),
-    cl::location(DisableLIRP::HashRecognize), cl::init(false),
-    cl::ReallyHidden);
+static cl::opt<bool, true>
+    DisableLIRPHashRecognize("disable-" DEBUG_TYPE "-hashrecognize",
+                             cl::desc("Proceed with loop idiom recognize pass, "
+                                      "but do not optimize CRC loops."),
+                             cl::location(DisableLIRP::HashRecognize),
+                             cl::init(false), cl::ReallyHidden);
 
 static cl::opt<bool> UseLIRCodeSizeHeurs(
     "use-lir-code-size-heurs",
@@ -167,7 +167,7 @@ class LoopIdiomRecognize {
   DominatorTree *DT;
   LoopInfo *LI;
   ScalarEvolution *SE;
-  const HashRecognize *HR;
+  std::optional<PolynomialInfo> HashRecognizeResult;
   TargetLibraryInfo *TLI;
   const TargetTransformInfo *TTI;
   const DataLayout *DL;
@@ -178,12 +178,13 @@ class LoopIdiomRecognize {
 public:
   explicit LoopIdiomRecognize(AliasAnalysis *AA, DominatorTree *DT,
                               LoopInfo *LI, ScalarEvolution *SE,
-                              const HashRecognize *HR, TargetLibraryInfo *TLI,
+                              std::optional<PolynomialInfo> HR,
+                              TargetLibraryInfo *TLI,
                               const TargetTransformInfo *TTI, MemorySSA *MSSA,
                               const DataLayout *DL,
                               OptimizationRemarkEmitter &ORE)
-      : AA(AA), DT(DT), LI(LI), SE(SE), HR(HR), TLI(TLI), TTI(TTI), DL(DL),
-        ORE(ORE) {
+      : AA(AA), DT(DT), LI(LI), SE(SE), HashRecognizeResult(HR), TLI(TLI),
+        TTI(TTI), DL(DL), ORE(ORE) {
     if (MSSA)
       MSSAU = std::make_unique<MemorySSAUpdater>(MSSA);
   }
@@ -295,9 +296,11 @@ PreservedAnalyses LoopIdiomRecognizePass::run(Loop &L, LoopAnalysisManager &AM,
   // but ORE cannot be preserved (see comment before the pass definition).
   OptimizationRemarkEmitter ORE(L.getHeader()->getParent());
 
-  const HashRecognize &HR = AM.getResult<HashRecognizeAnalysis>(L, AR);
+  std::optional<PolynomialInfo> HR;
+  if (!DisableLIRP::HashRecognize)
+    HR = AM.getResult<HashRecognizeAnalysis>(L, AR);
 
-  LoopIdiomRecognize LIR(&AR.AA, &AR.DT, &AR.LI, &AR.SE, &HR, &AR.TLI, &AR.TTI,
+  LoopIdiomRecognize LIR(&AR.AA, &AR.DT, &AR.LI, &AR.SE, HR, &AR.TLI, &AR.TTI,
                          AR.MSSA, DL, ORE);
   if (!LIR.runOnLoop(&L))
     return PreservedAnalyses::all();
@@ -340,7 +343,7 @@ bool LoopIdiomRecognize::runOnLoop(Loop *L) {
   HasMemsetPattern = TLI->has(LibFunc_memset_pattern16);
   HasMemcpy = TLI->has(LibFunc_memcpy);
 
-  if (HasMemset || HasMemsetPattern || HasMemcpy || !DisableLIRP::HashRecognize)
+  if (HasMemset || HasMemsetPattern || HasMemcpy || HashRecognizeResult)
     if (SE->hasLoopInvariantBackedgeTakenCount(L))
       return runOnCountableLoop();
 
@@ -384,11 +387,8 @@ bool LoopIdiomRecognize::runOnCountableLoop() {
     MadeChange |= runOnLoopBlock(BB, BECount, ExitBlocks);
   }
 
-  if (!DisableLIRP::HashRecognize) {
-    auto Result = HR->recognizeCRC();
-    if (std::holds_alternative<PolynomialInfo>(Result))
-      MadeChange |= optimizeCRCLoop(std::get<PolynomialInfo>(Result));
-  }
+  // Optimize a CRC loop if HashRecognize found one.
+  MadeChange |= HashRecognizeResult && optimizeCRCLoop(*HashRecognizeResult);
 
   return MadeChange;
 }
@@ -1505,11 +1505,8 @@ bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
   // Sarwate-lookup-table.
   Type *CRCTy = Info.LHS->getType();
   unsigned CRCBW = CRCTy->getIntegerBitWidth();
-  const APInt &GenPoly = Info.RHS;
-  std::array<APInt, 256> CRCTable =
-      HR->genSarwateTable(GenPoly, Info.ByteOrderSwapped);
   std::array<Constant *, 256> CRCConstants;
-  transform(CRCTable, CRCConstants.begin(),
+  transform(Info.SarwateTable, CRCConstants.begin(),
             [CRCTy](const APInt &E) { return ConstantInt::get(CRCTy, E); });
   Constant *ConstArray =
       ConstantArray::get(ArrayType::get(CRCTy, 256), CRCConstants);
@@ -1538,7 +1535,7 @@ bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
     BasicBlock *LoopBlk = CurLoop->getLoopLatch();
     BranchInst *BrInst = cast<BranchInst>(LoopBlk->getTerminator());
     CmpPredicate ExitPred = BrInst->getSuccessor(0) == LoopBlk
-                                ? ICmpInst::Predicate::ICMP_ULT
+                                ? ICmpInst::Predicate::ICMP_NE
                                 : ICmpInst::Predicate::ICMP_EQ;
     Instruction *ExitCond = CurLoop->getLatchCmpInst();
     IRBuilder<> Builder(ExitCond);
@@ -1557,43 +1554,75 @@ bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
   //   crc = (crc << 8) ^ tbl[data[iv] ^ (crc >> (crc.bw - 8))]
   {
     // Compute the top 8 bits of Op.
-    auto GetHiByte = [CRCBW](IRBuilderBase &Builder, Value *Op,
-                             StringRef Name) {
-      return Builder.CreateAShr(Op, ConstantInt::get(Op->getType(), CRCBW - 8),
-                                Name);
+    auto GetLoByte = [](IRBuilderBase &Builder, Value *Op, const Twine &Name) {
+      Type *OpTy = Op->getType();
+      return Builder.CreateAnd(Op, ConstantInt::get(OpTy, 0XFF), Name);
+    };
+    auto GetHiByte = [](IRBuilderBase &Builder, Value *Op, const Twine &Name) {
+      Type *OpTy = Op->getType();
+      unsigned OpBW = OpTy->getIntegerBitWidth();
+      return Builder.CreateLShr(
+          Builder.CreateAnd(
+              Op, ConstantInt::get(OpTy, APInt::getHighBitsSet(OpBW, 8)), Name),
+          ConstantInt::get(OpTy, OpBW - 8), Name + ".hi.extract");
     };
 
-    Constant *AllOnes = ConstantInt::get(CRCTy, APInt::getAllOnes(CRCBW));
-    Constant *LoByteMask = ConstantInt::get(CRCTy, 0xFF);
     IRBuilder<> Builder(CurLoop->getHeader(),
                         CurLoop->getHeader()->getFirstNonPHIIt());
-    Value *CRC = Info.LHSAux ? AllOnes : Info.LHS;
-    if (Info.LHSAux) {
-      // Compute Info.LHSAux[iv], when Info.LHSAux is an integer.
+    // Create the CRC PHI, and initialize its incoming value to AllOnes from the
+    // entry block.
+    PHINode *CRCPhi = Builder.CreatePHI(CRCTy, 2, "crc");
+    Constant *AllOnes = ConstantInt::get(CRCTy, APInt::getAllOnes(CRCBW));
+    CRCPhi->addIncoming(AllOnes, CurLoop->getLoopPreheader());
+
+    // CRC is now an evolving variable, initialized to the PHI.
+    Value *CRC = CRCPhi;
+
+    // Data is either LHSAux, if one is evolving in the loop or a loop-invariant
+    // LHS.
+    if (Value *Data = Info.LHSAux ? Info.LHSAux : Info.LHS) {
+      // Compute Data[iv], when Data is an integer.
       Value *IVLo = Builder.CreateZExtOrTrunc(
-          Builder.CreateMul(IV, ConstantInt::get(IVTy, 8), "iv.bits"),
-          Info.LHSAux->getType(), "iv.indexer");
-      Value *DataIndexer = GetHiByte(
-          Builder, Builder.CreateShl(Info.LHSAux, IVLo, "data.lo.indexer"),
-          "data.hi.indexer");
+          Builder.CreateShl(IV, ConstantInt::get(IVTy, 3), "iv.bits"),
+          Data->getType(), "iv.indexer");
+      Value *DataIndexer =
+          GetHiByte(Builder, Builder.CreateShl(Data, IVLo, "data.lo.indexer"),
+                    "data.hi.mask");
       CRC = Builder.CreateXor(
           CRC, Builder.CreateZExtOrTrunc(DataIndexer, CRCTy, "data.indexer"),
           "xor.crc.data");
     }
-    Value *CRCShift = Info.ByteOrderSwapped
-                          ? Builder.CreateShl(CRC, LoByteMask, "crc.be.shift")
-                          : Builder.CreateAShr(CRC, LoByteMask, "crc.le.shift");
 
-    // Compute either top 8 or bottom 8 bits of CRC.
+    // CRCShift = CRC (<<|>>) 8. No shift in case of CRC-8.
+    Value *CRCShift = nullptr;
+    if (CRCBW > 8)
+      CRCShift = Info.ByteOrderSwapped
+                     ? Builder.CreateShl(CRC, 8, "crc.be.shift")
+                     : Builder.CreateLShr(CRC, 8, "crc.le.shift");
+
+    // CRCTableLd = CRCTable[(top|bottom) byte of CRC].
     Value *CRCIndexer = Info.ByteOrderSwapped
-                            ? GetHiByte(Builder, CRC, "crc.hi.indexer")
-                            : Builder.CreateAnd(CRC, LoByteMask, "crc.indexer");
+                            ? GetHiByte(Builder, CRC, "crc.hi.mask")
+                            : GetLoByte(Builder, CRC, "crc.lo.mask");
     Value *CRCTableGEP = Builder.CreatePtrAdd(GV, CRCIndexer, "crc.tbl.indexer",
                                               GEPNoWrapFlags::inBounds());
     Value *CRCTableLd = Builder.CreateLoad(CRCTy, CRCTableGEP, "crc.tbl.index");
-    CRC = Builder.CreateXor(CRCShift, CRCTableLd, "xor.crcshift.tbl");
-    CRC = Info.LHSAux ? Builder.CreateXor(CRC, AllOnes, "finalize.crc") : CRC;
+
+    // CRC = CRCShift ^ CRCableLd. No XOR with shift in case of CRC-8.
+    if (CRCBW > 8)
+      CRC = Builder.CreateXor(CRCShift, CRCTableLd, "xor.crcshift.tbl");
+
+    // Connect the back-edge for the loop.
+    CRCPhi->addIncoming(CRC, CurLoop->getLoopLatch());
     Info.ComputedValue->replaceUsesOutsideBlock(CRC, CurLoop->getLoopLatch());
+
+    // Finalize the CRC and RAUW the LCSSAPhi in the exit block of the loop.
+    Builder.SetInsertPoint(CurLoop->getExitBlock()->getFirstNonPHIIt());
+    Value *FinalizedCRC =
+        Builder.CreateXor(Info.LCSSAPhi, AllOnes, "finalize.crc");
+    Info.LCSSAPhi->replaceUsesWithIf(FinalizedCRC, [FinalizedCRC](Use &U) {
+      return U.getUser() != FinalizedCRC;
+    });
   }
 
   // Cleanup.
diff --git a/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll
index 143813ab2bf70..8362719c17101 100644
--- a/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll
+++ b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll
@@ -18,19 +18,19 @@ define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) {
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; CHECK-NEXT:    [[IV_BITS:%.*]] = mul i8 [[IV]], 8
+; CHECK-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
 ; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i8 [[MSG]], [[IV_BITS]]
-; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i8 [[DATA_LO_INDEXER]], 8
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i8 [[DATA_LO_INDEXER]], 0
 ; CHECK-NEXT:    [[DATA_INDEXER:%.*]] = zext i8 [[DATA_HI_INDEXER]] to i16
 ; CHECK-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 -1, [[DATA_INDEXER]]
-; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i16 [[XOR_CRC_DATA]], 255
-; CHECK-NEXT:    [[CRC_INDEXER:%.*]] = and i16 [[XOR_CRC_DATA]], 255
-; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable, i16 [[CRC_INDEXER]]
+; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i16 [[XOR_CRC_DATA]], 8
+; CHECK-NEXT:    [[CRC_LO_INDEXER:%.*]] = and i16 [[XOR_CRC_DATA]], 255
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable, i16 [[CRC_LO_INDEXER]]
 ; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
 ; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_LE_SHIFT]], [[CRC_TBL_INDEX]]
 ; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i16 [[XOR_CRCSHIFT_TBL]], -1
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i8 [[IV]], 0
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
 ; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[FINALIZE_CRC]], %[[LOOP]] ]
@@ -66,19 +66,19 @@ define i16 @crc16.le.tc8.udiv(i8 %msg, i16 %checksum) {
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; CHECK-NEXT:    [[IV_BITS:%.*]] = mul i8 [[IV]], 8
+; CHECK-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
 ; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i8 [[MSG]], [[IV_BITS]]
-; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i8 [[DATA_LO_INDEXER]], 8
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i8 [[DATA_LO_INDEXER]], 0
 ; CHECK-NEXT:    [[DATA_INDEXER:%.*]] = zext i8 [[DATA_HI_INDEXER]] to i16
 ; CHECK-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 -1, [[DATA_INDEXER]]
-; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i16 [[XOR_CRC_DATA]], 255
-; CHECK-NEXT:    [[CRC_INDEXER:%.*]] = and i16 [[XOR_CRC_DATA]], 255
-; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.1, i16 [[CRC_INDEXER]]
+; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i16 [[XOR_CRC_DATA]], 8
+; CHECK-NEXT:    [[CRC_LO_INDEXER:%.*]] = and i16 [[XOR_CRC_DATA]], 255
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.1, i16 [[CRC_LO_INDEXER]]
 ; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
 ; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_LE_SHIFT]], [[CRC_TBL_INDEX]]
 ; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i16 [[XOR_CRCSHIFT_TBL]], -1
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i8 [[IV]], 0
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
 ; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[FINALIZE_CRC]], %[[LOOP]] ]
@@ -114,19 +114,19 @@ define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) {
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; CHECK-NEXT:    [[IV_BITS:%.*]] = mul i8 [[IV]], 8
+; CHECK-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
 ; CHECK-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
 ; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
 ; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i16 [[DATA_LO_INDEXER]], 8
 ; CHECK-NEXT:    [[XOR_CRC_DATA2:%.*]] = xor i16 -1, [[DATA_HI_INDEXER]]
-; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i16 [[XOR_CRC_DATA2]], 255
-; CHECK-NEXT:    [[CRC_INDEXER:%.*]] = and i16 [[XOR_CRC_DATA2]], 255
-; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.2, i16 [[CRC_INDEXER]]
+; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i16 [[XOR_CRC_DATA2]], 8
+; CHECK-NEXT:    [[CRC_LO_INDEXER:%.*]] = and i16 [[XOR_CRC_DATA2]], 255
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.2, i16 [[CRC_LO_INDEXER]]
 ; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
 ; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_LE_SHIFT]], [[CRC_TBL_INDEX]]
 ; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i16 [[XOR_CRCSHIFT_TBL]], -1
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i8 [[IV]], 1
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
 ; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[FINALIZE_CRC]], %[[LOOP]] ]
@@ -164,16 +164,22 @@ define i16 @crc16.be.tc8.crc.init.li(i16 %checksum, i8 %msg) {
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC_INIT]], 255
-; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i16 [[CRC_INIT]], 8
+; CHECK-NEXT:    [[IV_BITS:%.*]] = shl i32 [[IV]], 3
+; CHECK-NEXT:    [[IV_INDEXER:%.*]] = trunc i32 [[IV_BITS]] to i16
+; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i16 [[CRC_INIT]], [[IV_INDEXER]]
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i16 [[DATA_LO_INDEXER]], 8
+; CHECK-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 -1, [[DATA_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[XOR_CRC_DATA]], 8
+; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i16 [[XOR_CRC_DATA]], 8
 ; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.3, i16 [[CRC_HI_INDEXER]]
 ; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
 ; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_BE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i16 [[XOR_CRCSHIFT_TBL]], -1
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
-; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i32 [[IV]], 0
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i32 [[IV]], 0
 ; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:
-; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[XOR_CRCSHIFT_TBL]], %[[LOOP]] ]
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[FINALIZE_CRC]], %[[LOOP]] ]
 ; CHECK-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
@@ -204,16 +210,22 @@ define i16 @crc16.be.tc8.crc.init.arg(i16 %crc.init) {
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC_INIT]], 255
-; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i16 [[CRC_INIT]], 8
+; CHECK-NEXT:    [[IV_BITS:%.*]] = shl i32 [[IV]], 3
+; CHECK-NEXT:    [[IV_INDEXER:%.*]] = trunc i32 [[IV_BITS]] to i16
+; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i16 [[CRC_INIT]], [[IV_INDEXER]]
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i16 [[DATA_LO_INDEXER]], 8
+; CHECK-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 -1, [[DATA_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[XOR_CRC_DATA]], 8
+; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i16 [[XOR_CRC_DATA]], 8
 ; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.4, i16 [[CRC_HI_INDEXER]]
 ; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
 ; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_BE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i16 [[XOR_CRCSHIFT_TBL]], -1
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
-; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i32 [[IV]], 0
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i32 [[IV]], 0
 ; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:
-; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[XOR_CRCSHIFT_TBL]], %[[LOOP]] ]
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[FINALIZE_CRC]], %[[LOOP]] ]
 ; CHECK-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
@@ -241,16 +253,22 @@ define i16 @crc16.be.tc8.crc.init.arg.flipped.sb.check(i16 %crc.init) {
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i32 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC_INIT]], 255
-; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i16 [[CRC_INIT]], 8
+; CHECK-NEXT:    [[IV_BITS:%.*]] = shl i32 [[IV]], 3
+; CHECK-NEXT:    [[IV_INDEXER:%.*]] = trunc i32 [[IV_BITS]] to i16
+; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i16 [[CRC_INIT]], [[IV_INDEXER]]
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i16 [[DATA_LO_INDEXER]], 8
+; CHECK-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 -1, [[DATA_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[XOR_CRC_DATA]], 8
+; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i16 [[XOR_CRC_DATA]], 8
 ; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.5, i16 [[CRC_HI_INDEXER]]
 ; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i16, ptr [[CRC_TBL_INDEXER]], align 2
 ; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i16 [[CRC_BE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i16 [[XOR_CRCSHIFT_TBL]], -1
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
-; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i32 [[IV]], 0
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i32 [[IV]], 0
 ; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:
-; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[XOR_CRCSHIFT_TBL]], %[[LOOP]] ]
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[FINALIZE_CRC]], %[[LOOP]] ]
 ; CHECK-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
@@ -289,16 +307,20 @@ define i8 @crc8.be.tc8.ptr.nested.loop(ptr %msg, i32 %loop.limit) {
 ; CHECK-NEXT:    br label %[[INNER_LOOP:.*]]
 ; CHECK:       [[INNER_LOOP]]:
 ; CHECK-NEXT:    [[INNER_IV:%.*]] = phi i32 [ 0, %[[PH]] ], [ [[INNER_IV_NEXT:%.*]], %[[INNER_LOOP]] ]
-; CHECK-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i8 [[CRC_INIT]], -1
-; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i8 [[CRC_INIT]], 0
+; CHECK-NEXT:    [[IV_BITS:%.*]] = shl i32 [[INNER_IV]], 3
+; CHECK-NEXT:    [[IV_INDEXER:%.*]] = trunc i32 [[IV_BITS]] to i8
+; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i8 [[CRC_INIT]], [[IV_INDEXER]]
+; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i8 [[DATA_LO_INDEXER]], 0
+; CHECK-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 -1, [[DATA_HI_INDEXER]]
+; CHECK-NEXT:    [[CRC_HI_INDEXER:%.*]] = ashr i8 [[XOR_CRC_DATA]], 0
 ; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.6, i8 [[CRC_HI_INDEXER]]
 ; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i8, ptr [[CRC_TBL_INDEXER]], align 1
-; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i8 [[CRC_BE_SHIFT]], [[CRC_TBL_INDEX]]
+; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i8 [[XOR_CRC_DATA]], -1
 ; CHECK-NEXT:    [[INNER_IV_NEXT]] = add nuw nsw i32 [[INNER_IV]], 1
-; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i32 [[INNER_IV]], 0
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i32 [[INNER_IV]], 0
 ; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[INNER_LOOP]], label %[[INNER_EXIT]]
 ; CHECK:       [[INNER_EXIT]]:
-; CHECK-NEXT:    [[CRC_NEXT_LCSSA]] = phi i8 [ [[XOR_CRCSHIFT_TBL]], %[[INNER_LOOP]] ]
+; CHECK-NEXT:    [[CRC_NEXT_LCSSA]] = phi i8 [ [[FINALIZE_CRC]], %[[INNER_LOOP]] ]
 ; CHECK-NEXT:    [[OUTER_IV_NEXT]] = add i32 [[OUTER_IV]], 1
 ; CHECK-NEXT:    br label %[[OUTER_LOOP]]
 ; CHECK:       [[EXIT]]:
@@ -347,19 +369,19 @@ define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) {
 ; CHECK-NEXT:    br label %[[LOOP:.*]]
 ; CHECK:       [[LOOP]]:
 ; CHECK-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; CHECK-NEXT:    [[IV_BITS:%.*]] = mul i8 [[IV]], 8
+; CHECK-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
 ; CHECK-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
 ; CHECK-NEXT:    [[DATA_LO_INDEXER:%.*]] = shl i32 [[MSG]], [[IV_INDEXER]]
 ; CHECK-NEXT:    [[DATA_HI_INDEXER:%.*]] = ashr i32 [[DATA_LO_INDEXER]], 24
 ; CHECK-NEXT:    [[XOR_CRC_DATA2:%.*]] = xor i32 -1, [[DATA_HI_INDEXER]]
-; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i32 [[XOR_CRC_DATA2]], 255
-; CHECK-NEXT:    [[CRC_INDEXER:%.*]] = and i32 [[XOR_CRC_DATA2]], 255
-; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.7, i32 [[CRC_INDEXER]]
+; CHECK-NEXT:    [[CRC_LE_SHIFT:%.*]] = ashr i32 [[XOR_CRC_DATA2]], 8
+; CHECK-NEXT:    [[CRC_LO_INDEXER:%.*]] = and i32 [[XOR_CRC_DATA2]], 255
+; CHECK-NEXT:    [[CRC_TBL_INDEXER:%.*]] = getelementptr inbounds i8, ptr @.crctable.7, i32 [[CRC_LO_INDEXER]]
 ; CHECK-NEXT:    [[CRC_TBL_INDEX:%.*]] = load i32, ptr [[CRC_TBL_INDEXER]], align 4
 ; CHECK-NEXT:    [[XOR_CRCSHIFT_TBL:%.*]] = xor i32 [[CRC_LE_SHIFT]], [[CRC_TBL_INDEX]]
 ; CHECK-NEXT:    [[FINALIZE_CRC:%.*]] = xor i32 [[XOR_CRCSHIFT_TBL]], -1
 ; CHECK-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ult i8 [[IV]], 0
+; CHECK-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
 ; CHECK-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; CHECK:       [[EXIT]]:
 ; CHECK-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[FINALIZE_CRC]], %[[LOOP]] ]



More information about the llvm-commits mailing list