[llvm] [LoopIdiom] Use HashRecognize to optimize CRC (PR #143208)
Piotr Fusik via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 9 00:56:37 PDT 2025
================
@@ -1473,6 +1494,146 @@ bool LoopIdiomRecognize::avoidLIRForMultiBlockLoop(bool IsMemset,
return false;
}
+bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
+ // We currently only optimize CRC loops with TC a multiple of 8 with a table
+ // lookup: the table-lookup can be improved using target-specific
+ // instructions.
+ if (Info.TripCount % 8 != 0)
+ return false;
+
+ // First, create a new GlobalVariable corresponding to the
+ // Sarwate-lookup-table.
+ Type *CRCTy = Info.LHS->getType();
+ unsigned CRCBW = CRCTy->getIntegerBitWidth();
+ std::array<Constant *, 256> CRCConstants;
+ transform(Info.SarwateTable, CRCConstants.begin(),
+ [CRCTy](const APInt &E) { return ConstantInt::get(CRCTy, E); });
+ Constant *ConstArray =
+ ConstantArray::get(ArrayType::get(CRCTy, 256), CRCConstants);
+ Module &M = *CurLoop->getHeader()->getModule();
+ GlobalVariable *GV =
+ new GlobalVariable(M, ConstArray->getType(), true,
+ GlobalValue::PrivateLinkage, ConstArray, ".crctable");
+
+ PHINode *IV = CurLoop->getCanonicalInductionVariable();
+ Type *IVTy = IV->getType();
+ SmallVector<PHINode *, 2> Cleanup;
+
+ // Next, mark all PHIs for removal except IV.
+ {
+ for (PHINode &PN : CurLoop->getHeader()->phis()) {
+ if (&PN == IV)
+ continue;
+ PN.replaceAllUsesWith(PoisonValue::get(PN.getType()));
+ Cleanup.push_back(&PN);
+ }
+ }
+
+ // Next, fix up the trip count.
+ {
+ unsigned NewBTC = (Info.TripCount / 8) - 1;
+ BasicBlock *LoopBlk = CurLoop->getLoopLatch();
+ BranchInst *BrInst = cast<BranchInst>(LoopBlk->getTerminator());
+ CmpPredicate ExitPred = BrInst->getSuccessor(0) == LoopBlk
+ ? ICmpInst::Predicate::ICMP_NE
+ : ICmpInst::Predicate::ICMP_EQ;
+ Instruction *ExitCond = CurLoop->getLatchCmpInst();
+ IRBuilder<> Builder(ExitCond);
+ Value *NewExitCond = Builder.CreateICmp(
+ ExitPred, IV, ConstantInt::get(IVTy, NewBTC), "exit.cond");
+ ExitCond->replaceAllUsesWith(NewExitCond);
+ deleteDeadInstruction(ExitCond);
+ }
+
+ // Finally, fill the loop with the Sarwate-table-lookup logic, and replace all
+ // uses of ComputedValue.
+ //
+ // Little-endian:
+ // crc = (crc >> 8) ^ tbl[data[iv] ^ (crc & 0xFF)]
+ // Big-Endian:
+ // crc = (crc << 8) ^ tbl[data[iv] ^ (crc >> (crc.bw - 8))]
+ {
+ // Compute the top 8 bits of Op.
----------------
pfusik wrote:
Update this comment.
https://github.com/llvm/llvm-project/pull/143208
More information about the llvm-commits
mailing list