Skip to content

Commit cc16f88

Browse files
committed
[HashRecognize] Introduce new analysis
Introduce a fresh analysis for recognizing polynomial hashes, with the rationale that several targets have specific instructions to optimize things like CRC and GHASH (eg. X86 and RISC-V crypto extension). We limit the scope to polynomial hashes computed in a Galois field of characteristic 2, since this class of operations can also be optimized in the absence of target-specific instructions to use a lookup table. At the moment, we only recognize the CRC algorithm.
1 parent 6f7268e commit cc16f88

File tree

8 files changed

+1709
-2
lines changed

8 files changed

+1709
-2
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
//===- HashRecognize.h ------------------------------------------*- 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+
// Interface for the HashRecognize analysis, which identifies hash functions
10+
// that can be optimized using a lookup-table or with target-specific
11+
// instructions.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_ANALYSIS_HASHRECOGNIZE_H
16+
#define LLVM_ANALYSIS_HASHRECOGNIZE_H
17+
18+
#include "llvm/ADT/APInt.h"
19+
#include "llvm/Analysis/LoopAnalysisManager.h"
20+
#include "llvm/Analysis/ScalarEvolution.h"
21+
#include "llvm/IR/PassManager.h"
22+
#include "llvm/IR/Value.h"
23+
#include "llvm/Support/KnownBits.h"
24+
#include "llvm/Transforms/Scalar/LoopPassManager.h"
25+
26+
namespace llvm {
27+
/// A tuple of bits that are expected to be zero, number N of them expected to
28+
/// be zero, with a boolean indicating whether it's the top or bottom N bits
29+
/// expected to be zero.
30+
using ErrBits = std::tuple<KnownBits, unsigned, bool>;
31+
32+
/// A custom std::array with 256 entries, that also has a print function.
33+
struct CRCTable : public std::array<APInt, 256> {
34+
void print(raw_ostream &OS) const;
35+
};
36+
37+
/// The structure that is returned when a polynomial algorithm was recognized by
38+
/// the analysis. Currently, only the CRC algorithm is recognized.
39+
struct PolynomialInfo {
40+
// The small constant trip-count of the analyzed loop.
41+
unsigned TripCount;
42+
43+
// The LHS in a polynomial operation, or the initial variable of the
44+
// computation, since all polynomial operations must have a constant RHS,
45+
// which is the generating polynomial. It is the LHS of the polynomial
46+
// division in the case of CRC. Since polynomial division is an XOR in
47+
// GF(2^m), this variable must be XOR'ed with RHS in a loop to yield the
48+
// ComputedValue.
49+
const Value *LHS;
50+
51+
// The generating polynomial, or the RHS of the polynomial division in the
52+
// case of CRC.
53+
APInt RHS;
54+
55+
// The final computed value. This is a remainder of a polynomial division in
56+
// the case of CRC, which must be zero.
57+
const Value *ComputedValue;
58+
59+
// Set to true in the case of big-endian.
60+
bool ByteOrderSwapped;
61+
62+
// An optional auxiliary checksum that augments the LHS. In the case of CRC,
63+
// it is XOR'ed with the LHS, so that the computation's final remainder is
64+
// zero.
65+
const Value *LHSAux;
66+
67+
PolynomialInfo(unsigned TripCount, const Value *LHS, const APInt &RHS,
68+
const Value *ComputedValue, bool ByteOrderSwapped,
69+
const Value *LHSAux = nullptr);
70+
};
71+
72+
/// The analysis.
73+
class HashRecognize {
74+
const Loop &L;
75+
ScalarEvolution &SE;
76+
77+
public:
78+
HashRecognize(const Loop &L, ScalarEvolution &SE);
79+
80+
// The main analysis entry point.
81+
std::variant<PolynomialInfo, ErrBits, StringRef> recognizeCRC() const;
82+
83+
// Auxilary entry point after analysis to interleave the generating polynomial
84+
// and return a 256-entry CRC table.
85+
CRCTable genSarwateTable(const APInt &GenPoly, bool ByteOrderSwapped) const;
86+
87+
void print(raw_ostream &OS) const;
88+
};
89+
90+
class HashRecognizePrinterPass
91+
: public PassInfoMixin<HashRecognizePrinterPass> {
92+
raw_ostream &OS;
93+
94+
public:
95+
explicit HashRecognizePrinterPass(raw_ostream &OS) : OS(OS) {}
96+
PreservedAnalyses run(Loop &L, LoopAnalysisManager &AM,
97+
LoopStandardAnalysisResults &AR, LPMUpdater &);
98+
};
99+
100+
class HashRecognizeAnalysis : public AnalysisInfoMixin<HashRecognizeAnalysis> {
101+
friend AnalysisInfoMixin<HashRecognizeAnalysis>;
102+
static AnalysisKey Key;
103+
104+
public:
105+
using Result = HashRecognize;
106+
Result run(Loop &L, LoopAnalysisManager &AM, LoopStandardAnalysisResults &AR);
107+
};
108+
} // namespace llvm
109+
110+
#endif

llvm/lib/Analysis/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ add_llvm_component_library(LLVMAnalysis
7878
FunctionPropertiesAnalysis.cpp
7979
GlobalsModRef.cpp
8080
GuardUtils.cpp
81+
HashRecognize.cpp
8182
HeatUtils.cpp
8283
IR2Vec.cpp
8384
IRSimilarityIdentifier.cpp

0 commit comments

Comments
 (0)