[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