[llvm] [LoopIdiom] Use costing to determine CRC strategy (PR #211040)

Piotr Fusik via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 05:19:23 PDT 2026


================
@@ -1589,43 +1603,131 @@ 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: {
----------------
pfusik wrote:

Remove these per-case braces. I see no variables introduced.

https://github.com/llvm/llvm-project/pull/211040


More information about the llvm-commits mailing list