@@ -73,60 +73,10 @@ using namespace SCEVPatternMatch;
7373
7474#define DEBUG_TYPE " hash-recognize"
7575
76- // / Check the well-formedness of the (most|least) significant bit check \p SI,
77- // / where \p BitShift is the bit-shift branch: the other branch must be a
78- // / bit-shift-and-xor-poly branch, as already checked by
79- // / matchConditionalRecurrence. We check that the compare is `>= 0` in the
80- // / big-endian case, and `== 0` in the little-endian case (or the inverse, in
81- // / which case the branches of the compare are swapped). We check LCR against
82- // / CheckLCR, which is full-set in the big-endian case, and [0, 2) in the
83- // / little-endian case: CheckLCR checks that the comparison is `>= 0` in the
84- // / big-endian case, and that the compare is to 0 or 1 in the little-endian case
85- // / (as a value and'ed with 1 is passed as the operand). We then check
86- // / AllowedByR against CheckAllowedByR, which is [0, smin) in the big-endian
87- // / case, and [0, 1) in the little-endian case: CheckAllowedByR checks for
88- // / significant-bit-clear, and this must be equal to \p BitShift for
89- // / well-formedness.
90- static bool isSignificantBitCheckWellFormed (const SelectInst *SI,
91- const BinaryOperator *BitShift,
92- bool ByteOrderSwapped) {
93- DataLayout DL = SI->getParent ()->getDataLayout ();
94- CmpPredicate Pred;
95- Value *L, *R;
96- Instruction *TV, *FV;
97- [[maybe_unused]] bool Match =
98- match (SI, m_Select (m_ICmp (Pred, m_Value (L), m_Value (R)),
99- m_Instruction (TV), m_Instruction (FV)));
100- assert (Match && " Select(ICmp()) expected in signficant-bit-check" );
101-
102- KnownBits KnownL = computeKnownBits (L, DL);
103- unsigned ICmpBW = KnownL.getBitWidth ();
104- auto LCR = ConstantRange::fromKnownBits (KnownL, false );
105- auto CheckLCR = ConstantRange::getNonEmpty (
106- APInt::getZero (ICmpBW),
107- ByteOrderSwapped ? APInt::getZero (ICmpBW) : APInt (ICmpBW, 2 ));
108- if (LCR != CheckLCR)
109- return false ;
110-
111- KnownBits KnownR = computeKnownBits (R, DL);
112- auto RCR = ConstantRange::fromKnownBits (KnownR, false );
113- auto AllowedByR = ConstantRange::makeAllowedICmpRegion (Pred, RCR);
114- ConstantRange CheckAllowedByR (
115- APInt::getZero (ICmpBW),
116- ByteOrderSwapped ? APInt::getSignedMinValue (ICmpBW) : APInt (ICmpBW, 1 ));
117-
118- if (AllowedByR == CheckAllowedByR)
119- return TV == BitShift;
120- if (AllowedByR.inverse () == CheckAllowedByR)
121- return FV == BitShift;
122- return false ;
123- }
124-
125- // / Checks if Loop \p L contains instructions unreachable or unhandled from \p
126- // / Roots on the use-def chain.
127- static bool
128- containsUnreachableOrUnhandled (const Loop &L,
129- ArrayRef<const Instruction *> Roots) {
76+ // / Checks if Loop \p L contains instructions unreachable \p Roots on the
77+ // / use-def chain.
78+ static bool containsUnreachable (const Loop &L,
79+ ArrayRef<const Instruction *> Roots) {
13080 SmallPtrSet<const Instruction *, 16 > Visited;
13181 BasicBlock *Latch = L.getLoopLatch ();
13282
@@ -138,18 +88,13 @@ containsUnreachableOrUnhandled(const Loop &L,
13888 if (isa<PHINode>(I))
13989 continue ;
14090
141- if (!isa<TruncInst, BinaryOperator, SelectInst, CmpInst, BranchInst>(I))
142- return true ;
143-
14491 for (const Use &U : I->operands ()) {
14592 if (auto *UI = dyn_cast<Instruction>(U)) {
14693 if (!L.contains (UI))
14794 return true ;
14895 Worklist.push_back (UI);
14996 continue ;
15097 }
151- if (!isa<ConstantInt, BasicBlock>(U))
152- return true ;
15398 }
15499 }
155100 return std::distance (Latch->begin (), Latch->end ()) != Visited.size ();
@@ -204,6 +149,60 @@ struct RecurrenceInfo {
204149 Instruction::BinaryOps BOWithConstOpToMatch = Instruction::BinaryOpsEnd);
205150};
206151
152+ // / Check the well-formedness of the (most|least) significant bit check given \p
153+ // / ConditionalRecurrence, \p SimpleRecurrence, depending on \p
154+ // / ByteOrderSwapped. We check that ConditionalRecurrence.Step is a
155+ // / Select(Cmp()) where the compare is `>= 0` in the big-endian case, and `== 0`
156+ // / in the little-endian case (or the inverse, in which case the branches of the
157+ // / compare are swapped). We check that the LHS is (ConditionalRecurrence.Phi
158+ // / [xor SimpleRecurrence.Phi]) in the big-endian case, and additionally check
159+ // / for an AND with one in the little-endian case. We then check AllowedByR
160+ // / against CheckAllowedByR, which is [0, smin) in the big-endian case, and [0,
161+ // / 1) in the little-endian case: CheckAllowedByR checks for
162+ // / significant-bit-clear, and this must be equal to ConditionalRecurrence.BO
163+ // / (which is the bit-shift, as already checked by isBigEndianBitShift) for
164+ // / well-formedness.
165+ static bool
166+ isSignificantBitCheckWellFormed (const RecurrenceInfo &ConditionalRecurrence,
167+ const RecurrenceInfo &SimpleRecurrence,
168+ bool ByteOrderSwapped) {
169+ auto *SI = cast<SelectInst>(ConditionalRecurrence.Step );
170+ DataLayout DL = SI->getParent ()->getDataLayout ();
171+ CmpPredicate Pred;
172+ const Value *L;
173+ const APInt *R;
174+ Instruction *TV, *FV;
175+ if (!match (SI, m_Select (m_ICmp (Pred, m_Value (L), m_APInt (R)),
176+ m_Instruction (TV), m_Instruction (FV))))
177+ return false ;
178+
179+ // Match predicate with or without a SimpleRecurrence (the corresponding data
180+ // is LHSAux).
181+ auto MatchPred =
182+ m_CombineOr (m_Specific (ConditionalRecurrence.Phi ),
183+ m_c_Xor (m_CastOrSelf (m_Specific (ConditionalRecurrence.Phi )),
184+ m_CastOrSelf (m_Specific (SimpleRecurrence.Phi ))));
185+ bool LWellFormed = ByteOrderSwapped ? match (L, MatchPred)
186+ : match (L, m_c_And (MatchPred, m_One ()));
187+ if (!LWellFormed)
188+ return false ;
189+
190+ KnownBits KnownR = KnownBits::makeConstant (*R);
191+ unsigned BW = KnownR.getBitWidth ();
192+ auto RCR = ConstantRange::fromKnownBits (KnownR, false );
193+ auto AllowedByR = ConstantRange::makeAllowedICmpRegion (Pred, RCR);
194+ ConstantRange CheckAllowedByR (APInt::getZero (BW),
195+ ByteOrderSwapped ? APInt::getSignedMinValue (BW)
196+ : APInt (BW, 1 ));
197+
198+ BinaryOperator *BitShift = ConditionalRecurrence.BO ;
199+ if (AllowedByR == CheckAllowedByR)
200+ return TV == BitShift;
201+ if (AllowedByR.inverse () == CheckAllowedByR)
202+ return FV == BitShift;
203+ return false ;
204+ }
205+
207206// / Wraps llvm::matchSimpleRecurrence. Match a simple first order recurrence
208207// / cycle of the form:
209208// /
@@ -375,7 +374,7 @@ CRCTable HashRecognize::genSarwateTable(const APInt &GenPoly,
375374// / Checks that \p P1 and \p P2 are used together in an XOR in the use-def chain
376375// / of \p SI's condition, ignoring any casts. The purpose of this function is to
377376// / ensure that LHSAux from the SimpleRecurrence is used correctly in the CRC
378- // / computation. We cannot check the correctness of casts at this point.
377+ // / computation.
379378// /
380379// / In other words, it checks for the following pattern:
381380// /
@@ -497,9 +496,8 @@ std::variant<PolynomialInfo, StringRef> HashRecognize::recognizeCRC() const {
497496 " Expected ExtraConst in conditional recurrence" );
498497 const APInt &GenPoly = *ConditionalRecurrence.ExtraConst ;
499498
500- if (!isSignificantBitCheckWellFormed (
501- cast<SelectInst>(ConditionalRecurrence.Step ),
502- ConditionalRecurrence.BO , *ByteOrderSwapped))
499+ if (!isSignificantBitCheckWellFormed (ConditionalRecurrence, SimpleRecurrence,
500+ *ByteOrderSwapped))
503501 return " Malformed significant-bit check" ;
504502
505503 SmallVector<const Instruction *> Roots (
@@ -508,8 +506,8 @@ std::variant<PolynomialInfo, StringRef> HashRecognize::recognizeCRC() const {
508506 L.getLatchCmpInst (), Latch->getTerminator ()});
509507 if (SimpleRecurrence)
510508 Roots.push_back (SimpleRecurrence.BO );
511- if (containsUnreachableOrUnhandled (L, Roots))
512- return " Found stray unvisited or unhandled instructions" ;
509+ if (containsUnreachable (L, Roots))
510+ return " Found stray unvisited instructions" ;
513511
514512 return PolynomialInfo (TC, LHS, GenPoly, ComputedValue, *ByteOrderSwapped,
515513 LHSAux);
0 commit comments