[LoopIdiomRecognize] Enable clmul optimization for CRC loops (#203405)

The current `optimizeCRCLoop` function always optimizes CRC loops to use
a 256-entry Sarwate lookup table to process a byte at a time (except on
Hexagon and with optsize). However, some targets are able to process
larger chunks of CRC data with carry-less/polynomial multiplication
instructions. Implement this approach in IR for such targets using the
`llvm.clmul` intrinsic. (Only with optsize for the moment, though.)

Like the current CRC loop optimization, this does not apply to the
Hexagon target, despite it having a `pmpyw` instruction.

Assisted-by: Claude Opus 4.8
This commit is contained in:
Sean Clarke 2026-07-16 09:53:09 -05:00 committed by GitHub
parent 6e7ff09291
commit c7a5b9c0dd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 3519 additions and 335 deletions

View file

@ -88,6 +88,16 @@ public:
LLVM_ABI static CRCTable genSarwateTable(const APInt &GenPoly,
bool IsBigEndian);
/// Auxilary entry point after analysis to generate constants for a GF(2)
/// Barrett Reduction.
/// Returns a pair of Mu of bitwidth TC+1 and FullGenPoly of bitwidth BW+1.
/// Mu is used in the first clmul operation. Mu = floor(x^(BW+TC) / P(x)).
/// FullGenPoly is used in the second clmul operation, and is Info.RHS with
/// the implied BW'th bit.
/// Endianness is accounted for using Info.IsBigEndian.
LLVM_ABI static std::pair<APInt, APInt>
genBarrettConstants(const PolynomialInfo &Info);
LLVM_ABI void print(raw_ostream &OS) const;
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

View file

@ -1193,6 +1193,10 @@ public:
/// Return true if the hardware has a fast square-root instruction.
LLVM_ABI bool haveFastSqrt(Type *Ty) const;
/// Return true if the hardware has a fast carry-less multiplication
/// instruction.
LLVM_ABI bool haveFastClmul(IntegerType *Ty) const;
/// Return true if the cost of the instruction is too high to speculatively
/// execute and should be kept behind a branch.
/// This normally just wraps around a getInstructionCost() call, but some

View file

@ -570,6 +570,8 @@ public:
virtual bool haveFastSqrt(Type *Ty) const { return false; }
virtual bool haveFastClmul(IntegerType *Ty) const { return false; }
virtual bool isExpensiveToSpeculativelyExecute(const Instruction *I) const {
return true;
}

View file

@ -682,6 +682,20 @@ public:
TLI->isOperationLegalOrCustom(ISD::FSQRT, VT);
}
bool haveFastClmul(IntegerType *Ty) const override {
// FIXME: clmul should really be Promote for any bitwidth under the largest
// legal bitwidth for clmul. Using IndexTy instead of Ty is a hack to get
// around that shortcoming.
IntegerType *IndexTy =
DL.getIndexType(Ty->getContext(), DL.getAllocaAddrSpace());
if (Ty->getBitWidth() > IndexTy->getBitWidth())
return false;
const TargetLoweringBase *TLI = getTLI();
EVT VT = TLI->getValueType(DL, IndexTy);
return TLI->isOperationLegalOrCustom(ISD::CLMUL, VT);
}
bool isFCmpOrdCheaperThanFCmpZero(Type *Ty) const override { return true; }
InstructionCost getFPOpCost(Type *Ty) const override {

View file

@ -376,6 +376,71 @@ CRCTable HashRecognize::genSarwateTable(const APInt &GenPoly,
return Table;
}
/// Perform polynomial (GF(2)) floor division. This is based on the
/// floor_division(S, P) algorithm in
/// https://www.corsix.org/content/barrett-reduction-polynomials. Note that the
/// maximum degree of the returned polynomial is
/// max(0, deg(Dividend) - deg(Divisor)), but the bit width will be the same as
/// that of Dividend.
static APInt floorDivideGF2(APInt Dividend, APInt Divisor) {
assert(!Divisor.isZero() && "Cannot divide by zero");
// Extend the divisor bit width to match the dividend.
Divisor = Divisor.zext(Dividend.getBitWidth());
// Note that getActiveBits returns deg+1, but the computation below
// still holds.
unsigned DivisorActiveBits = Divisor.getActiveBits();
// Q = 0
APInt Quotient = APInt::getZero(Dividend.getBitWidth());
// S != 0 and deg(S) >= deg(P)
// (S != 0 implied by DivisorActiveBits > 0)
while (Dividend.getActiveBits() >= DivisorActiveBits) {
// T = S[deg(S)] / P[deg(P)]
unsigned Shift = Dividend.getActiveBits() - DivisorActiveBits;
// Q = Q + T
Quotient.setBit(Shift);
// S = S - T * P
Dividend ^= Divisor.shl(Shift);
}
return Quotient;
}
/// Generate the constants for performing a Polynomial (GF(2)) Barrett Reduction
/// according to Intel's Fast CRC Computation white paper with some adjustments
/// to account for the fact that bit width and trip count can vary.
std::pair<APInt, APInt>
HashRecognize::genBarrettConstants(const PolynomialInfo &Info) {
unsigned BW = Info.RHS.getBitWidth();
unsigned TC = Info.TripCount;
// Recover the full generating polynomial in normal form by reflecting the LE
// case and adding the implied x^BW term.
// deg(P(x)) = BW due to the implied term, and thus P(x) must fit in exactly
// BW+1 bits.
APInt FullGenPoly =
(Info.IsBigEndian ? Info.RHS : Info.RHS.reverseBits()).zext(BW + 1);
FullGenPoly.setBit(BW);
// Calculate mu = floor(x^(BW+TC) / P(x)).
// deg(mu) <= deg(x^(BW+TC)) - deg(P(x)) = BW+TC - BW = TC, and thus mu must
// fit in at most TC+1 bits.
unsigned DivBW = BW + TC + 1;
APInt Mu = floorDivideGF2(APInt::getOneBitSet(DivBW, BW + TC), FullGenPoly)
.trunc(TC + 1);
// In the bit-reflected (little-endian) case, mu and P(x) must be
// bit-reflected across their respective widths for the corresponding Barrett
// reduction steps.
if (!Info.IsBigEndian) {
Mu = Mu.reverseBits();
FullGenPoly = FullGenPoly.reverseBits();
}
return {Mu, FullGenPoly};
}
/// Checks that \p P1 and \p P2 are used together in an XOR in the use-def chain
/// of \p SI's condition, ignoring any casts. The purpose of this function is to
/// ensure that LHSAux from the SimpleRecurrence is used correctly in the CRC
@ -576,6 +641,13 @@ void HashRecognize::print(raw_ostream &OS) const {
}
OS.indent(2) << "Computed CRC lookup table:\n";
genSarwateTable(Info.RHS, Info.IsBigEndian).print(OS);
OS.indent(2) << "Computed CRC Barrett constants:\n";
auto [Mu, FullGenPoly] = genBarrettConstants(Info);
OS << "Mu = ";
Mu.print(OS, false);
OS << ", FullGenPoly = ";
FullGenPoly.print(OS, false);
OS << "\n";
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

View file

@ -742,6 +742,10 @@ bool TargetTransformInfo::haveFastSqrt(Type *Ty) const {
return TTIImpl->haveFastSqrt(Ty);
}
bool TargetTransformInfo::haveFastClmul(IntegerType *Ty) const {
return TTIImpl->haveFastClmul(Ty);
}
bool TargetTransformInfo::isExpensiveToSpeculativelyExecute(
const Instruction *I) const {
return TTIImpl->isExpensiveToSpeculativelyExecute(I);

View file

@ -32,6 +32,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
@ -166,6 +167,11 @@ static cl::opt<bool> ForceMemsetPatternIntrinsic(
cl::desc("Use memset.pattern intrinsic whenever possible"), cl::init(false),
cl::Hidden);
static cl::opt<bool> ForceCRCClmul(
"loop-idiom-force-crc-clmul",
cl::desc("Use the clmul-based CRC loop optimization whenever possible"),
cl::init(false), cl::Hidden);
extern cl::opt<bool> ProfcheckDisableMetadataFixes;
} // namespace llvm
@ -259,6 +265,9 @@ private:
bool avoidLIRForMultiBlockLoop(bool IsMemset = false,
bool IsLoopMemset = false);
bool optimizeCRCLoop(const PolynomialInfo &Info);
void optimizeCRCLoopUsingClmul(const PolynomialInfo &Info,
IntegerType *ClmulTy);
void optimizeCRCLoopUsingTableLookup(const PolynomialInfo &Info);
/// @}
/// \name Noncountable Loop Idiom Handling
@ -397,11 +406,10 @@ bool LoopIdiomRecognize::runOnCountableLoop() {
MadeChange |= runOnLoopBlock(BB, BECount, ExitBlocks);
}
// Optimize a CRC loop if HashRecognize found one, provided we're not
// optimizing for size.
if (!DisableLIRP::HashRecognize && !ApplyCodeSizeHeuristics)
// Attempt to optimize a CRC loop if one is detected by HashRecognize.
if (!DisableLIRP::HashRecognize)
if (auto Res = HashRecognize(*CurLoop, *SE).getResult())
optimizeCRCLoop(*Res);
MadeChange |= optimizeCRCLoop(*Res);
return MadeChange;
}
@ -1582,6 +1590,159 @@ bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
if (TT.getArch() == Triple::hexagon)
return false;
// In the clmul optimization, the first clmul uses 2*TC bits, and the second
// clmul uses CRCBW+TC bits. For simplicity, have both clmuls operate on the
// same bit width.
unsigned CRCBW = Info.LHS->getType()->getIntegerBitWidth();
unsigned ClmulBW = std::max(2 * Info.TripCount, CRCBW + Info.TripCount);
auto *ClmulTy = IntegerType::get(Info.LHS->getContext(), ClmulBW);
// The force-crc-clmul flag should cause the clmul optimization to run
// unconditionally.
if (ForceCRCClmul) {
optimizeCRCLoopUsingClmul(Info, ClmulTy);
return true;
}
// FIXME: Once intrinsic cost modeling is more reliable for clmul, that should
// be used to determine which optimization to use. Until then, only apply the
// clmul optimization when optimizing for size, since a lookup table is not
// viable in that case.
if (!ApplyCodeSizeHeuristics) {
optimizeCRCLoopUsingTableLookup(Info);
return true;
}
// The clmul optimization should only be applied if clmul with the required
// bit width is a fast operation on the target.
// TODO: If clmul exists on the target but not for the required width, it
// might be possible to split into multiple iterations of reduction.
if (TTI->haveFastClmul(ClmulTy)) {
optimizeCRCLoopUsingClmul(Info, ClmulTy);
return true;
}
return false;
}
// The algorithm used in this optimization is a Polynomial (GF(2)) Barrett
// Reduction based on Intel's "Fast CRC Computation for Generic Polynomials
// Using PCLMULQDQ Instruction" white paper (December 2009).
void LoopIdiomRecognize::optimizeCRCLoopUsingClmul(const PolynomialInfo &Info,
IntegerType *ClmulTy) {
Type *CRCTy = Info.LHS->getType();
LLVMContext &Ctx = CRCTy->getContext();
unsigned CRCBW = CRCTy->getIntegerBitWidth();
// The loop's TripCount determines how many bits of the data are processed,
// regardless of whether the actual data bit width matches (if auxiliary data
// is even used at all).
unsigned TC = Info.TripCount;
unsigned ClmulBW = ClmulTy->getBitWidth();
// First, generate the constants required for GF(2) Barrett reduction.
auto [Mu, FullGenPoly] = HashRecognize::genBarrettConstants(Info);
Value *MuConst = ConstantInt::get(Ctx, Mu.zext(ClmulBW));
Value *GenPolyConst = ConstantInt::get(Ctx, FullGenPoly.zext(ClmulBW));
IRBuilder<> Builder(CurLoop->getLoopPreheader()->getTerminator());
auto LoTCBits = [TC, &Builder, &Ctx](Value *Op, const Twine &Name) {
unsigned OpBW = Op->getType()->getIntegerBitWidth();
assert(OpBW >= TC && "Bit width should be at least TripCount");
auto *Mask = ConstantInt::get(Ctx, APInt::getLowBitsSet(OpBW, TC));
return Builder.CreateAnd(Op, Mask, Name);
};
Value *LHS = Builder.CreateZExt(Info.LHS, ClmulTy, "crc.cast");
// Based on the Intel white paper, in our case, we have
// R(x) = (LHS*x^TC) xor (LHSAux ? getTCBits(LHSAux)*x^CRCBW : 0)
// since the CRC loop multiplies LHS by x each iteration, and the x^CRCBW term
// of getTCBits(LHSAux) is XORed in for the significant bit check.
// Rather than compute the full R(x), we can split it in two: a quotient for
// step 1 (floor(R(x)/x^CRCBW)) and a remainder for step 3 (R(x) mod x^CRCBW).
//
// ClmulMuInput is an evolving variable that will eventually become the part
// used in step 1, which can be simplified to
// (LHS*x^(TC-CRCBW)) xor (LHSAux ? getTCBits(LHSAux) : 0).
// Thanks to restrictions imposed by HashRecognize for big-endian CRC loops,
// getTCBits(LHSAux) = LHSAux*x^(TC-CRCBW), so this can be further simplified
// to (LHS xor (LHSAux ? LHSAux : 0))*x^(TC-CRCBW).
Value *ClmulMuInput = LHS;
// If auxiliary data is present, XOR it in with the CRC.
if (Value *Data = Info.LHSAux) {
// This is usually a zext, but DataBW may exceed ClmulBW if both CRCBW and
// TC are small enough.
Data = Builder.CreateZExtOrTrunc(Data, ClmulTy, "data.cast");
ClmulMuInput = Builder.CreateXor(ClmulMuInput, Data, "xor.crc.data");
}
// Align the current CRC with TripCount (multiply or divide by x^(TC-CRCBW)).
if (Info.IsBigEndian && TC != CRCBW) {
ClmulMuInput =
TC > CRCBW
? Builder.CreateShl(ClmulMuInput, TC - CRCBW, "crc.align.tc")
: Builder.CreateLShr(ClmulMuInput, CRCBW - TC, "crc.align.tc");
}
// Zero out any bits above (TC-1) for calculation since the original loop
// doesn't use them in the significant bit checks.
ClmulMuInput = LoTCBits(ClmulMuInput, "crc.tcbits");
// Step 1: T1(x) = floor(R(x)/x^CRCBW) * mu
// Input is TC bits and mu is TC+1 bits, so result will be 2*TC bits.
Value *ClmulMu = Builder.CreateBinaryIntrinsic(
Intrinsic::clmul, ClmulMuInput, MuConst, /*FMFSource=*/{}, "clmul.mu");
// Calculate floor(T1(x)/x^TC) for step 2.
Value *ClmulGPInput = Info.IsBigEndian
? Builder.CreateLShr(ClmulMu, TC, "quot.lshr")
: LoTCBits(ClmulMu, "quot.mask");
// Step 2: T2(x) = floor(T1(x)/x^TC) * P(x)
// Input is TC bits and P(x) is CRCBW+1 bits, so result will be CRCBW+TC bits.
Value *ClmulGP = Builder.CreateBinaryIntrinsic(Intrinsic::clmul, ClmulGPInput,
GenPolyConst,
/*FMFSource=*/{}, "clmul.gp");
// Calculate the least significant part of R(x) for step 3 as specified above.
// R(x) mod x^CRCBW = LHS*x^TC mod x^CRCBW, though the (mod x^CRCBW) is
// handled later on when truncating back to CRCBW for ComputedValue.
Value *CRCAlignClmul =
Info.IsBigEndian ? Builder.CreateShl(LHS, TC, "crc.shl") : LHS;
// Step 3: C(x) = (R(x) xor T2(x)) mod x^CRCBW
Value *CRCNext = Builder.CreateXor(CRCAlignClmul, ClmulGP, "xor.crc.mult");
if (!Info.IsBigEndian)
CRCNext = Builder.CreateLShr(CRCNext, TC, "crc.lshr");
// Bring the result back down the the CRC bit width.
CRCNext = Builder.CreateTrunc(CRCNext, CRCTy, "crc.next");
// Replace the result of the loop with the new computed CRC value.
Info.ComputedValue->replaceUsesOutsideBlock(CRCNext, CurLoop->getLoopLatch());
// Finally, clean up the loop as much as possible so it can be trivially
// deleted.
{
for (PHINode &PN : make_early_inc_range(CurLoop->getHeader()->phis())) {
PN.replaceAllUsesWith(PoisonValue::get(PN.getType()));
RecursivelyDeleteDeadPHINode(&PN);
}
// Replace the exit condition with constant true/false to always cause a
// branch to the exit block.
deleteDeadInstruction(CurLoop->getLatchCmpInst());
auto *BrInst = cast<CondBrInst>(CurLoop->getLoopLatch()->getTerminator());
BrInst->setCondition(ConstantInt::getBool(
Ctx, BrInst->getSuccessor(0) == CurLoop->getExitBlock()));
SE->forgetLoop(CurLoop);
}
}
void LoopIdiomRecognize::optimizeCRCLoopUsingTableLookup(
const PolynomialInfo &Info) {
// First, create a new GlobalVariable corresponding to the
// Sarwate-lookup-table.
Type *CRCTy = Info.LHS->getType();
@ -1592,9 +1753,9 @@ bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
[CRCTy](const APInt &E) { return ConstantInt::get(CRCTy, E); });
Constant *ConstArray =
ConstantArray::get(ArrayType::get(CRCTy, 256), CRCConstants);
GlobalVariable *GV =
new GlobalVariable(M, ConstArray->getType(), true,
GlobalValue::PrivateLinkage, ConstArray, ".crctable");
GlobalVariable *GV = new GlobalVariable(
*CurLoop->getHeader()->getModule(), ConstArray->getType(), true,
GlobalValue::PrivateLinkage, ConstArray, ".crctable");
PHINode *IV = CurLoop->getCanonicalInductionVariable();
SmallVector<PHINode *, 2> Cleanup;
@ -1718,7 +1879,6 @@ bool LoopIdiomRecognize::optimizeCRCLoop(const PolynomialInfo &Info) {
RecursivelyDeleteDeadPHINode(PN);
SE->forgetLoop(CurLoop);
}
return true;
}
bool LoopIdiomRecognize::runOnNoncountableLoop() {

View file

@ -25,6 +25,8 @@ define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) {
; CHECK-NEXT: 39937 23744 23936 40257 24320 40897 40577 24128 23040 39617 39809 23360 39169 22976 22656 38977
; CHECK-NEXT: 34817 18624 18816 35137 19200 35777 35457 19008 19968 36545 36737 20288 36097 19904 19584 35905
; CHECK-NEXT: 17408 33985 34177 17728 34561 18368 18048 34369 33281 17088 17280 33601 16640 33217 32897 16448
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 511, FullGenPoly = 81923
;
entry:
br label %loop
@ -73,6 +75,8 @@ define i16 @crc16.le.tc8.udiv(i8 %msg, i16 %checksum) {
; CHECK-NEXT: 39937 23744 23936 40257 24320 40897 40577 24128 23040 39617 39809 23360 39169 22976 22656 38977
; CHECK-NEXT: 34817 18624 18816 35137 19200 35777 35457 19008 19968 36545 36737 20288 36097 19904 19584 35905
; CHECK-NEXT: 17408 33985 34177 17728 34561 18368 18048 34369 33281 17088 17280 33601 16640 33217 32897 16448
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 511, FullGenPoly = 81923
;
entry:
br label %loop
@ -121,6 +125,8 @@ define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) {
; CHECK-NEXT: 39937 23744 23936 40257 24320 40897 40577 24128 23040 39617 39809 23360 39169 22976 22656 38977
; CHECK-NEXT: 34817 18624 18816 35137 19200 35777 35457 19008 19968 36545 36737 20288 36097 19904 19584 35905
; CHECK-NEXT: 17408 33985 34177 17728 34561 18368 18048 34369 33281 17088 17280 33601 16640 33217 32897 16448
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 114687, FullGenPoly = 81923
;
entry:
br label %loop
@ -168,6 +174,8 @@ define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) {
; CHECK-NEXT: 4 13 22 31 27 18 9 0 1 8 19 26 30 23 12 5
; CHECK-NEXT: 26 19 8 1 5 12 23 30 31 22 13 4 0 9 18 27
; CHECK-NEXT: 16 25 2 11 15 6 29 20 21 28 7 14 10 3 24 17
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 24423, FullGenPoly = 59
;
entry:
br label %loop
@ -215,6 +223,8 @@ define i16 @crc16.be.tc8.crc.init.li(i16 %checksum, i8 %msg) {
; CHECK-NEXT: 52093 56156 60223 64286 35833 39896 43963 48026 19061 23124 27191 31254 2801 6864 10931 14994
; CHECK-NEXT: 64814 60687 56684 52557 48554 44427 40424 36297 31782 27655 23652 19525 15522 11395 7392 3265
; CHECK-NEXT: 61215 65342 53085 57212 44955 49082 36825 40952 28183 32310 20053 24180 11923 16050 3793 7920
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 273, FullGenPoly = 69665
;
entry:
%msg.ext = zext i8 %msg to i16
@ -260,6 +270,8 @@ define i16 @crc16.be.tc8.crc.init.arg(i16 %crc.init) {
; CHECK-NEXT: 52093 56156 60223 64286 35833 39896 43963 48026 19061 23124 27191 31254 2801 6864 10931 14994
; CHECK-NEXT: 64814 60687 56684 52557 48554 44427 40424 36297 31782 27655 23652 19525 15522 11395 7392 3265
; CHECK-NEXT: 61215 65342 53085 57212 44955 49082 36825 40952 28183 32310 20053 24180 11923 16050 3793 7920
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 273, FullGenPoly = 69665
;
entry:
br label %loop
@ -302,6 +314,8 @@ define i16 @crc16.be.tc8.crc.init.arg.flipped.sb.check(i16 %crc.init) {
; CHECK-NEXT: 52093 56156 60223 64286 35833 39896 43963 48026 19061 23124 27191 31254 2801 6864 10931 14994
; CHECK-NEXT: 64814 60687 56684 52557 48554 44427 40424 36297 31782 27655 23652 19525 15522 11395 7392 3265
; CHECK-NEXT: 61215 65342 53085 57212 44955 49082 36825 40952 28183 32310 20053 24180 11923 16050 3793 7920
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 273, FullGenPoly = 69665
;
entry:
br label %loop
@ -344,6 +358,8 @@ define i8 @crc8.be.tc8.ptr.nested.loop(ptr %msg, i32 %loop.limit) {
; CHECK-NEXT: 248 229 194 223 140 145 182 171 16 13 42 55 100 121 94 67
; CHECK-NEXT: 178 175 136 149 198 219 252 225 90 71 96 125 46 51 20 9
; CHECK-NEXT: 127 98 69 88 11 22 49 44 151 138 173 176 227 254 217 196
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 284, FullGenPoly = 285
;
entry:
br label %outer.loop
@ -380,6 +396,54 @@ exit: ; preds = %outer.loop
ret i8 %crc.outer
}
define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) {
; CHECK-LABEL: 'crc16.be.tc16'
; CHECK-NEXT: Found big-endian CRC-16 loop with trip count 16
; CHECK-NEXT: Initial CRC: i16 %checksum
; CHECK-NEXT: Generating polynomial: 4129
; CHECK-NEXT: Computed CRC: %crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor
; CHECK-NEXT: Auxiliary data: i16 %msg
; CHECK-NEXT: Computed CRC lookup table:
; CHECK-NEXT: 0 4129 8258 12387 16516 20645 24774 28903 33032 37161 41290 45419 49548 53677 57806 61935
; CHECK-NEXT: 4657 528 12915 8786 21173 17044 29431 25302 37689 33560 45947 41818 54205 50076 62463 58334
; CHECK-NEXT: 9314 13379 1056 5121 25830 29895 17572 21637 42346 46411 34088 38153 58862 62927 50604 54669
; CHECK-NEXT: 13907 9842 5649 1584 30423 26358 22165 18100 46939 42874 38681 34616 63455 59390 55197 51132
; CHECK-NEXT: 18628 22757 26758 30887 2112 6241 10242 14371 51660 55789 59790 63919 35144 39273 43274 47403
; CHECK-NEXT: 23285 19156 31415 27286 6769 2640 14899 10770 56317 52188 64447 60318 39801 35672 47931 43802
; CHECK-NEXT: 27814 31879 19684 23749 11298 15363 3168 7233 60846 64911 52716 56781 44330 48395 36200 40265
; CHECK-NEXT: 32407 28342 24277 20212 15891 11826 7761 3696 65439 61374 57309 53244 48923 44858 40793 36728
; CHECK-NEXT: 37256 33193 45514 41451 53516 49453 61774 57711 4224 161 12482 8419 20484 16421 28742 24679
; CHECK-NEXT: 33721 37784 41979 46042 49981 54044 58239 62302 689 4752 8947 13010 16949 21012 25207 29270
; CHECK-NEXT: 46570 42443 38312 34185 62830 58703 54572 50445 13538 9411 5280 1153 29798 25671 21540 17413
; CHECK-NEXT: 42971 47098 34713 38840 59231 63358 50973 55100 9939 14066 1681 5808 26199 30326 17941 22068
; CHECK-NEXT: 55628 51565 63758 59695 39368 35305 47498 43435 22596 18533 30726 26663 6336 2273 14466 10403
; CHECK-NEXT: 52093 56156 60223 64286 35833 39896 43963 48026 19061 23124 27191 31254 2801 6864 10931 14994
; CHECK-NEXT: 64814 60687 56684 52557 48554 44427 40424 36297 31782 27655 23652 19525 15522 11395 7392 3265
; CHECK-NEXT: 61215 65342 53085 57212 44955 49082 36825 40952 28183 32310 20053 24180 11923 16050 3793 7920
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 69936, FullGenPoly = 69665
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %crc, %data
%data.next = shl i16 %data, 1
%check.sb = icmp sge i16 %xor.crc.data, 0
%crc.shl = shl i16 %crc, 1
%crc.xor = xor i16 %crc.shl, 4129
%crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) {
; CHECK-LABEL: 'crc16.be.tc8.misalign'
; CHECK-NEXT: Found big-endian CRC-16 loop with trip count 8
@ -403,6 +467,8 @@ define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) {
; CHECK-NEXT: 52093 56156 60223 64286 35833 39896 43963 48026 19061 23124 27191 31254 2801 6864 10931 14994
; CHECK-NEXT: 64814 60687 56684 52557 48554 44427 40424 36297 31782 27655 23652 19525 15522 11395 7392 3265
; CHECK-NEXT: 61215 65342 53085 57212 44955 49082 36825 40952 28183 32310 20053 24180 11923 16050 3793 7920
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 273, FullGenPoly = 69665
;
entry:
br label %loop
@ -426,6 +492,104 @@ exit: ; preds = %loop
ret i16 %crc.next
}
define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) {
; CHECK-LABEL: 'crc8.be.tc16.misalign'
; CHECK-NEXT: Found big-endian CRC-8 loop with trip count 16
; CHECK-NEXT: Initial CRC: i8 %checksum
; CHECK-NEXT: Generating polynomial: 29
; CHECK-NEXT: Computed CRC: %crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
; CHECK-NEXT: Auxiliary data: i16 %msg
; CHECK-NEXT: Computed CRC lookup table:
; CHECK-NEXT: 0 29 58 39 116 105 78 83 232 245 210 207 156 129 166 187
; CHECK-NEXT: 205 208 247 234 185 164 131 158 37 56 31 2 81 76 107 118
; CHECK-NEXT: 135 154 189 160 243 238 201 212 111 114 85 72 27 6 33 60
; CHECK-NEXT: 74 87 112 109 62 35 4 25 162 191 152 133 214 203 236 241
; CHECK-NEXT: 19 14 41 52 103 122 93 64 251 230 193 220 143 146 181 168
; CHECK-NEXT: 222 195 228 249 170 183 144 141 54 43 12 17 66 95 120 101
; CHECK-NEXT: 148 137 174 179 224 253 218 199 124 97 70 91 8 21 50 47
; CHECK-NEXT: 89 68 99 126 45 48 23 10 177 172 139 150 197 216 255 226
; CHECK-NEXT: 38 59 28 1 82 79 104 117 206 211 244 233 186 167 128 157
; CHECK-NEXT: 235 246 209 204 159 130 165 184 3 30 57 36 119 106 77 80
; CHECK-NEXT: 161 188 155 134 213 200 239 242 73 84 115 110 61 32 7 26
; CHECK-NEXT: 108 113 86 75 24 5 34 63 132 153 190 163 240 237 202 215
; CHECK-NEXT: 53 40 15 18 65 92 123 102 221 192 231 250 169 180 147 142
; CHECK-NEXT: 248 229 194 223 140 145 182 171 16 13 42 55 100 121 94 67
; CHECK-NEXT: 178 175 136 149 198 219 252 225 90 71 96 125 46 51 20 9
; CHECK-NEXT: 127 98 69 88 11 22 49 44 151 138 173 176 227 254 217 196
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 72779, FullGenPoly = 285
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%data.next = shl i16 %data, 1
%check.sb = icmp sge i8 %xor.crc.data, 0
%crc.shl = shl i8 %crc, 1
%crc.xor = xor i8 %crc.shl, 29
%crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) {
; CHECK-LABEL: 'crc8.be.tc8.data16.misalign'
; CHECK-NEXT: Found big-endian CRC-8 loop with trip count 8
; CHECK-NEXT: Initial CRC: i8 %checksum
; CHECK-NEXT: Generating polynomial: 29
; CHECK-NEXT: Computed CRC: %crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
; CHECK-NEXT: Auxiliary data: i16 %msg
; CHECK-NEXT: Computed CRC lookup table:
; CHECK-NEXT: 0 29 58 39 116 105 78 83 232 245 210 207 156 129 166 187
; CHECK-NEXT: 205 208 247 234 185 164 131 158 37 56 31 2 81 76 107 118
; CHECK-NEXT: 135 154 189 160 243 238 201 212 111 114 85 72 27 6 33 60
; CHECK-NEXT: 74 87 112 109 62 35 4 25 162 191 152 133 214 203 236 241
; CHECK-NEXT: 19 14 41 52 103 122 93 64 251 230 193 220 143 146 181 168
; CHECK-NEXT: 222 195 228 249 170 183 144 141 54 43 12 17 66 95 120 101
; CHECK-NEXT: 148 137 174 179 224 253 218 199 124 97 70 91 8 21 50 47
; CHECK-NEXT: 89 68 99 126 45 48 23 10 177 172 139 150 197 216 255 226
; CHECK-NEXT: 38 59 28 1 82 79 104 117 206 211 244 233 186 167 128 157
; CHECK-NEXT: 235 246 209 204 159 130 165 184 3 30 57 36 119 106 77 80
; CHECK-NEXT: 161 188 155 134 213 200 239 242 73 84 115 110 61 32 7 26
; CHECK-NEXT: 108 113 86 75 24 5 34 63 132 153 190 163 240 237 202 215
; CHECK-NEXT: 53 40 15 18 65 92 123 102 221 192 231 250 169 180 147 142
; CHECK-NEXT: 248 229 194 223 140 145 182 171 16 13 42 55 100 121 94 67
; CHECK-NEXT: 178 175 136 149 198 219 252 225 90 71 96 125 46 51 20 9
; CHECK-NEXT: 127 98 69 88 11 22 49 44 151 138 173 176 227 254 217 196
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 284, FullGenPoly = 285
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%data.next = shl i16 %data, 1
%check.sb = icmp sge i8 %xor.crc.data, 0
%crc.shl = shl i8 %crc, 1
%crc.xor = xor i8 %crc.shl, 29
%crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) {
; CHECK-LABEL: 'crc32.le.tc8.data32'
; CHECK-NEXT: Found little-endian CRC-32 loop with trip count 8
@ -450,6 +614,8 @@ define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) {
; CHECK-NEXT: 54925 50948 62879 58390 37033 33056 46011 41522 23237 19276 31191 26718 7393 3432 16371 11898
; CHECK-NEXT: 59150 63111 50204 54677 41258 45219 33336 37809 27462 31439 18516 23005 11618 15595 3696 8185
; CHECK-NEXT: 63375 58886 54429 50452 45483 40994 37561 33584 31687 27214 22741 18780 15843 11370 7921 3960
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 273, FullGenPoly = 67601
;
entry:
br label %loop
@ -473,6 +639,56 @@ exit: ; preds = %loop
ret i32 %crc.next
}
define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) {
; CHECK-LABEL: 'crc8.le.tc8.data32'
; CHECK-NEXT: Found little-endian CRC-8 loop with trip count 8
; CHECK-NEXT: Initial CRC: i8 %checksum
; CHECK-NEXT: Generating polynomial: 59
; CHECK-NEXT: Computed CRC: %crc.next = select i1 %check.sb, i8 %crc.lshr, i8 %crc.xor
; CHECK-NEXT: Auxiliary data: i32 %msg
; CHECK-NEXT: Computed CRC lookup table:
; CHECK-NEXT: 0 16 32 48 55 39 23 7 25 9 57 41 46 62 14 30
; CHECK-NEXT: 50 34 18 2 5 21 37 53 43 59 11 27 28 12 60 44
; CHECK-NEXT: 19 3 51 35 36 52 4 20 10 26 42 58 61 45 29 13
; CHECK-NEXT: 33 49 1 17 22 6 54 38 56 40 24 8 15 31 47 63
; CHECK-NEXT: 38 54 6 22 17 1 49 33 63 47 31 15 8 24 40 56
; CHECK-NEXT: 20 4 52 36 35 51 3 19 13 29 45 61 58 42 26 10
; CHECK-NEXT: 53 37 21 5 2 18 34 50 44 60 12 28 27 11 59 43
; CHECK-NEXT: 7 23 39 55 48 32 16 0 30 14 62 46 41 57 9 25
; CHECK-NEXT: 59 43 27 11 12 28 44 60 34 50 2 18 21 5 53 37
; CHECK-NEXT: 9 25 41 57 62 46 30 14 16 0 48 32 39 55 7 23
; CHECK-NEXT: 40 56 8 24 31 15 63 47 49 33 17 1 6 22 38 54
; CHECK-NEXT: 26 10 58 42 45 61 13 29 3 19 35 51 52 36 20 4
; CHECK-NEXT: 29 13 61 45 42 58 10 26 4 20 36 52 51 35 19 3
; CHECK-NEXT: 47 63 15 31 24 8 56 40 54 38 22 6 1 17 33 49
; CHECK-NEXT: 14 30 46 62 57 41 25 9 23 7 55 39 32 48 0 16
; CHECK-NEXT: 60 44 28 12 11 27 43 59 37 53 5 21 18 2 50 34
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 107, FullGenPoly = 119
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%data.trunc = trunc i32 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%sb.crc.data = and i8 %xor.crc.data, 1
%check.sb = icmp eq i8 %sb.crc.data, 0
%crc.lshr = lshr i8 %crc, 1
%crc.xor = xor i8 %crc.lshr, 59
%crc.next = select i1 %check.sb, i8 %crc.lshr, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i16 @crc16.be.tc8.zext.data(i8 %msg, i16 %checksum) {
; CHECK-LABEL: 'crc16.be.tc8.zext.data'
; CHECK-NEXT: Found big-endian CRC-16 loop with trip count 8
@ -496,6 +712,8 @@ define i16 @crc16.be.tc8.zext.data(i8 %msg, i16 %checksum) {
; CHECK-NEXT: 53664 53410 54180 53926 54696 54442 55212 54958 55728 55474 56244 55990 56760 56506 57276 57022
; CHECK-NEXT: 57792 57538 58308 58054 58824 58570 59340 59086 59856 59602 60372 60118 60888 60634 61404 61150
; CHECK-NEXT: 61920 61666 62436 62182 62952 62698 63468 63214 63984 63730 64500 64246 65016 64762 65532 65278
; CHECK-NEXT: Computed CRC Barrett constants:
; CHECK-NEXT: Mu = 257, FullGenPoly = 65794
;
entry:
br label %loop

View file

@ -0,0 +1,707 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
; RUN: opt -passes=loop-idiom -mtriple=aarch64 -mattr=-aes -S %s | FileCheck --check-prefixes=ALL,NOAES %s
; RUN: opt -passes=loop-idiom -mtriple=aarch64 -mattr=+aes -S %s | FileCheck --check-prefixes=ALL,AES %s
define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) optsize {
; NOAES-LABEL: define i16 @crc16.le.tc8(
; NOAES-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
; NOAES-NEXT: [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
; NOAES-NEXT: [[AND_DATA_CRC:%.*]] = and i8 [[XOR_DATA_CRC]], 1
; NOAES-NEXT: [[DATA_NEXT]] = lshr i8 [[DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp eq i8 [[AND_DATA_CRC]], 0
; NOAES-NEXT: [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
; NOAES-NEXT: [[XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i16 @crc16.le.tc8(
; AES-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i24
; AES-NEXT: [[DATA_CAST:%.*]] = zext i8 [[MSG]] to i24
; AES-NEXT: [[XOR_CRC_DATA:%.*]] = xor i24 [[CRC_CAST]], [[DATA_CAST]]
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i24 [[XOR_CRC_DATA]], 255
; AES-NEXT: [[CLMUL_MU:%.*]] = call i24 @llvm.clmul.i24(i24 [[CRC_TCBITS]], i24 511)
; AES-NEXT: [[QUOT_MASK:%.*]] = and i24 [[CLMUL_MU]], 255
; AES-NEXT: [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_MASK]], i24 81923)
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_CAST]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_LSHR1:%.*]] = lshr i24 [[XOR_CRC_MULT]], 8
; AES-NEXT: [[CRC_NEXT2:%.*]] = trunc i24 [[CRC_LSHR1]] to i16
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
; AES-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
%crc.trunc = trunc i16 %crc to i8
%xor.data.crc = xor i8 %data, %crc.trunc
%and.data.crc = and i8 %xor.data.crc, 1
%data.next = lshr i8 %data, 1
%check.sb = icmp eq i8 %and.data.crc, 0
%crc.lshr = lshr i16 %crc, 1
%xor = xor i16 %crc.lshr, -24575
%crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) optsize {
; NOAES-LABEL: define i16 @crc16.le.tc16(
; NOAES-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
; NOAES-NEXT: [[AND_CRC_DATA:%.*]] = and i16 [[XOR_CRC_DATA]], 1
; NOAES-NEXT: [[DATA_NEXT]] = lshr i16 [[DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp eq i16 [[AND_CRC_DATA]], 0
; NOAES-NEXT: [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
; NOAES-NEXT: [[CRC_XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[CRC_XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i16 @crc16.le.tc16(
; AES-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i32
; AES-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; AES-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[XOR_CRC_DATA1]], 65535
; AES-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 114687)
; AES-NEXT: [[QUOT_MASK:%.*]] = and i32 [[CLMUL_MU]], 65535
; AES-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_MASK]], i32 81923)
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_CAST]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_LSHR2:%.*]] = lshr i32 [[XOR_CRC_MULT]], 16
; AES-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[CRC_LSHR2]] to i16
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
; AES-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %crc, %data
%and.crc.data = and i16 %xor.crc.data, 1
%data.next = lshr i16 %data, 1
%check.sb = icmp eq i16 %and.crc.data, 0
%crc.lshr = lshr i16 %crc, 1
%crc.xor = xor i16 %crc.lshr, -24575
%crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) optsize {
; NOAES-LABEL: define i8 @crc8.le.tc16(
; NOAES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
; NOAES-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOAES-NEXT: [[AND_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
; NOAES-NEXT: [[DATA_NEXT]] = lshr i16 [[DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp eq i8 [[AND_CRC_DATA]], 0
; NOAES-NEXT: [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
; NOAES-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 29
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i8 @crc8.le.tc16(
; AES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i32
; AES-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; AES-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[XOR_CRC_DATA1]], 65535
; AES-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 24423)
; AES-NEXT: [[QUOT_MASK:%.*]] = and i32 [[CLMUL_MU]], 65535
; AES-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_MASK]], i32 59)
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_CAST]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_LSHR2:%.*]] = lshr i32 [[XOR_CRC_MULT]], 16
; AES-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[CRC_LSHR2]] to i8
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; AES-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%and.crc.data = and i8 %xor.crc.data, 1
%data.next = lshr i16 %data, 1
%check.sb = icmp eq i8 %and.crc.data, 0
%crc.lshr = lshr i8 %crc, 1
%crc.xor = xor i8 %crc.lshr, 29
%crc.next = select i1 %check.sb, i8 %crc.lshr, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) optsize {
; NOAES-LABEL: define i16 @crc16.be.tc16(
; NOAES-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
; NOAES-NEXT: [[DATA_NEXT]] = shl i16 [[DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp sge i16 [[XOR_CRC_DATA]], 0
; NOAES-NEXT: [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
; NOAES-NEXT: [[CRC_XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[CRC_XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i16 @crc16.be.tc16(
; AES-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i32
; AES-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; AES-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[XOR_CRC_DATA1]], 65535
; AES-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 69936)
; AES-NEXT: [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
; AES-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_LSHR]], i32 69665)
; AES-NEXT: [[CRC_SHL2:%.*]] = shl i32 [[CRC_CAST]], 16
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_SHL2]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[XOR_CRC_MULT]] to i16
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
; AES-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %crc, %data
%data.next = shl i16 %data, 1
%check.sb = icmp sge i16 %xor.crc.data, 0
%crc.shl = shl i16 %crc, 1
%crc.xor = xor i16 %crc.shl, 4129
%crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) optsize {
; NOAES-LABEL: define i16 @crc16.be.tc8.misalign(
; NOAES-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
; NOAES-NEXT: [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
; NOAES-NEXT: [[DATA_NEXT]] = shl i8 [[DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_DATA_CRC]], 0
; NOAES-NEXT: [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
; NOAES-NEXT: [[XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i16 @crc16.be.tc8.misalign(
; AES-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i24
; AES-NEXT: [[CRC_ALIGN_TC:%.*]] = lshr i24 [[CRC_CAST]], 8
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i24 [[CRC_ALIGN_TC]], 255
; AES-NEXT: [[CLMUL_MU:%.*]] = call i24 @llvm.clmul.i24(i24 [[CRC_TCBITS]], i24 273)
; AES-NEXT: [[QUOT_LSHR:%.*]] = lshr i24 [[CLMUL_MU]], 8
; AES-NEXT: [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_LSHR]], i24 69665)
; AES-NEXT: [[CRC_SHL1:%.*]] = shl i24 [[CRC_CAST]], 8
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_SHL1]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_NEXT2:%.*]] = trunc i24 [[XOR_CRC_MULT]] to i16
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
; AES-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
%crc.trunc = trunc i16 %crc to i8
%xor.data.crc = xor i8 %data, %crc.trunc
%data.next = shl i8 %data, 1
%check.sb = icmp sge i8 %xor.data.crc, 0
%crc.shl = shl i16 %crc, 1
%xor = xor i16 %crc.shl, 4129
%crc.next = select i1 %check.sb, i16 %crc.shl, i16 %xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) optsize {
; NOAES-LABEL: define i8 @crc8.be.tc16.misalign(
; NOAES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
; NOAES-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOAES-NEXT: [[DATA_NEXT]] = shl i16 [[DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
; NOAES-NEXT: [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
; NOAES-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i8 @crc8.be.tc16.misalign(
; AES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i32
; AES-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; AES-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; AES-NEXT: [[CRC_ALIGN_TC:%.*]] = shl i32 [[XOR_CRC_DATA1]], 8
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[CRC_ALIGN_TC]], 65535
; AES-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 72779)
; AES-NEXT: [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
; AES-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_LSHR]], i32 285)
; AES-NEXT: [[CRC_SHL2:%.*]] = shl i32 [[CRC_CAST]], 16
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_SHL2]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[XOR_CRC_MULT]] to i8
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; AES-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%data.next = shl i16 %data, 1
%check.sb = icmp sge i8 %xor.crc.data, 0
%crc.shl = shl i8 %crc, 1
%crc.xor = xor i8 %crc.shl, 29
%crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) optsize {
; NOAES-LABEL: define i8 @crc8.be.tc8.data16.misalign(
; NOAES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
; NOAES-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOAES-NEXT: [[DATA_NEXT]] = shl i16 [[DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
; NOAES-NEXT: [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
; NOAES-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i8 @crc8.be.tc8.data16.misalign(
; AES-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i16
; AES-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i16 [[CRC_CAST]], [[MSG]]
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i16 [[XOR_CRC_DATA1]], 255
; AES-NEXT: [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[CRC_TCBITS]], i16 284)
; AES-NEXT: [[QUOT_LSHR:%.*]] = lshr i16 [[CLMUL_MU]], 8
; AES-NEXT: [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_LSHR]], i16 285)
; AES-NEXT: [[CRC_SHL2:%.*]] = shl i16 [[CRC_CAST]], 8
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_SHL2]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_NEXT3:%.*]] = trunc i16 [[XOR_CRC_MULT]] to i8
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; AES-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%data.next = shl i16 %data, 1
%check.sb = icmp sge i8 %xor.crc.data, 0
%crc.shl = shl i8 %crc, 1
%crc.xor = xor i8 %crc.shl, 29
%crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) optsize {
; NOAES-LABEL: define i32 @crc32.le.tc8.data32(
; NOAES-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
; NOAES-NEXT: [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
; NOAES-NEXT: [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
; NOAES-NEXT: [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i32 @crc32.le.tc8.data32(
; AES-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i32 [[CHECKSUM]] to i40
; AES-NEXT: [[DATA_CAST:%.*]] = zext i32 [[MSG]] to i40
; AES-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i40 [[CRC_CAST]], [[DATA_CAST]]
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i40 [[XOR_CRC_DATA1]], 255
; AES-NEXT: [[CLMUL_MU:%.*]] = call i40 @llvm.clmul.i40(i40 [[CRC_TCBITS]], i40 273)
; AES-NEXT: [[QUOT_MASK:%.*]] = and i40 [[CLMUL_MU]], 255
; AES-NEXT: [[CLMUL_GP:%.*]] = call i40 @llvm.clmul.i40(i40 [[QUOT_MASK]], i40 67601)
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i40 [[CRC_CAST]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_LSHR2:%.*]] = lshr i40 [[XOR_CRC_MULT]], 8
; AES-NEXT: [[CRC_NEXT3:%.*]] = trunc i40 [[CRC_LSHR2]] to i32
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
; AES-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i32 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%xor.crc.data = xor i32 %crc, %data
%sb.crc.data = and i32 %xor.crc.data, 1
%check.sb = icmp eq i32 %sb.crc.data, 0
%crc.lshr = lshr i32 %crc, 1
%crc.xor = xor i32 %crc.lshr, 33800
%crc.next = select i1 %check.sb, i32 %crc.lshr, i32 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i32 %crc.next
}
define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) optsize {
; NOAES-LABEL: define i8 @crc8.le.tc8.data32(
; NOAES-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA_TRUNC:%.*]] = trunc i32 [[DATA]] to i8
; NOAES-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOAES-NEXT: [[SB_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp eq i8 [[SB_CRC_DATA]], 0
; NOAES-NEXT: [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
; NOAES-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 59
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i8 @crc8.le.tc8.data32(
; AES-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i16
; AES-NEXT: [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i16
; AES-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i16 [[CRC_CAST]], [[DATA_CAST]]
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i16 [[XOR_CRC_DATA1]], 255
; AES-NEXT: [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[CRC_TCBITS]], i16 107)
; AES-NEXT: [[QUOT_MASK:%.*]] = and i16 [[CLMUL_MU]], 255
; AES-NEXT: [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_MASK]], i16 119)
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_CAST]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_LSHR2:%.*]] = lshr i16 [[XOR_CRC_MULT]], 8
; AES-NEXT: [[CRC_NEXT3:%.*]] = trunc i16 [[CRC_LSHR2]] to i8
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; AES-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%data.trunc = trunc i32 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%sb.crc.data = and i8 %xor.crc.data, 1
%check.sb = icmp eq i8 %sb.crc.data, 0
%crc.lshr = lshr i8 %crc, 1
%crc.xor = xor i8 %crc.lshr, 59
%crc.next = select i1 %check.sb, i8 %crc.lshr, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) optsize {
; NOAES-LABEL: define i32 @crc32.le.tc32(
; NOAES-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; NOAES-NEXT: [[ENTRY:.*]]:
; NOAES-NEXT: br label %[[LOOP:.*]]
; NOAES: [[LOOP]]:
; NOAES-NEXT: [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOAES-NEXT: [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
; NOAES-NEXT: [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
; NOAES-NEXT: [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
; NOAES-NEXT: [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
; NOAES-NEXT: [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
; NOAES-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
; NOAES-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOAES-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; NOAES-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
; NOAES-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOAES: [[EXIT]]:
; NOAES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOAES-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
; AES-LABEL: define i32 @crc32.le.tc32(
; AES-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; AES-NEXT: [[ENTRY:.*:]]
; AES-NEXT: [[CRC_CAST:%.*]] = zext i32 [[CHECKSUM]] to i64
; AES-NEXT: [[DATA_CAST:%.*]] = zext i32 [[MSG]] to i64
; AES-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i64 [[CRC_CAST]], [[DATA_CAST]]
; AES-NEXT: [[CRC_TCBITS:%.*]] = and i64 [[XOR_CRC_DATA1]], 4294967295
; AES-NEXT: [[CLMUL_MU:%.*]] = call i64 @llvm.clmul.i64(i64 [[CRC_TCBITS]], i64 4770502929)
; AES-NEXT: [[QUOT_MASK:%.*]] = and i64 [[CLMUL_MU]], 4294967295
; AES-NEXT: [[CLMUL_GP:%.*]] = call i64 @llvm.clmul.i64(i64 [[QUOT_MASK]], i64 67601)
; AES-NEXT: [[XOR_CRC_MULT:%.*]] = xor i64 [[CRC_CAST]], [[CLMUL_GP]]
; AES-NEXT: [[CRC_LSHR2:%.*]] = lshr i64 [[XOR_CRC_MULT]], 32
; AES-NEXT: [[CRC_NEXT3:%.*]] = trunc i64 [[CRC_LSHR2]] to i32
; AES-NEXT: br label %[[LOOP:.*]]
; AES: [[LOOP]]:
; AES-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; AES: [[EXIT]]:
; AES-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
; AES-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i32 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%xor.crc.data = xor i32 %crc, %data
%sb.crc.data = and i32 %xor.crc.data, 1
%check.sb = icmp eq i32 %sb.crc.data, 0
%crc.lshr = lshr i32 %crc, 1
%crc.xor = xor i32 %crc.lshr, 33800
%crc.next = select i1 %check.sb, i32 %crc.lshr, i32 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 31
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i32 %crc.next
}
define i64 @crc64.le.tc64(i64 %checksum, i64 %msg) optsize {
; ALL-LABEL: define i64 @crc64.le.tc64(
; ALL-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0:[0-9]+]] {
; ALL-NEXT: [[ENTRY:.*]]:
; ALL-NEXT: br label %[[LOOP:.*]]
; ALL: [[LOOP]]:
; ALL-NEXT: [[CRC:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; ALL-NEXT: [[DATA:%.*]] = phi i64 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; ALL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; ALL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i64 [[CRC]], [[DATA]]
; ALL-NEXT: [[SB_CRC_DATA:%.*]] = and i64 [[XOR_CRC_DATA]], 1
; ALL-NEXT: [[CHECK_SB:%.*]] = icmp eq i64 [[SB_CRC_DATA]], 0
; ALL-NEXT: [[CRC_LSHR:%.*]] = lshr i64 [[CRC]], 1
; ALL-NEXT: [[CRC_XOR:%.*]] = xor i64 [[CRC_LSHR]], 33800
; ALL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i64 [[CRC_LSHR]], i64 [[CRC_XOR]]
; ALL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; ALL-NEXT: [[DATA_NEXT]] = lshr i64 [[DATA]], 1
; ALL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 63
; ALL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; ALL: [[EXIT]]:
; ALL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT]], %[[LOOP]] ]
; ALL-NEXT: ret i64 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i64 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i64 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%xor.crc.data = xor i64 %crc, %data
%sb.crc.data = and i64 %xor.crc.data, 1
%check.sb = icmp eq i64 %sb.crc.data, 0
%crc.lshr = lshr i64 %crc, 1
%crc.xor = xor i64 %crc.lshr, 33800
%crc.next = select i1 %check.sb, i64 %crc.lshr, i64 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i64 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 63
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i64 %crc.next
}
;.
; NOAES: attributes #[[ATTR0]] = { optsize "target-features"="-aes" }
;.
; AES: attributes #[[ATTR0]] = { optsize "target-features"="+aes" }
; AES: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
;.

View file

@ -0,0 +1,761 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
; RUN: opt -passes=loop-idiom -mtriple=riscv32 -mattr=-zbc -S %s | FileCheck --check-prefixes=ALL,NOZBC,NOZBC32 %s
; RUN: opt -passes=loop-idiom -mtriple=riscv64 -mattr=-zbc -S %s | FileCheck --check-prefixes=ALL,NOZBC,NOZBC64 %s
; RUN: opt -passes=loop-idiom -mtriple=riscv32 -mattr=+zbc -S %s | FileCheck --check-prefixes=ALL,ZBC,ZBC32 %s
; RUN: opt -passes=loop-idiom -mtriple=riscv64 -mattr=+zbc -S %s | FileCheck --check-prefixes=ALL,ZBC,ZBC64 %s
define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) optsize {
; NOZBC-LABEL: define i16 @crc16.le.tc8(
; NOZBC-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
; NOZBC-NEXT: [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
; NOZBC-NEXT: [[AND_DATA_CRC:%.*]] = and i8 [[XOR_DATA_CRC]], 1
; NOZBC-NEXT: [[DATA_NEXT]] = lshr i8 [[DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp eq i8 [[AND_DATA_CRC]], 0
; NOZBC-NEXT: [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
; NOZBC-NEXT: [[XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; ZBC-LABEL: define i16 @crc16.le.tc8(
; ZBC-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
; ZBC-NEXT: [[ENTRY:.*:]]
; ZBC-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i24
; ZBC-NEXT: [[DATA_CAST:%.*]] = zext i8 [[MSG]] to i24
; ZBC-NEXT: [[XOR_CRC_DATA:%.*]] = xor i24 [[CRC_CAST]], [[DATA_CAST]]
; ZBC-NEXT: [[CRC_TCBITS:%.*]] = and i24 [[XOR_CRC_DATA]], 255
; ZBC-NEXT: [[CLMUL_MU:%.*]] = call i24 @llvm.clmul.i24(i24 [[CRC_TCBITS]], i24 511)
; ZBC-NEXT: [[QUOT_MASK:%.*]] = and i24 [[CLMUL_MU]], 255
; ZBC-NEXT: [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_MASK]], i24 81923)
; ZBC-NEXT: [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_CAST]], [[CLMUL_GP]]
; ZBC-NEXT: [[CRC_LSHR1:%.*]] = lshr i24 [[XOR_CRC_MULT]], 8
; ZBC-NEXT: [[CRC_NEXT2:%.*]] = trunc i24 [[CRC_LSHR1]] to i16
; ZBC-NEXT: br label %[[LOOP:.*]]
; ZBC: [[LOOP]]:
; ZBC-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC: [[EXIT]]:
; ZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
; ZBC-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
%crc.trunc = trunc i16 %crc to i8
%xor.data.crc = xor i8 %data, %crc.trunc
%and.data.crc = and i8 %xor.data.crc, 1
%data.next = lshr i8 %data, 1
%check.sb = icmp eq i8 %and.data.crc, 0
%crc.lshr = lshr i16 %crc, 1
%xor = xor i16 %crc.lshr, -24575
%crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) optsize {
; NOZBC-LABEL: define i16 @crc16.le.tc16(
; NOZBC-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
; NOZBC-NEXT: [[AND_CRC_DATA:%.*]] = and i16 [[XOR_CRC_DATA]], 1
; NOZBC-NEXT: [[DATA_NEXT]] = lshr i16 [[DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp eq i16 [[AND_CRC_DATA]], 0
; NOZBC-NEXT: [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
; NOZBC-NEXT: [[CRC_XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[CRC_XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; ZBC-LABEL: define i16 @crc16.le.tc16(
; ZBC-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; ZBC-NEXT: [[ENTRY:.*:]]
; ZBC-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i32
; ZBC-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; ZBC-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; ZBC-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[XOR_CRC_DATA1]], 65535
; ZBC-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 114687)
; ZBC-NEXT: [[QUOT_MASK:%.*]] = and i32 [[CLMUL_MU]], 65535
; ZBC-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_MASK]], i32 81923)
; ZBC-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_CAST]], [[CLMUL_GP]]
; ZBC-NEXT: [[CRC_LSHR2:%.*]] = lshr i32 [[XOR_CRC_MULT]], 16
; ZBC-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[CRC_LSHR2]] to i16
; ZBC-NEXT: br label %[[LOOP:.*]]
; ZBC: [[LOOP]]:
; ZBC-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC: [[EXIT]]:
; ZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
; ZBC-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %crc, %data
%and.crc.data = and i16 %xor.crc.data, 1
%data.next = lshr i16 %data, 1
%check.sb = icmp eq i16 %and.crc.data, 0
%crc.lshr = lshr i16 %crc, 1
%crc.xor = xor i16 %crc.lshr, -24575
%crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) optsize {
; NOZBC-LABEL: define i8 @crc8.le.tc16(
; NOZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
; NOZBC-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOZBC-NEXT: [[AND_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
; NOZBC-NEXT: [[DATA_NEXT]] = lshr i16 [[DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp eq i8 [[AND_CRC_DATA]], 0
; NOZBC-NEXT: [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
; NOZBC-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 29
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; ZBC-LABEL: define i8 @crc8.le.tc16(
; ZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; ZBC-NEXT: [[ENTRY:.*:]]
; ZBC-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i32
; ZBC-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; ZBC-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; ZBC-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[XOR_CRC_DATA1]], 65535
; ZBC-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 24423)
; ZBC-NEXT: [[QUOT_MASK:%.*]] = and i32 [[CLMUL_MU]], 65535
; ZBC-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_MASK]], i32 59)
; ZBC-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_CAST]], [[CLMUL_GP]]
; ZBC-NEXT: [[CRC_LSHR2:%.*]] = lshr i32 [[XOR_CRC_MULT]], 16
; ZBC-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[CRC_LSHR2]] to i8
; ZBC-NEXT: br label %[[LOOP:.*]]
; ZBC: [[LOOP]]:
; ZBC-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC: [[EXIT]]:
; ZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; ZBC-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%and.crc.data = and i8 %xor.crc.data, 1
%data.next = lshr i16 %data, 1
%check.sb = icmp eq i8 %and.crc.data, 0
%crc.lshr = lshr i8 %crc, 1
%crc.xor = xor i8 %crc.lshr, 29
%crc.next = select i1 %check.sb, i8 %crc.lshr, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) optsize {
; NOZBC-LABEL: define i16 @crc16.be.tc16(
; NOZBC-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
; NOZBC-NEXT: [[DATA_NEXT]] = shl i16 [[DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp sge i16 [[XOR_CRC_DATA]], 0
; NOZBC-NEXT: [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
; NOZBC-NEXT: [[CRC_XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[CRC_XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; ZBC-LABEL: define i16 @crc16.be.tc16(
; ZBC-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; ZBC-NEXT: [[ENTRY:.*:]]
; ZBC-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i32
; ZBC-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; ZBC-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; ZBC-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[XOR_CRC_DATA1]], 65535
; ZBC-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 69936)
; ZBC-NEXT: [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
; ZBC-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_LSHR]], i32 69665)
; ZBC-NEXT: [[CRC_SHL2:%.*]] = shl i32 [[CRC_CAST]], 16
; ZBC-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_SHL2]], [[CLMUL_GP]]
; ZBC-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[XOR_CRC_MULT]] to i16
; ZBC-NEXT: br label %[[LOOP:.*]]
; ZBC: [[LOOP]]:
; ZBC-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC: [[EXIT]]:
; ZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
; ZBC-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %crc, %data
%data.next = shl i16 %data, 1
%check.sb = icmp sge i16 %xor.crc.data, 0
%crc.shl = shl i16 %crc, 1
%crc.xor = xor i16 %crc.shl, 4129
%crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) optsize {
; NOZBC-LABEL: define i16 @crc16.be.tc8.misalign(
; NOZBC-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
; NOZBC-NEXT: [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
; NOZBC-NEXT: [[DATA_NEXT]] = shl i8 [[DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_DATA_CRC]], 0
; NOZBC-NEXT: [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
; NOZBC-NEXT: [[XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; ZBC-LABEL: define i16 @crc16.be.tc8.misalign(
; ZBC-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; ZBC-NEXT: [[ENTRY:.*:]]
; ZBC-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i24
; ZBC-NEXT: [[CRC_ALIGN_TC:%.*]] = lshr i24 [[CRC_CAST]], 8
; ZBC-NEXT: [[CRC_TCBITS:%.*]] = and i24 [[CRC_ALIGN_TC]], 255
; ZBC-NEXT: [[CLMUL_MU:%.*]] = call i24 @llvm.clmul.i24(i24 [[CRC_TCBITS]], i24 273)
; ZBC-NEXT: [[QUOT_LSHR:%.*]] = lshr i24 [[CLMUL_MU]], 8
; ZBC-NEXT: [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_LSHR]], i24 69665)
; ZBC-NEXT: [[CRC_SHL1:%.*]] = shl i24 [[CRC_CAST]], 8
; ZBC-NEXT: [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_SHL1]], [[CLMUL_GP]]
; ZBC-NEXT: [[CRC_NEXT2:%.*]] = trunc i24 [[XOR_CRC_MULT]] to i16
; ZBC-NEXT: br label %[[LOOP:.*]]
; ZBC: [[LOOP]]:
; ZBC-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC: [[EXIT]]:
; ZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
; ZBC-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
%crc.trunc = trunc i16 %crc to i8
%xor.data.crc = xor i8 %data, %crc.trunc
%data.next = shl i8 %data, 1
%check.sb = icmp sge i8 %xor.data.crc, 0
%crc.shl = shl i16 %crc, 1
%xor = xor i16 %crc.shl, 4129
%crc.next = select i1 %check.sb, i16 %crc.shl, i16 %xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) optsize {
; NOZBC-LABEL: define i8 @crc8.be.tc16.misalign(
; NOZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
; NOZBC-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOZBC-NEXT: [[DATA_NEXT]] = shl i16 [[DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
; NOZBC-NEXT: [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
; NOZBC-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; ZBC-LABEL: define i8 @crc8.be.tc16.misalign(
; ZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; ZBC-NEXT: [[ENTRY:.*:]]
; ZBC-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i32
; ZBC-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; ZBC-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; ZBC-NEXT: [[CRC_ALIGN_TC:%.*]] = shl i32 [[XOR_CRC_DATA1]], 8
; ZBC-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[CRC_ALIGN_TC]], 65535
; ZBC-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 72779)
; ZBC-NEXT: [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
; ZBC-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_LSHR]], i32 285)
; ZBC-NEXT: [[CRC_SHL2:%.*]] = shl i32 [[CRC_CAST]], 16
; ZBC-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_SHL2]], [[CLMUL_GP]]
; ZBC-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[XOR_CRC_MULT]] to i8
; ZBC-NEXT: br label %[[LOOP:.*]]
; ZBC: [[LOOP]]:
; ZBC-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC: [[EXIT]]:
; ZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; ZBC-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%data.next = shl i16 %data, 1
%check.sb = icmp sge i8 %xor.crc.data, 0
%crc.shl = shl i8 %crc, 1
%crc.xor = xor i8 %crc.shl, 29
%crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) optsize {
; NOZBC-LABEL: define i8 @crc8.be.tc8.data16.misalign(
; NOZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
; NOZBC-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOZBC-NEXT: [[DATA_NEXT]] = shl i16 [[DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
; NOZBC-NEXT: [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
; NOZBC-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; ZBC-LABEL: define i8 @crc8.be.tc8.data16.misalign(
; ZBC-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; ZBC-NEXT: [[ENTRY:.*:]]
; ZBC-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i16
; ZBC-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i16 [[CRC_CAST]], [[MSG]]
; ZBC-NEXT: [[CRC_TCBITS:%.*]] = and i16 [[XOR_CRC_DATA1]], 255
; ZBC-NEXT: [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[CRC_TCBITS]], i16 284)
; ZBC-NEXT: [[QUOT_LSHR:%.*]] = lshr i16 [[CLMUL_MU]], 8
; ZBC-NEXT: [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_LSHR]], i16 285)
; ZBC-NEXT: [[CRC_SHL2:%.*]] = shl i16 [[CRC_CAST]], 8
; ZBC-NEXT: [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_SHL2]], [[CLMUL_GP]]
; ZBC-NEXT: [[CRC_NEXT3:%.*]] = trunc i16 [[XOR_CRC_MULT]] to i8
; ZBC-NEXT: br label %[[LOOP:.*]]
; ZBC: [[LOOP]]:
; ZBC-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC: [[EXIT]]:
; ZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; ZBC-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%data.next = shl i16 %data, 1
%check.sb = icmp sge i8 %xor.crc.data, 0
%crc.shl = shl i8 %crc, 1
%crc.xor = xor i8 %crc.shl, 29
%crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) optsize {
; NOZBC-LABEL: define i32 @crc32.le.tc8.data32(
; NOZBC-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
; NOZBC-NEXT: [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
; NOZBC-NEXT: [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
; NOZBC-NEXT: [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
; ZBC32-LABEL: define i32 @crc32.le.tc8.data32(
; ZBC32-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; ZBC32-NEXT: [[ENTRY:.*]]:
; ZBC32-NEXT: br label %[[LOOP:.*]]
; ZBC32: [[LOOP]]:
; ZBC32-NEXT: [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; ZBC32-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; ZBC32-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; ZBC32-NEXT: [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
; ZBC32-NEXT: [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
; ZBC32-NEXT: [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
; ZBC32-NEXT: [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
; ZBC32-NEXT: [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
; ZBC32-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
; ZBC32-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; ZBC32-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; ZBC32-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; ZBC32-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; ZBC32: [[EXIT]]:
; ZBC32-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
; ZBC32-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
; ZBC64-LABEL: define i32 @crc32.le.tc8.data32(
; ZBC64-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; ZBC64-NEXT: [[ENTRY:.*:]]
; ZBC64-NEXT: [[CRC_CAST:%.*]] = zext i32 [[CHECKSUM]] to i40
; ZBC64-NEXT: [[DATA_CAST:%.*]] = zext i32 [[MSG]] to i40
; ZBC64-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i40 [[CRC_CAST]], [[DATA_CAST]]
; ZBC64-NEXT: [[CRC_TCBITS:%.*]] = and i40 [[XOR_CRC_DATA1]], 255
; ZBC64-NEXT: [[CLMUL_MU:%.*]] = call i40 @llvm.clmul.i40(i40 [[CRC_TCBITS]], i40 273)
; ZBC64-NEXT: [[QUOT_MASK:%.*]] = and i40 [[CLMUL_MU]], 255
; ZBC64-NEXT: [[CLMUL_GP:%.*]] = call i40 @llvm.clmul.i40(i40 [[QUOT_MASK]], i40 67601)
; ZBC64-NEXT: [[XOR_CRC_MULT:%.*]] = xor i40 [[CRC_CAST]], [[CLMUL_GP]]
; ZBC64-NEXT: [[CRC_LSHR2:%.*]] = lshr i40 [[XOR_CRC_MULT]], 8
; ZBC64-NEXT: [[CRC_NEXT3:%.*]] = trunc i40 [[CRC_LSHR2]] to i32
; ZBC64-NEXT: br label %[[LOOP:.*]]
; ZBC64: [[LOOP]]:
; ZBC64-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC64: [[EXIT]]:
; ZBC64-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
; ZBC64-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i32 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%xor.crc.data = xor i32 %crc, %data
%sb.crc.data = and i32 %xor.crc.data, 1
%check.sb = icmp eq i32 %sb.crc.data, 0
%crc.lshr = lshr i32 %crc, 1
%crc.xor = xor i32 %crc.lshr, 33800
%crc.next = select i1 %check.sb, i32 %crc.lshr, i32 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i32 %crc.next
}
define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) optsize {
; NOZBC-LABEL: define i8 @crc8.le.tc8.data32(
; NOZBC-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA_TRUNC:%.*]] = trunc i32 [[DATA]] to i8
; NOZBC-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOZBC-NEXT: [[SB_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp eq i8 [[SB_CRC_DATA]], 0
; NOZBC-NEXT: [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
; NOZBC-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 59
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; ZBC-LABEL: define i8 @crc8.le.tc8.data32(
; ZBC-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; ZBC-NEXT: [[ENTRY:.*:]]
; ZBC-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i16
; ZBC-NEXT: [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i16
; ZBC-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i16 [[CRC_CAST]], [[DATA_CAST]]
; ZBC-NEXT: [[CRC_TCBITS:%.*]] = and i16 [[XOR_CRC_DATA1]], 255
; ZBC-NEXT: [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[CRC_TCBITS]], i16 107)
; ZBC-NEXT: [[QUOT_MASK:%.*]] = and i16 [[CLMUL_MU]], 255
; ZBC-NEXT: [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_MASK]], i16 119)
; ZBC-NEXT: [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_CAST]], [[CLMUL_GP]]
; ZBC-NEXT: [[CRC_LSHR2:%.*]] = lshr i16 [[XOR_CRC_MULT]], 8
; ZBC-NEXT: [[CRC_NEXT3:%.*]] = trunc i16 [[CRC_LSHR2]] to i8
; ZBC-NEXT: br label %[[LOOP:.*]]
; ZBC: [[LOOP]]:
; ZBC-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC: [[EXIT]]:
; ZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; ZBC-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%data.trunc = trunc i32 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%sb.crc.data = and i8 %xor.crc.data, 1
%check.sb = icmp eq i8 %sb.crc.data, 0
%crc.lshr = lshr i8 %crc, 1
%crc.xor = xor i8 %crc.lshr, 59
%crc.next = select i1 %check.sb, i8 %crc.lshr, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) optsize {
; NOZBC-LABEL: define i32 @crc32.le.tc32(
; NOZBC-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; NOZBC-NEXT: [[ENTRY:.*]]:
; NOZBC-NEXT: br label %[[LOOP:.*]]
; NOZBC: [[LOOP]]:
; NOZBC-NEXT: [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOZBC-NEXT: [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
; NOZBC-NEXT: [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
; NOZBC-NEXT: [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
; NOZBC-NEXT: [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
; NOZBC-NEXT: [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
; NOZBC-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
; NOZBC-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOZBC-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; NOZBC-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
; NOZBC-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOZBC: [[EXIT]]:
; NOZBC-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOZBC-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
; ZBC32-LABEL: define i32 @crc32.le.tc32(
; ZBC32-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; ZBC32-NEXT: [[ENTRY:.*]]:
; ZBC32-NEXT: br label %[[LOOP:.*]]
; ZBC32: [[LOOP]]:
; ZBC32-NEXT: [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; ZBC32-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; ZBC32-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; ZBC32-NEXT: [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
; ZBC32-NEXT: [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
; ZBC32-NEXT: [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
; ZBC32-NEXT: [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
; ZBC32-NEXT: [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
; ZBC32-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
; ZBC32-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; ZBC32-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; ZBC32-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
; ZBC32-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; ZBC32: [[EXIT]]:
; ZBC32-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
; ZBC32-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
; ZBC64-LABEL: define i32 @crc32.le.tc32(
; ZBC64-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; ZBC64-NEXT: [[ENTRY:.*:]]
; ZBC64-NEXT: [[CRC_CAST:%.*]] = zext i32 [[CHECKSUM]] to i64
; ZBC64-NEXT: [[DATA_CAST:%.*]] = zext i32 [[MSG]] to i64
; ZBC64-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i64 [[CRC_CAST]], [[DATA_CAST]]
; ZBC64-NEXT: [[CRC_TCBITS:%.*]] = and i64 [[XOR_CRC_DATA1]], 4294967295
; ZBC64-NEXT: [[CLMUL_MU:%.*]] = call i64 @llvm.clmul.i64(i64 [[CRC_TCBITS]], i64 4770502929)
; ZBC64-NEXT: [[QUOT_MASK:%.*]] = and i64 [[CLMUL_MU]], 4294967295
; ZBC64-NEXT: [[CLMUL_GP:%.*]] = call i64 @llvm.clmul.i64(i64 [[QUOT_MASK]], i64 67601)
; ZBC64-NEXT: [[XOR_CRC_MULT:%.*]] = xor i64 [[CRC_CAST]], [[CLMUL_GP]]
; ZBC64-NEXT: [[CRC_LSHR2:%.*]] = lshr i64 [[XOR_CRC_MULT]], 32
; ZBC64-NEXT: [[CRC_NEXT3:%.*]] = trunc i64 [[CRC_LSHR2]] to i32
; ZBC64-NEXT: br label %[[LOOP:.*]]
; ZBC64: [[LOOP]]:
; ZBC64-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; ZBC64: [[EXIT]]:
; ZBC64-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
; ZBC64-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i32 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%xor.crc.data = xor i32 %crc, %data
%sb.crc.data = and i32 %xor.crc.data, 1
%check.sb = icmp eq i32 %sb.crc.data, 0
%crc.lshr = lshr i32 %crc, 1
%crc.xor = xor i32 %crc.lshr, 33800
%crc.next = select i1 %check.sb, i32 %crc.lshr, i32 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 31
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i32 %crc.next
}
define i64 @crc64.le.tc64(i64 %checksum, i64 %msg) optsize {
; ALL-LABEL: define i64 @crc64.le.tc64(
; ALL-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0:[0-9]+]] {
; ALL-NEXT: [[ENTRY:.*]]:
; ALL-NEXT: br label %[[LOOP:.*]]
; ALL: [[LOOP]]:
; ALL-NEXT: [[CRC:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; ALL-NEXT: [[DATA:%.*]] = phi i64 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; ALL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; ALL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i64 [[CRC]], [[DATA]]
; ALL-NEXT: [[SB_CRC_DATA:%.*]] = and i64 [[XOR_CRC_DATA]], 1
; ALL-NEXT: [[CHECK_SB:%.*]] = icmp eq i64 [[SB_CRC_DATA]], 0
; ALL-NEXT: [[CRC_LSHR:%.*]] = lshr i64 [[CRC]], 1
; ALL-NEXT: [[CRC_XOR:%.*]] = xor i64 [[CRC_LSHR]], 33800
; ALL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i64 [[CRC_LSHR]], i64 [[CRC_XOR]]
; ALL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; ALL-NEXT: [[DATA_NEXT]] = lshr i64 [[DATA]], 1
; ALL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 63
; ALL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; ALL: [[EXIT]]:
; ALL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT]], %[[LOOP]] ]
; ALL-NEXT: ret i64 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i64 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i64 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%xor.crc.data = xor i64 %crc, %data
%sb.crc.data = and i64 %xor.crc.data, 1
%check.sb = icmp eq i64 %sb.crc.data, 0
%crc.lshr = lshr i64 %crc, 1
%crc.xor = xor i64 %crc.lshr, 33800
%crc.next = select i1 %check.sb, i64 %crc.lshr, i64 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i64 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 63
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i64 %crc.next
}
;.
; NOZBC32: attributes #[[ATTR0]] = { optsize "target-features"="-zbc" }
;.
; NOZBC64: attributes #[[ATTR0]] = { optsize "target-features"="-zbc" }
;.
; ZBC32: attributes #[[ATTR0]] = { optsize "target-features"="+zbc" }
; ZBC32: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
;.
; ZBC64: attributes #[[ATTR0]] = { optsize "target-features"="+zbc" }
; ZBC64: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
;.
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; NOZBC32: {{.*}}
; NOZBC64: {{.*}}

View file

@ -0,0 +1,707 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 5
; RUN: opt -passes=loop-idiom -mtriple=x86_64 -mattr=-pclmul -S %s | FileCheck --check-prefixes=ALL,NOPCLMUL %s
; RUN: opt -passes=loop-idiom -mtriple=x86_64 -mattr=+pclmul -S %s | FileCheck --check-prefixes=ALL,PCLMUL %s
define i16 @crc16.le.tc8(i8 %msg, i16 %checksum) optsize {
; NOPCLMUL-LABEL: define i16 @crc16.le.tc8(
; NOPCLMUL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
; NOPCLMUL-NEXT: [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
; NOPCLMUL-NEXT: [[AND_DATA_CRC:%.*]] = and i8 [[XOR_DATA_CRC]], 1
; NOPCLMUL-NEXT: [[DATA_NEXT]] = lshr i8 [[DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp eq i8 [[AND_DATA_CRC]], 0
; NOPCLMUL-NEXT: [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
; NOPCLMUL-NEXT: [[XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i16 @crc16.le.tc8(
; PCLMUL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0:[0-9]+]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i24
; PCLMUL-NEXT: [[DATA_CAST:%.*]] = zext i8 [[MSG]] to i24
; PCLMUL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i24 [[CRC_CAST]], [[DATA_CAST]]
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i24 [[XOR_CRC_DATA]], 255
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i24 @llvm.clmul.i24(i24 [[CRC_TCBITS]], i24 511)
; PCLMUL-NEXT: [[QUOT_MASK:%.*]] = and i24 [[CLMUL_MU]], 255
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_MASK]], i24 81923)
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_CAST]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_LSHR1:%.*]] = lshr i24 [[XOR_CRC_MULT]], 8
; PCLMUL-NEXT: [[CRC_NEXT2:%.*]] = trunc i24 [[CRC_LSHR1]] to i16
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
%crc.trunc = trunc i16 %crc to i8
%xor.data.crc = xor i8 %data, %crc.trunc
%and.data.crc = and i8 %xor.data.crc, 1
%data.next = lshr i8 %data, 1
%check.sb = icmp eq i8 %and.data.crc, 0
%crc.lshr = lshr i16 %crc, 1
%xor = xor i16 %crc.lshr, -24575
%crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i16 @crc16.le.tc16(i16 %msg, i16 %checksum) optsize {
; NOPCLMUL-LABEL: define i16 @crc16.le.tc16(
; NOPCLMUL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
; NOPCLMUL-NEXT: [[AND_CRC_DATA:%.*]] = and i16 [[XOR_CRC_DATA]], 1
; NOPCLMUL-NEXT: [[DATA_NEXT]] = lshr i16 [[DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp eq i16 [[AND_CRC_DATA]], 0
; NOPCLMUL-NEXT: [[CRC_LSHR:%.*]] = lshr i16 [[CRC]], 1
; NOPCLMUL-NEXT: [[CRC_XOR:%.*]] = xor i16 [[CRC_LSHR]], -24575
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_LSHR]], i16 [[CRC_XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i16 @crc16.le.tc16(
; PCLMUL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i32
; PCLMUL-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; PCLMUL-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[XOR_CRC_DATA1]], 65535
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 114687)
; PCLMUL-NEXT: [[QUOT_MASK:%.*]] = and i32 [[CLMUL_MU]], 65535
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_MASK]], i32 81923)
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_CAST]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_LSHR2:%.*]] = lshr i32 [[XOR_CRC_MULT]], 16
; PCLMUL-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[CRC_LSHR2]] to i16
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %crc, %data
%and.crc.data = and i16 %xor.crc.data, 1
%data.next = lshr i16 %data, 1
%check.sb = icmp eq i16 %and.crc.data, 0
%crc.lshr = lshr i16 %crc, 1
%crc.xor = xor i16 %crc.lshr, -24575
%crc.next = select i1 %check.sb, i16 %crc.lshr, i16 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i8 @crc8.le.tc16(i16 %msg, i8 %checksum) optsize {
; NOPCLMUL-LABEL: define i8 @crc8.le.tc16(
; NOPCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
; NOPCLMUL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOPCLMUL-NEXT: [[AND_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
; NOPCLMUL-NEXT: [[DATA_NEXT]] = lshr i16 [[DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp eq i8 [[AND_CRC_DATA]], 0
; NOPCLMUL-NEXT: [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
; NOPCLMUL-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 29
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i8 @crc8.le.tc16(
; PCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i32
; PCLMUL-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; PCLMUL-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[XOR_CRC_DATA1]], 65535
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 24423)
; PCLMUL-NEXT: [[QUOT_MASK:%.*]] = and i32 [[CLMUL_MU]], 65535
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_MASK]], i32 59)
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_CAST]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_LSHR2:%.*]] = lshr i32 [[XOR_CRC_MULT]], 16
; PCLMUL-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[CRC_LSHR2]] to i8
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%and.crc.data = and i8 %xor.crc.data, 1
%data.next = lshr i16 %data, 1
%check.sb = icmp eq i8 %and.crc.data, 0
%crc.lshr = lshr i8 %crc, 1
%crc.xor = xor i8 %crc.lshr, 29
%crc.next = select i1 %check.sb, i8 %crc.lshr, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i16 @crc16.be.tc16(i16 %msg, i16 %checksum) optsize {
; NOPCLMUL-LABEL: define i16 @crc16.be.tc16(
; NOPCLMUL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i16 [[CRC]], [[DATA]]
; NOPCLMUL-NEXT: [[DATA_NEXT]] = shl i16 [[DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp sge i16 [[XOR_CRC_DATA]], 0
; NOPCLMUL-NEXT: [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
; NOPCLMUL-NEXT: [[CRC_XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[CRC_XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i16 @crc16.be.tc16(
; PCLMUL-SAME: i16 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i32
; PCLMUL-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; PCLMUL-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[XOR_CRC_DATA1]], 65535
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 69936)
; PCLMUL-NEXT: [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_LSHR]], i32 69665)
; PCLMUL-NEXT: [[CRC_SHL2:%.*]] = shl i32 [[CRC_CAST]], 16
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_SHL2]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[XOR_CRC_MULT]] to i16
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT3]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%xor.crc.data = xor i16 %crc, %data
%data.next = shl i16 %data, 1
%check.sb = icmp sge i16 %xor.crc.data, 0
%crc.shl = shl i16 %crc, 1
%crc.xor = xor i16 %crc.shl, 4129
%crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i16 @crc16.be.tc8.misalign(i8 %msg, i16 %checksum) optsize {
; NOPCLMUL-LABEL: define i16 @crc16.be.tc8.misalign(
; NOPCLMUL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i16 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i8 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[CRC_TRUNC:%.*]] = trunc i16 [[CRC]] to i8
; NOPCLMUL-NEXT: [[XOR_DATA_CRC:%.*]] = xor i8 [[DATA]], [[CRC_TRUNC]]
; NOPCLMUL-NEXT: [[DATA_NEXT]] = shl i8 [[DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_DATA_CRC]], 0
; NOPCLMUL-NEXT: [[CRC_SHL:%.*]] = shl i16 [[CRC]], 1
; NOPCLMUL-NEXT: [[XOR:%.*]] = xor i16 [[CRC_SHL]], 4129
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i16 [[CRC_SHL]], i16 [[XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i16 @crc16.be.tc8.misalign(
; PCLMUL-SAME: i8 [[MSG:%.*]], i16 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i16 [[CHECKSUM]] to i24
; PCLMUL-NEXT: [[CRC_ALIGN_TC:%.*]] = lshr i24 [[CRC_CAST]], 8
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i24 [[CRC_ALIGN_TC]], 255
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i24 @llvm.clmul.i24(i24 [[CRC_TCBITS]], i24 273)
; PCLMUL-NEXT: [[QUOT_LSHR:%.*]] = lshr i24 [[CLMUL_MU]], 8
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i24 @llvm.clmul.i24(i24 [[QUOT_LSHR]], i24 69665)
; PCLMUL-NEXT: [[CRC_SHL1:%.*]] = shl i24 [[CRC_CAST]], 8
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i24 [[CRC_SHL1]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_NEXT2:%.*]] = trunc i24 [[XOR_CRC_MULT]] to i16
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i16 [ [[CRC_NEXT2]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i16 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i16 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i8 [ %msg, %entry ], [ %data.next, %loop ]
%crc.trunc = trunc i16 %crc to i8
%xor.data.crc = xor i8 %data, %crc.trunc
%data.next = shl i8 %data, 1
%check.sb = icmp sge i8 %xor.data.crc, 0
%crc.shl = shl i16 %crc, 1
%xor = xor i16 %crc.shl, 4129
%crc.next = select i1 %check.sb, i16 %crc.shl, i16 %xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i16 %crc.next
}
define i8 @crc8.be.tc16.misalign(i16 %msg, i8 %checksum) optsize {
; NOPCLMUL-LABEL: define i8 @crc8.be.tc16.misalign(
; NOPCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
; NOPCLMUL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOPCLMUL-NEXT: [[DATA_NEXT]] = shl i16 [[DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
; NOPCLMUL-NEXT: [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
; NOPCLMUL-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 15
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i8 @crc8.be.tc16.misalign(
; PCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i32
; PCLMUL-NEXT: [[DATA_CAST:%.*]] = zext i16 [[MSG]] to i32
; PCLMUL-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i32 [[CRC_CAST]], [[DATA_CAST]]
; PCLMUL-NEXT: [[CRC_ALIGN_TC:%.*]] = shl i32 [[XOR_CRC_DATA1]], 8
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i32 [[CRC_ALIGN_TC]], 65535
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i32 @llvm.clmul.i32(i32 [[CRC_TCBITS]], i32 72779)
; PCLMUL-NEXT: [[QUOT_LSHR:%.*]] = lshr i32 [[CLMUL_MU]], 16
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i32 @llvm.clmul.i32(i32 [[QUOT_LSHR]], i32 285)
; PCLMUL-NEXT: [[CRC_SHL2:%.*]] = shl i32 [[CRC_CAST]], 16
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i32 [[CRC_SHL2]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_NEXT3:%.*]] = trunc i32 [[XOR_CRC_MULT]] to i8
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%data.next = shl i16 %data, 1
%check.sb = icmp sge i8 %xor.crc.data, 0
%crc.shl = shl i8 %crc, 1
%crc.xor = xor i8 %crc.shl, 29
%crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 15
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i8 @crc8.be.tc8.data16.misalign(i16 %msg, i8 %checksum) optsize {
; NOPCLMUL-LABEL: define i8 @crc8.be.tc8.data16.misalign(
; NOPCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i16 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA_TRUNC:%.*]] = trunc i16 [[DATA]] to i8
; NOPCLMUL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOPCLMUL-NEXT: [[DATA_NEXT]] = shl i16 [[DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp sge i8 [[XOR_CRC_DATA]], 0
; NOPCLMUL-NEXT: [[CRC_SHL:%.*]] = shl i8 [[CRC]], 1
; NOPCLMUL-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_SHL]], 29
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_SHL]], i8 [[CRC_XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i8 @crc8.be.tc8.data16.misalign(
; PCLMUL-SAME: i16 [[MSG:%.*]], i8 [[CHECKSUM:%.*]]) #[[ATTR0]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i16
; PCLMUL-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i16 [[CRC_CAST]], [[MSG]]
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i16 [[XOR_CRC_DATA1]], 255
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[CRC_TCBITS]], i16 284)
; PCLMUL-NEXT: [[QUOT_LSHR:%.*]] = lshr i16 [[CLMUL_MU]], 8
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_LSHR]], i16 285)
; PCLMUL-NEXT: [[CRC_SHL2:%.*]] = shl i16 [[CRC_CAST]], 8
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_SHL2]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_NEXT3:%.*]] = trunc i16 [[XOR_CRC_MULT]] to i8
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i16 [ %msg, %entry ], [ %data.next, %loop ]
%data.trunc = trunc i16 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%data.next = shl i16 %data, 1
%check.sb = icmp sge i8 %xor.crc.data, 0
%crc.shl = shl i8 %crc, 1
%crc.xor = xor i8 %crc.shl, 29
%crc.next = select i1 %check.sb, i8 %crc.shl, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i32 @crc32.le.tc8.data32(i32 %checksum, i32 %msg) optsize {
; NOPCLMUL-LABEL: define i32 @crc32.le.tc8.data32(
; NOPCLMUL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
; NOPCLMUL-NEXT: [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
; NOPCLMUL-NEXT: [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
; NOPCLMUL-NEXT: [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i32 @crc32.le.tc8.data32(
; PCLMUL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i32 [[CHECKSUM]] to i40
; PCLMUL-NEXT: [[DATA_CAST:%.*]] = zext i32 [[MSG]] to i40
; PCLMUL-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i40 [[CRC_CAST]], [[DATA_CAST]]
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i40 [[XOR_CRC_DATA1]], 255
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i40 @llvm.clmul.i40(i40 [[CRC_TCBITS]], i40 273)
; PCLMUL-NEXT: [[QUOT_MASK:%.*]] = and i40 [[CLMUL_MU]], 255
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i40 @llvm.clmul.i40(i40 [[QUOT_MASK]], i40 67601)
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i40 [[CRC_CAST]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_LSHR2:%.*]] = lshr i40 [[XOR_CRC_MULT]], 8
; PCLMUL-NEXT: [[CRC_NEXT3:%.*]] = trunc i40 [[CRC_LSHR2]] to i32
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i32 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%xor.crc.data = xor i32 %crc, %data
%sb.crc.data = and i32 %xor.crc.data, 1
%check.sb = icmp eq i32 %sb.crc.data, 0
%crc.lshr = lshr i32 %crc, 1
%crc.xor = xor i32 %crc.lshr, 33800
%crc.next = select i1 %check.sb, i32 %crc.lshr, i32 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i32 %crc.next
}
define i8 @crc8.le.tc8.data32(i8 %checksum, i32 %msg) optsize {
; NOPCLMUL-LABEL: define i8 @crc8.le.tc8.data32(
; NOPCLMUL-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i8 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA_TRUNC:%.*]] = trunc i32 [[DATA]] to i8
; NOPCLMUL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i8 [[CRC]], [[DATA_TRUNC]]
; NOPCLMUL-NEXT: [[SB_CRC_DATA:%.*]] = and i8 [[XOR_CRC_DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp eq i8 [[SB_CRC_DATA]], 0
; NOPCLMUL-NEXT: [[CRC_LSHR:%.*]] = lshr i8 [[CRC]], 1
; NOPCLMUL-NEXT: [[CRC_XOR:%.*]] = xor i8 [[CRC_LSHR]], 59
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i8 [[CRC_LSHR]], i8 [[CRC_XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 7
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i8 @crc8.le.tc8.data32(
; PCLMUL-SAME: i8 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i8 [[CHECKSUM]] to i16
; PCLMUL-NEXT: [[DATA_CAST:%.*]] = trunc i32 [[MSG]] to i16
; PCLMUL-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i16 [[CRC_CAST]], [[DATA_CAST]]
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i16 [[XOR_CRC_DATA1]], 255
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i16 @llvm.clmul.i16(i16 [[CRC_TCBITS]], i16 107)
; PCLMUL-NEXT: [[QUOT_MASK:%.*]] = and i16 [[CLMUL_MU]], 255
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i16 @llvm.clmul.i16(i16 [[QUOT_MASK]], i16 119)
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i16 [[CRC_CAST]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_LSHR2:%.*]] = lshr i16 [[XOR_CRC_MULT]], 8
; PCLMUL-NEXT: [[CRC_NEXT3:%.*]] = trunc i16 [[CRC_LSHR2]] to i8
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i8 [ [[CRC_NEXT3]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i8 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i8 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%data.trunc = trunc i32 %data to i8
%xor.crc.data = xor i8 %crc, %data.trunc
%sb.crc.data = and i8 %xor.crc.data, 1
%check.sb = icmp eq i8 %sb.crc.data, 0
%crc.lshr = lshr i8 %crc, 1
%crc.xor = xor i8 %crc.lshr, 59
%crc.next = select i1 %check.sb, i8 %crc.lshr, i8 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 7
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i8 %crc.next
}
define i32 @crc32.le.tc32(i32 %checksum, i32 %msg) optsize {
; NOPCLMUL-LABEL: define i32 @crc32.le.tc32(
; NOPCLMUL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; NOPCLMUL-NEXT: [[ENTRY:.*]]:
; NOPCLMUL-NEXT: br label %[[LOOP:.*]]
; NOPCLMUL: [[LOOP]]:
; NOPCLMUL-NEXT: [[CRC:%.*]] = phi i32 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[DATA:%.*]] = phi i32 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; NOPCLMUL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i32 [[CRC]], [[DATA]]
; NOPCLMUL-NEXT: [[SB_CRC_DATA:%.*]] = and i32 [[XOR_CRC_DATA]], 1
; NOPCLMUL-NEXT: [[CHECK_SB:%.*]] = icmp eq i32 [[SB_CRC_DATA]], 0
; NOPCLMUL-NEXT: [[CRC_LSHR:%.*]] = lshr i32 [[CRC]], 1
; NOPCLMUL-NEXT: [[CRC_XOR:%.*]] = xor i32 [[CRC_LSHR]], 33800
; NOPCLMUL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i32 [[CRC_LSHR]], i32 [[CRC_XOR]]
; NOPCLMUL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; NOPCLMUL-NEXT: [[DATA_NEXT]] = lshr i32 [[DATA]], 1
; NOPCLMUL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 31
; NOPCLMUL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; NOPCLMUL: [[EXIT]]:
; NOPCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT]], %[[LOOP]] ]
; NOPCLMUL-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
; PCLMUL-LABEL: define i32 @crc32.le.tc32(
; PCLMUL-SAME: i32 [[CHECKSUM:%.*]], i32 [[MSG:%.*]]) #[[ATTR0]] {
; PCLMUL-NEXT: [[ENTRY:.*:]]
; PCLMUL-NEXT: [[CRC_CAST:%.*]] = zext i32 [[CHECKSUM]] to i64
; PCLMUL-NEXT: [[DATA_CAST:%.*]] = zext i32 [[MSG]] to i64
; PCLMUL-NEXT: [[XOR_CRC_DATA1:%.*]] = xor i64 [[CRC_CAST]], [[DATA_CAST]]
; PCLMUL-NEXT: [[CRC_TCBITS:%.*]] = and i64 [[XOR_CRC_DATA1]], 4294967295
; PCLMUL-NEXT: [[CLMUL_MU:%.*]] = call i64 @llvm.clmul.i64(i64 [[CRC_TCBITS]], i64 4770502929)
; PCLMUL-NEXT: [[QUOT_MASK:%.*]] = and i64 [[CLMUL_MU]], 4294967295
; PCLMUL-NEXT: [[CLMUL_GP:%.*]] = call i64 @llvm.clmul.i64(i64 [[QUOT_MASK]], i64 67601)
; PCLMUL-NEXT: [[XOR_CRC_MULT:%.*]] = xor i64 [[CRC_CAST]], [[CLMUL_GP]]
; PCLMUL-NEXT: [[CRC_LSHR2:%.*]] = lshr i64 [[XOR_CRC_MULT]], 32
; PCLMUL-NEXT: [[CRC_NEXT3:%.*]] = trunc i64 [[CRC_LSHR2]] to i32
; PCLMUL-NEXT: br label %[[LOOP:.*]]
; PCLMUL: [[LOOP]]:
; PCLMUL-NEXT: br i1 false, label %[[LOOP]], label %[[EXIT:.*]]
; PCLMUL: [[EXIT]]:
; PCLMUL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i32 [ [[CRC_NEXT3]], %[[LOOP]] ]
; PCLMUL-NEXT: ret i32 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i32 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%xor.crc.data = xor i32 %crc, %data
%sb.crc.data = and i32 %xor.crc.data, 1
%check.sb = icmp eq i32 %sb.crc.data, 0
%crc.lshr = lshr i32 %crc, 1
%crc.xor = xor i32 %crc.lshr, 33800
%crc.next = select i1 %check.sb, i32 %crc.lshr, i32 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i32 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 31
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i32 %crc.next
}
define i64 @crc64.le.tc64(i64 %checksum, i64 %msg) optsize {
; ALL-LABEL: define i64 @crc64.le.tc64(
; ALL-SAME: i64 [[CHECKSUM:%.*]], i64 [[MSG:%.*]]) #[[ATTR0:[0-9]+]] {
; ALL-NEXT: [[ENTRY:.*]]:
; ALL-NEXT: br label %[[LOOP:.*]]
; ALL: [[LOOP]]:
; ALL-NEXT: [[CRC:%.*]] = phi i64 [ [[CHECKSUM]], %[[ENTRY]] ], [ [[CRC_NEXT:%.*]], %[[LOOP]] ]
; ALL-NEXT: [[DATA:%.*]] = phi i64 [ [[MSG]], %[[ENTRY]] ], [ [[DATA_NEXT:%.*]], %[[LOOP]] ]
; ALL-NEXT: [[IV:%.*]] = phi i8 [ 0, %[[ENTRY]] ], [ [[IV_NEXT:%.*]], %[[LOOP]] ]
; ALL-NEXT: [[XOR_CRC_DATA:%.*]] = xor i64 [[CRC]], [[DATA]]
; ALL-NEXT: [[SB_CRC_DATA:%.*]] = and i64 [[XOR_CRC_DATA]], 1
; ALL-NEXT: [[CHECK_SB:%.*]] = icmp eq i64 [[SB_CRC_DATA]], 0
; ALL-NEXT: [[CRC_LSHR:%.*]] = lshr i64 [[CRC]], 1
; ALL-NEXT: [[CRC_XOR:%.*]] = xor i64 [[CRC_LSHR]], 33800
; ALL-NEXT: [[CRC_NEXT]] = select i1 [[CHECK_SB]], i64 [[CRC_LSHR]], i64 [[CRC_XOR]]
; ALL-NEXT: [[IV_NEXT]] = add nuw nsw i8 [[IV]], 1
; ALL-NEXT: [[DATA_NEXT]] = lshr i64 [[DATA]], 1
; ALL-NEXT: [[EXIT_COND:%.*]] = icmp samesign ult i8 [[IV]], 63
; ALL-NEXT: br i1 [[EXIT_COND]], label %[[LOOP]], label %[[EXIT:.*]]
; ALL: [[EXIT]]:
; ALL-NEXT: [[CRC_NEXT_LCSSA:%.*]] = phi i64 [ [[CRC_NEXT]], %[[LOOP]] ]
; ALL-NEXT: ret i64 [[CRC_NEXT_LCSSA]]
;
entry:
br label %loop
loop: ; preds = %loop, %entry
%crc = phi i64 [ %checksum, %entry ], [ %crc.next, %loop ]
%data = phi i64 [ %msg, %entry ], [ %data.next, %loop ]
%iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
%xor.crc.data = xor i64 %crc, %data
%sb.crc.data = and i64 %xor.crc.data, 1
%check.sb = icmp eq i64 %sb.crc.data, 0
%crc.lshr = lshr i64 %crc, 1
%crc.xor = xor i64 %crc.lshr, 33800
%crc.next = select i1 %check.sb, i64 %crc.lshr, i64 %crc.xor
%iv.next = add nuw nsw i8 %iv, 1
%data.next = lshr i64 %data, 1
%exit.cond = icmp samesign ult i8 %iv, 63
br i1 %exit.cond, label %loop, label %exit
exit: ; preds = %loop
ret i64 %crc.next
}
;.
; NOPCLMUL: attributes #[[ATTR0]] = { optsize "target-features"="-pclmul" }
;.
; PCLMUL: attributes #[[ATTR0]] = { optsize "target-features"="+pclmul" }
; PCLMUL: attributes #[[ATTR1:[0-9]+]] = { nocallback nocreateundeforpoison nofree nosync nounwind speculatable willreturn memory(none) }
;.

File diff suppressed because it is too large Load diff