diff --git a/llvm/lib/Analysis/HashRecognize.cpp b/llvm/lib/Analysis/HashRecognize.cpp index b245548dea6d5..1edb8b3bdc9a8 100644 --- a/llvm/lib/Analysis/HashRecognize.cpp +++ b/llvm/lib/Analysis/HashRecognize.cpp @@ -542,7 +542,11 @@ static bool arePHIsIntertwined( // doing this, we're immune to whether the IR expression is mul/udiv or // equivalently shl/lshr. Return false when it is a UDiv, true when it is a Mul, // and std::nullopt otherwise. -static std::optional isBigEndianBitShift(const SCEV *E) { +static std::optional isBigEndianBitShift(Value *V, ScalarEvolution &SE) { + if (!V->getType()->isIntegerTy()) + return {}; + + const SCEV *E = SE.getSCEV(V); if (match(E, m_scev_UDiv(m_SCEV(), m_scev_SpecificInt(2)))) return false; if (match(E, m_scev_Mul(m_scev_SpecificInt(2), m_SCEV()))) @@ -576,12 +580,11 @@ HashRecognize::recognizeCRC() const { // Make sure that all recurrences are either all SCEVMul with two or SCEVDiv // with two, or in other words, that they're single bit-shifts. std::optional ByteOrderSwapped = - isBigEndianBitShift(SE.getSCEV(ConditionalRecurrence.BO)); + isBigEndianBitShift(ConditionalRecurrence.BO, SE); if (!ByteOrderSwapped) return "Loop with non-unit bitshifts"; if (SimpleRecurrence) { - if (isBigEndianBitShift(SE.getSCEV(SimpleRecurrence.BO)) != - ByteOrderSwapped) + if (isBigEndianBitShift(SimpleRecurrence.BO, SE) != ByteOrderSwapped) return "Loop with non-unit bitshifts"; if (!arePHIsIntertwined(SimpleRecurrence.Phi, ConditionalRecurrence.Phi, L, Instruction::BinaryOps::Xor)) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index 0a460786d00ea..bb1f61e413c0e 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -9058,6 +9058,7 @@ bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO, // Handle the case of a simple two-predecessor recurrence PHI. // There's a lot more that could theoretically be done here, but // this is sufficient to catch some interesting cases. + // TODO: Expand list -- gep, uadd.sat etc. if (P->getNumIncomingValues() != 2) return false; @@ -9068,35 +9069,16 @@ bool llvm::matchSimpleRecurrence(const PHINode *P, BinaryOperator *&BO, if (!LU) continue; unsigned Opcode = LU->getOpcode(); - - switch (Opcode) { - default: - continue; - // TODO: Expand list -- xor, gep, uadd.sat etc. - case Instruction::LShr: - case Instruction::AShr: - case Instruction::Shl: - case Instruction::Add: - case Instruction::Sub: - case Instruction::UDiv: - case Instruction::URem: - case Instruction::And: - case Instruction::Or: - case Instruction::Mul: - case Instruction::FMul: { - Value *LL = LU->getOperand(0); - Value *LR = LU->getOperand(1); - // Find a recurrence. - if (LL == P) - L = LR; - else if (LR == P) - L = LL; - else - continue; // Check for recurrence with L and R flipped. - - break; // Match! - } - }; + Value *LL = LU->getOperand(0); + Value *LR = LU->getOperand(1); + + // Find a recurrence. + if (LL == P) + L = LR; + else if (LR == P) + L = LL; + else + continue; // Check for recurrence with L and R flipped. // We have matched a recurrence of the form: // %iv = [R, %entry], [%iv.next, %backedge] diff --git a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll index 3e05a9b5c8499..7a3082056ad29 100644 --- a/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll +++ b/llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll @@ -873,7 +873,7 @@ exit: ; preds = %loop define i16 @not.crc.float.simple.recurrence(float %msg, i16 %checksum) { ; CHECK-LABEL: 'not.crc.float.simple.recurrence' ; CHECK-NEXT: Did not find a hash algorithm -; CHECK-NEXT: Reason: Found stray PHI +; CHECK-NEXT: Reason: Loop with non-unit bitshifts ; entry: br label %loop @@ -897,3 +897,31 @@ loop: ; preds = %loop, %entry exit: ; preds = %loop ret i16 %crc.next } + +define i16 @not.crc.stray.phi(i8 %msg, i16 %checksum, i1 %c) { +; CHECK-LABEL: 'not.crc.stray.phi' +; CHECK-NEXT: Did not find a hash algorithm +; CHECK-NEXT: Reason: Found stray PHI +; +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 = select i1 %c, i8 %data, i8 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 +}