LLVM 24.0.0git
HashRecognize.cpp
Go to the documentation of this file.
1//===- HashRecognize.cpp ----------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// The HashRecognize analysis recognizes unoptimized polynomial hash functions
10// with operations over a Galois field of characteristic 2, also called binary
11// fields, or GF(2^n). 2^n is termed the order of the Galois field. This class
12// of hash functions can be optimized using a lookup-table-driven
13// implementation, or with target-specific instructions.
14//
15// Examples:
16//
17// 1. Cyclic redundancy check (CRC), which is a polynomial division in GF(2).
18// 2. Rabin fingerprint, a component of the Rabin-Karp algorithm, which is a
19// rolling hash polynomial division in GF(2).
20// 3. Rijndael MixColumns, a step in AES computation, which is a polynomial
21// multiplication in GF(2^3).
22// 4. GHASH, the authentication mechanism in AES Galois/Counter Mode (GCM),
23// which is a polynomial evaluation in GF(2^128).
24//
25// All of them use an irreducible generating polynomial of degree m,
26//
27// c_m * x^m + c_(m-1) * x^(m-1) + ... + c_0 * x^0
28//
29// where each coefficient c is can take values 0 or 1. The polynomial is simply
30// represented by m+1 bits, corresponding to the coefficients. The different
31// variants of CRC are named by degree of generating polynomial used: so CRC-32
32// would use a polynomial of degree 32.
33//
34// The reason algorithms on GF(2^n) can be optimized with a lookup-table is the
35// following: in such fields, polynomial addition and subtraction are identical
36// and equivalent to XOR, polynomial multiplication is an AND, and polynomial
37// division is identity: the XOR and AND operations in unoptimized
38// implementations are performed bit-wise, and can be optimized to be performed
39// chunk-wise, by interleaving copies of the generating polynomial, and storing
40// the pre-computed values in a table.
41//
42// A generating polynomial of m bits always has the MSB set, so we usually
43// omit it. An example of a 16-bit polynomial is the CRC-16-CCITT polynomial:
44//
45// (x^16) + x^12 + x^5 + 1 = (1) 0001 0000 0010 0001 = 0x1021
46//
47// Transmissions are either in big-endian or little-endian form, and hash
48// algorithms are written according to this. For example, IEEE 802 and RS-232
49// specify little-endian transmission.
50//
51//===----------------------------------------------------------------------===//
52//
53// At the moment, we only recognize the CRC algorithm.
54// Documentation on CRC32 from the kernel:
55// https://www.kernel.org/doc/Documentation/crc32.txt
56//
57//
58//===----------------------------------------------------------------------===//
59
61#include "llvm/ADT/APInt.h"
69
70using namespace llvm;
71using namespace PatternMatch;
72using namespace SCEVPatternMatch;
73
74#define DEBUG_TYPE "hash-recognize"
75
76/// Checks if there's a stray instruction in the loop \p L outside of the
77/// use-def chains from \p Roots, or if we escape the loop during the use-def
78/// walk.
79static bool containsUnreachable(const Loop &L,
82 BasicBlock *Latch = L.getLoopLatch();
83
85 while (!Worklist.empty()) {
86 const Instruction *I = Worklist.pop_back_val();
87 // Skip this instruction if we have already visited it before.
88 if (!Visited.insert(I).second)
89 continue;
90
91 if (isa<PHINode>(I))
92 continue;
93
94 for (const Use &U : I->operands()) {
95 if (auto *UI = dyn_cast<Instruction>(U)) {
96 if (!L.contains(UI))
97 return true;
98 Worklist.push_back(UI);
99 }
100 }
101 }
102 return Latch->size() != Visited.size();
103}
104
105/// A structure that can hold either a Simple Recurrence or a Conditional
106/// Recurrence. Note that in the case of a Simple Recurrence, Step is an operand
107/// of the BO, while in a Conditional Recurrence, it is a SelectInst.
109 const Loop &L;
110 const PHINode *Phi = nullptr;
111 BinaryOperator *BO = nullptr;
112 Value *Start = nullptr;
113 Value *Step = nullptr;
114 std::optional<APInt> ExtraConst;
115
116 RecurrenceInfo(const Loop &L) : L(L) {}
117 operator bool() const { return BO; }
118
119 void print(raw_ostream &OS, unsigned Indent = 0) const {
120 OS.indent(Indent) << "Phi: ";
121 Phi->print(OS);
122 OS << "\n";
123 OS.indent(Indent) << "BinaryOperator: ";
124 BO->print(OS);
125 OS << "\n";
126 OS.indent(Indent) << "Start: ";
127 Start->print(OS);
128 OS << "\n";
129 OS.indent(Indent) << "Step: ";
130 Step->print(OS);
131 OS << "\n";
132 if (ExtraConst) {
133 OS.indent(Indent) << "ExtraConst: ";
134 ExtraConst->print(OS, false);
135 OS << "\n";
136 }
137 }
138
139#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
140 LLVM_DUMP_METHOD void dump() const { print(dbgs()); }
141#endif
142
143 bool matchSimpleRecurrence(const PHINode *P);
145 const PHINode *P,
146 Instruction::BinaryOps BOWithConstOpToMatch = Instruction::BinaryOpsEnd);
147
148private:
149 BinaryOperator *digRecurrence(
150 Instruction *V,
151 Instruction::BinaryOps BOWithConstOpToMatch = Instruction::BinaryOpsEnd);
152};
153
154/// Check the well-formedness of the (most|least) significant bit check given \p
155/// ConditionalRecurrence, \p SimpleRecurrence, depending on \p IsBigEndian. We
156/// check that ConditionalRecurrence.Step is a Select(Cmp()) where the compare
157/// is `>= 0` in the big-endian case, and `== 0` in the little-endian case (or
158/// the inverse, in which case the branches of the compare are swapped). We
159/// check that the LHS is (ConditionalRecurrence.Phi [xor SimpleRecurrence.Phi])
160/// in the big-endian case, and additionally check for an AND with one in the
161/// little-endian case. We then check AllowedByR against CheckAllowedByR, which
162/// is [0, smin) in the big-endian case, and is [0, 1) in the little-endian
163/// case. CheckAllowedByR checks for significant-bit-clear, and we match the
164/// corresponding arms of the select against bit-shift and
165/// bit-shift-and-xor-gen-poly.
166static bool
168 const RecurrenceInfo &SimpleRecurrence,
169 bool IsBigEndian) {
170 auto *SI = cast<SelectInst>(ConditionalRecurrence.Step);
171 CmpPredicate Pred;
172 const Value *L;
173 const APInt *R;
174 Instruction *TV, *FV;
175 if (!match(SI, m_Select(m_ICmp(Pred, m_Value(L), m_APInt(R)),
176 m_Instruction(TV), m_Instruction(FV))))
177 return false;
178
179 // Match predicate with or without a SimpleRecurrence (the corresponding data
180 // is LHSAux).
181 auto MatchPred = m_CombineOr(
182 m_Specific(ConditionalRecurrence.Phi),
183 m_c_Xor(m_ZExtOrTruncOrSelf(m_Specific(ConditionalRecurrence.Phi)),
184 m_ZExtOrTruncOrSelf(m_Specific(SimpleRecurrence.Phi))));
185 bool LWellFormed =
186 IsBigEndian ? match(L, MatchPred) : match(L, m_c_And(MatchPred, m_One()));
187 if (!LWellFormed)
188 return false;
189
191 unsigned BW = KnownR.getBitWidth();
192 auto RCR = ConstantRange::fromKnownBits(KnownR, false);
193 auto AllowedByR = ConstantRange::makeAllowedICmpRegion(Pred, RCR);
194 ConstantRange CheckAllowedByR(APInt::getZero(BW),
195 IsBigEndian ? APInt::getSignedMinValue(BW)
196 : APInt(BW, 1));
197
198 BinaryOperator *BitShift = ConditionalRecurrence.BO;
199 if (AllowedByR == CheckAllowedByR)
200 return TV == BitShift &&
201 match(FV, m_c_Xor(m_Specific(BitShift),
202 m_SpecificInt(*ConditionalRecurrence.ExtraConst)));
203 if (AllowedByR.inverse() == CheckAllowedByR)
204 return FV == BitShift &&
205 match(TV, m_c_Xor(m_Specific(BitShift),
206 m_SpecificInt(*ConditionalRecurrence.ExtraConst)));
207 return false;
208}
209
210/// Wraps llvm::matchSimpleRecurrence. Match a simple first order recurrence
211/// cycle of the form:
212///
213/// loop:
214/// %rec = phi [%start, %entry], [%BO, %loop]
215/// ...
216/// %BO = binop %rec, %step
217///
218/// or
219///
220/// loop:
221/// %rec = phi [%start, %entry], [%BO, %loop]
222/// ...
223/// %BO = binop %step, %rec
224///
227 Phi = P;
228 return true;
229 }
230 return false;
231}
232
233/// Digs for a recurrence starting with \p V hitting the PHI node in a use-def
234/// chain. Used by matchConditionalRecurrence.
236RecurrenceInfo::digRecurrence(Instruction *V,
237 Instruction::BinaryOps BOWithConstOpToMatch) {
240 Worklist.push_back(V);
241 while (!Worklist.empty()) {
242 Instruction *I = Worklist.pop_back_val();
243 // Skip this instruction if we have already visited it before.
244 if (!Visited.insert(I).second)
245 continue;
246
247 // Don't add a PHI's operands to the Worklist.
248 if (isa<PHINode>(I))
249 continue;
250
251 // Find a recurrence over a BinOp, by matching either of its operands
252 // with with the PHINode.
254 return cast<BinaryOperator>(I);
255
256 // Bind to ExtraConst, if we match exactly one.
257 if (I->getOpcode() == BOWithConstOpToMatch) {
258 if (ExtraConst)
259 return nullptr;
260 const APInt *C = nullptr;
261 if (match(I, m_c_BinOp(m_APInt(C), m_Value())))
262 ExtraConst = *C;
263 }
264
265 // Continue along the use-def chain.
266 for (Use &U : I->operands())
267 if (auto *UI = dyn_cast<Instruction>(U))
268 if (L.contains(UI))
269 Worklist.push_back(UI);
270 }
271 return nullptr;
272}
273
274/// A Conditional Recurrence is a recurrence of the form:
275///
276/// loop:
277/// %rec = phi [%start, %entry], [%step, %loop]
278/// ...
279/// %step = select _, %tv, %fv
280///
281/// where %tv and %fv ultimately end up using %rec via the same %BO instruction,
282/// after digging through the use-def chain.
283///
284/// ExtraConst is relevant if \p BOWithConstOpToMatch is supplied: when digging
285/// the use-def chain, a BinOp with opcode \p BOWithConstOpToMatch is matched,
286/// and ExtraConst is a constant operand of that BinOp. This peculiarity exists,
287/// because in a CRC algorithm, the \p BOWithConstOpToMatch is an XOR, and the
288/// ExtraConst ends up being the generating polynomial.
290 const PHINode *P, Instruction::BinaryOps BOWithConstOpToMatch) {
291 Phi = P;
292 if (Phi->getNumIncomingValues() != 2)
293 return false;
294
295 // Step comes from the loop latch, start comes from the other incoming value.
296 int LatchIdx = Phi->getBasicBlockIndex(L.getLoopLatch());
297 if (LatchIdx < 0)
298 return false;
299 Value *FoundStep = Phi->getIncomingValue(LatchIdx);
300 Value *FoundStart = Phi->getIncomingValue(!LatchIdx);
301
302 Instruction *TV, *FV;
303 if (!match(FoundStep,
305 return false;
306
307 // For a conditional recurrence, both the true and false values of the
308 // select must ultimately end up in the same recurrent BinOp.
309 BinaryOperator *FoundBO = digRecurrence(TV, BOWithConstOpToMatch);
310 BinaryOperator *AltBO = digRecurrence(FV, BOWithConstOpToMatch);
311 if (!FoundBO || FoundBO != AltBO)
312 return false;
313
314 if (BOWithConstOpToMatch != Instruction::BinaryOpsEnd && !ExtraConst) {
315 LLVM_DEBUG(dbgs() << "HashRecognize: Unable to match single BinaryOp "
316 "with constant in conditional recurrence\n");
317 return false;
318 }
319
320 BO = FoundBO;
321 Start = FoundStart;
322 Step = FoundStep;
323 return true;
324}
325
326/// Iterates over all the phis in \p LoopLatch, and attempts to extract a
327/// Conditional Recurrence and an optional Simple Recurrence.
328static std::optional<std::pair<RecurrenceInfo, RecurrenceInfo>>
329getRecurrences(BasicBlock *LoopLatch, const PHINode *IndVar, const Loop &L) {
330 auto Phis = LoopLatch->phis();
331 unsigned NumPhis = std::distance(Phis.begin(), Phis.end());
332 if (NumPhis != 2 && NumPhis != 3)
333 return {};
334
335 RecurrenceInfo SimpleRecurrence(L);
336 RecurrenceInfo ConditionalRecurrence(L);
337 for (PHINode &P : Phis) {
338 if (&P == IndVar)
339 continue;
340 if (!SimpleRecurrence)
341 SimpleRecurrence.matchSimpleRecurrence(&P);
342 if (!ConditionalRecurrence)
343 ConditionalRecurrence.matchConditionalRecurrence(
344 &P, Instruction::BinaryOps::Xor);
345 }
346 if (NumPhis == 3 && (!SimpleRecurrence || !ConditionalRecurrence))
347 return {};
348 return std::make_pair(SimpleRecurrence, ConditionalRecurrence);
349}
350
356
357/// Generate a lookup table of 256 entries by interleaving the generating
358/// polynomial. The optimization technique of table-lookup for CRC is also
359/// called the Sarwate algorithm.
361 bool IsBigEndian) {
362 unsigned BW = GenPoly.getBitWidth();
364 Table[0] = APInt::getZero(BW);
365
366 if (IsBigEndian) {
367 APInt CRCInit = APInt::getSignedMinValue(BW);
368 for (unsigned I = 1; I < 256; I <<= 1) {
369 CRCInit = CRCInit.shl(1) ^
370 (CRCInit.isSignBitSet() ? GenPoly : APInt::getZero(BW));
371 for (unsigned J = 0; J < I; ++J)
372 Table[I + J] = CRCInit ^ Table[J];
373 }
374 return Table;
375 }
376
377 APInt CRCInit(BW, 1);
378 for (unsigned I = 128; I; I >>= 1) {
379 CRCInit = CRCInit.lshr(1) ^ (CRCInit[0] ? GenPoly : APInt::getZero(BW));
380 for (unsigned J = 0; J < 256; J += (I << 1))
381 Table[I + J] = CRCInit ^ Table[J];
382 }
383 return Table;
384}
385
386/// Perform polynomial (GF(2)) floor division. This is based on the
387/// floor_division(S, P) algorithm in
388/// https://www.corsix.org/content/barrett-reduction-polynomials. Note that the
389/// maximum degree of the returned polynomial is
390/// max(0, deg(Dividend) - deg(Divisor)), but the bit width will be the same as
391/// that of Dividend.
392static APInt floorDivideGF2(APInt Dividend, APInt Divisor) {
393 assert(!Divisor.isZero() && "Cannot divide by zero");
394
395 // Extend the divisor bit width to match the dividend.
396 Divisor = Divisor.zext(Dividend.getBitWidth());
397
398 // Note that getActiveBits returns deg+1, but the computation below
399 // still holds.
400 unsigned DivisorActiveBits = Divisor.getActiveBits();
401
402 // Q = 0
403 APInt Quotient = APInt::getZero(Dividend.getBitWidth());
404 // S != 0 and deg(S) >= deg(P)
405 // (S != 0 implied by DivisorActiveBits > 0)
406 while (Dividend.getActiveBits() >= DivisorActiveBits) {
407 // T = S[deg(S)] / P[deg(P)]
408 unsigned Shift = Dividend.getActiveBits() - DivisorActiveBits;
409 // Q = Q + T
410 Quotient.setBit(Shift);
411 // S = S - T * P
412 Dividend ^= Divisor.shl(Shift);
413 }
414 return Quotient;
415}
416
417/// Generate the constants for performing a Polynomial (GF(2)) Barrett Reduction
418/// according to Intel's Fast CRC Computation white paper with some adjustments
419/// to account for the fact that bit width and trip count can vary.
420std::pair<APInt, APInt>
422 unsigned BW = Info.RHS.getBitWidth();
423 unsigned TC = Info.TripCount;
424
425 // Recover the full generating polynomial in normal form by reflecting the LE
426 // case and adding the implied x^BW term.
427 // deg(P(x)) = BW due to the implied term, and thus P(x) must fit in exactly
428 // BW+1 bits.
429 APInt FullGenPoly =
430 (Info.IsBigEndian ? Info.RHS : Info.RHS.reverseBits()).zext(BW + 1);
431 FullGenPoly.setBit(BW);
432
433 // Calculate mu = floor(x^(BW+TC) / P(x)).
434 // deg(mu) <= deg(x^(BW+TC)) - deg(P(x)) = BW+TC - BW = TC, and thus mu must
435 // fit in at most TC+1 bits.
436 unsigned DivBW = BW + TC + 1;
437 APInt Mu = floorDivideGF2(APInt::getOneBitSet(DivBW, BW + TC), FullGenPoly)
438 .trunc(TC + 1);
439
440 // In the bit-reflected (little-endian) case, mu and P(x) must be
441 // bit-reflected across their respective widths for the corresponding Barrett
442 // reduction steps.
443 if (!Info.IsBigEndian) {
444 Mu = Mu.reverseBits();
445 FullGenPoly = FullGenPoly.reverseBits();
446 }
447
448 return {Mu, FullGenPoly};
449}
450
451/// Checks that \p P1 and \p P2 are used together in an XOR in the use-def chain
452/// of \p SI's condition, ignoring any casts. The purpose of this function is to
453/// ensure that LHSAux from the SimpleRecurrence is used correctly in the CRC
454/// computation.
455///
456/// In other words, it checks for the following pattern:
457///
458/// loop:
459/// %P1 = phi [_, %entry], [%P1.next, %loop]
460/// %P2 = phi [_, %entry], [%P2.next, %loop]
461/// ...
462/// %xor = xor (CastOrSelf %P1), (CastOrSelf %P2)
463///
464/// where %xor is in the use-def chain of \p SI's condition.
465static bool isConditionalOnXorOfPHIs(const SelectInst *SI, const PHINode *P1,
466 const PHINode *P2, const Loop &L) {
469
470 // matchConditionalRecurrence has already ensured that the SelectInst's
471 // condition is an Instruction.
472 Worklist.push_back(cast<Instruction>(SI->getCondition()));
473
474 while (!Worklist.empty()) {
475 const Instruction *I = Worklist.pop_back_val();
476 // Skip this instruction if we have already visited it before.
477 if (!Visited.insert(I).second)
478 continue;
479
480 // Don't add a PHI's operands to the Worklist.
481 if (isa<PHINode>(I))
482 continue;
483
484 // If we match an XOR of the two PHIs ignoring casts, we're done.
487 return true;
488
489 // Continue along the use-def chain.
490 for (const Use &U : I->operands())
491 if (auto *UI = dyn_cast<Instruction>(U))
492 if (L.contains(UI))
493 Worklist.push_back(UI);
494 }
495 return false;
496}
497
498// Recognizes a multiplication or division by the constant two, using SCEV. By
499// doing this, we're immune to whether the IR expression is mul/udiv or
500// equivalently shl/lshr. Return false when it is a UDiv, true when it is a Mul,
501// and std::nullopt otherwise.
502static std::optional<bool> isBigEndianBitShift(Value *V, ScalarEvolution &SE) {
503 if (!V->getType()->isIntegerTy())
504 return {};
505
506 const SCEV *E = SE.getSCEV(V);
508 return false;
510 return true;
511 return {};
512}
513
514/// The main entry point for analyzing a loop and recognizing the CRC algorithm.
515/// Returns a PolynomialInfo on success, and a StringRef on failure.
516std::variant<PolynomialInfo, StringRef> HashRecognize::recognizeCRC() const {
517 if (!L.isInnermost())
518 return "Loop is not innermost";
519 BasicBlock *Latch = L.getLoopLatch();
520 BasicBlock *Exit = L.getExitBlock();
521 const PHINode *IndVar = L.getCanonicalInductionVariable();
522 if (!Latch || !Exit || !IndVar || L.getNumBlocks() != 1 ||
523 !L.getLatchCmpInst())
524 return "Loop not in canonical form";
525 unsigned TC = SE.getSmallConstantTripCount(&L);
526 if (!TC)
527 return "Unable to find a small constant trip count";
528
529 auto R = getRecurrences(Latch, IndVar, L);
530 if (!R)
531 return "Found stray PHI";
532 auto [SimpleRecurrence, ConditionalRecurrence] = *R;
533 if (!ConditionalRecurrence)
534 return "Unable to find conditional recurrence";
535
536 // Make sure that all recurrences are either all SCEVMul with two or SCEVDiv
537 // with two, or in other words, that they're single bit-shifts.
538 std::optional<bool> IsBigEndian =
539 isBigEndianBitShift(ConditionalRecurrence.BO, SE);
540 if (!IsBigEndian)
541 return "Loop with non-unit bitshifts";
542 if (SimpleRecurrence) {
543 if (isBigEndianBitShift(SimpleRecurrence.BO, SE) != IsBigEndian)
544 return "Loop with non-unit bitshifts";
545
546 // Ensure that the PHIs have exactly two uses:
547 // the bit-shift, and the XOR (or a cast feeding into the XOR).
548 // Also ensure that the SimpleRecurrence's evolution doesn't have stray
549 // users.
550 if (!ConditionalRecurrence.Phi->hasNUses(2) ||
551 !SimpleRecurrence.Phi->hasNUses(2) ||
552 SimpleRecurrence.BO->getUniqueUndroppableUser() != SimpleRecurrence.Phi)
553 return "Recurrences have stray uses";
554
555 // Check that the SelectInst ConditionalRecurrence.Step is conditional on
556 // the XOR of SimpleRecurrence.Phi and ConditionalRecurrence.Phi.
557 if (!isConditionalOnXorOfPHIs(cast<SelectInst>(ConditionalRecurrence.Step),
558 SimpleRecurrence.Phi,
559 ConditionalRecurrence.Phi, L))
560 return "Recurrences not intertwined with XOR";
561 }
562
563 Value *LHS = ConditionalRecurrence.Start;
564 Value *LHSAux = SimpleRecurrence ? SimpleRecurrence.Start : nullptr;
565
566 // In the big-endian case where LHSAux is narrower than LHS, the most
567 // significant bit check will never be influenced by LHSAux. In this case,
568 // SimpleRecurrence must still be well-formed, but LHSAux is effectively dead.
569 // This also averts a possible miscompile later where LHSAux gets shifted by
570 // its entire bit width, creating poison.
571 if (*IsBigEndian && LHSAux &&
572 LHSAux->getType()->getIntegerBitWidth() <
573 LHS->getType()->getIntegerBitWidth())
574 LHSAux = nullptr;
575
576 // Make sure that the TC doesn't exceed the bitwidth of LHSAux, or LHS.
577 if (TC > (LHSAux ? LHSAux->getType()->getIntegerBitWidth()
578 : LHS->getType()->getIntegerBitWidth()))
579 return "Loop iterations exceed bitwidth of data";
580
581 // Ensure nothing other than the computed value makes its way out of the loop.
582 // Since the loop is in LCSSA form, this is as simple as checking the PHI
583 // nodes in the exit block.
584 auto *ComputedValue = cast<SelectInst>(ConditionalRecurrence.Step);
585 if (any_of(Exit->phis(), [Latch, ComputedValue](PHINode &PN) {
586 return PN.getIncomingValueForBlock(Latch) != ComputedValue;
587 }))
588 return "Found stray incoming values in loop exit block";
589
590 assert(ConditionalRecurrence.ExtraConst &&
591 "Expected ExtraConst in conditional recurrence");
592 const APInt &GenPoly = *ConditionalRecurrence.ExtraConst;
593
594 if (!isSignificantBitCheckWellFormed(ConditionalRecurrence, SimpleRecurrence,
595 *IsBigEndian))
596 return "Malformed significant-bit check";
597
599 {ComputedValue,
601 L.getLatchCmpInst(), Latch->getTerminator()});
602 if (SimpleRecurrence)
603 Roots.push_back(SimpleRecurrence.BO);
604 if (containsUnreachable(L, Roots))
605 return "Found stray unvisited instructions";
606
607 return PolynomialInfo(TC, LHS, GenPoly, ComputedValue, *IsBigEndian, LHSAux);
608}
609
611 for (unsigned I = 0; I < 256; I++) {
612 (*this)[I].print(OS, false);
613 OS << (I % 16 == 15 ? '\n' : ' ');
614 }
615}
616
617#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
618void CRCTable::dump() const { print(dbgs()); }
619#endif
620
622 if (!L.isInnermost())
623 return;
624 OS << "HashRecognize: Checking a loop in '"
625 << L.getHeader()->getParent()->getName() << "' from " << L.getLocStr()
626 << "\n";
627 auto Ret = recognizeCRC();
628 if (!std::holds_alternative<PolynomialInfo>(Ret)) {
629 OS << "Did not find a hash algorithm\n";
630 if (std::holds_alternative<StringRef>(Ret))
631 OS << "Reason: " << std::get<StringRef>(Ret) << "\n";
632 return;
633 }
634
635 auto Info = std::get<PolynomialInfo>(Ret);
636 OS << "Found" << (Info.IsBigEndian ? " big-endian " : " little-endian ")
637 << "CRC-" << Info.RHS.getBitWidth() << " loop with trip count "
638 << Info.TripCount << "\n";
639 OS.indent(2) << "Initial CRC: ";
640 Info.LHS->print(OS);
641 OS << "\n";
642 OS.indent(2) << "Generating polynomial: ";
643 Info.RHS.print(OS, false);
644 OS << "\n";
645 OS.indent(2) << "Computed CRC: ";
646 Info.ComputedValue->print(OS);
647 OS << "\n";
648 if (Info.LHSAux) {
649 OS.indent(2) << "Auxiliary data: ";
650 Info.LHSAux->print(OS);
651 OS << "\n";
652 }
653 OS.indent(2) << "Computed CRC lookup table:\n";
654 genSarwateTable(Info.RHS, Info.IsBigEndian).print(OS);
655 OS.indent(2) << "Computed CRC Barrett constants:\n";
656 auto [Mu, FullGenPoly] = genBarrettConstants(Info);
657 OS << "Mu = ";
658 Mu.print(OS, false);
659 OS << ", FullGenPoly = ";
660 FullGenPoly.print(OS, false);
661 OS << "\n";
662}
663
664#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
665void HashRecognize::dump() const { print(dbgs()); }
666#endif
667
668std::optional<PolynomialInfo> HashRecognize::getResult() const {
669 auto Res = HashRecognize(L, SE).recognizeCRC();
670 if (std::holds_alternative<PolynomialInfo>(Res))
671 return std::get<PolynomialInfo>(Res);
672 return std::nullopt;
673}
674
676 : L(L), SE(SE) {}
677
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds.
Definition Compiler.h:678
static bool containsUnreachable(const Loop &L, ArrayRef< const Instruction * > Roots)
Checks if there's a stray instruction in the loop L outside of the use-def chains from Roots,...
static bool isSignificantBitCheckWellFormed(const RecurrenceInfo &ConditionalRecurrence, const RecurrenceInfo &SimpleRecurrence, bool IsBigEndian)
Check the well-formedness of the (most|least) significant bit check given ConditionalRecurrence,...
static bool isConditionalOnXorOfPHIs(const SelectInst *SI, const PHINode *P1, const PHINode *P2, const Loop &L)
Checks that P1 and P2 are used together in an XOR in the use-def chain of SI's condition,...
static std::optional< std::pair< RecurrenceInfo, RecurrenceInfo > > getRecurrences(BasicBlock *LoopLatch, const PHINode *IndVar, const Loop &L)
Iterates over all the phis in LoopLatch, and attempts to extract a Conditional Recurrence and an opti...
static std::optional< bool > isBigEndianBitShift(Value *V, ScalarEvolution &SE)
static APInt floorDivideGF2(APInt Dividend, APInt Divisor)
Perform polynomial (GF(2)) floor division.
This header provides classes for managing per-loop analyses.
#define I(x, y, z)
Definition MD5.cpp:57
#define P(N)
#define LLVM_DEBUG(...)
Definition Debug.h:119
Class for arbitrary precision integers.
Definition APInt.h:78
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
Definition APInt.cpp:1055
unsigned getActiveBits() const
Compute the number of active bits in the value.
Definition APInt.h:1537
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
Definition APInt.cpp:968
void setBit(unsigned BitPosition)
Set the given bit to 1 whose position is given as "bitPosition".
Definition APInt.h:1355
bool isZero() const
Determine if this value is zero, i.e. all bits are clear.
Definition APInt.h:381
unsigned getBitWidth() const
Return the number of bits in the APInt.
Definition APInt.h:1513
LLVM_ABI APInt reverseBits() const
Definition APInt.cpp:790
static APInt getSignedMinValue(unsigned numBits)
Gets minimum signed value of APInt for a specific bit width.
Definition APInt.h:220
APInt shl(unsigned shiftAmt) const
Left-shift function.
Definition APInt.h:880
bool isSignBitSet() const
Determine if sign bit of this APInt is set.
Definition APInt.h:342
static APInt getZero(unsigned numBits)
Get the '0' value for the specified bit-width.
Definition APInt.h:201
static APInt getOneBitSet(unsigned numBits, unsigned BitNo)
Return an APInt with exactly one bit set in the result.
Definition APInt.h:240
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
Definition APInt.h:858
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
LLVM Basic Block Representation.
Definition BasicBlock.h:62
iterator_range< const_phi_iterator > phis() const
Returns a range that iterates over the phis in the basic block.
Definition BasicBlock.h:530
size_t size() const
Definition BasicBlock.h:482
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Definition BasicBlock.h:237
An abstraction over a floating-point predicate, and a pack of an integer predicate with samesign info...
This class represents a range of values.
static LLVM_ABI ConstantRange fromKnownBits(const KnownBits &Known, bool IsSigned)
Initialize a range based on a known bits constraint.
static LLVM_ABI ConstantRange makeAllowedICmpRegion(CmpInst::Predicate Pred, const ConstantRange &Other)
Produce the smallest range such that all values that may satisfy the given predicate with any value c...
LLVM_ABI PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR, LPMUpdater &)
static LLVM_ABI CRCTable genSarwateTable(const APInt &GenPoly, bool IsBigEndian)
Generate a lookup table of 256 entries by interleaving the generating polynomial.
static LLVM_ABI std::pair< APInt, APInt > genBarrettConstants(const PolynomialInfo &Info)
Auxilary entry point after analysis to generate constants for a GF(2) Barrett Reduction.
LLVM_ABI std::optional< PolynomialInfo > getResult() const
LLVM_DUMP_METHOD void dump() const
LLVM_ABI HashRecognize(const Loop &L, ScalarEvolution &SE)
LLVM_ABI void print(raw_ostream &OS) const
LLVM_ABI std::variant< PolynomialInfo, StringRef > recognizeCRC() const
The main entry point for analyzing a loop and recognizing the CRC algorithm.
This class provides an interface for updating the loop pass manager based on mutations to the loop ne...
Represents a single loop in the control flow graph.
Definition LoopInfo.h:40
Value * getIncomingValueForBlock(const BasicBlock *BB) const
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
This class represents an analyzed expression in the program.
The main scalar evolution driver.
LLVM_ABI const SCEV * getSCEV(Value *V)
Return a SCEV expression for the full generality of the specified expression.
This class represents the LLVM 'select' instruction.
size_type size() const
Definition SmallPtrSet.h:99
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
LLVM_ABI unsigned getIntegerBitWidth() const
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:255
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
raw_ostream & indent(unsigned NumSpaces)
indent - Insert 'NumSpaces' spaces.
match_combine_or< Ty... > m_CombineOr(const Ty &...Ps)
Combine pattern matchers matching any of Ps patterns.
auto m_Cmp()
Matches any compare instruction and ignore it.
ap_match< APInt > m_APInt(const APInt *&Res)
Match a ConstantInt or splatted ConstantVector, binding the specified pointer to the contained APInt.
BinaryOp_match< LHS, RHS, Instruction::And, true > m_c_And(const LHS &L, const RHS &R)
Matches an And with LHS and RHS in either order.
specific_intval< false > m_SpecificInt(const APInt &V)
Match a specific integer value or vector with all elements equal to the value.
bool match(Val *V, const Pattern &P)
match_bind< Instruction > m_Instruction(Instruction *&I)
Match an instruction, capturing it if we match.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
cst_pred_ty< is_one > m_One()
Match an integer 1 or a vector with all elements equal to 1.
ThreeOps_match< Cond, LHS, RHS, Instruction::Select > m_Select(const Cond &C, const LHS &L, const RHS &R)
Matches SelectInst.
auto m_Value()
Match an arbitrary value and ignore it.
BinaryOp_match< LHS, RHS, Instruction::Xor, true > m_c_Xor(const LHS &L, const RHS &R)
Matches an Xor with LHS and RHS in either order.
auto m_ZExtOrTruncOrSelf(const OpTy &Op)
AnyBinaryOp_match< LHS, RHS, true > m_c_BinOp(const LHS &L, const RHS &R)
Matches a BinaryOperator with LHS and RHS in either order.
CmpClass_match< LHS, RHS, ICmpInst > m_ICmp(CmpPredicate &Pred, const LHS &L, const RHS &R)
match_bind< const SCEVMulExpr > m_scev_Mul(const SCEVMulExpr *&V)
bool match(const SCEV *S, const Pattern &P)
SCEVBinaryExpr_match< SCEVUDivExpr, Op0_t, Op1_t > m_scev_UDiv(const Op0_t &Op0, const Op1_t &Op1)
cst_pred_ty< is_specific_cst > m_scev_SpecificInt(uint64_t V)
Match an SCEV constant with a plain unsigned integer.
This is an optimization pass for GlobalISel generic memory operations.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
AnalysisManager< Loop, LoopStandardAnalysisResults & > LoopAnalysisManager
The loop analysis manager.
LLVM_ABI bool matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO, Value *&Start, Value *&Step)
Attempt to match a simple first order recurrence cycle of the form: iv = phi Ty [Start,...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
A structure that can hold either a Simple Recurrence or a Conditional Recurrence.
const PHINode * Phi
LLVM_DUMP_METHOD void dump() const
bool matchConditionalRecurrence(const PHINode *P, Instruction::BinaryOps BOWithConstOpToMatch=Instruction::BinaryOpsEnd)
A Conditional Recurrence is a recurrence of the form:
void print(raw_ostream &OS, unsigned Indent=0) const
std::optional< APInt > ExtraConst
bool matchSimpleRecurrence(const PHINode *P)
Wraps llvm::matchSimpleRecurrence.
BinaryOperator * BO
RecurrenceInfo(const Loop &L)
A custom std::array with 256 entries, that also has a print function.
LLVM_ABI LLVM_DUMP_METHOD void dump() const
LLVM_ABI void print(raw_ostream &OS) const
static KnownBits makeConstant(const APInt &C)
Create known bits from a known constant.
Definition KnownBits.h:315
unsigned getBitWidth() const
Get the bit width of this value.
Definition KnownBits.h:44
The adaptor from a function pass to a loop pass computes these analyses and makes them available to t...
The structure that is returned when a polynomial algorithm was recognized by the analysis.
LLVM_ABI PolynomialInfo(unsigned TripCount, Value *LHS, const APInt &RHS, Value *ComputedValue, bool IsBigEndian, Value *LHSAux=nullptr)