Skip to content

Commit bc7936e

Browse files
committed
[HashRecognize] Track visited in ValueEvolution
Require that all Instructions in the Loop are visited by ValueEvolution, as any stray instructions would complicate life for the optimization.
1 parent c13d2ca commit bc7936e

File tree

2 files changed

+50
-35
lines changed

2 files changed

+50
-35
lines changed

llvm/lib/Analysis/HashRecognize.cpp

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ class ValueEvolution {
9191
APInt GenPoly;
9292
StringRef ErrStr;
9393

94+
// A set of instructions visited by ValueEvolution. Anything that's not in the
95+
// use-def chain of the PHIs' evolution will be reported as unvisited.
96+
SmallPtrSet<const Instruction *, 16> Visited;
97+
9498
// Compute the KnownBits of a BinaryOperator.
9599
KnownBits computeBinOp(const BinaryOperator *I);
96100

@@ -102,15 +106,19 @@ class ValueEvolution {
102106

103107
public:
104108
// 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.
107-
ValueEvolution(unsigned TripCount, bool ByteOrderSwapped);
109+
// whether the polynomial algorithm is big-endian for the significant-bit
110+
// check, and an initial value for the Visited set.
111+
ValueEvolution(unsigned TripCount, bool ByteOrderSwapped,
112+
ArrayRef<const Instruction *> InitVisited);
108113

109114
// Given a list of PHI nodes along with their incoming value from within the
110115
// loop, computeEvolutions computes the KnownBits of each of the PHI nodes on
111116
// the final iteration. Returns true on success and false on error.
112117
bool computeEvolutions(ArrayRef<PhiStepPair> PhiEvolutions);
113118

119+
// Query the Visited set.
120+
bool isVisited(const Instruction *I) const { return Visited.contains(I); }
121+
114122
// In case ValueEvolution encounters an error, this is meant to be used for a
115123
// precise error message.
116124
StringRef getError() const { return ErrStr; }
@@ -120,8 +128,11 @@ class ValueEvolution {
120128
KnownPhiMap KnownPhis;
121129
};
122130

123-
ValueEvolution::ValueEvolution(unsigned TripCount, bool ByteOrderSwapped)
124-
: TripCount(TripCount), ByteOrderSwapped(ByteOrderSwapped) {}
131+
ValueEvolution::ValueEvolution(unsigned TripCount, bool ByteOrderSwapped,
132+
ArrayRef<const Instruction *> InitVisited)
133+
: TripCount(TripCount), ByteOrderSwapped(ByteOrderSwapped) {
134+
Visited.insert_range(InitVisited);
135+
}
125136

126137
KnownBits ValueEvolution::computeBinOp(const BinaryOperator *I) {
127138
KnownBits KnownL(compute(I->getOperand(0)));
@@ -177,6 +188,9 @@ KnownBits ValueEvolution::computeBinOp(const BinaryOperator *I) {
177188
KnownBits ValueEvolution::computeInstr(const Instruction *I) {
178189
unsigned BitWidth = I->getType()->getScalarSizeInBits();
179190

191+
// computeInstr is the only entry-point that needs to update the Visited set.
192+
Visited.insert(I);
193+
180194
// We look up in the map that contains the KnownBits of the PHI from the
181195
// previous iteration.
182196
if (const PHINode *P = dyn_cast<PHINode>(I))
@@ -185,9 +199,14 @@ KnownBits ValueEvolution::computeInstr(const Instruction *I) {
185199
// Compute the KnownBits for a Select(Cmp()), forcing it to take the branch
186200
// that is predicated on the (least|most)-significant-bit check.
187201
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)))) {
202+
Value *L, *R;
203+
Instruction *TV, *FV;
204+
if (match(I, m_Select(m_ICmp(Pred, m_Value(L), m_Value(R)), m_Instruction(TV),
205+
m_Instruction(FV)))) {
206+
Visited.insert(cast<Instruction>(I->getOperand(0)));
207+
Visited.insert(TV);
208+
Visited.insert(FV);
209+
191210
// We need to check LCR against [0, 2) in the little-endian case, because
192211
// the RCR check is insufficient: it is simply [0, 1).
193212
if (!ByteOrderSwapped) {
@@ -209,6 +228,9 @@ KnownBits ValueEvolution::computeInstr(const Instruction *I) {
209228
ConstantRange CheckRCR(APInt::getZero(ICmpBW),
210229
ByteOrderSwapped ? APInt::getSignedMinValue(ICmpBW)
211230
: APInt(ICmpBW, 1));
231+
232+
// We only compute KnownBits of either TV or FV, as the other value would
233+
// just be a bit-shift as checked by isBigEndianBitShift.
212234
if (AllowedR == CheckRCR)
213235
return compute(TV);
214236
if (AllowedR.inverse() == CheckRCR)
@@ -629,11 +651,23 @@ HashRecognize::recognizeCRC() const {
629651
if (SimpleRecurrence)
630652
PhiEvolutions.emplace_back(SimpleRecurrence.Phi, SimpleRecurrence.BO);
631653

632-
ValueEvolution VE(TC, *ByteOrderSwapped);
654+
// Initialize the Visited set in ValueEvolution with the IndVar-related
655+
// instructions.
656+
std::initializer_list<const Instruction *> InitVisited = {
657+
IndVar, Latch->getTerminator(), L.getLatchCmpInst(),
658+
cast<Instruction>(IndVar->getIncomingValueForBlock(Latch))};
659+
660+
ValueEvolution VE(TC, *ByteOrderSwapped, InitVisited);
633661
if (!VE.computeEvolutions(PhiEvolutions))
634662
return VE.getError();
635663
KnownBits ResultBits = VE.KnownPhis.at(ConditionalRecurrence.Phi);
636664

665+
// Any unvisited instructions from the KnownBits propagation can complicate
666+
// the optimization, which would just replace the entire loop with the
667+
// table-lookup version of the hash algorithm.
668+
if (any_of(*Latch, [VE](const Instruction &I) { return !VE.isVisited(&I); }))
669+
return "Found stray unvisited instructions";
670+
637671
unsigned N = std::min(TC, ResultBits.getBitWidth());
638672
auto IsZero = [](const KnownBits &K) { return K.isZero(); };
639673
if (!checkExtractBits(ResultBits, N, IsZero, *ByteOrderSwapped))

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

Lines changed: 7 additions & 26 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
@@ -1190,29 +1190,10 @@ exit: ; preds = %loop
11901190
ret i16 %crc.next
11911191
}
11921192

1193-
define i16 @not.crc.stray.unvisited.inst(i16 %crc.init) {
1194-
; CHECK-LABEL: 'not.crc.stray.unvisited.inst'
1195-
; CHECK-NEXT: Found big-endian CRC-16 loop with trip count 8
1196-
; CHECK-NEXT: Initial CRC: i16 %crc.init
1197-
; CHECK-NEXT: Generating polynomial: 4129
1198-
; CHECK-NEXT: Computed CRC: %crc.next = select i1 %check.sb, i16 %crc.xor, i16 %crc.shl
1199-
; CHECK-NEXT: Computed CRC lookup table:
1200-
; CHECK-NEXT: 0 4129 8258 12387 16516 20645 24774 28903 33032 37161 41290 45419 49548 53677 57806 61935
1201-
; CHECK-NEXT: 4657 528 12915 8786 21173 17044 29431 25302 37689 33560 45947 41818 54205 50076 62463 58334
1202-
; CHECK-NEXT: 9314 13379 1056 5121 25830 29895 17572 21637 42346 46411 34088 38153 58862 62927 50604 54669
1203-
; CHECK-NEXT: 13907 9842 5649 1584 30423 26358 22165 18100 46939 42874 38681 34616 63455 59390 55197 51132
1204-
; CHECK-NEXT: 18628 22757 26758 30887 2112 6241 10242 14371 51660 55789 59790 63919 35144 39273 43274 47403
1205-
; CHECK-NEXT: 23285 19156 31415 27286 6769 2640 14899 10770 56317 52188 64447 60318 39801 35672 47931 43802
1206-
; CHECK-NEXT: 27814 31879 19684 23749 11298 15363 3168 7233 60846 64911 52716 56781 44330 48395 36200 40265
1207-
; CHECK-NEXT: 32407 28342 24277 20212 15891 11826 7761 3696 65439 61374 57309 53244 48923 44858 40793 36728
1208-
; CHECK-NEXT: 37256 33193 45514 41451 53516 49453 61774 57711 4224 161 12482 8419 20484 16421 28742 24679
1209-
; CHECK-NEXT: 33721 37784 41979 46042 49981 54044 58239 62302 689 4752 8947 13010 16949 21012 25207 29270
1210-
; CHECK-NEXT: 46570 42443 38312 34185 62830 58703 54572 50445 13538 9411 5280 1153 29798 25671 21540 17413
1211-
; CHECK-NEXT: 42971 47098 34713 38840 59231 63358 50973 55100 9939 14066 1681 5808 26199 30326 17941 22068
1212-
; CHECK-NEXT: 55628 51565 63758 59695 39368 35305 47498 43435 22596 18533 30726 26663 6336 2273 14466 10403
1213-
; CHECK-NEXT: 52093 56156 60223 64286 35833 39896 43963 48026 19061 23124 27191 31254 2801 6864 10931 14994
1214-
; CHECK-NEXT: 64814 60687 56684 52557 48554 44427 40424 36297 31782 27655 23652 19525 15522 11395 7392 3265
1215-
; CHECK-NEXT: 61215 65342 53085 57212 44955 49082 36825 40952 28183 32310 20053 24180 11923 16050 3793 7920
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
12161197
;
12171198
entry:
12181199
br label %loop

0 commit comments

Comments
 (0)