Path: blob/main/contrib/llvm-project/llvm/lib/Analysis/HashRecognize.cpp
213765 views
//===- HashRecognize.cpp ----------------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// The HashRecognize analysis recognizes unoptimized polynomial hash functions9// with operations over a Galois field of characteristic 2, also called binary10// fields, or GF(2^n): this class of hash functions can be optimized using a11// lookup-table-driven implementation, or with target-specific instructions.12// Examples:13//14// 1. Cyclic redundancy check (CRC), which is a polynomial division in GF(2).15// 2. Rabin fingerprint, a component of the Rabin-Karp algorithm, which is a16// rolling hash polynomial division in GF(2).17// 3. Rijndael MixColumns, a step in AES computation, which is a polynomial18// multiplication in GF(2^3).19// 4. GHASH, the authentication mechanism in AES Galois/Counter Mode (GCM),20// which is a polynomial evaluation in GF(2^128).21//22// All of them use an irreducible generating polynomial of degree m,23//24// c_m * x^m + c_(m-1) * x^(m-1) + ... + c_0 * x^025//26// where each coefficient c is can take values in GF(2^n), where 2^n is termed27// the order of the Galois field. For GF(2), each coefficient can take values28// either 0 or 1, and the polynomial is simply represented by m+1 bits,29// corresponding to the coefficients. The different variants of CRC are named by30// degree of generating polynomial used: so CRC-32 would use a polynomial of31// degree 32.32//33// The reason algorithms on GF(2^n) can be optimized with a lookup-table is the34// following: in such fields, polynomial addition and subtraction are identical35// and equivalent to XOR, polynomial multiplication is an AND, and polynomial36// division is identity: the XOR and AND operations in unoptimized37// implementations are performed bit-wise, and can be optimized to be performed38// chunk-wise, by interleaving copies of the generating polynomial, and storing39// the pre-computed values in a table.40//41// A generating polynomial of m bits always has the MSB set, so we usually42// omit it. An example of a 16-bit polynomial is the CRC-16-CCITT polynomial:43//44// (x^16) + x^12 + x^5 + 1 = (1) 0001 0000 0010 0001 = 0x102145//46// Transmissions are either in big-endian or little-endian form, and hash47// algorithms are written according to this. For example, IEEE 802 and RS-23248// specify little-endian transmission.49//50//===----------------------------------------------------------------------===//51//52// At the moment, we only recognize the CRC algorithm.53// Documentation on CRC32 from the kernel:54// https://www.kernel.org/doc/Documentation/crc32.txt55//56//57//===----------------------------------------------------------------------===//5859#include "llvm/Analysis/HashRecognize.h"60#include "llvm/ADT/APInt.h"61#include "llvm/Analysis/LoopAnalysisManager.h"62#include "llvm/Analysis/LoopInfo.h"63#include "llvm/Analysis/ScalarEvolution.h"64#include "llvm/Analysis/ScalarEvolutionPatternMatch.h"65#include "llvm/Analysis/ValueTracking.h"66#include "llvm/IR/PatternMatch.h"67#include "llvm/Support/KnownBits.h"6869using namespace llvm;70using namespace PatternMatch;71using namespace SCEVPatternMatch;7273#define DEBUG_TYPE "hash-recognize"7475// KnownBits for a PHI node. There are at most two PHI nodes, corresponding to76// the Simple Recurrence and Conditional Recurrence. The IndVar PHI is not77// relevant.78using KnownPhiMap = SmallDenseMap<const PHINode *, KnownBits, 2>;7980// A pair of a PHI node along with its incoming value from within a loop.81using PhiStepPair = std::pair<const PHINode *, const Instruction *>;8283/// A much simpler version of ValueTracking, in that it computes KnownBits of84/// values, except that it computes the evolution of KnownBits in a loop with a85/// given trip count, and predication is specialized for a significant-bit86/// check.87class ValueEvolution {88const unsigned TripCount;89const bool ByteOrderSwapped;90APInt GenPoly;91StringRef ErrStr;9293// Compute the KnownBits of a BinaryOperator.94KnownBits computeBinOp(const BinaryOperator *I);9596// Compute the KnownBits of an Instruction.97KnownBits computeInstr(const Instruction *I);9899// Compute the KnownBits of a Value.100KnownBits compute(const Value *V);101102public:103// ValueEvolution is meant to be constructed with the TripCount of the loop,104// and whether the polynomial algorithm is big-endian, for the significant-bit105// check.106ValueEvolution(unsigned TripCount, bool ByteOrderSwapped);107108// Given a list of PHI nodes along with their incoming value from within the109// loop, computeEvolutions computes the KnownBits of each of the PHI nodes on110// the final iteration. Returns true on success and false on error.111bool computeEvolutions(ArrayRef<PhiStepPair> PhiEvolutions);112113// In case ValueEvolution encounters an error, this is meant to be used for a114// precise error message.115StringRef getError() const { return ErrStr; }116117// The computed KnownBits for each PHI node, which is populated after118// computeEvolutions is called.119KnownPhiMap KnownPhis;120};121122ValueEvolution::ValueEvolution(unsigned TripCount, bool ByteOrderSwapped)123: TripCount(TripCount), ByteOrderSwapped(ByteOrderSwapped) {}124125KnownBits ValueEvolution::computeBinOp(const BinaryOperator *I) {126KnownBits KnownL(compute(I->getOperand(0)));127KnownBits KnownR(compute(I->getOperand(1)));128129switch (I->getOpcode()) {130case Instruction::BinaryOps::And:131return KnownL & KnownR;132case Instruction::BinaryOps::Or:133return KnownL | KnownR;134case Instruction::BinaryOps::Xor:135return KnownL ^ KnownR;136case Instruction::BinaryOps::Shl: {137auto *OBO = cast<OverflowingBinaryOperator>(I);138return KnownBits::shl(KnownL, KnownR, OBO->hasNoUnsignedWrap(),139OBO->hasNoSignedWrap());140}141case Instruction::BinaryOps::LShr:142return KnownBits::lshr(KnownL, KnownR);143case Instruction::BinaryOps::AShr:144return KnownBits::ashr(KnownL, KnownR);145case Instruction::BinaryOps::Add: {146auto *OBO = cast<OverflowingBinaryOperator>(I);147return KnownBits::add(KnownL, KnownR, OBO->hasNoUnsignedWrap(),148OBO->hasNoSignedWrap());149}150case Instruction::BinaryOps::Sub: {151auto *OBO = cast<OverflowingBinaryOperator>(I);152return KnownBits::sub(KnownL, KnownR, OBO->hasNoUnsignedWrap(),153OBO->hasNoSignedWrap());154}155case Instruction::BinaryOps::Mul: {156Value *Op0 = I->getOperand(0);157Value *Op1 = I->getOperand(1);158bool SelfMultiply = Op0 == Op1 && isGuaranteedNotToBeUndef(Op0);159return KnownBits::mul(KnownL, KnownR, SelfMultiply);160}161case Instruction::BinaryOps::UDiv:162return KnownBits::udiv(KnownL, KnownR);163case Instruction::BinaryOps::SDiv:164return KnownBits::sdiv(KnownL, KnownR);165case Instruction::BinaryOps::URem:166return KnownBits::urem(KnownL, KnownR);167case Instruction::BinaryOps::SRem:168return KnownBits::srem(KnownL, KnownR);169default:170ErrStr = "Unknown BinaryOperator";171unsigned BitWidth = I->getType()->getScalarSizeInBits();172return {BitWidth};173}174}175176KnownBits ValueEvolution::computeInstr(const Instruction *I) {177unsigned BitWidth = I->getType()->getScalarSizeInBits();178179// We look up in the map that contains the KnownBits of the PHI from the180// previous iteration.181if (const PHINode *P = dyn_cast<PHINode>(I))182return KnownPhis.lookup_or(P, BitWidth);183184// Compute the KnownBits for a Select(Cmp()), forcing it to take the branch185// that is predicated on the (least|most)-significant-bit check.186CmpPredicate Pred;187Value *L, *R, *TV, *FV;188if (match(I, m_Select(m_ICmp(Pred, m_Value(L), m_Value(R)), m_Value(TV),189m_Value(FV)))) {190// We need to check LCR against [0, 2) in the little-endian case, because191// the RCR check is insufficient: it is simply [0, 1).192if (!ByteOrderSwapped) {193KnownBits KnownL = compute(L);194unsigned ICmpBW = KnownL.getBitWidth();195auto LCR = ConstantRange::fromKnownBits(KnownL, false);196auto CheckLCR = ConstantRange(APInt::getZero(ICmpBW), APInt(ICmpBW, 2));197if (LCR != CheckLCR) {198ErrStr = "Bad LHS of significant-bit-check";199return {BitWidth};200}201}202203// Check that the predication is on (most|least) significant bit.204KnownBits KnownR = compute(R);205unsigned ICmpBW = KnownR.getBitWidth();206auto RCR = ConstantRange::fromKnownBits(KnownR, false);207auto AllowedR = ConstantRange::makeAllowedICmpRegion(Pred, RCR);208ConstantRange CheckRCR(APInt::getZero(ICmpBW),209ByteOrderSwapped ? APInt::getSignedMinValue(ICmpBW)210: APInt(ICmpBW, 1));211if (AllowedR == CheckRCR)212return compute(TV);213if (AllowedR.inverse() == CheckRCR)214return compute(FV);215216ErrStr = "Bad RHS of significant-bit-check";217return {BitWidth};218}219220if (auto *BO = dyn_cast<BinaryOperator>(I))221return computeBinOp(BO);222223switch (I->getOpcode()) {224case Instruction::CastOps::Trunc:225return compute(I->getOperand(0)).trunc(BitWidth);226case Instruction::CastOps::ZExt:227return compute(I->getOperand(0)).zext(BitWidth);228case Instruction::CastOps::SExt:229return compute(I->getOperand(0)).sext(BitWidth);230default:231ErrStr = "Unknown Instruction";232return {BitWidth};233}234}235236KnownBits ValueEvolution::compute(const Value *V) {237if (auto *CI = dyn_cast<ConstantInt>(V))238return KnownBits::makeConstant(CI->getValue());239240if (auto *I = dyn_cast<Instruction>(V))241return computeInstr(I);242243ErrStr = "Unknown Value";244unsigned BitWidth = V->getType()->getScalarSizeInBits();245return {BitWidth};246}247248bool ValueEvolution::computeEvolutions(ArrayRef<PhiStepPair> PhiEvolutions) {249for (unsigned I = 0; I < TripCount; ++I)250for (auto [Phi, Step] : PhiEvolutions)251KnownPhis.emplace_or_assign(Phi, computeInstr(Step));252253return ErrStr.empty();254}255256/// A structure that can hold either a Simple Recurrence or a Conditional257/// Recurrence. Note that in the case of a Simple Recurrence, Step is an operand258/// of the BO, while in a Conditional Recurrence, it is a SelectInst.259struct RecurrenceInfo {260const Loop &L;261const PHINode *Phi = nullptr;262BinaryOperator *BO = nullptr;263Value *Start = nullptr;264Value *Step = nullptr;265std::optional<APInt> ExtraConst;266267RecurrenceInfo(const Loop &L) : L(L) {}268operator bool() const { return BO; }269270void print(raw_ostream &OS, unsigned Indent = 0) const {271OS.indent(Indent) << "Phi: ";272Phi->print(OS);273OS << "\n";274OS.indent(Indent) << "BinaryOperator: ";275BO->print(OS);276OS << "\n";277OS.indent(Indent) << "Start: ";278Start->print(OS);279OS << "\n";280OS.indent(Indent) << "Step: ";281Step->print(OS);282OS << "\n";283if (ExtraConst) {284OS.indent(Indent) << "ExtraConst: ";285ExtraConst->print(OS, false);286OS << "\n";287}288}289290#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)291LLVM_DUMP_METHOD void dump() const { print(dbgs()); }292#endif293294bool matchSimpleRecurrence(const PHINode *P);295bool matchConditionalRecurrence(296const PHINode *P,297Instruction::BinaryOps BOWithConstOpToMatch = Instruction::BinaryOpsEnd);298299private:300BinaryOperator *digRecurrence(301Instruction *V,302Instruction::BinaryOps BOWithConstOpToMatch = Instruction::BinaryOpsEnd);303};304305/// Wraps llvm::matchSimpleRecurrence. Match a simple first order recurrence306/// cycle of the form:307///308/// loop:309/// %rec = phi [%start, %entry], [%BO, %loop]310/// ...311/// %BO = binop %rec, %step312///313/// or314///315/// loop:316/// %rec = phi [%start, %entry], [%BO, %loop]317/// ...318/// %BO = binop %step, %rec319///320bool RecurrenceInfo::matchSimpleRecurrence(const PHINode *P) {321Phi = P;322return llvm::matchSimpleRecurrence(Phi, BO, Start, Step);323}324325/// Digs for a recurrence starting with \p V hitting the PHI node in a use-def326/// chain. Used by matchConditionalRecurrence.327BinaryOperator *328RecurrenceInfo::digRecurrence(Instruction *V,329Instruction::BinaryOps BOWithConstOpToMatch) {330SmallVector<Instruction *> Worklist;331Worklist.push_back(V);332while (!Worklist.empty()) {333Instruction *I = Worklist.pop_back_val();334335// Don't add a PHI's operands to the Worklist.336if (isa<PHINode>(I))337continue;338339// Find a recurrence over a BinOp, by matching either of its operands340// with with the PHINode.341if (match(I, m_c_BinOp(m_Value(), m_Specific(Phi))))342return cast<BinaryOperator>(I);343344// Bind to ExtraConst, if we match exactly one.345if (I->getOpcode() == BOWithConstOpToMatch) {346if (ExtraConst)347return nullptr;348const APInt *C = nullptr;349if (match(I, m_c_BinOp(m_APInt(C), m_Value())))350ExtraConst = *C;351}352353// Continue along the use-def chain.354for (Use &U : I->operands())355if (auto *UI = dyn_cast<Instruction>(U))356if (L.contains(UI))357Worklist.push_back(UI);358}359return nullptr;360}361362/// A Conditional Recurrence is a recurrence of the form:363///364/// loop:365/// %rec = phi [%start, %entry], [%step, %loop]366/// ...367/// %step = select _, %tv, %fv368///369/// where %tv and %fv ultimately end up using %rec via the same %BO instruction,370/// after digging through the use-def chain.371///372/// ExtraConst is relevant if \p BOWithConstOpToMatch is supplied: when digging373/// the use-def chain, a BinOp with opcode \p BOWithConstOpToMatch is matched,374/// and ExtraConst is a constant operand of that BinOp. This peculiarity exists,375/// because in a CRC algorithm, the \p BOWithConstOpToMatch is an XOR, and the376/// ExtraConst ends up being the generating polynomial.377bool RecurrenceInfo::matchConditionalRecurrence(378const PHINode *P, Instruction::BinaryOps BOWithConstOpToMatch) {379Phi = P;380if (Phi->getNumIncomingValues() != 2)381return false;382383for (unsigned Idx = 0; Idx != 2; ++Idx) {384Value *FoundStep = Phi->getIncomingValue(Idx);385Value *FoundStart = Phi->getIncomingValue(!Idx);386387Instruction *TV, *FV;388if (!match(FoundStep,389m_Select(m_Cmp(), m_Instruction(TV), m_Instruction(FV))))390continue;391392// For a conditional recurrence, both the true and false values of the393// select must ultimately end up in the same recurrent BinOp.394BinaryOperator *FoundBO = digRecurrence(TV, BOWithConstOpToMatch);395BinaryOperator *AltBO = digRecurrence(FV, BOWithConstOpToMatch);396if (!FoundBO || FoundBO != AltBO)397return false;398399if (BOWithConstOpToMatch != Instruction::BinaryOpsEnd && !ExtraConst) {400LLVM_DEBUG(dbgs() << "HashRecognize: Unable to match single BinaryOp "401"with constant in conditional recurrence\n");402return false;403}404405BO = FoundBO;406Start = FoundStart;407Step = FoundStep;408return true;409}410return false;411}412413/// Iterates over all the phis in \p LoopLatch, and attempts to extract a414/// Conditional Recurrence and an optional Simple Recurrence.415static std::optional<std::pair<RecurrenceInfo, RecurrenceInfo>>416getRecurrences(BasicBlock *LoopLatch, const PHINode *IndVar, const Loop &L) {417auto Phis = LoopLatch->phis();418unsigned NumPhis = std::distance(Phis.begin(), Phis.end());419if (NumPhis != 2 && NumPhis != 3)420return {};421422RecurrenceInfo SimpleRecurrence(L);423RecurrenceInfo ConditionalRecurrence(L);424for (PHINode &P : Phis) {425if (&P == IndVar)426continue;427if (!SimpleRecurrence)428SimpleRecurrence.matchSimpleRecurrence(&P);429if (!ConditionalRecurrence)430ConditionalRecurrence.matchConditionalRecurrence(431&P, Instruction::BinaryOps::Xor);432}433if (NumPhis == 3 && (!SimpleRecurrence || !ConditionalRecurrence))434return {};435return std::make_pair(SimpleRecurrence, ConditionalRecurrence);436}437438PolynomialInfo::PolynomialInfo(unsigned TripCount, Value *LHS, const APInt &RHS,439Value *ComputedValue, bool ByteOrderSwapped,440Value *LHSAux)441: TripCount(TripCount), LHS(LHS), RHS(RHS), ComputedValue(ComputedValue),442ByteOrderSwapped(ByteOrderSwapped), LHSAux(LHSAux) {}443444/// In the big-endian case, checks the bottom N bits against CheckFn, and that445/// the rest are unknown. In the little-endian case, checks the top N bits446/// against CheckFn, and that the rest are unknown. Callers usually call this447/// function with N = TripCount, and CheckFn checking that the remainder bits of448/// the CRC polynomial division are zero.449static bool checkExtractBits(const KnownBits &Known, unsigned N,450function_ref<bool(const KnownBits &)> CheckFn,451bool ByteOrderSwapped) {452// Check that the entire thing is a constant.453if (N == Known.getBitWidth())454return CheckFn(Known.extractBits(N, 0));455456// Check that the {top, bottom} N bits are not unknown and that the {bottom,457// top} N bits are known.458unsigned BitPos = ByteOrderSwapped ? 0 : Known.getBitWidth() - N;459unsigned SwappedBitPos = ByteOrderSwapped ? N : 0;460return CheckFn(Known.extractBits(N, BitPos)) &&461Known.extractBits(Known.getBitWidth() - N, SwappedBitPos).isUnknown();462}463464/// Generate a lookup table of 256 entries by interleaving the generating465/// polynomial. The optimization technique of table-lookup for CRC is also466/// called the Sarwate algorithm.467CRCTable HashRecognize::genSarwateTable(const APInt &GenPoly,468bool ByteOrderSwapped) {469unsigned BW = GenPoly.getBitWidth();470CRCTable Table;471Table[0] = APInt::getZero(BW);472473if (ByteOrderSwapped) {474APInt CRCInit = APInt::getSignedMinValue(BW);475for (unsigned I = 1; I < 256; I <<= 1) {476CRCInit = CRCInit.shl(1) ^477(CRCInit.isSignBitSet() ? GenPoly : APInt::getZero(BW));478for (unsigned J = 0; J < I; ++J)479Table[I + J] = CRCInit ^ Table[J];480}481return Table;482}483484APInt CRCInit(BW, 1);485for (unsigned I = 128; I; I >>= 1) {486CRCInit = CRCInit.lshr(1) ^ (CRCInit[0] ? GenPoly : APInt::getZero(BW));487for (unsigned J = 0; J < 256; J += (I << 1))488Table[I + J] = CRCInit ^ Table[J];489}490return Table;491}492493/// Checks that \p P1 and \p P2 are used together in an XOR in the use-def chain494/// of \p SI's condition, ignoring any casts. The purpose of this function is to495/// ensure that LHSAux from the SimpleRecurrence is used correctly in the CRC496/// computation. We cannot check the correctness of casts at this point, and497/// rely on the KnownBits propagation to check correctness of the CRC498/// computation.499///500/// In other words, it checks for the following pattern:501///502/// loop:503/// %P1 = phi [_, %entry], [%P1.next, %loop]504/// %P2 = phi [_, %entry], [%P2.next, %loop]505/// ...506/// %xor = xor (CastOrSelf %P1), (CastOrSelf %P2)507///508/// where %xor is in the use-def chain of \p SI's condition.509static bool isConditionalOnXorOfPHIs(const SelectInst *SI, const PHINode *P1,510const PHINode *P2, const Loop &L) {511SmallVector<const Instruction *> Worklist;512513// matchConditionalRecurrence has already ensured that the SelectInst's514// condition is an Instruction.515Worklist.push_back(cast<Instruction>(SI->getCondition()));516517while (!Worklist.empty()) {518const Instruction *I = Worklist.pop_back_val();519520// Don't add a PHI's operands to the Worklist.521if (isa<PHINode>(I))522continue;523524// If we match an XOR of the two PHIs ignoring casts, we're done.525if (match(I, m_c_Xor(m_CastOrSelf(m_Specific(P1)),526m_CastOrSelf(m_Specific(P2)))))527return true;528529// Continue along the use-def chain.530for (const Use &U : I->operands())531if (auto *UI = dyn_cast<Instruction>(U))532if (L.contains(UI))533Worklist.push_back(UI);534}535return false;536}537538// Recognizes a multiplication or division by the constant two, using SCEV. By539// doing this, we're immune to whether the IR expression is mul/udiv or540// equivalently shl/lshr. Return false when it is a UDiv, true when it is a Mul,541// and std::nullopt otherwise.542static std::optional<bool> isBigEndianBitShift(Value *V, ScalarEvolution &SE) {543if (!V->getType()->isIntegerTy())544return {};545546const SCEV *E = SE.getSCEV(V);547if (match(E, m_scev_UDiv(m_SCEV(), m_scev_SpecificInt(2))))548return false;549if (match(E, m_scev_Mul(m_scev_SpecificInt(2), m_SCEV())))550return true;551return {};552}553554/// The main entry point for analyzing a loop and recognizing the CRC algorithm.555/// Returns a PolynomialInfo on success, and either an ErrBits or a StringRef on556/// failure.557std::variant<PolynomialInfo, ErrBits, StringRef>558HashRecognize::recognizeCRC() const {559if (!L.isInnermost())560return "Loop is not innermost";561BasicBlock *Latch = L.getLoopLatch();562BasicBlock *Exit = L.getExitBlock();563const PHINode *IndVar = L.getCanonicalInductionVariable();564if (!Latch || !Exit || !IndVar || L.getNumBlocks() != 1)565return "Loop not in canonical form";566unsigned TC = SE.getSmallConstantTripCount(&L);567if (!TC || TC > 256 || TC % 8)568return "Unable to find a small constant byte-multiple trip count";569570auto R = getRecurrences(Latch, IndVar, L);571if (!R)572return "Found stray PHI";573auto [SimpleRecurrence, ConditionalRecurrence] = *R;574if (!ConditionalRecurrence)575return "Unable to find conditional recurrence";576577// Make sure that all recurrences are either all SCEVMul with two or SCEVDiv578// with two, or in other words, that they're single bit-shifts.579std::optional<bool> ByteOrderSwapped =580isBigEndianBitShift(ConditionalRecurrence.BO, SE);581if (!ByteOrderSwapped)582return "Loop with non-unit bitshifts";583if (SimpleRecurrence) {584if (isBigEndianBitShift(SimpleRecurrence.BO, SE) != ByteOrderSwapped)585return "Loop with non-unit bitshifts";586587// Ensure that the PHIs have exactly two uses:588// the bit-shift, and the XOR (or a cast feeding into the XOR).589if (!ConditionalRecurrence.Phi->hasNUses(2) ||590!SimpleRecurrence.Phi->hasNUses(2))591return "Recurrences have stray uses";592593// Check that the SelectInst ConditionalRecurrence.Step is conditional on594// the XOR of SimpleRecurrence.Phi and ConditionalRecurrence.Phi.595if (!isConditionalOnXorOfPHIs(cast<SelectInst>(ConditionalRecurrence.Step),596SimpleRecurrence.Phi,597ConditionalRecurrence.Phi, L))598return "Recurrences not intertwined with XOR";599}600601// Make sure that the TC doesn't exceed the bitwidth of LHSAux, or LHS.602Value *LHS = ConditionalRecurrence.Start;603Value *LHSAux = SimpleRecurrence ? SimpleRecurrence.Start : nullptr;604if (TC > (LHSAux ? LHSAux->getType()->getIntegerBitWidth()605: LHS->getType()->getIntegerBitWidth()))606return "Loop iterations exceed bitwidth of data";607608// Make sure that the computed value is used in the exit block: this should be609// true even if it is only really used in an outer loop's exit block, since610// the loop is in LCSSA form.611auto *ComputedValue = cast<SelectInst>(ConditionalRecurrence.Step);612if (none_of(ComputedValue->users(), [Exit](User *U) {613auto *UI = dyn_cast<Instruction>(U);614return UI && UI->getParent() == Exit;615}))616return "Unable to find use of computed value in loop exit block";617618assert(ConditionalRecurrence.ExtraConst &&619"Expected ExtraConst in conditional recurrence");620const APInt &GenPoly = *ConditionalRecurrence.ExtraConst;621622// PhiEvolutions are pairs of PHINodes along with their incoming value from623// within the loop, which we term as their step. Note that in the case of a624// Simple Recurrence, Step is an operand of the BO, while in a Conditional625// Recurrence, it is a SelectInst.626SmallVector<PhiStepPair, 2> PhiEvolutions;627PhiEvolutions.emplace_back(ConditionalRecurrence.Phi, ComputedValue);628if (SimpleRecurrence)629PhiEvolutions.emplace_back(SimpleRecurrence.Phi, SimpleRecurrence.BO);630631ValueEvolution VE(TC, *ByteOrderSwapped);632if (!VE.computeEvolutions(PhiEvolutions))633return VE.getError();634KnownBits ResultBits = VE.KnownPhis.at(ConditionalRecurrence.Phi);635636unsigned N = std::min(TC, ResultBits.getBitWidth());637auto IsZero = [](const KnownBits &K) { return K.isZero(); };638if (!checkExtractBits(ResultBits, N, IsZero, *ByteOrderSwapped))639return ErrBits(ResultBits, TC, *ByteOrderSwapped);640641return PolynomialInfo(TC, LHS, GenPoly, ComputedValue, *ByteOrderSwapped,642LHSAux);643}644645void CRCTable::print(raw_ostream &OS) const {646for (unsigned I = 0; I < 256; I++) {647(*this)[I].print(OS, false);648OS << (I % 16 == 15 ? '\n' : ' ');649}650}651652#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)653void CRCTable::dump() const { print(dbgs()); }654#endif655656void HashRecognize::print(raw_ostream &OS) const {657if (!L.isInnermost())658return;659OS << "HashRecognize: Checking a loop in '"660<< L.getHeader()->getParent()->getName() << "' from " << L.getLocStr()661<< "\n";662auto Ret = recognizeCRC();663if (!std::holds_alternative<PolynomialInfo>(Ret)) {664OS << "Did not find a hash algorithm\n";665if (std::holds_alternative<StringRef>(Ret))666OS << "Reason: " << std::get<StringRef>(Ret) << "\n";667if (std::holds_alternative<ErrBits>(Ret)) {668auto [Actual, Iter, ByteOrderSwapped] = std::get<ErrBits>(Ret);669OS << "Reason: Expected " << (ByteOrderSwapped ? "bottom " : "top ")670<< Iter << " bits zero (";671Actual.print(OS);672OS << ")\n";673}674return;675}676677auto Info = std::get<PolynomialInfo>(Ret);678OS << "Found" << (Info.ByteOrderSwapped ? " big-endian " : " little-endian ")679<< "CRC-" << Info.RHS.getBitWidth() << " loop with trip count "680<< Info.TripCount << "\n";681OS.indent(2) << "Initial CRC: ";682Info.LHS->print(OS);683OS << "\n";684OS.indent(2) << "Generating polynomial: ";685Info.RHS.print(OS, false);686OS << "\n";687OS.indent(2) << "Computed CRC: ";688Info.ComputedValue->print(OS);689OS << "\n";690if (Info.LHSAux) {691OS.indent(2) << "Auxiliary data: ";692Info.LHSAux->print(OS);693OS << "\n";694}695OS.indent(2) << "Computed CRC lookup table:\n";696genSarwateTable(Info.RHS, Info.ByteOrderSwapped).print(OS);697}698699#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)700void HashRecognize::dump() const { print(dbgs()); }701#endif702703std::optional<PolynomialInfo> HashRecognize::getResult() const {704auto Res = HashRecognize(L, SE).recognizeCRC();705if (std::holds_alternative<PolynomialInfo>(Res))706return std::get<PolynomialInfo>(Res);707return std::nullopt;708}709710HashRecognize::HashRecognize(const Loop &L, ScalarEvolution &SE)711: L(L), SE(SE) {}712713PreservedAnalyses HashRecognizePrinterPass::run(Loop &L,714LoopAnalysisManager &AM,715LoopStandardAnalysisResults &AR,716LPMUpdater &) {717HashRecognize(L, AR.SE).print(OS);718return PreservedAnalyses::all();719}720721722