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

Sean Clarke via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 22 08:00:06 PDT 2026


================
@@ -1589,43 +1600,113 @@ 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) {
+  // The Sarwate lookup table optimization requires a byte-multiple trip count,
+  // and should not be applied if optimizing for size.
+  bool TableStrategyPossible =
+      Info.TripCount % 8 == 0 && !ApplyCodeSizeHeuristics;
+
+  switch (CRCStrategy) {
+  default:
+    break;
+  case CRCStrategyKind::Table: {
+    if (TableStrategyPossible) {
+      optimizeCRCLoopUsingTableLookup(Info);
+      return true;
+    }
+    return false;
+  }
+  case CRCStrategyKind::Clmul:
     optimizeCRCLoopUsingClmul(Info);
     return true;
   }
 
-  // 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);
+  LLVMContext &Ctx = Info.LHS->getContext();
+  Type *CRCTy = Info.LHS->getType();
+  unsigned CRCBW = CRCTy->getIntegerBitWidth();
+
+  // The clmul optimization should be applied on optsize if clmul with the
+  // required bit width is a fast operation on the target. The first clmul needs
+  // 2*TC bits, and the second clmul needs CRCBW+TC bits, so test the wider one.
+  // FIXME: I'm not sure it makes sense to have this anymore. Optsize might need
+  // separate costing to determine which is smaller.
+  IntegerType *WidestClmulTy = IntegerType::get(
+      Ctx, std::max(2 * Info.TripCount, CRCBW + Info.TripCount));
+  if (ApplyCodeSizeHeuristics && TTI->haveFastClmul(WidestClmulTy)) {
+    optimizeCRCLoopUsingClmul(Info);
     return true;
   }
 
-  // The clmul optimization should only be applied if clmul with the required
-  // bit width is a fast operation on the target. The first clmul needs 2*TC
-  // bits, and the second clmul needs CRCBW+TC bits, so test the widest clmul.
-  // 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 CRCBW = Info.LHS->getType()->getIntegerBitWidth();
-  IntegerType *WidestClmulTy =
-      IntegerType::get(Info.LHS->getContext(),
-                       std::max(2 * Info.TripCount, CRCBW + Info.TripCount));
-  if (TTI->haveFastClmul(WidestClmulTy)) {
+  TargetTransformInfo::TargetCostKind CostKind =
+      TargetTransformInfo::TCK_Latency;
----------------
xarkenz wrote:

My understanding is that generally latency is used for costing of serial code and reciprocal throughput for parallel code. The CRC loop seems very serial, which is why I opted for this. It also gives a much better comparison between the two optimizations in this case, from my testing. I'm open to suggestions if you have a better idea of how to cost this.

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


More information about the llvm-commits mailing list