Skip to content

Commit 9eec333

Browse files
author
git apple-llvm automerger
committed
Merge commit '10d4652144fb' from llvm.org/main into next
2 parents d0a04c5 + 10d4652 commit 9eec333

File tree

2 files changed

+90
-10
lines changed

2 files changed

+90
-10
lines changed

llvm/lib/Analysis/HashRecognize.cpp

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -102,8 +102,8 @@ class ValueEvolution {
102102

103103
public:
104104
// ValueEvolution is meant to be constructed with the TripCount of the loop,
105-
// and whether the polynomial algorithm is big-endian, for the significant-bit
106-
// check.
105+
// and a boolean indicating whether the polynomial algorithm is big-endian
106+
// (for the significant-bit check).
107107
ValueEvolution(unsigned TripCount, bool ByteOrderSwapped);
108108

109109
// Given a list of PHI nodes along with their incoming value from within the
@@ -115,6 +115,10 @@ class ValueEvolution {
115115
// precise error message.
116116
StringRef getError() const { return ErrStr; }
117117

118+
// A set of Instructions visited by ValueEvolution. The only unvisited
119+
// instructions will be ones not on the use-def chain of the PHIs' evolutions.
120+
SmallPtrSet<const Instruction *, 16> Visited;
121+
118122
// The computed KnownBits for each PHI node, which is populated after
119123
// computeEvolutions is called.
120124
KnownPhiMap KnownPhis;
@@ -177,6 +181,9 @@ KnownBits ValueEvolution::computeBinOp(const BinaryOperator *I) {
177181
KnownBits ValueEvolution::computeInstr(const Instruction *I) {
178182
unsigned BitWidth = I->getType()->getScalarSizeInBits();
179183

184+
// computeInstr is the only entry-point that needs to update the Visited set.
185+
Visited.insert(I);
186+
180187
// We look up in the map that contains the KnownBits of the PHI from the
181188
// previous iteration.
182189
if (const PHINode *P = dyn_cast<PHINode>(I))
@@ -185,9 +192,12 @@ KnownBits ValueEvolution::computeInstr(const Instruction *I) {
185192
// Compute the KnownBits for a Select(Cmp()), forcing it to take the branch
186193
// that is predicated on the (least|most)-significant-bit check.
187194
CmpPredicate Pred;
188-
Value *L, *R, *TV, *FV;
189-
if (match(I, m_Select(m_ICmp(Pred, m_Value(L), m_Value(R)), m_Value(TV),
190-
m_Value(FV)))) {
195+
Value *L, *R;
196+
Instruction *TV, *FV;
197+
if (match(I, m_Select(m_ICmp(Pred, m_Value(L), m_Value(R)), m_Instruction(TV),
198+
m_Instruction(FV)))) {
199+
Visited.insert(cast<Instruction>(I->getOperand(0)));
200+
191201
// We need to check LCR against [0, 2) in the little-endian case, because
192202
// the RCR check is insufficient: it is simply [0, 1).
193203
if (!ByteOrderSwapped) {
@@ -209,10 +219,17 @@ KnownBits ValueEvolution::computeInstr(const Instruction *I) {
209219
ConstantRange CheckRCR(APInt::getZero(ICmpBW),
210220
ByteOrderSwapped ? APInt::getSignedMinValue(ICmpBW)
211221
: APInt(ICmpBW, 1));
212-
if (AllowedR == CheckRCR)
222+
223+
// We only compute KnownBits of either TV or FV, as the other value would
224+
// just be a bit-shift as checked by isBigEndianBitShift.
225+
if (AllowedR == CheckRCR) {
226+
Visited.insert(FV);
213227
return compute(TV);
214-
if (AllowedR.inverse() == CheckRCR)
228+
}
229+
if (AllowedR.inverse() == CheckRCR) {
230+
Visited.insert(TV);
215231
return compute(FV);
232+
}
216233

217234
ErrStr = "Bad RHS of significant-bit-check";
218235
return {BitWidth};
@@ -634,6 +651,17 @@ HashRecognize::recognizeCRC() const {
634651
return VE.getError();
635652
KnownBits ResultBits = VE.KnownPhis.at(ConditionalRecurrence.Phi);
636653

654+
// There must be exactly four unvisited instructions, corresponding to the
655+
// IndVar PHI. Any other unvisited instructions from the KnownBits propagation
656+
// can complicate the optimization, which replaces the entire loop with the
657+
// table-lookup version of the hash algorithm.
658+
std::initializer_list<const Instruction *> AugmentVisited = {
659+
IndVar, Latch->getTerminator(), L.getLatchCmpInst(),
660+
cast<Instruction>(IndVar->getIncomingValueForBlock(Latch))};
661+
VE.Visited.insert_range(AugmentVisited);
662+
if (std::distance(Latch->begin(), Latch->end()) != VE.Visited.size())
663+
return "Found stray unvisited instructions";
664+
637665
unsigned N = std::min(TC, ResultBits.getBitWidth());
638666
auto IsZero = [](const KnownBits &K) { return K.isZero(); };
639667
if (!checkExtractBits(ResultBits, N, IsZero, *ByteOrderSwapped))

llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll

Lines changed: 55 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -909,10 +909,10 @@ exit: ; preds = %loop
909909
ret i16 %crc.next
910910
}
911911

912-
define i16 @not.crc.bad.cast(i8 %msg, i16 %checksum) {
913-
; CHECK-LABEL: 'not.crc.bad.cast'
912+
define i16 @not.crc.bad.endian.swapped.sb.check(i8 %msg, i16 %checksum) {
913+
; CHECK-LABEL: 'not.crc.bad.endian.swapped.sb.check'
914914
; CHECK-NEXT: Did not find a hash algorithm
915-
; CHECK-NEXT: Reason: Expected bottom 8 bits zero (????????00001011)
915+
; CHECK-NEXT: Reason: Found stray unvisited instructions
916916
;
917917
entry:
918918
br label %loop
@@ -1189,3 +1189,55 @@ loop: ; preds = %loop, %entry
11891189
exit: ; preds = %loop
11901190
ret i16 %crc.next
11911191
}
1192+
1193+
define i16 @not.crc.stray.unvisited.call(i16 %crc.init) {
1194+
; CHECK-LABEL: 'not.crc.stray.unvisited.call'
1195+
; CHECK-NEXT: Did not find a hash algorithm
1196+
; CHECK-NEXT: Reason: Found stray unvisited instructions
1197+
;
1198+
entry:
1199+
br label %loop
1200+
1201+
loop: ; preds = %loop, %entry
1202+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
1203+
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
1204+
%crc.shl = shl i16 %crc, 1
1205+
%crc.xor = xor i16 %crc.shl, 4129
1206+
%check.sb = icmp slt i16 %crc, 0
1207+
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
1208+
call void @print(i16 %crc.next)
1209+
%iv.next = add nuw nsw i32 %iv, 1
1210+
%exit.cond = icmp samesign ult i32 %iv, 7
1211+
br i1 %exit.cond, label %loop, label %exit
1212+
1213+
exit: ; preds = %loop
1214+
ret i16 %crc.next
1215+
}
1216+
1217+
declare void @print(i16)
1218+
1219+
define i16 @not.crc.call.sb.check(i16 %crc.init) {
1220+
; CHECK-LABEL: 'not.crc.call.sb.check'
1221+
; CHECK-NEXT: Did not find a hash algorithm
1222+
; CHECK-NEXT: Reason: Found stray unvisited instructions
1223+
;
1224+
entry:
1225+
br label %loop
1226+
1227+
loop: ; preds = %loop, %entry
1228+
%iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
1229+
%crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
1230+
%crc.shl = shl i16 %crc, 1
1231+
%crc.xor = xor i16 %crc.shl, 4129
1232+
%call = call i16 @side.effect()
1233+
%check.sb = icmp slt i16 %call, 0
1234+
%crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
1235+
%iv.next = add nuw nsw i32 %iv, 1
1236+
%exit.cond = icmp samesign ult i32 %iv, 7
1237+
br i1 %exit.cond, label %loop, label %exit
1238+
1239+
exit: ; preds = %loop
1240+
ret i16 %crc.next
1241+
}
1242+
1243+
declare i16 @side.effect()

0 commit comments

Comments
 (0)