[llvm] 28d9aec - [LoopIdiom] Use costing to determine CRC strategy (#211040)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 08:40:45 PDT 2026


Author: Sean Clarke
Date: 2026-07-31T16:40:39+01:00
New Revision: 28d9aec513c63beffd2631412adfae327763559e

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

LOG: [LoopIdiom] Use costing to determine CRC strategy (#211040)

The CRC loop clmul optimization currently only runs under optsize,
despite being significantly faster than the Sarwate table optimization
in many cases. Model the costs of each approach and weigh them against
each other to determine which optimization should be used. Since the
benefits of clmul are unclear for optsize, simply bail in that case
instead.

Assisted-by: Claude Opus 4.8

Added: 
    llvm/test/Transforms/LoopIdiom/crc-debugify-remarks.ll

Modified: 
    llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
    llvm/test/Transforms/LoopIdiom/AArch64/cyclic-redundancy-check.ll
    llvm/test/Transforms/LoopIdiom/RISCV/cyclic-redundancy-check.ll
    llvm/test/Transforms/LoopIdiom/X86/cyclic-redundancy-check.ll
    llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
index 131eaa7e08072..4e5cd8462cc4d 100644
--- a/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopIdiomRecognize.cpp
@@ -152,7 +152,7 @@ bool DisableLIRP::HashRecognize;
 static cl::opt<bool, true>
     DisableLIRPHashRecognize("disable-" DEBUG_TYPE "-hashrecognize",
                              cl::desc("Proceed with loop idiom recognize pass, "
-                                      "but do not optimize CRC loops."),
+                                      "but do not do hash-recognize analysis."),
                              cl::location(DisableLIRP::HashRecognize),
                              cl::init(false), cl::ReallyHidden);
 
@@ -167,10 +167,24 @@ static cl::opt<bool> ForceMemsetPatternIntrinsic(
     cl::desc("Use memset.pattern intrinsic whenever possible"), cl::init(false),
     cl::Hidden);
 
-static cl::opt<bool> ForceCRCClmul(
-    "loop-idiom-force-crc-clmul",
-    cl::desc("Use the clmul-based CRC loop optimization whenever possible"),
-    cl::init(false), cl::Hidden);
+enum class CRCStrategyKind {
+  Disable,
+  Auto,
+  Table,
+  Clmul,
+};
+static cl::opt<CRCStrategyKind> CRCStrategy(
+    DEBUG_TYPE "-crc-strategy",
+    cl::desc("Preferred strategy for optimizing CRC loops"),
+    cl::init(CRCStrategyKind::Auto), cl::Hidden,
+    cl::values(clEnumValN(CRCStrategyKind::Disable, "disable",
+                          "Do not optimize CRC loops"),
+               clEnumValN(CRCStrategyKind::Auto, "auto",
+                          "Use costing to determine strategy"),
+               clEnumValN(CRCStrategyKind::Table, "table",
+                          "Use a Sarwate table when possible"),
+               clEnumValN(CRCStrategyKind::Clmul, "clmul",
+                          "Use carry-less multiplication when possible")));
 
 extern cl::opt<bool> ProfcheckDisableMetadataFixes;
 
@@ -406,7 +420,7 @@ bool LoopIdiomRecognize::runOnCountableLoop() {
   }
 
   // Attempt to optimize a CRC loop if one is detected by HashRecognize.
-  if (!DisableLIRP::HashRecognize)
+  if (!DisableLIRP::HashRecognize && CRCStrategy != CRCStrategyKind::Disable)
     if (auto Res = HashRecognize(*CurLoop, *SE).getResult())
       MadeChange |= optimizeCRCLoop(*Res);
 
@@ -1593,43 +1607,127 @@ bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
   if (TT.getArch() == Triple::hexagon)
     return false;
 
-  // The force-crc-clmul flag should cause the clmul optimization to run
-  // unconditionally.
-  if (ForceCRCClmul) {
+  LLVMContext &Ctx = Info.LHS->getContext();
+  Type *CRCTy = Info.LHS->getType();
+  unsigned CRCBW = CRCTy->getIntegerBitWidth();
+
+  // CRC computation is mostly serial, so latency works best for comparison.
+  TargetTransformInfo::TargetCostKind CostKind =
+      TargetTransformInfo::TCK_Latency;
+
+  InstructionCost XorCost =
+      TTI->getArithmeticInstrCost(Instruction::Xor, CRCTy, CostKind);
+  InstructionCost ShiftCost =
+      TTI->getArithmeticInstrCost(Instruction::LShr, CRCTy, CostKind);
+  InstructionCost AndCost =
+      TTI->getArithmeticInstrCost(Instruction::And, CRCTy, CostKind);
+  InstructionCost SelectCost =
+      TTI->getCmpSelInstrCost(Instruction::Select, CRCTy, Type::getInt1Ty(Ctx),
+                              CmpInst::BAD_ICMP_PREDICATE, CostKind);
+  InstructionCost LoadCost =
+      TTI->getMemoryOpCost(Instruction::Load, CRCTy, DL->getABITypeAlign(CRCTy),
+                           DL->getDefaultGlobalsAddressSpace(), CostKind);
+  auto ClmulCost = [&](unsigned BW) {
+    auto *Ty = IntegerType::get(Ctx, BW);
+    IntrinsicCostAttributes Attrs(Intrinsic::clmul, Ty, {Ty, Ty});
+    return TTI->getIntrinsicInstrCost(Attrs, CostKind);
+  };
+
+  // Estimate the cost of the original, unoptimized loop.
+  InstructionCost OrigLoopCost =
+      (2 * ShiftCost + 2 * XorCost + AndCost + SelectCost) * Info.TripCount;
+
+  // Estimate the cost of the Sarwate lookup table optimization strategy.
+  // As mentioned previously, a byte-multiple trip count is required.
+  InstructionCost TableStrategyCost =
+      Info.TripCount % 8 != 0
+          ? InstructionCost::getInvalid()
+          : (LoadCost + XorCost + 2 * ShiftCost) * (Info.TripCount / 8);
+
+  // Estimate the cost of the carry-less multiplication optimization strategy.
+  InstructionCost ClmulStrategyCost = ClmulCost(2 * Info.TripCount) +
+                                      ClmulCost(CRCBW + Info.TripCount) +
+                                      2 * XorCost + 2 * ShiftCost + AndCost;
+
+  ORE.emit([&]() {
+    return OptimizationRemarkAnalysis(DEBUG_TYPE, "CRCLoopCosts",
+                                      CurLoop->getStartLoc(),
+                                      CurLoop->getHeader())
+           << "CRC loop costs: original="
+           << ore::NV("OrigLoopCost", OrigLoopCost)
+           << ", table=" << ore::NV("TableStrategyCost", TableStrategyCost)
+           << ", clmul=" << ore::NV("ClmulStrategyCost", ClmulStrategyCost);
+  });
+
+  auto ReportMissed = [&](StringRef Reason) {
+    ORE.emit([&]() {
+      return OptimizationRemarkMissed(DEBUG_TYPE, "CRCLoopMissed",
+                                      CurLoop->getStartLoc(),
+                                      CurLoop->getHeader())
+             << "CRC loop not optimized: " << Reason;
+    });
+  };
+  auto ReportOptimized = [&](StringRef Strategy, StringRef Reason) {
+    ORE.emit([&]() {
+      return OptimizationRemark(DEBUG_TYPE, "CRCLoopOptimized",
+                                CurLoop->getStartLoc(), CurLoop->getHeader())
+             << "CRC loop optimized using " << ore::NV("Strategy", Strategy)
+             << ": " << Reason;
+    });
+  };
+
+  switch (CRCStrategy) {
+  default:
+    ReportMissed("disabled by user");
+    return false;
+  case CRCStrategyKind::Table:
+    // The table strategy is not possible in its current form without a byte-
+    // multiple trip count.
+    if (Info.TripCount % 8 == 0) {
+      optimizeCRCLoopUsingTableLookup(Info);
+      ReportOptimized("table", "forced by user");
+      return true;
+    }
+    ReportMissed("table strategy forced, but not possible");
+    return false;
+  case CRCStrategyKind::Clmul:
     optimizeCRCLoopUsingClmul(Info);
+    ReportOptimized("clmul", "forced by user");
     return true;
-  }
+  case CRCStrategyKind::Auto:
+    // When using the auto strategy, bail if we are optimizing for size since
+    // there's usually not a clear size benefit.
+    // TODO: The clmul optimization is around the same size in many cases, so it
+    // could be worth it to take advantage of that fact, especially if it would
+    // be much faster than the original loop.
+    if (ApplyCodeSizeHeuristics) {
+      ReportMissed("optimizing for size");
+      return false;
+    }
 
-  // FIXME: Once intrinsic cost modeling is more reliable for clmul, that should
-  // be used to determine which optimization to use. Until then, only apply the
-  // clmul optimization when optimizing for size, since a lookup table is not
-  // viable in that case.
-  if (!ApplyCodeSizeHeuristics && Info.TripCount % 8 == 0) {
-    optimizeCRCLoopUsingTableLookup(Info);
-    return true;
-  }
+    // Only apply an optimization if there's a clear benefit to doing so.
+    if (std::min(TableStrategyCost, ClmulStrategyCost) >= OrigLoopCost) {
+      ReportMissed("no profitable strategy");
+      return false;
+    }
 
-  // The clmul optimization should be applied if it is fast and likely to lower
-  // in a way that keeps code small.
-  // TODO: If clmul exists on the target but not for the required width, it
-  // might be possible to split into multiple iterations of reduction.
-  unsigned ClmulMuBW = Info.IsBigEndian ? 2 * Info.TripCount : Info.TripCount;
-  unsigned ClmulGPBW =
-      Info.LHS->getType()->getIntegerBitWidth() + Info.TripCount;
-  IntegerType *WidestClmulTy =
-      IntegerType::get(Info.LHS->getContext(), std::max(ClmulMuBW, ClmulGPBW));
-  if (TTI->haveFastClmul(WidestClmulTy)) {
-    optimizeCRCLoopUsingClmul(Info);
+    if (TableStrategyCost <= ClmulStrategyCost) {
+      optimizeCRCLoopUsingTableLookup(Info);
+      ReportOptimized("table", "most profitable strategy");
+    } else {
+      optimizeCRCLoopUsingClmul(Info);
+      ReportOptimized("clmul", "most profitable strategy");
+    }
     return true;
   }
-
-  return false;
 }
 
 // The algorithm used in this optimization is a Polynomial (GF(2)) Barrett
 // Reduction based on Intel's "Fast CRC Computation for Generic Polynomials
 // Using PCLMULQDQ Instruction" white paper (December 2009).
 void LoopIdiomRecognize::optimizeCRCLoopUsingClmul(const PolynomialInfo &Info) {
+  // TODO: If clmul exists on the target but not for the required width, it
+  // might be possible to split into multiple iterations of reduction.
   Type *CRCTy = Info.LHS->getType();
   LLVMContext &Ctx = CRCTy->getContext();
   unsigned CRCBW = CRCTy->getIntegerBitWidth();

diff  --git a/llvm/test/Transforms/LoopIdiom/AArch64/cyclic-redundancy-check.ll b/llvm/test/Transforms/LoopIdiom/AArch64/cyclic-redundancy-check.ll
index 89b6f085f128d..d94f8b959e9a9 100644
--- a/llvm/test/Transforms/LoopIdiom/AArch64/cyclic-redundancy-check.ll
+++ b/llvm/test/Transforms/LoopIdiom/AArch64/cyclic-redundancy-check.ll
@@ -1,49 +1,30 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 5
 ; RUN: opt -passes=loop-idiom -mtriple=aarch64 -mattr=-aes -S %s | FileCheck --check-prefixes=ALL,NOAES %s
 ; RUN: opt -passes=loop-idiom -mtriple=aarch64 -mattr=+aes -S %s | FileCheck --check-prefixes=ALL,AES %s
 
-define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) optsize {
-; NOAES-LABEL: define i16 @crc16.le.tc8(
-; NOAES-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
-; NOAES-NEXT:  [[ENTRY:.*]]:
-; NOAES-NEXT:    br label %[[LOOP:.*]]
-; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
-; NOAES-NEXT:    [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
-; NOAES-NEXT:    [[AND_DATA_CRC:%.*]] = and i8 [[XOR_DATA_CRC]], 1
-; NOAES-NEXT:    [[DATA_NEXT]] = lshr i8 [[DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp eq i8 [[AND_DATA_CRC]], 0
-; NOAES-NEXT:    [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
-; NOAES-NEXT:    [[XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[XOR]]
-; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOAES-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; AES-LABEL: define i16 @crc16.le.tc8(
-; AES-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
-; AES-NEXT:  [[ENTRY:.*:]]
-; AES-NEXT:    [[CRC_CAST:%.*]] = trunc i16 [[CHECKSUM]] to i8
-; AES-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC_CAST]], [[MSG]]
-; AES-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA]], i8 -1)
-; AES-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i24
-; AES-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 81923)
-; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i24
-; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_RECAST]], [[CLMUL_GP]]
-; AES-NEXT:    [[CRC_LSHR1:%.*]] = lshr i24 [[XOR_CRC_MULT]], 8
-; AES-NEXT:    [[CRC_NEXT2:%.*]] = trunc i24 [[CRC_LSHR1]] to i16
-; AES-NEXT:    br label %[[LOOP:.*]]
-; AES:       [[LOOP]]:
-; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; AES:       [[EXIT]]:
-; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
-; AES-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) {
+; ALL-LABEL: define i16 @crc16.le.tc8(
+; ALL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i8 [[MSG]], [[IV_BITS]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = trunc i16 [[CRC2]] to i8
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i8 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[CRC_DATA_INDEXER]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ALL-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -68,46 +49,30 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) optsize {
-; NOAES-LABEL: define i16 @crc16.le.tc16(
-; NOAES-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOAES-NEXT:  [[ENTRY:.*]]:
-; NOAES-NEXT:    br label %[[LOOP:.*]]
-; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
-; NOAES-NEXT:    [[AND_CRC_DATA:%.*]] = and i16 [[XOR_CRC_DATA]], 1
-; NOAES-NEXT:    [[DATA_NEXT]] = lshr i16 [[DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp eq i16 [[AND_CRC_DATA]], 0
-; NOAES-NEXT:    [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
-; NOAES-NEXT:    [[CRC_XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[CRC_XOR]]
-; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOAES-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; AES-LABEL: define i16 @crc16.le.tc16(
-; AES-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; AES-NEXT:  [[ENTRY:.*:]]
-; AES-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i16 [[CHECKSUM]], [[MSG]]
-; AES-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[XOR_CRC_DATA1]], i16 -16385)
-; AES-NEXT:    [[QUOT_CAST:%.*]] = zext i16 [[CLMUL_MU]] to i32
-; AES-NEXT:    [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_CAST]], i32 81923)
-; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i32
-; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_RECAST]], [[CLMUL_GP]]
-; AES-NEXT:    [[CRC_LSHR2:%.*]] = lshr i32 [[XOR_CRC_MULT]], 16
-; AES-NEXT:    [[CRC_NEXT3:%.*]] = trunc i32 [[CRC_LSHR2]] to i16
-; AES-NEXT:    br label %[[LOOP:.*]]
-; AES:       [[LOOP]]:
-; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; AES:       [[EXIT]]:
-; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; AES-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) {
+; ALL-LABEL: define i16 @crc16.le.tc16(
+; ALL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC2]]
+; ALL-NEXT:    [[INDEXER_LO:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.1, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ALL-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -131,48 +96,29 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) optsize {
-; NOAES-LABEL: define i8 @crc8.le.tc16(
-; NOAES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOAES-NEXT:  [[ENTRY:.*]]:
-; NOAES-NEXT:    br label %[[LOOP:.*]]
-; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
-; NOAES-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOAES-NEXT:    [[AND_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
-; NOAES-NEXT:    [[DATA_NEXT]] = lshr i16 [[DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp eq i8 [[AND_CRC_DATA]], 0
-; NOAES-NEXT:    [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
-; NOAES-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 29
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
-; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOAES-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; AES-LABEL: define i8 @crc8.le.tc16(
-; AES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; AES-NEXT:  [[ENTRY:.*:]]
-; AES-NEXT:    [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i16
-; AES-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i16 [[CRC_CAST]], [[MSG]]
-; AES-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[XOR_CRC_DATA1]], i16 24423)
-; AES-NEXT:    [[QUOT_CAST:%.*]] = zext i16 [[CLMUL_MU]] to i24
-; AES-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 59)
-; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i24
-; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_RECAST]], [[CLMUL_GP]]
-; AES-NEXT:    [[CRC_LSHR2:%.*]] = lshr i24 [[XOR_CRC_MULT]], 16
-; AES-NEXT:    [[CRC_NEXT3:%.*]] = trunc i24 [[CRC_LSHR2]] to i8
-; AES-NEXT:    br label %[[LOOP:.*]]
-; AES:       [[LOOP]]:
-; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; AES:       [[EXIT]]:
-; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; AES-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) {
+; ALL-LABEL: define i8 @crc8.le.tc16(
+; ALL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_LO:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.2, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ALL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -197,46 +143,31 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) optsize {
-; NOAES-LABEL: define i16 @crc16.be.tc16(
-; NOAES-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOAES-NEXT:  [[ENTRY:.*]]:
-; NOAES-NEXT:    br label %[[LOOP:.*]]
-; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
-; NOAES-NEXT:    [[DATA_NEXT]] = shl i16 [[DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp sge i16 [[XOR_CRC_DATA]], 0
-; NOAES-NEXT:    [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
-; NOAES-NEXT:    [[CRC_XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[CRC_XOR]]
-; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOAES-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; AES-LABEL: define i16 @crc16.be.tc16(
-; AES-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; AES-NEXT:  [[ENTRY:.*:]]
-; AES-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i16 [[CHECKSUM]], [[MSG]]
-; AES-NEXT:    [[TCBITS_CAST:%.*]] = zext i16 [[XOR_CRC_DATA1]] to i32
-; AES-NEXT:    [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[TCBITS_CAST]], i32 69936)
-; AES-NEXT:    [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
-; AES-NEXT:    [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_LSHR]], i32 69665)
-; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i32
-; AES-NEXT:    [[CRC_SHL2:%.*]] = shl i32 [[CRC_RECAST]], 16
-; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_SHL2]], [[CLMUL_GP]]
-; AES-NEXT:    [[CRC_NEXT3:%.*]] = trunc i32 [[XOR_CRC_MULT]] to i16
-; AES-NEXT:    br label %[[LOOP:.*]]
-; AES:       [[LOOP]]:
-; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; AES:       [[EXIT]]:
-; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; AES-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) {
+; ALL-LABEL: define i16 @crc16.be.tc16(
+; ALL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC2]]
+; ALL-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC_DATA_INDEXER]], 8
+; ALL-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.3, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ALL-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -259,50 +190,27 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) optsize {
-; NOAES-LABEL: define i16 @crc16.be.tc8.misalign(
-; NOAES-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOAES-NEXT:  [[ENTRY:.*]]:
-; NOAES-NEXT:    br label %[[LOOP:.*]]
-; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
-; NOAES-NEXT:    [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
-; NOAES-NEXT:    [[DATA_NEXT]] = shl i8 [[DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_DATA_CRC]], 0
-; NOAES-NEXT:    [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
-; NOAES-NEXT:    [[XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[XOR]]
-; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOAES-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; AES-LABEL: define i16 @crc16.be.tc8.misalign(
-; AES-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; AES-NEXT:  [[ENTRY:.*:]]
-; AES-NEXT:    [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i24
-; AES-NEXT:    [[CRC_ALIGN_TC:%.*]] = lshr i24 [[CRC_CAST]], 8
-; AES-NEXT:    [[CRC_TCBITS:%.*]] = and i24 [[CRC_ALIGN_TC]], 255
-; AES-NEXT:    [[TCBITS_CAST:%.*]] = trunc i24 [[CRC_TCBITS]] to i16
-; AES-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[TCBITS_CAST]], i16 273)
-; AES-NEXT:    [[QUOT_LSHR:%.*]] = lshr i16 [[CLMUL_MU]], 8
-; AES-NEXT:    [[QUOT_CAST:%.*]] = zext i16 [[QUOT_LSHR]] to i24
-; AES-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 69665)
-; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i24
-; AES-NEXT:    [[CRC_SHL1:%.*]] = shl i24 [[CRC_RECAST]], 8
-; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_SHL1]], [[CLMUL_GP]]
-; AES-NEXT:    [[CRC_NEXT2:%.*]] = trunc i24 [[XOR_CRC_MULT]] to i16
-; AES-NEXT:    br label %[[LOOP:.*]]
-; AES:       [[LOOP]]:
-; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; AES:       [[EXIT]]:
-; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
-; AES-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) {
+; ALL-LABEL: define i16 @crc16.be.tc8.misalign(
+; ALL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC2]], 8
+; ALL-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.4, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ALL-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -326,52 +234,29 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) optsize {
-; NOAES-LABEL: define i8 @crc8.be.tc16.misalign(
-; NOAES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOAES-NEXT:  [[ENTRY:.*]]:
-; NOAES-NEXT:    br label %[[LOOP:.*]]
-; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
-; NOAES-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOAES-NEXT:    [[DATA_NEXT]] = shl i16 [[DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
-; NOAES-NEXT:    [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
-; NOAES-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
-; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOAES-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; AES-LABEL: define i8 @crc8.be.tc16.misalign(
-; AES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; AES-NEXT:  [[ENTRY:.*:]]
-; AES-NEXT:    [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i24
-; AES-NEXT:    [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i24
-; AES-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i24 [[CRC_CAST]], [[DATA_CAST]]
-; AES-NEXT:    [[CRC_ALIGN_TC:%.*]] = shl i24 [[XOR_CRC_DATA1]], 8
-; AES-NEXT:    [[CRC_TCBITS:%.*]] = and i24 [[CRC_ALIGN_TC]], 65535
-; AES-NEXT:    [[TCBITS_CAST:%.*]] = zext i24 [[CRC_TCBITS]] to i32
-; AES-NEXT:    [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[TCBITS_CAST]], i32 72779)
-; AES-NEXT:    [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
-; AES-NEXT:    [[QUOT_CAST:%.*]] = trunc i32 [[QUOT_LSHR]] to i24
-; AES-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 285)
-; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i24
-; AES-NEXT:    [[CRC_SHL2:%.*]] = shl i24 [[CRC_RECAST]], 16
-; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_SHL2]], [[CLMUL_GP]]
-; AES-NEXT:    [[CRC_NEXT3:%.*]] = trunc i24 [[XOR_CRC_MULT]] to i8
-; AES-NEXT:    br label %[[LOOP:.*]]
-; AES:       [[LOOP]]:
-; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; AES:       [[EXIT]]:
-; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; AES-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) {
+; ALL-LABEL: define i8 @crc8.be.tc16.misalign(
+; ALL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.5, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ALL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -395,48 +280,29 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) optsize {
-; NOAES-LABEL: define i8 @crc8.be.tc8.data16.misalign(
-; NOAES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOAES-NEXT:  [[ENTRY:.*]]:
-; NOAES-NEXT:    br label %[[LOOP:.*]]
-; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
-; NOAES-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOAES-NEXT:    [[DATA_NEXT]] = shl i16 [[DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
-; NOAES-NEXT:    [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
-; NOAES-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
-; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOAES-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; AES-LABEL: define i8 @crc8.be.tc8.data16.misalign(
-; AES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; AES-NEXT:  [[ENTRY:.*:]]
-; AES-NEXT:    [[DATA_CAST:%.*]] = trunc i16 [[MSG]] to i8
-; AES-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CHECKSUM]], [[DATA_CAST]]
-; AES-NEXT:    [[TCBITS_CAST:%.*]] = zext i8 [[XOR_CRC_DATA1]] to i16
-; AES-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[TCBITS_CAST]], i16 284)
-; AES-NEXT:    [[QUOT_LSHR:%.*]] = lshr i16 [[CLMUL_MU]], 8
-; AES-NEXT:    [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_LSHR]], i16 285)
-; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i16
-; AES-NEXT:    [[CRC_SHL2:%.*]] = shl i16 [[CRC_RECAST]], 8
-; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_SHL2]], [[CLMUL_GP]]
-; AES-NEXT:    [[CRC_NEXT3:%.*]] = trunc i16 [[XOR_CRC_MULT]] to i8
-; AES-NEXT:    br label %[[LOOP:.*]]
-; AES:       [[LOOP]]:
-; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; AES:       [[EXIT]]:
-; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; AES-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) {
+; ALL-LABEL: define i8 @crc8.be.tc8.data16.misalign(
+; ALL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.6, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ALL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -460,48 +326,30 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) optsize {
-; NOAES-LABEL: define i32 @crc32.le.tc8.data32(
-; NOAES-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; NOAES-NEXT:  [[ENTRY:.*]]:
-; NOAES-NEXT:    br label %[[LOOP:.*]]
-; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
-; NOAES-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
-; NOAES-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
-; NOAES-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
-; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOAES-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
-;
-; AES-LABEL: define i32 @crc32.le.tc8.data32(
-; AES-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; AES-NEXT:  [[ENTRY:.*:]]
-; AES-NEXT:    [[CRC_CAST:%.*]] = trunc i32 [[CHECKSUM]] to i8
-; AES-NEXT:    [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i8
-; AES-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CRC_CAST]], [[DATA_CAST]]
-; AES-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA1]], i8 17)
-; AES-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i40
-; AES-NEXT:    [[CLMUL_GP:%.*]] = call i40 @llvm.clmul.i40(i40 [[QUOT_CAST]], i40 67601)
-; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i32 [[CHECKSUM]] to i40
-; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i40 [[CRC_RECAST]], [[CLMUL_GP]]
-; AES-NEXT:    [[CRC_LSHR2:%.*]] = lshr i40 [[XOR_CRC_MULT]], 8
-; AES-NEXT:    [[CRC_NEXT3:%.*]] = trunc i40 [[CRC_LSHR2]] to i32
-; AES-NEXT:    br label %[[LOOP:.*]]
-; AES:       [[LOOP]]:
-; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; AES:       [[EXIT]]:
-; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; AES-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
+define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) {
+; ALL-LABEL: define i32 @crc32.le.tc8.data32(
+; ALL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; ALL-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.7, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; ALL-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -525,48 +373,29 @@ exit:                                              ; preds = %loop
   ret i32 %crc.next
 }
 
-define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) optsize {
-; NOAES-LABEL: define i8 @crc8.le.tc8.data32(
-; NOAES-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; NOAES-NEXT:  [[ENTRY:.*]]:
-; NOAES-NEXT:    br label %[[LOOP:.*]]
-; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA_TRUNC:%.*]] = trunc i32 [[DATA]] to i8
-; NOAES-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOAES-NEXT:    [[SB_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp eq i8 [[SB_CRC_DATA]], 0
-; NOAES-NEXT:    [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
-; NOAES-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 59
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
-; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOAES-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; AES-LABEL: define i8 @crc8.le.tc8.data32(
-; AES-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; AES-NEXT:  [[ENTRY:.*:]]
-; AES-NEXT:    [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i8
-; AES-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CHECKSUM]], [[DATA_CAST]]
-; AES-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA1]], i8 107)
-; AES-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i16
-; AES-NEXT:    [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_CAST]], i16 119)
-; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i16
-; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_RECAST]], [[CLMUL_GP]]
-; AES-NEXT:    [[CRC_LSHR2:%.*]] = lshr i16 [[XOR_CRC_MULT]], 8
-; AES-NEXT:    [[CRC_NEXT3:%.*]] = trunc i16 [[CRC_LSHR2]] to i8
-; AES-NEXT:    br label %[[LOOP:.*]]
-; AES:       [[LOOP]]:
-; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; AES:       [[EXIT]]:
-; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; AES-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) {
+; ALL-LABEL: define i8 @crc8.le.tc8.data32(
+; ALL-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i32
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.8, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ALL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -591,27 +420,29 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) optsize {
+define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) {
 ; NOAES-LABEL: define i32 @crc32.le.tc32(
 ; NOAES-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
 ; NOAES-NEXT:  [[ENTRY:.*]]:
 ; NOAES-NEXT:    br label %[[LOOP:.*]]
 ; NOAES:       [[LOOP]]:
-; NOAES-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
 ; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOAES-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
-; NOAES-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
-; NOAES-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
-; NOAES-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
-; NOAES-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
-; NOAES-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
+; NOAES-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOAES-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOAES-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; NOAES-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; NOAES-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; NOAES-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; NOAES-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; NOAES-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.9, i64 [[INDEXER_EXT]]
+; NOAES-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; NOAES-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; NOAES-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
 ; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOAES-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; NOAES-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
-; NOAES-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOAES-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 3
+; NOAES-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; NOAES:       [[EXIT]]:
-; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
+; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
 ; NOAES-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
 ;
 ; AES-LABEL: define i32 @crc32.le.tc32(
@@ -654,28 +485,48 @@ exit:                                              ; preds = %loop
   ret i32 %crc.next
 }
 
-define i64 @crc64.le.tc64(i64 %checksum, i64 %msg) optsize {
-; ALL-LABEL: define i64 @crc64.le.tc64(
-; ALL-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0:[0-9]+]] {
-; ALL-NEXT:  [[ENTRY:.*]]:
-; ALL-NEXT:    br label %[[LOOP:.*]]
-; ALL:       [[LOOP]]:
-; ALL-NEXT:    [[CRC:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; ALL-NEXT:    [[DATA:%.*]] = phi i64 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; ALL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i64 [[CRC]], [[DATA]]
-; ALL-NEXT:    [[SB_CRC_DATA:%.*]] = and i64 [[XOR_CRC_DATA]], 1
-; ALL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i64 [[SB_CRC_DATA]], 0
-; ALL-NEXT:    [[CRC_LSHR:%.*]] = lshr i64 [[CRC]], 1
-; ALL-NEXT:    [[CRC_XOR:%.*]] = xor i64 [[CRC_LSHR]], 33800
-; ALL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i64 [[CRC_LSHR]], i64 [[CRC_XOR]]
-; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; ALL-NEXT:    [[DATA_NEXT]] = lshr i64 [[DATA]], 1
-; ALL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 63
-; ALL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; ALL:       [[EXIT]]:
-; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT]], %[[LOOP]] ]
-; ALL-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
+define i64 @crc64.le.tc64(i64 %checksum, i64 %msg) {
+; NOAES-LABEL: define i64 @crc64.le.tc64(
+; NOAES-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0]] {
+; NOAES-NEXT:  [[ENTRY:.*]]:
+; NOAES-NEXT:    br label %[[LOOP:.*]]
+; NOAES:       [[LOOP]]:
+; NOAES-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOAES-NEXT:    [[CRC2:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOAES-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOAES-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i64
+; NOAES-NEXT:    [[DATA_INDEXER:%.*]] = lshr i64 [[MSG]], [[IV_INDEXER]]
+; NOAES-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i64 [[DATA_INDEXER]], [[CRC2]]
+; NOAES-NEXT:    [[INDEXER_LO:%.*]] = trunc i64 [[CRC_DATA_INDEXER]] to i8
+; NOAES-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; NOAES-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i64, ptr @.crctable.10, i64 [[INDEXER_EXT]]
+; NOAES-NEXT:    [[TBL_LD:%.*]] = load i64, ptr [[TBL_PTRADD]], align 8
+; NOAES-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i64 [[CRC2]], 8
+; NOAES-NEXT:    [[CRC_NEXT3]] = xor i64 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOAES-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOAES-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 7
+; NOAES-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOAES:       [[EXIT]]:
+; NOAES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOAES-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
+;
+; AES-LABEL: define i64 @crc64.le.tc64(
+; AES-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0]] {
+; AES-NEXT:  [[ENTRY:.*:]]
+; AES-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i64 [[CHECKSUM]], [[MSG]]
+; AES-NEXT:    [[CLMUL_MU:%.*]] = call i64 @llvm.clmul.i64(i64 [[XOR_CRC_DATA1]], i64 -8819450999508297455)
+; AES-NEXT:    [[QUOT_CAST:%.*]] = zext i64 [[CLMUL_MU]] to i128
+; AES-NEXT:    [[CLMUL_GP:%.*]] = call i128 @llvm.clmul.i128(i128 [[QUOT_CAST]], i128 67601)
+; AES-NEXT:    [[CRC_RECAST:%.*]] = zext i64 [[CHECKSUM]] to i128
+; AES-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i128 [[CRC_RECAST]], [[CLMUL_GP]]
+; AES-NEXT:    [[CRC_LSHR2:%.*]] = lshr i128 [[XOR_CRC_MULT]], 64
+; AES-NEXT:    [[CRC_NEXT3:%.*]] = trunc i128 [[CRC_LSHR2]] to i64
+; AES-NEXT:    br label %[[LOOP:.*]]
+; AES:       [[LOOP]]:
+; AES-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
+; AES:       [[EXIT]]:
+; AES-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; AES-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -698,9 +549,48 @@ loop:                                              ; preds = %loop, %entry
 exit:                                              ; preds = %loop
   ret i64 %crc.next
 }
-;.
-; NOAES: attributes #[[ATTR0]] = { optsize "target-features"="-aes" }
-;.
-; AES: attributes #[[ATTR0]] = { optsize "target-features"="+aes" }
-; AES: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
-;.
+
+define i32 @crc.disabled.optsize(i32 %checksum, i32 %msg) optsize {
+; ALL-LABEL: define i32 @crc.disabled.optsize(
+; ALL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR1:[0-9]+]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
+; ALL-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
+; ALL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
+; ALL-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
+; ALL-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
+; ALL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
+; ALL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
+; ALL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
+; ALL-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, 31
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i32 %crc.next
+}

diff  --git a/llvm/test/Transforms/LoopIdiom/RISCV/cyclic-redundancy-check.ll b/llvm/test/Transforms/LoopIdiom/RISCV/cyclic-redundancy-check.ll
index 3b841e8f3faf3..6af075808f6c1 100644
--- a/llvm/test/Transforms/LoopIdiom/RISCV/cyclic-redundancy-check.ll
+++ b/llvm/test/Transforms/LoopIdiom/RISCV/cyclic-redundancy-check.ll
@@ -1,51 +1,101 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
-; RUN: opt -passes=loop-idiom -mtriple=riscv32 -mattr=-zbc -S %s | FileCheck --check-prefixes=ALL,NOZBC,NOZBC32 %s
-; RUN: opt -passes=loop-idiom -mtriple=riscv64 -mattr=-zbc -S %s | FileCheck --check-prefixes=ALL,NOZBC,NOZBC64 %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 5
+; RUN: opt -passes=loop-idiom -mtriple=riscv32 -mattr=-zbc -S %s | FileCheck --check-prefixes=ALL,NOZBC32 %s
+; RUN: opt -passes=loop-idiom -mtriple=riscv64 -mattr=-zbc -S %s | FileCheck --check-prefixes=ALL,NOZBC64 %s
 ; RUN: opt -passes=loop-idiom -mtriple=riscv32 -mattr=+zbc -S %s | FileCheck --check-prefixes=ALL,ZBC,ZBC32 %s
 ; RUN: opt -passes=loop-idiom -mtriple=riscv64 -mattr=+zbc -S %s | FileCheck --check-prefixes=ALL,ZBC,ZBC64 %s
 
-define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) optsize {
-; NOZBC-LABEL: define i16 @crc16.le.tc8(
-; NOZBC-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
-; NOZBC-NEXT:    [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
-; NOZBC-NEXT:    [[AND_DATA_CRC:%.*]] = and i8 [[XOR_DATA_CRC]], 1
-; NOZBC-NEXT:    [[DATA_NEXT]] = lshr i8 [[DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp eq i8 [[AND_DATA_CRC]], 0
-; NOZBC-NEXT:    [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
-; NOZBC-NEXT:    [[XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; ZBC-LABEL: define i16 @crc16.le.tc8(
-; ZBC-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
-; ZBC-NEXT:  [[ENTRY:.*:]]
-; ZBC-NEXT:    [[CRC_CAST:%.*]] = trunc i16 [[CHECKSUM]] to i8
-; ZBC-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC_CAST]], [[MSG]]
-; ZBC-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA]], i8 -1)
-; ZBC-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i24
-; ZBC-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 81923)
-; ZBC-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i24
-; ZBC-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_RECAST]], [[CLMUL_GP]]
-; ZBC-NEXT:    [[CRC_LSHR1:%.*]] = lshr i24 [[XOR_CRC_MULT]], 8
-; ZBC-NEXT:    [[CRC_NEXT2:%.*]] = trunc i24 [[CRC_LSHR1]] to i16
-; ZBC-NEXT:    br label %[[LOOP:.*]]
-; ZBC:       [[LOOP]]:
-; ZBC-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; ZBC:       [[EXIT]]:
-; ZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
-; ZBC-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) {
+; NOZBC32-LABEL: define i16 @crc16.le.tc8(
+; NOZBC32-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i8 [[MSG]], [[IV_BITS]]
+; NOZBC32-NEXT:    [[CRC_INDEXER_CAST:%.*]] = trunc i16 [[CRC2]] to i8
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i8 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[CRC_DATA_INDEXER]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; NOZBC32-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; NOZBC32-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i16 @crc16.le.tc8(
+; NOZBC64-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i8 [[MSG]], [[IV_BITS]]
+; NOZBC64-NEXT:    [[CRC_INDEXER_CAST:%.*]] = trunc i16 [[CRC2]] to i8
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i8 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[CRC_DATA_INDEXER]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; NOZBC64-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; NOZBC64-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+; ZBC32-LABEL: define i16 @crc16.le.tc8(
+; ZBC32-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
+; ZBC32-NEXT:  [[ENTRY:.*]]:
+; ZBC32-NEXT:    br label %[[LOOP:.*]]
+; ZBC32:       [[LOOP]]:
+; ZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i8 [[MSG]], [[IV_BITS]]
+; ZBC32-NEXT:    [[CRC_INDEXER_CAST:%.*]] = trunc i16 [[CRC2]] to i8
+; ZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i8 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[CRC_DATA_INDEXER]] to i32
+; ZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable, i32 [[INDEXER_EXT]]
+; ZBC32-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ZBC32-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; ZBC32-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC32:       [[EXIT]]:
+; ZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ZBC32-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+; ZBC64-LABEL: define i16 @crc16.le.tc8(
+; ZBC64-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
+; ZBC64-NEXT:  [[ENTRY:.*]]:
+; ZBC64-NEXT:    br label %[[LOOP:.*]]
+; ZBC64:       [[LOOP]]:
+; ZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i8 [[MSG]], [[IV_BITS]]
+; ZBC64-NEXT:    [[CRC_INDEXER_CAST:%.*]] = trunc i16 [[CRC2]] to i8
+; ZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i8 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[CRC_DATA_INDEXER]] to i64
+; ZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable, i64 [[INDEXER_EXT]]
+; ZBC64-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ZBC64-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; ZBC64-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC64:       [[EXIT]]:
+; ZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ZBC64-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -70,31 +120,57 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) optsize {
-; NOZBC-LABEL: define i16 @crc16.le.tc16(
-; NOZBC-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
-; NOZBC-NEXT:    [[AND_CRC_DATA:%.*]] = and i16 [[XOR_CRC_DATA]], 1
-; NOZBC-NEXT:    [[DATA_NEXT]] = lshr i16 [[DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp eq i16 [[AND_CRC_DATA]], 0
-; NOZBC-NEXT:    [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
-; NOZBC-NEXT:    [[CRC_XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[CRC_XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) {
+; NOZBC32-LABEL: define i16 @crc16.le.tc16(
+; NOZBC32-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC32-NEXT:    [[INDEXER_LO:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.1, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; NOZBC32-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; NOZBC32-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i16 @crc16.le.tc16(
+; NOZBC64-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC64-NEXT:    [[INDEXER_LO:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.1, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; NOZBC64-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; NOZBC64-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 ; ZBC-LABEL: define i16 @crc16.le.tc16(
-; ZBC-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ZBC-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
 ; ZBC-NEXT:  [[ENTRY:.*:]]
 ; ZBC-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i16 [[CHECKSUM]], [[MSG]]
 ; ZBC-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[XOR_CRC_DATA1]], i16 -16385)
@@ -133,29 +209,52 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) optsize {
-; NOZBC-LABEL: define i8 @crc8.le.tc16(
-; NOZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
-; NOZBC-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOZBC-NEXT:    [[AND_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
-; NOZBC-NEXT:    [[DATA_NEXT]] = lshr i16 [[DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp eq i8 [[AND_CRC_DATA]], 0
-; NOZBC-NEXT:    [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
-; NOZBC-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 29
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) {
+; NOZBC32-LABEL: define i8 @crc8.le.tc16(
+; NOZBC32-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC32-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC32-NEXT:    [[INDEXER_LO:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.2, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i8 @crc8.le.tc16(
+; NOZBC64-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC64-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC64-NEXT:    [[INDEXER_LO:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.2, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 ; ZBC-LABEL: define i8 @crc8.le.tc16(
 ; ZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
@@ -199,27 +298,56 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) optsize {
-; NOZBC-LABEL: define i16 @crc16.be.tc16(
-; NOZBC-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
-; NOZBC-NEXT:    [[DATA_NEXT]] = shl i16 [[DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp sge i16 [[XOR_CRC_DATA]], 0
-; NOZBC-NEXT:    [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
-; NOZBC-NEXT:    [[CRC_XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[CRC_XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) {
+; NOZBC32-LABEL: define i16 @crc16.be.tc16(
+; NOZBC32-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC32-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC_DATA_INDEXER]], 8
+; NOZBC32-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.3, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; NOZBC32-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; NOZBC32-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i16 @crc16.be.tc16(
+; NOZBC64-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC64-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC_DATA_INDEXER]], 8
+; NOZBC64-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.3, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; NOZBC64-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; NOZBC64-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 ; ZBC-LABEL: define i16 @crc16.be.tc16(
 ; ZBC-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
@@ -261,50 +389,90 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) optsize {
-; NOZBC-LABEL: define i16 @crc16.be.tc8.misalign(
-; NOZBC-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
-; NOZBC-NEXT:    [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
-; NOZBC-NEXT:    [[DATA_NEXT]] = shl i8 [[DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_DATA_CRC]], 0
-; NOZBC-NEXT:    [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
-; NOZBC-NEXT:    [[XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; ZBC-LABEL: define i16 @crc16.be.tc8.misalign(
-; ZBC-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; ZBC-NEXT:  [[ENTRY:.*:]]
-; ZBC-NEXT:    [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i24
-; ZBC-NEXT:    [[CRC_ALIGN_TC:%.*]] = lshr i24 [[CRC_CAST]], 8
-; ZBC-NEXT:    [[CRC_TCBITS:%.*]] = and i24 [[CRC_ALIGN_TC]], 255
-; ZBC-NEXT:    [[TCBITS_CAST:%.*]] = trunc i24 [[CRC_TCBITS]] to i16
-; ZBC-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[TCBITS_CAST]], i16 273)
-; ZBC-NEXT:    [[QUOT_LSHR:%.*]] = lshr i16 [[CLMUL_MU]], 8
-; ZBC-NEXT:    [[QUOT_CAST:%.*]] = zext i16 [[QUOT_LSHR]] to i24
-; ZBC-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 69665)
-; ZBC-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i24
-; ZBC-NEXT:    [[CRC_SHL1:%.*]] = shl i24 [[CRC_RECAST]], 8
-; ZBC-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_SHL1]], [[CLMUL_GP]]
-; ZBC-NEXT:    [[CRC_NEXT2:%.*]] = trunc i24 [[XOR_CRC_MULT]] to i16
-; ZBC-NEXT:    br label %[[LOOP:.*]]
-; ZBC:       [[LOOP]]:
-; ZBC-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; ZBC:       [[EXIT]]:
-; ZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
-; ZBC-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) {
+; NOZBC32-LABEL: define i16 @crc16.be.tc8.misalign(
+; NOZBC32-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC2]], 8
+; NOZBC32-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.4, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; NOZBC32-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; NOZBC32-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i16 @crc16.be.tc8.misalign(
+; NOZBC64-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC2]], 8
+; NOZBC64-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.4, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; NOZBC64-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; NOZBC64-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+; ZBC32-LABEL: define i16 @crc16.be.tc8.misalign(
+; ZBC32-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ZBC32-NEXT:  [[ENTRY:.*]]:
+; ZBC32-NEXT:    br label %[[LOOP:.*]]
+; ZBC32:       [[LOOP]]:
+; ZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC2]], 8
+; ZBC32-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; ZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i32
+; ZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.1, i32 [[INDEXER_EXT]]
+; ZBC32-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ZBC32-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; ZBC32-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; ZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC32:       [[EXIT]]:
+; ZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ZBC32-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+;
+; ZBC64-LABEL: define i16 @crc16.be.tc8.misalign(
+; ZBC64-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ZBC64-NEXT:  [[ENTRY:.*]]:
+; ZBC64-NEXT:    br label %[[LOOP:.*]]
+; ZBC64:       [[LOOP]]:
+; ZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC2]], 8
+; ZBC64-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; ZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.1, i64 [[INDEXER_EXT]]
+; ZBC64-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ZBC64-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; ZBC64-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; ZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC64:       [[EXIT]]:
+; ZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ZBC64-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -328,28 +496,52 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) optsize {
-; NOZBC-LABEL: define i8 @crc8.be.tc16.misalign(
-; NOZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
-; NOZBC-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOZBC-NEXT:    [[DATA_NEXT]] = shl i16 [[DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
-; NOZBC-NEXT:    [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
-; NOZBC-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) {
+; NOZBC32-LABEL: define i8 @crc8.be.tc16.misalign(
+; NOZBC32-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC32-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC32-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.5, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i8 @crc8.be.tc16.misalign(
+; NOZBC64-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC64-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC64-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.5, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 ; ZBC-LABEL: define i8 @crc8.be.tc16.misalign(
 ; ZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
@@ -397,48 +589,98 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) optsize {
-; NOZBC-LABEL: define i8 @crc8.be.tc8.data16.misalign(
-; NOZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
-; NOZBC-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOZBC-NEXT:    [[DATA_NEXT]] = shl i16 [[DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
-; NOZBC-NEXT:    [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
-; NOZBC-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; ZBC-LABEL: define i8 @crc8.be.tc8.data16.misalign(
-; ZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; ZBC-NEXT:  [[ENTRY:.*:]]
-; ZBC-NEXT:    [[DATA_CAST:%.*]] = trunc i16 [[MSG]] to i8
-; ZBC-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CHECKSUM]], [[DATA_CAST]]
-; ZBC-NEXT:    [[TCBITS_CAST:%.*]] = zext i8 [[XOR_CRC_DATA1]] to i16
-; ZBC-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[TCBITS_CAST]], i16 284)
-; ZBC-NEXT:    [[QUOT_LSHR:%.*]] = lshr i16 [[CLMUL_MU]], 8
-; ZBC-NEXT:    [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_LSHR]], i16 285)
-; ZBC-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i16
-; ZBC-NEXT:    [[CRC_SHL2:%.*]] = shl i16 [[CRC_RECAST]], 8
-; ZBC-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_SHL2]], [[CLMUL_GP]]
-; ZBC-NEXT:    [[CRC_NEXT3:%.*]] = trunc i16 [[XOR_CRC_MULT]] to i8
-; ZBC-NEXT:    br label %[[LOOP:.*]]
-; ZBC:       [[LOOP]]:
-; ZBC-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; ZBC:       [[EXIT]]:
-; ZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; ZBC-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) {
+; NOZBC32-LABEL: define i8 @crc8.be.tc8.data16.misalign(
+; NOZBC32-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC32-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC32-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.6, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i8 @crc8.be.tc8.data16.misalign(
+; NOZBC64-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; NOZBC64-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC64-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.6, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+;
+; ZBC32-LABEL: define i8 @crc8.be.tc8.data16.misalign(
+; ZBC32-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ZBC32-NEXT:  [[ENTRY:.*]]:
+; ZBC32-NEXT:    br label %[[LOOP:.*]]
+; ZBC32:       [[LOOP]]:
+; ZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ZBC32-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; ZBC32-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; ZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ZBC32-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i32
+; ZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.2, i32 [[INDEXER_EXT]]
+; ZBC32-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC32:       [[EXIT]]:
+; ZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ZBC32-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+;
+; ZBC64-LABEL: define i8 @crc8.be.tc8.data16.misalign(
+; ZBC64-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ZBC64-NEXT:  [[ENTRY:.*]]:
+; ZBC64-NEXT:    br label %[[LOOP:.*]]
+; ZBC64:       [[LOOP]]:
+; ZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ZBC64-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; ZBC64-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; ZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ZBC64-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.2, i64 [[INDEXER_EXT]]
+; ZBC64-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC64:       [[EXIT]]:
+; ZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ZBC64-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -462,67 +704,99 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) optsize {
-; NOZBC-LABEL: define i32 @crc32.le.tc8.data32(
-; NOZBC-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
-; NOZBC-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
-; NOZBC-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
-; NOZBC-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
+define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) {
+; NOZBC32-LABEL: define i32 @crc32.le.tc8.data32(
+; NOZBC32-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC32-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.7, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; NOZBC32-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; NOZBC32-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i32 @crc32.le.tc8.data32(
+; NOZBC64-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC64-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.7, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; NOZBC64-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; NOZBC64-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
 ;
 ; ZBC32-LABEL: define i32 @crc32.le.tc8.data32(
 ; ZBC32-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
 ; ZBC32-NEXT:  [[ENTRY:.*]]:
 ; ZBC32-NEXT:    br label %[[LOOP:.*]]
 ; ZBC32:       [[LOOP]]:
-; ZBC32-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; ZBC32-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
 ; ZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; ZBC32-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
-; ZBC32-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
-; ZBC32-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
-; ZBC32-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
-; ZBC32-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
-; ZBC32-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
+; ZBC32-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; ZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; ZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; ZBC32-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; ZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i32
+; ZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.3, i32 [[INDEXER_EXT]]
+; ZBC32-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; ZBC32-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; ZBC32-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
 ; ZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; ZBC32-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; ZBC32-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; ZBC32-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; ZBC32:       [[EXIT]]:
-; ZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
 ; ZBC32-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
 ;
 ; ZBC64-LABEL: define i32 @crc32.le.tc8.data32(
 ; ZBC64-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; ZBC64-NEXT:  [[ENTRY:.*:]]
-; ZBC64-NEXT:    [[CRC_CAST:%.*]] = trunc i32 [[CHECKSUM]] to i8
-; ZBC64-NEXT:    [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i8
-; ZBC64-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CRC_CAST]], [[DATA_CAST]]
-; ZBC64-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA1]], i8 17)
-; ZBC64-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i40
-; ZBC64-NEXT:    [[CLMUL_GP:%.*]] = call i40 @llvm.clmul.i40(i40 [[QUOT_CAST]], i40 67601)
-; ZBC64-NEXT:    [[CRC_RECAST:%.*]] = zext i32 [[CHECKSUM]] to i40
-; ZBC64-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i40 [[CRC_RECAST]], [[CLMUL_GP]]
-; ZBC64-NEXT:    [[CRC_LSHR2:%.*]] = lshr i40 [[XOR_CRC_MULT]], 8
-; ZBC64-NEXT:    [[CRC_NEXT3:%.*]] = trunc i40 [[CRC_LSHR2]] to i32
+; ZBC64-NEXT:  [[ENTRY:.*]]:
 ; ZBC64-NEXT:    br label %[[LOOP:.*]]
 ; ZBC64:       [[LOOP]]:
-; ZBC64-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; ZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; ZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; ZBC64-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; ZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.3, i64 [[INDEXER_EXT]]
+; ZBC64-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; ZBC64-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; ZBC64-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; ZBC64:       [[EXIT]]:
 ; ZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
 ; ZBC64-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
@@ -549,48 +823,98 @@ exit:                                              ; preds = %loop
   ret i32 %crc.next
 }
 
-define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) optsize {
-; NOZBC-LABEL: define i8 @crc8.le.tc8.data32(
-; NOZBC-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA_TRUNC:%.*]] = trunc i32 [[DATA]] to i8
-; NOZBC-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOZBC-NEXT:    [[SB_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp eq i8 [[SB_CRC_DATA]], 0
-; NOZBC-NEXT:    [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
-; NOZBC-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 59
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; ZBC-LABEL: define i8 @crc8.le.tc8.data32(
-; ZBC-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; ZBC-NEXT:  [[ENTRY:.*:]]
-; ZBC-NEXT:    [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i8
-; ZBC-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CHECKSUM]], [[DATA_CAST]]
-; ZBC-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA1]], i8 107)
-; ZBC-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i16
-; ZBC-NEXT:    [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_CAST]], i16 119)
-; ZBC-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i16
-; ZBC-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_RECAST]], [[CLMUL_GP]]
-; ZBC-NEXT:    [[CRC_LSHR2:%.*]] = lshr i16 [[XOR_CRC_MULT]], 8
-; ZBC-NEXT:    [[CRC_NEXT3:%.*]] = trunc i16 [[CRC_LSHR2]] to i8
-; ZBC-NEXT:    br label %[[LOOP:.*]]
-; ZBC:       [[LOOP]]:
-; ZBC-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; ZBC:       [[EXIT]]:
-; ZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; ZBC-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) {
+; NOZBC32-LABEL: define i8 @crc8.le.tc8.data32(
+; NOZBC32-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; NOZBC32-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i32
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC32-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.8, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i8 @crc8.le.tc8.data32(
+; NOZBC64-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; NOZBC64-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i32
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; NOZBC64-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.8, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+;
+; ZBC32-LABEL: define i8 @crc8.le.tc8.data32(
+; ZBC32-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; ZBC32-NEXT:  [[ENTRY:.*]]:
+; ZBC32-NEXT:    br label %[[LOOP:.*]]
+; ZBC32:       [[LOOP]]:
+; ZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; ZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; ZBC32-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i32
+; ZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ZBC32-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; ZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i32
+; ZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.4, i32 [[INDEXER_EXT]]
+; ZBC32-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC32:       [[EXIT]]:
+; ZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ZBC32-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+;
+; ZBC64-LABEL: define i8 @crc8.le.tc8.data32(
+; ZBC64-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; ZBC64-NEXT:  [[ENTRY:.*]]:
+; ZBC64-NEXT:    br label %[[LOOP:.*]]
+; ZBC64:       [[LOOP]]:
+; ZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; ZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; ZBC64-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i32
+; ZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ZBC64-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; ZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.4, i64 [[INDEXER_EXT]]
+; ZBC64-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC64:       [[EXIT]]:
+; ZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ZBC64-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -615,68 +939,72 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) optsize {
-; NOZBC-LABEL: define i32 @crc32.le.tc32(
-; NOZBC-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; NOZBC-NEXT:  [[ENTRY:.*]]:
-; NOZBC-NEXT:    br label %[[LOOP:.*]]
-; NOZBC:       [[LOOP]]:
-; NOZBC-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOZBC-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
-; NOZBC-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
-; NOZBC-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
-; NOZBC-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
-; NOZBC-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
-; NOZBC-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
-; NOZBC-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOZBC-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; NOZBC-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
-; NOZBC-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOZBC:       [[EXIT]]:
-; NOZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOZBC-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
-;
-; ZBC32-LABEL: define i32 @crc32.le.tc32(
-; ZBC32-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; ZBC32-NEXT:  [[ENTRY:.*]]:
-; ZBC32-NEXT:    br label %[[LOOP:.*]]
-; ZBC32:       [[LOOP]]:
-; ZBC32-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; ZBC32-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; ZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; ZBC32-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
-; ZBC32-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
-; ZBC32-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
-; ZBC32-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
-; ZBC32-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
-; ZBC32-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
-; ZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; ZBC32-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; ZBC32-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
-; ZBC32-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; ZBC32:       [[EXIT]]:
-; ZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
-; ZBC32-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
+define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) {
+; NOZBC32-LABEL: define i32 @crc32.le.tc32(
+; NOZBC32-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC32-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.9, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; NOZBC32-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; NOZBC32-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 3
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
 ;
-; ZBC64-LABEL: define i32 @crc32.le.tc32(
-; ZBC64-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; ZBC64-NEXT:  [[ENTRY:.*:]]
-; ZBC64-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i32 [[CHECKSUM]], [[MSG]]
-; ZBC64-NEXT:    [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[XOR_CRC_DATA1]], i32 475535633)
-; ZBC64-NEXT:    [[QUOT_CAST:%.*]] = zext i32 [[CLMUL_MU]] to i64
-; ZBC64-NEXT:    [[CLMUL_GP:%.*]] = call i64 @llvm.clmul.i64(i64 [[QUOT_CAST]], i64 67601)
-; ZBC64-NEXT:    [[CRC_RECAST:%.*]] = zext i32 [[CHECKSUM]] to i64
-; ZBC64-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i64 [[CRC_RECAST]], [[CLMUL_GP]]
-; ZBC64-NEXT:    [[CRC_LSHR2:%.*]] = lshr i64 [[XOR_CRC_MULT]], 32
-; ZBC64-NEXT:    [[CRC_NEXT3:%.*]] = trunc i64 [[CRC_LSHR2]] to i32
-; ZBC64-NEXT:    br label %[[LOOP:.*]]
-; ZBC64:       [[LOOP]]:
-; ZBC64-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; ZBC64:       [[EXIT]]:
-; ZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; ZBC64-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
+; NOZBC64-LABEL: define i32 @crc32.le.tc32(
+; NOZBC64-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC64-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.9, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; NOZBC64-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; NOZBC64-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 3
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
+;
+; ZBC-LABEL: define i32 @crc32.le.tc32(
+; ZBC-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; ZBC-NEXT:  [[ENTRY:.*:]]
+; ZBC-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i32 [[CHECKSUM]], [[MSG]]
+; ZBC-NEXT:    [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[XOR_CRC_DATA1]], i32 475535633)
+; ZBC-NEXT:    [[QUOT_CAST:%.*]] = zext i32 [[CLMUL_MU]] to i64
+; ZBC-NEXT:    [[CLMUL_GP:%.*]] = call i64 @llvm.clmul.i64(i64 [[QUOT_CAST]], i64 67601)
+; ZBC-NEXT:    [[CRC_RECAST:%.*]] = zext i32 [[CHECKSUM]] to i64
+; ZBC-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i64 [[CRC_RECAST]], [[CLMUL_GP]]
+; ZBC-NEXT:    [[CRC_LSHR2:%.*]] = lshr i64 [[XOR_CRC_MULT]], 32
+; ZBC-NEXT:    [[CRC_NEXT3:%.*]] = trunc i64 [[CRC_LSHR2]] to i32
+; ZBC-NEXT:    br label %[[LOOP:.*]]
+; ZBC:       [[LOOP]]:
+; ZBC-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC:       [[EXIT]]:
+; ZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ZBC-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -700,28 +1028,72 @@ exit:                                              ; preds = %loop
   ret i32 %crc.next
 }
 
-define i64 @crc64.le.tc64(i64 %checksum, i64 %msg) optsize {
-; ALL-LABEL: define i64 @crc64.le.tc64(
-; ALL-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0:[0-9]+]] {
-; ALL-NEXT:  [[ENTRY:.*]]:
-; ALL-NEXT:    br label %[[LOOP:.*]]
-; ALL:       [[LOOP]]:
-; ALL-NEXT:    [[CRC:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; ALL-NEXT:    [[DATA:%.*]] = phi i64 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; ALL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i64 [[CRC]], [[DATA]]
-; ALL-NEXT:    [[SB_CRC_DATA:%.*]] = and i64 [[XOR_CRC_DATA]], 1
-; ALL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i64 [[SB_CRC_DATA]], 0
-; ALL-NEXT:    [[CRC_LSHR:%.*]] = lshr i64 [[CRC]], 1
-; ALL-NEXT:    [[CRC_XOR:%.*]] = xor i64 [[CRC_LSHR]], 33800
-; ALL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i64 [[CRC_LSHR]], i64 [[CRC_XOR]]
-; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; ALL-NEXT:    [[DATA_NEXT]] = lshr i64 [[DATA]], 1
-; ALL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 63
-; ALL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; ALL:       [[EXIT]]:
-; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT]], %[[LOOP]] ]
-; ALL-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
+define i64 @crc64.le.tc64(i64 %checksum, i64 %msg) {
+; NOZBC32-LABEL: define i64 @crc64.le.tc64(
+; NOZBC32-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0]] {
+; NOZBC32-NEXT:  [[ENTRY:.*]]:
+; NOZBC32-NEXT:    br label %[[LOOP:.*]]
+; NOZBC32:       [[LOOP]]:
+; NOZBC32-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[CRC2:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC32-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC32-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i64
+; NOZBC32-NEXT:    [[DATA_INDEXER:%.*]] = lshr i64 [[MSG]], [[IV_INDEXER]]
+; NOZBC32-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i64 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC32-NEXT:    [[INDEXER_LO:%.*]] = trunc i64 [[CRC_DATA_INDEXER]] to i8
+; NOZBC32-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i32
+; NOZBC32-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i64, ptr @.crctable.10, i32 [[INDEXER_EXT]]
+; NOZBC32-NEXT:    [[TBL_LD:%.*]] = load i64, ptr [[TBL_PTRADD]], align 8
+; NOZBC32-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i64 [[CRC2]], 8
+; NOZBC32-NEXT:    [[CRC_NEXT3]] = xor i64 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC32-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC32-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 7
+; NOZBC32-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC32:       [[EXIT]]:
+; NOZBC32-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC32-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
+;
+; NOZBC64-LABEL: define i64 @crc64.le.tc64(
+; NOZBC64-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0]] {
+; NOZBC64-NEXT:  [[ENTRY:.*]]:
+; NOZBC64-NEXT:    br label %[[LOOP:.*]]
+; NOZBC64:       [[LOOP]]:
+; NOZBC64-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[CRC2:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOZBC64-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOZBC64-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i64
+; NOZBC64-NEXT:    [[DATA_INDEXER:%.*]] = lshr i64 [[MSG]], [[IV_INDEXER]]
+; NOZBC64-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i64 [[DATA_INDEXER]], [[CRC2]]
+; NOZBC64-NEXT:    [[INDEXER_LO:%.*]] = trunc i64 [[CRC_DATA_INDEXER]] to i8
+; NOZBC64-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; NOZBC64-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i64, ptr @.crctable.10, i64 [[INDEXER_EXT]]
+; NOZBC64-NEXT:    [[TBL_LD:%.*]] = load i64, ptr [[TBL_PTRADD]], align 8
+; NOZBC64-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i64 [[CRC2]], 8
+; NOZBC64-NEXT:    [[CRC_NEXT3]] = xor i64 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOZBC64-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOZBC64-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 7
+; NOZBC64-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOZBC64:       [[EXIT]]:
+; NOZBC64-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOZBC64-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
+;
+; ZBC-LABEL: define i64 @crc64.le.tc64(
+; ZBC-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0]] {
+; ZBC-NEXT:  [[ENTRY:.*:]]
+; ZBC-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i64 [[CHECKSUM]], [[MSG]]
+; ZBC-NEXT:    [[CLMUL_MU:%.*]] = call i64 @llvm.clmul.i64(i64 [[XOR_CRC_DATA1]], i64 -8819450999508297455)
+; ZBC-NEXT:    [[QUOT_CAST:%.*]] = zext i64 [[CLMUL_MU]] to i128
+; ZBC-NEXT:    [[CLMUL_GP:%.*]] = call i128 @llvm.clmul.i128(i128 [[QUOT_CAST]], i128 67601)
+; ZBC-NEXT:    [[CRC_RECAST:%.*]] = zext i64 [[CHECKSUM]] to i128
+; ZBC-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i128 [[CRC_RECAST]], [[CLMUL_GP]]
+; ZBC-NEXT:    [[CRC_LSHR2:%.*]] = lshr i128 [[XOR_CRC_MULT]], 64
+; ZBC-NEXT:    [[CRC_NEXT3:%.*]] = trunc i128 [[CRC_LSHR2]] to i64
+; ZBC-NEXT:    br label %[[LOOP:.*]]
+; ZBC:       [[LOOP]]:
+; ZBC-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
+; ZBC:       [[EXIT]]:
+; ZBC-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ZBC-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -744,17 +1116,48 @@ loop:                                              ; preds = %loop, %entry
 exit:                                              ; preds = %loop
   ret i64 %crc.next
 }
-;.
-; NOZBC32: attributes #[[ATTR0]] = { optsize "target-features"="-zbc" }
-;.
-; NOZBC64: attributes #[[ATTR0]] = { optsize "target-features"="-zbc" }
-;.
-; ZBC32: attributes #[[ATTR0]] = { optsize "target-features"="+zbc" }
-; ZBC32: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
-;.
-; ZBC64: attributes #[[ATTR0]] = { optsize "target-features"="+zbc" }
-; ZBC64: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
-;.
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; NOZBC32: {{.*}}
-; NOZBC64: {{.*}}
+
+define i32 @crc.disabled.optsize(i32 %checksum, i32 %msg) optsize {
+; ALL-LABEL: define i32 @crc.disabled.optsize(
+; ALL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR1:[0-9]+]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
+; ALL-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
+; ALL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
+; ALL-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
+; ALL-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
+; ALL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
+; ALL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
+; ALL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
+; ALL-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, 31
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i32 %crc.next
+}

diff  --git a/llvm/test/Transforms/LoopIdiom/X86/cyclic-redundancy-check.ll b/llvm/test/Transforms/LoopIdiom/X86/cyclic-redundancy-check.ll
index fdb2881b20792..7b03edc1842e2 100644
--- a/llvm/test/Transforms/LoopIdiom/X86/cyclic-redundancy-check.ll
+++ b/llvm/test/Transforms/LoopIdiom/X86/cyclic-redundancy-check.ll
@@ -1,49 +1,30 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals none --version 5
 ; RUN: opt -passes=loop-idiom -mtriple=x86_64 -mattr=-pclmul -S %s | FileCheck --check-prefixes=ALL,NOPCLMUL %s
 ; RUN: opt -passes=loop-idiom -mtriple=x86_64 -mattr=+pclmul -S %s | FileCheck --check-prefixes=ALL,PCLMUL %s
 
-define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) optsize {
-; NOPCLMUL-LABEL: define i16 @crc16.le.tc8(
-; NOPCLMUL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
-; NOPCLMUL-NEXT:    [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
-; NOPCLMUL-NEXT:    [[AND_DATA_CRC:%.*]] = and i8 [[XOR_DATA_CRC]], 1
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = lshr i8 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i8 [[AND_DATA_CRC]], 0
-; NOPCLMUL-NEXT:    [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i16 @crc16.le.tc8(
-; PCLMUL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[CRC_CAST:%.*]] = trunc i16 [[CHECKSUM]] to i8
-; PCLMUL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC_CAST]], [[MSG]]
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA]], i8 -1)
-; PCLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i24
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 81923)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i24
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_RECAST]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_LSHR1:%.*]] = lshr i24 [[XOR_CRC_MULT]], 8
-; PCLMUL-NEXT:    [[CRC_NEXT2:%.*]] = trunc i24 [[CRC_LSHR1]] to i16
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) {
+; ALL-LABEL: define i16 @crc16.le.tc8(
+; ALL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i8 [[MSG]], [[IV_BITS]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = trunc i16 [[CRC2]] to i8
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i8 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[CRC_DATA_INDEXER]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ALL-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -68,46 +49,30 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) optsize {
-; NOPCLMUL-LABEL: define i16 @crc16.le.tc16(
-; NOPCLMUL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
-; NOPCLMUL-NEXT:    [[AND_CRC_DATA:%.*]] = and i16 [[XOR_CRC_DATA]], 1
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = lshr i16 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i16 [[AND_CRC_DATA]], 0
-; NOPCLMUL-NEXT:    [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[CRC_XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[CRC_XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i16 @crc16.le.tc16(
-; PCLMUL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i16 [[CHECKSUM]], [[MSG]]
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[XOR_CRC_DATA1]], i16 -16385)
-; PCLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i16 [[CLMUL_MU]] to i32
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_CAST]], i32 81923)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i32
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_RECAST]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_LSHR2:%.*]] = lshr i32 [[XOR_CRC_MULT]], 16
-; PCLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i32 [[CRC_LSHR2]] to i16
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) {
+; ALL-LABEL: define i16 @crc16.le.tc16(
+; ALL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC2]]
+; ALL-NEXT:    [[INDEXER_LO:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.1, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ALL-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i16 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -131,48 +96,29 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) optsize {
-; NOPCLMUL-LABEL: define i8 @crc8.le.tc16(
-; NOPCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
-; NOPCLMUL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOPCLMUL-NEXT:    [[AND_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = lshr i16 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i8 [[AND_CRC_DATA]], 0
-; NOPCLMUL-NEXT:    [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 29
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i8 @crc8.le.tc16(
-; PCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i16
-; PCLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i16 [[CRC_CAST]], [[MSG]]
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[XOR_CRC_DATA1]], i16 24423)
-; PCLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i16 [[CLMUL_MU]] to i24
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 59)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i24
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_RECAST]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_LSHR2:%.*]] = lshr i24 [[XOR_CRC_MULT]], 16
-; PCLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i24 [[CRC_LSHR2]] to i8
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) {
+; ALL-LABEL: define i8 @crc8.le.tc16(
+; ALL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_LO:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.2, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ALL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -197,46 +143,31 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) optsize {
-; NOPCLMUL-LABEL: define i16 @crc16.be.tc16(
-; NOPCLMUL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = shl i16 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp sge i16 [[XOR_CRC_DATA]], 0
-; NOPCLMUL-NEXT:    [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[CRC_XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[CRC_XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i16 @crc16.be.tc16(
-; PCLMUL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i16 [[CHECKSUM]], [[MSG]]
-; PCLMUL-NEXT:    [[TCBITS_CAST:%.*]] = zext i16 [[XOR_CRC_DATA1]] to i32
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[TCBITS_CAST]], i32 69936)
-; PCLMUL-NEXT:    [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_LSHR]], i32 69665)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i32
-; PCLMUL-NEXT:    [[CRC_SHL2:%.*]] = shl i32 [[CRC_RECAST]], 16
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_SHL2]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i32 [[XOR_CRC_MULT]] to i16
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) {
+; ALL-LABEL: define i16 @crc16.be.tc16(
+; ALL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC2]]
+; ALL-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC_DATA_INDEXER]], 8
+; ALL-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.3, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ALL-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -259,50 +190,27 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) optsize {
-; NOPCLMUL-LABEL: define i16 @crc16.be.tc8.misalign(
-; NOPCLMUL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
-; NOPCLMUL-NEXT:    [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = shl i8 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_DATA_CRC]], 0
-; NOPCLMUL-NEXT:    [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i16 @crc16.be.tc8.misalign(
-; PCLMUL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i24
-; PCLMUL-NEXT:    [[CRC_ALIGN_TC:%.*]] = lshr i24 [[CRC_CAST]], 8
-; PCLMUL-NEXT:    [[CRC_TCBITS:%.*]] = and i24 [[CRC_ALIGN_TC]], 255
-; PCLMUL-NEXT:    [[TCBITS_CAST:%.*]] = trunc i24 [[CRC_TCBITS]] to i16
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[TCBITS_CAST]], i16 273)
-; PCLMUL-NEXT:    [[QUOT_LSHR:%.*]] = lshr i16 [[CLMUL_MU]], 8
-; PCLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i16 [[QUOT_LSHR]] to i24
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 69665)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i16 [[CHECKSUM]] to i24
-; PCLMUL-NEXT:    [[CRC_SHL1:%.*]] = shl i24 [[CRC_RECAST]], 8
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_SHL1]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_NEXT2:%.*]] = trunc i24 [[XOR_CRC_MULT]] to i16
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
+define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) {
+; ALL-LABEL: define i16 @crc16.be.tc8.misalign(
+; ALL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[INDEXER_HI:%.*]] = lshr i16 [[CRC2]], 8
+; ALL-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[INDEXER_HI]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i16, ptr @.crctable.4, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i16, ptr [[TBL_PTRADD]], align 2
+; ALL-NEXT:    [[CRC_BE_SHIFT:%.*]] = shl i16 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i16 [[CRC_BE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i16 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -326,52 +234,29 @@ exit:                                              ; preds = %loop
   ret i16 %crc.next
 }
 
-define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) optsize {
-; NOPCLMUL-LABEL: define i8 @crc8.be.tc16.misalign(
-; NOPCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
-; NOPCLMUL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = shl i16 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
-; NOPCLMUL-NEXT:    [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i8 @crc8.be.tc16.misalign(
-; PCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i24
-; PCLMUL-NEXT:    [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i24
-; PCLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i24 [[CRC_CAST]], [[DATA_CAST]]
-; PCLMUL-NEXT:    [[CRC_ALIGN_TC:%.*]] = shl i24 [[XOR_CRC_DATA1]], 8
-; PCLMUL-NEXT:    [[CRC_TCBITS:%.*]] = and i24 [[CRC_ALIGN_TC]], 65535
-; PCLMUL-NEXT:    [[TCBITS_CAST:%.*]] = zext i24 [[CRC_TCBITS]] to i32
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[TCBITS_CAST]], i32 72779)
-; PCLMUL-NEXT:    [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
-; PCLMUL-NEXT:    [[QUOT_CAST:%.*]] = trunc i32 [[QUOT_LSHR]] to i24
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_CAST]], i24 285)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i24
-; PCLMUL-NEXT:    [[CRC_SHL2:%.*]] = shl i24 [[CRC_RECAST]], 16
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_SHL2]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i24 [[XOR_CRC_MULT]] to i8
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) {
+; ALL-LABEL: define i8 @crc8.be.tc16.misalign(
+; ALL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.5, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 1
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ALL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -395,48 +280,29 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) optsize {
-; NOPCLMUL-LABEL: define i8 @crc8.be.tc8.data16.misalign(
-; NOPCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
-; NOPCLMUL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = shl i16 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
-; NOPCLMUL-NEXT:    [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i8 @crc8.be.tc8.data16.misalign(
-; PCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[DATA_CAST:%.*]] = trunc i16 [[MSG]] to i8
-; PCLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CHECKSUM]], [[DATA_CAST]]
-; PCLMUL-NEXT:    [[TCBITS_CAST:%.*]] = zext i8 [[XOR_CRC_DATA1]] to i16
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[TCBITS_CAST]], i16 284)
-; PCLMUL-NEXT:    [[QUOT_LSHR:%.*]] = lshr i16 [[CLMUL_MU]], 8
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_LSHR]], i16 285)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i16
-; PCLMUL-NEXT:    [[CRC_SHL2:%.*]] = shl i16 [[CRC_RECAST]], 8
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_SHL2]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i16 [[XOR_CRC_MULT]] to i8
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) {
+; ALL-LABEL: define i8 @crc8.be.tc8.data16.misalign(
+; ALL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i16
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = shl i16 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i16
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i16 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_HI_LO_BYTE:%.*]] = trunc i16 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_HI_LO_BYTE]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.6, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ALL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -460,48 +326,30 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) optsize {
-; NOPCLMUL-LABEL: define i32 @crc32.le.tc8.data32(
-; NOPCLMUL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
-; NOPCLMUL-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
-; NOPCLMUL-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i32 @crc32.le.tc8.data32(
-; PCLMUL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[CRC_CAST:%.*]] = trunc i32 [[CHECKSUM]] to i8
-; PCLMUL-NEXT:    [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i8
-; PCLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CRC_CAST]], [[DATA_CAST]]
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA1]], i8 17)
-; PCLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i40
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i40 @llvm.clmul.i40(i40 [[QUOT_CAST]], i40 67601)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i32 [[CHECKSUM]] to i40
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i40 [[CRC_RECAST]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_LSHR2:%.*]] = lshr i40 [[XOR_CRC_MULT]], 8
-; PCLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i40 [[CRC_LSHR2]] to i32
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
+define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) {
+; ALL-LABEL: define i32 @crc32.le.tc8.data32(
+; ALL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; ALL-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.7, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; ALL-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -525,48 +373,29 @@ exit:                                              ; preds = %loop
   ret i32 %crc.next
 }
 
-define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) optsize {
-; NOPCLMUL-LABEL: define i8 @crc8.le.tc8.data32(
-; NOPCLMUL-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA_TRUNC:%.*]] = trunc i32 [[DATA]] to i8
-; NOPCLMUL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
-; NOPCLMUL-NEXT:    [[SB_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i8 [[SB_CRC_DATA]], 0
-; NOPCLMUL-NEXT:    [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 59
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i8 @crc8.le.tc8.data32(
-; PCLMUL-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i8
-; PCLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CHECKSUM]], [[DATA_CAST]]
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA1]], i8 107)
-; PCLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i16
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_CAST]], i16 119)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i8 [[CHECKSUM]] to i16
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_RECAST]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_LSHR2:%.*]] = lshr i16 [[XOR_CRC_MULT]], 8
-; PCLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i16 [[CRC_LSHR2]] to i8
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
+define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) {
+; ALL-LABEL: define i8 @crc8.le.tc8.data32(
+; ALL-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[TBL_LD:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_INDEXER_CAST:%.*]] = zext i8 [[CRC2]] to i32
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC_INDEXER_CAST]]
+; ALL-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i8, ptr @.crctable.8, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD]] = load i8, ptr [[TBL_PTRADD]], align 1
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 0
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[TBL_LD]], %[[LOOP]] ]
+; ALL-NEXT:    ret i8 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -591,46 +420,30 @@ exit:                                              ; preds = %loop
   ret i8 %crc.next
 }
 
-define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) optsize {
-; NOPCLMUL-LABEL: define i32 @crc32.le.tc32(
-; NOPCLMUL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
-; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
-; NOPCLMUL:       [[LOOP]]:
-; NOPCLMUL-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
-; NOPCLMUL-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
-; NOPCLMUL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
-; NOPCLMUL-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
-; NOPCLMUL-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
-; NOPCLMUL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
-; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; NOPCLMUL-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; NOPCLMUL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
-; NOPCLMUL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; NOPCLMUL:       [[EXIT]]:
-; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
-; NOPCLMUL-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
-;
-; PCLMUL-LABEL: define i32 @crc32.le.tc32(
-; PCLMUL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
-; PCLMUL-NEXT:  [[ENTRY:.*:]]
-; PCLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i32 [[CHECKSUM]], [[MSG]]
-; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[XOR_CRC_DATA1]], i32 475535633)
-; PCLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i32 [[CLMUL_MU]] to i64
-; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i64 @llvm.clmul.i64(i64 [[QUOT_CAST]], i64 67601)
-; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i32 [[CHECKSUM]] to i64
-; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i64 [[CRC_RECAST]], [[CLMUL_GP]]
-; PCLMUL-NEXT:    [[CRC_LSHR2:%.*]] = lshr i64 [[XOR_CRC_MULT]], 32
-; PCLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i64 [[CRC_LSHR2]] to i32
-; PCLMUL-NEXT:    br label %[[LOOP:.*]]
-; PCLMUL:       [[LOOP]]:
-; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
-; PCLMUL:       [[EXIT]]:
-; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
-; PCLMUL-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
+define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) {
+; ALL-LABEL: define i32 @crc32.le.tc32(
+; ALL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; ALL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; ALL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; ALL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; ALL-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; ALL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; ALL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.9, i64 [[INDEXER_EXT]]
+; ALL-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; ALL-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; ALL-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 3
+; ALL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; ALL-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -654,28 +467,48 @@ exit:                                              ; preds = %loop
   ret i32 %crc.next
 }
 
-define i64 @crc64.le.tc64(i64 %checksum, i64 %msg) optsize {
-; ALL-LABEL: define i64 @crc64.le.tc64(
-; ALL-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0:[0-9]+]] {
-; ALL-NEXT:  [[ENTRY:.*]]:
-; ALL-NEXT:    br label %[[LOOP:.*]]
-; ALL:       [[LOOP]]:
-; ALL-NEXT:    [[CRC:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; ALL-NEXT:    [[DATA:%.*]] = phi i64 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
-; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; ALL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i64 [[CRC]], [[DATA]]
-; ALL-NEXT:    [[SB_CRC_DATA:%.*]] = and i64 [[XOR_CRC_DATA]], 1
-; ALL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i64 [[SB_CRC_DATA]], 0
-; ALL-NEXT:    [[CRC_LSHR:%.*]] = lshr i64 [[CRC]], 1
-; ALL-NEXT:    [[CRC_XOR:%.*]] = xor i64 [[CRC_LSHR]], 33800
-; ALL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i64 [[CRC_LSHR]], i64 [[CRC_XOR]]
-; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; ALL-NEXT:    [[DATA_NEXT]] = lshr i64 [[DATA]], 1
-; ALL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 63
-; ALL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
-; ALL:       [[EXIT]]:
-; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT]], %[[LOOP]] ]
-; ALL-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
+define i64 @crc64.le.tc64(i64 %checksum, i64 %msg) {
+; NOPCLMUL-LABEL: define i64 @crc64.le.tc64(
+; NOPCLMUL-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0]] {
+; NOPCLMUL-NEXT:  [[ENTRY:.*]]:
+; NOPCLMUL-NEXT:    br label %[[LOOP:.*]]
+; NOPCLMUL:       [[LOOP]]:
+; NOPCLMUL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; NOPCLMUL-NEXT:    [[CRC2:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; NOPCLMUL-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; NOPCLMUL-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i64
+; NOPCLMUL-NEXT:    [[DATA_INDEXER:%.*]] = lshr i64 [[MSG]], [[IV_INDEXER]]
+; NOPCLMUL-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i64 [[DATA_INDEXER]], [[CRC2]]
+; NOPCLMUL-NEXT:    [[INDEXER_LO:%.*]] = trunc i64 [[CRC_DATA_INDEXER]] to i8
+; NOPCLMUL-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; NOPCLMUL-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i64, ptr @.crctable.10, i64 [[INDEXER_EXT]]
+; NOPCLMUL-NEXT:    [[TBL_LD:%.*]] = load i64, ptr [[TBL_PTRADD]], align 8
+; NOPCLMUL-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i64 [[CRC2]], 8
+; NOPCLMUL-NEXT:    [[CRC_NEXT3]] = xor i64 [[CRC_LE_SHIFT]], [[TBL_LD]]
+; NOPCLMUL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; NOPCLMUL-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 7
+; NOPCLMUL-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
+; NOPCLMUL:       [[EXIT]]:
+; NOPCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; NOPCLMUL-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
+;
+; PCLMUL-LABEL: define i64 @crc64.le.tc64(
+; PCLMUL-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0]] {
+; PCLMUL-NEXT:  [[ENTRY:.*:]]
+; PCLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i64 [[CHECKSUM]], [[MSG]]
+; PCLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i64 @llvm.clmul.i64(i64 [[XOR_CRC_DATA1]], i64 -8819450999508297455)
+; PCLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i64 [[CLMUL_MU]] to i128
+; PCLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i128 @llvm.clmul.i128(i128 [[QUOT_CAST]], i128 67601)
+; PCLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i64 [[CHECKSUM]] to i128
+; PCLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i128 [[CRC_RECAST]], [[CLMUL_GP]]
+; PCLMUL-NEXT:    [[CRC_LSHR2:%.*]] = lshr i128 [[XOR_CRC_MULT]], 64
+; PCLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i128 [[CRC_LSHR2]] to i64
+; PCLMUL-NEXT:    br label %[[LOOP:.*]]
+; PCLMUL:       [[LOOP]]:
+; PCLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
+; PCLMUL:       [[EXIT]]:
+; PCLMUL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT3]], %[[LOOP]] ]
+; PCLMUL-NEXT:    ret i64 [[CRC_NEXT_LCSSA]]
 ;
 entry:
   br label %loop
@@ -698,9 +531,48 @@ loop:                                              ; preds = %loop, %entry
 exit:                                              ; preds = %loop
   ret i64 %crc.next
 }
-;.
-; NOPCLMUL: attributes #[[ATTR0]] = { optsize "target-features"="-pclmul" }
-;.
-; PCLMUL: attributes #[[ATTR0]] = { optsize "target-features"="+pclmul" }
-; PCLMUL: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
-;.
+
+define i32 @crc.disabled.optsize(i32 %checksum, i32 %msg) optsize {
+; ALL-LABEL: define i32 @crc.disabled.optsize(
+; ALL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR1:[0-9]+]] {
+; ALL-NEXT:  [[ENTRY:.*]]:
+; ALL-NEXT:    br label %[[LOOP:.*]]
+; ALL:       [[LOOP]]:
+; ALL-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
+; ALL-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
+; ALL-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
+; ALL-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
+; ALL-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
+; ALL-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
+; ALL-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
+; ALL-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
+; ALL-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
+; ALL-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
+; ALL-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
+; ALL:       [[EXIT]]:
+; ALL-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
+; ALL-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, 31
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i32 %crc.next
+}

diff  --git a/llvm/test/Transforms/LoopIdiom/crc-debugify-remarks.ll b/llvm/test/Transforms/LoopIdiom/crc-debugify-remarks.ll
new file mode 100644
index 0000000000000..5b49fbc1deed8
--- /dev/null
+++ b/llvm/test/Transforms/LoopIdiom/crc-debugify-remarks.ll
@@ -0,0 +1,96 @@
+; RUN: opt -passes=debugify,loop-idiom -pass-remarks=loop-idiom -pass-remarks-missed=loop-idiom -pass-remarks-analysis=loop-idiom -pass-remarks-output=%t.yaml -disable-output < %s
+; RUN: FileCheck --input-file=%t.yaml %s --check-prefixes=YAML
+
+; YAML:      --- !Analysis
+; YAML-NEXT: Pass:            loop-idiom
+; YAML-NEXT: Name:            CRCLoopCosts
+; YAML-NEXT: DebugLoc:        { File: '<stdin>', Line: 1, Column: 1 }
+; YAML-NEXT: Function:        crc32.le.tc32
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'CRC loop costs: original='
+; YAML-NEXT:   - OrigLoopCost:    '192'
+; YAML-NEXT:   - String:          ', table='
+; YAML-NEXT:   - TableStrategyCost: '16'
+; YAML-NEXT:   - String:          ', clmul='
+; YAML-NEXT:   - ClmulStrategyCost: '7'
+; YAML-NEXT: ...
+; YAML:      --- !Passed
+; YAML-NEXT: Pass:            loop-idiom
+; YAML-NEXT: Name:            CRCLoopOptimized
+; YAML-NEXT: DebugLoc:        { File: '<stdin>', Line: 1, Column: 1 }
+; YAML-NEXT: Function:        crc32.le.tc32
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'CRC loop optimized using '
+; YAML-NEXT:   - Strategy:        clmul
+; YAML-NEXT:   - String:          ': '
+; YAML-NEXT:   - String:          most profitable strategy
+; YAML-NEXT: ...
+
+define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) {
+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, 31
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i32 %crc.next
+}
+
+; YAML:      --- !Analysis
+; YAML-NEXT: Pass:            loop-idiom
+; YAML-NEXT: Name:            CRCLoopCosts
+; YAML-NEXT: DebugLoc:        { File: '<stdin>', Line: 16, Column: 1 }
+; YAML-NEXT: Function:        crc32.le.tc32.optsize
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'CRC loop costs: original='
+; YAML-NEXT:   - OrigLoopCost:    '192'
+; YAML-NEXT:   - String:          ', table='
+; YAML-NEXT:   - TableStrategyCost: '16'
+; YAML-NEXT:   - String:          ', clmul='
+; YAML-NEXT:   - ClmulStrategyCost: '7'
+; YAML-NEXT: ...
+; YAML:      --- !Missed
+; YAML-NEXT: Pass:            loop-idiom
+; YAML-NEXT: Name:            CRCLoopMissed
+; YAML-NEXT: DebugLoc:        { File: '<stdin>', Line: 16, Column: 1 }
+; YAML-NEXT: Function:        crc32.le.tc32.optsize
+; YAML-NEXT: Args:
+; YAML-NEXT:   - String:          'CRC loop not optimized: '
+; YAML-NEXT:   - String:          optimizing for size
+; YAML-NEXT: ...
+
+define i32 @crc32.le.tc32.optsize(i32 %checksum, i32 %msg) optsize {
+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, 31
+  br i1 %exit.cond, label %loop, label %exit
+
+exit:                                              ; preds = %loop
+  ret i32 %crc.next
+}

diff  --git a/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll
index 904f155127bb5..29b5875b1e7c6 100644
--- a/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll
+++ b/llvm/test/Transforms/LoopIdiom/cyclic-redundancy-check.ll
@@ -1,6 +1,6 @@
 ; 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 --check-prefixes=ALL,TABLE %s
-; RUN: opt -passes=loop-idiom -loop-idiom-force-crc-clmul -S %s | FileCheck --check-prefixes=ALL,CLMUL %s
+; RUN: opt -passes=loop-idiom -loop-idiom-crc-strategy=table -S %s | FileCheck --check-prefixes=ALL,TABLE %s
+; RUN: opt -passes=loop-idiom -loop-idiom-crc-strategy=clmul -S %s | FileCheck --check-prefixes=ALL,CLMUL %s
 
 ;.
 ; TABLE: @.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]
@@ -19,6 +19,7 @@
 ; TABLE: @.crctable.13 = private constant [256 x i8] c"\00\10 07'\17\07\19\099).>\0E\1E2\22\12\02\05\15%5+
 ; TABLE: @.crctable.14 = private constant [256 x i16] [i16 0, i16 258, i16 516, i16 774, i16 1032, i16 1290, i16 1548, i16 1806, i16 2064, i16 2322, i16 2580, i16 2838, i16 3096, i16 3354, i16 3612, i16 3870, i16 4128, i16 4386, i16 4644, i16 4902, i16 5160, i16 5418, i16 5676, i16 5934, i16 6192, i16 6450, i16 6708, i16 6966, i16 7224, i16 7482, i16 7740, i16 7998, i16 8256, i16 8514, i16 8772, i16 9030, i16 9288, i16 9546, i16 9804, i16 10062, i16 10320, i16 10578, i16 10836, i16 11094, i16 11352, i16 11610, i16 11868, i16 12126, i16 12384, i16 12642, i16 12900, i16 13158, i16 13416, i16 13674, i16 13932, i16 14190, i16 14448, i16 14706, i16 14964, i16 15222, i16 15480, i16 15738, i16 15996, i16 16254, i16 16512, i16 16770, i16 17028, i16 17286, i16 17544, i16 17802, i16 18060, i16 18318, i16 18576, i16 18834, i16 19092, i16 19350, i16 19608, i16 19866, i16 20124, i16 20382, i16 20640, i16 20898, i16 21156, i16 21414, i16 21672, i16 21930, i16 22188, i16 22446, i16 22704, i16 22962, i16 23220, i16 23478, i16 23736, i16 23994, i16 24252, i16 24510, i16 24768, i16 25026, i16 25284, i16 25542, i16 25800, i16 26058, i16 26316, i16 26574, i16 26832, i16 27090, i16 27348, i16 27606, i16 27864, i16 28122, i16 28380, i16 28638, i16 28896, i16 29154, i16 29412, i16 29670, i16 29928, i16 30186, i16 30444, i16 30702, i16 30960, i16 31218, i16 31476, i16 31734, i16 31992, i16 32250, i16 32508, i16 32766, i16 -32512, i16 -32766, i16 -31996, i16 -32250, i16 -31480, i16 -31734, i16 -30964, i16 -31218, i16 -30448, i16 -30702, i16 -29932, i16 -30186, i16 -29416, i16 -29670, i16 -28900, i16 -29154, i16 -28384, i16 -28638, i16 -27868, i16 -28122, i16 -27352, i16 -27606, i16 -26836, i16 -27090, i16 -26320, i16 -26574, i16 -25804, i16 -26058, i16 -25288, i16 -25542, i16 -24772, i16 -25026, i16 -24256, i16 -24510, i16 -23740, i16 -23994, i16 -23224, i16 -23478, i16 -22708, i16 -22962, i16 -22192, i16 -22446, i16 -21676, i16 -21930, i16 -21160, i16 -21414, i16 -20644, i16 -20898, i16 -20128, i16 -20382, i16 -19612, i16 -19866, i16 -19096, i16 -19350, i16 -18580, i16 -18834, i16 -18064, i16 -18318, i16 -17548, i16 -17802, i16 -17032, i16 -17286, i16 -16516, i16 -16770, i16 -16000, i16 -16254, i16 -15484, i16 -15738, i16 -14968, i16 -15222, i16 -14452, i16 -14706, i16 -13936, i16 -14190, i16 -13420, i16 -13674, i16 -12904, i16 -13158, i16 -12388, i16 -12642, i16 -11872, i16 -12126, i16 -11356, i16 -11610, i16 -10840, i16 -11094, i16 -10324, i16 -10578, i16 -9808, i16 -10062, i16 -9292, i16 -9546, i16 -8776, i16 -9030, i16 -8260, i16 -8514, i16 -7744, i16 -7998, i16 -7228, i16 -7482, i16 -6712, i16 -6966, i16 -6196, i16 -6450, i16 -5680, i16 -5934, i16 -5164, i16 -5418, i16 -4648, i16 -4902, i16 -4132, i16 -4386, i16 -3616, i16 -3870, i16 -3100, i16 -3354, i16 -2584, i16 -2838, i16 -2068, i16 -2322, i16 -1552, i16 -1806, i16 -1036, i16 -1290, i16 -520, i16 -774, i16 -4, i16 -258]
 ; TABLE: @.crctable.15 = private constant [256 x i4] [i4 0, i4 3, i4 6, i4 5, i4 -4, i4 -1, i4 -6, i4 -7, i4 -5, i4 -8, i4 -3, i4 -2, i4 7, i4 4, i4 1, i4 2, i4 5, i4 6, i4 3, i4 0, i4 -7, i4 -6, i4 -1, i4 -4, i4 -2, i4 -3, i4 -8, i4 -5, i4 2, i4 1, i4 4, i4 7, i4 -6, i4 -7, i4 -4, i4 -1, i4 6, i4 5, i4 0, i4 3, i4 1, i4 2, i4 7, i4 4, i4 -3, i4 -2, i4 -5, i4 -8, i4 -1, i4 -4, i4 -7, i4 -6, i4 3, i4 0, i4 5, i4 6, i4 4, i4 7, i4 2, i4 1, i4 -8, i4 -5, i4 -2, i4 -3, i4 7, i4 4, i4 1, i4 2, i4 -5, i4 -8, i4 -3, i4 -2, i4 -4, i4 -1, i4 -6, i4 -7, i4 0, i4 3, i4 6, i4 5, i4 2, i4 1, i4 4, i4 7, i4 -2, i4 -3, i4 -8, i4 -5, i4 -7, i4 -6, i4 -1, i4 -4, i4 5, i4 6, i4 3, i4 0, i4 -3, i4 -2, i4 -5, i4 -8, i4 1, i4 2, i4 7, i4 4, i4 6, i4 5, i4 0, i4 3, i4 -6, i4 -7, i4 -4, i4 -1, i4 -8, i4 -5, i4 -2, i4 -3, i4 4, i4 7, i4 2, i4 1, i4 3, i4 0, i4 5, i4 6, i4 -1, i4 -4, i4 -7, i4 -6, i4 -2, i4 -3, i4 -8, i4 -5, i4 2, i4 1, i4 4, i4 7, i4 5, i4 6, i4 3, i4 0, i4 -7, i4 -6, i4 -1, i4 -4, i4 -5, i4 -8, i4 -3, i4 -2, i4 7, i4 4, i4 1, i4 2, i4 0, i4 3, i4 6, i4 5, i4 -4, i4 -1, i4 -6, i4 -7, i4 4, i4 7, i4 2, i4 1, i4 -8, i4 -5, i4 -2, i4 -3, i4 -1, i4 -4, i4 -7, i4 -6, i4 3, i4 0, i4 5, i4 6, i4 1, i4 2, i4 7, i4 4, i4 -3, i4 -2, i4 -5, i4 -8, i4 -6, i4 -7, i4 -4, i4 -1, i4 6, i4 5, i4 0, i4 3, i4 -7, i4 -6, i4 -1, i4 -4, i4 5, i4 6, i4 3, i4 0, i4 2, i4 1, i4 4, i4 7, i4 -2, i4 -3, i4 -8, i4 -5, i4 -4, i4 -1, i4 -6, i4 -7, i4 0, i4 3, i4 6, i4 5, i4 7, i4 4, i4 1, i4 2, i4 -5, i4 -8, i4 -3, i4 -2, i4 3, i4 0, i4 5, i4 6, i4 -1, i4 -4, i4 -7, i4 -6, i4 -8, i4 -5, i4 -2, i4 -3, i4 4, i4 7, i4 2, i4 1, i4 6, i4 5, i4 0, i4 3, i4 -6, i4 -7, i4 -4, i4 -1, i4 -3, i4 -2, i4 -5, i4 -8, i4 1, i4 2, i4 7, i4 4]
+; TABLE: @.crctable.16 = 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) {
 ; TABLE-LABEL: define i16 @crc16.le.tc8(
@@ -1245,42 +1246,42 @@ exit:                                              ; preds = %loop
   ret i32 %crc.next
 }
 
-define i32 @crc.disabled.optsize(i32 %checksum, i32 %msg) optsize {
-; TABLE-LABEL: define i32 @crc.disabled.optsize(
+define i32 @crc.strategy.override.optsize(i32 %checksum, i32 %msg) optsize {
+; TABLE-LABEL: define i32 @crc.strategy.override.optsize(
 ; TABLE-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
 ; TABLE-NEXT:  [[ENTRY:.*]]:
 ; TABLE-NEXT:    br label %[[LOOP:.*]]
 ; TABLE:       [[LOOP]]:
-; TABLE-NEXT:    [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
-; TABLE-NEXT:    [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
 ; TABLE-NEXT:    [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
-; TABLE-NEXT:    [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
-; TABLE-NEXT:    [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
-; TABLE-NEXT:    [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
-; TABLE-NEXT:    [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
-; TABLE-NEXT:    [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
-; TABLE-NEXT:    [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
+; TABLE-NEXT:    [[CRC2:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT3:%.*]], %[[LOOP]] ]
+; TABLE-NEXT:    [[IV_BITS:%.*]] = shl i8 [[IV]], 3
+; TABLE-NEXT:    [[IV_INDEXER:%.*]] = zext i8 [[IV_BITS]] to i32
+; TABLE-NEXT:    [[DATA_INDEXER:%.*]] = lshr i32 [[MSG]], [[IV_INDEXER]]
+; TABLE-NEXT:    [[CRC_DATA_INDEXER:%.*]] = xor i32 [[DATA_INDEXER]], [[CRC2]]
+; TABLE-NEXT:    [[INDEXER_LO:%.*]] = trunc i32 [[CRC_DATA_INDEXER]] to i8
+; TABLE-NEXT:    [[INDEXER_EXT:%.*]] = zext i8 [[INDEXER_LO]] to i64
+; TABLE-NEXT:    [[TBL_PTRADD:%.*]] = getelementptr inbounds i32, ptr @.crctable.16, i64 [[INDEXER_EXT]]
+; TABLE-NEXT:    [[TBL_LD:%.*]] = load i32, ptr [[TBL_PTRADD]], align 4
+; TABLE-NEXT:    [[CRC_LE_SHIFT:%.*]] = lshr i32 [[CRC2]], 8
+; TABLE-NEXT:    [[CRC_NEXT3]] = xor i32 [[CRC_LE_SHIFT]], [[TBL_LD]]
 ; TABLE-NEXT:    [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
-; TABLE-NEXT:    [[DATA_NEXT]] = lshr i32 [[DATA]], 1
-; TABLE-NEXT:    [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
-; TABLE-NEXT:    br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
+; TABLE-NEXT:    [[EXIT_COND1:%.*]] = icmp ne i8 [[IV]], 3
+; TABLE-NEXT:    br i1 [[EXIT_COND1]], label %[[LOOP]], label %[[EXIT:.*]]
 ; TABLE:       [[EXIT]]:
-; TABLE-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
+; TABLE-NEXT:    [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
 ; TABLE-NEXT:    ret i32 [[CRC_NEXT_LCSSA]]
 ;
-; CLMUL-LABEL: define i32 @crc.disabled.optsize(
+; CLMUL-LABEL: define i32 @crc.strategy.override.optsize(
 ; CLMUL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
 ; CLMUL-NEXT:  [[ENTRY:.*:]]
-; CLMUL-NEXT:    [[CRC_CAST:%.*]] = trunc i32 [[CHECKSUM]] to i8
-; CLMUL-NEXT:    [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i8
-; CLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i8 [[CRC_CAST]], [[DATA_CAST]]
-; CLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i8 @llvm.clmul.i8(i8 [[XOR_CRC_DATA1]], i8 17)
-; CLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i8 [[CLMUL_MU]] to i40
-; CLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i40 @llvm.clmul.i40(i40 [[QUOT_CAST]], i40 67601)
-; CLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i32 [[CHECKSUM]] to i40
-; CLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i40 [[CRC_RECAST]], [[CLMUL_GP]]
-; CLMUL-NEXT:    [[CRC_LSHR2:%.*]] = lshr i40 [[XOR_CRC_MULT]], 8
-; CLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i40 [[CRC_LSHR2]] to i32
+; CLMUL-NEXT:    [[XOR_CRC_DATA1:%.*]] = xor i32 [[CHECKSUM]], [[MSG]]
+; CLMUL-NEXT:    [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[XOR_CRC_DATA1]], i32 475535633)
+; CLMUL-NEXT:    [[QUOT_CAST:%.*]] = zext i32 [[CLMUL_MU]] to i64
+; CLMUL-NEXT:    [[CLMUL_GP:%.*]] = call i64 @llvm.clmul.i64(i64 [[QUOT_CAST]], i64 67601)
+; CLMUL-NEXT:    [[CRC_RECAST:%.*]] = zext i32 [[CHECKSUM]] to i64
+; CLMUL-NEXT:    [[XOR_CRC_MULT:%.*]] = xor i64 [[CRC_RECAST]], [[CLMUL_GP]]
+; CLMUL-NEXT:    [[CRC_LSHR2:%.*]] = lshr i64 [[XOR_CRC_MULT]], 32
+; CLMUL-NEXT:    [[CRC_NEXT3:%.*]] = trunc i64 [[CRC_LSHR2]] to i32
 ; CLMUL-NEXT:    br label %[[LOOP:.*]]
 ; CLMUL:       [[LOOP]]:
 ; CLMUL-NEXT:    br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
@@ -1303,7 +1304,7 @@ loop:                                              ; preds = %loop, %entry
   %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
+  %exit.cond = icmp samesign ult i8 %iv, 31
   br i1 %exit.cond, label %loop, label %exit
 
 exit:                                              ; preds = %loop


        


More information about the llvm-commits mailing list