[llvm] cca454b - [ValueTracking] Remove opcode whitelist from matchSimpleRecurrence. (#144031)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 16 01:12:46 PDT 2025
Author: Ricardo Jesus
Date: 2025-06-16T09:12:42+01:00
New Revision: cca454b54c7d58930e261c7fa72f44a1a8976997
URL: https://github.com/llvm/llvm-project/commit/cca454b54c7d58930e261c7fa72f44a1a8976997
DIFF: https://github.com/llvm/llvm-project/commit/cca454b54c7d58930e261c7fa72f44a1a8976997.diff
LOG: [ValueTracking] Remove opcode whitelist from matchSimpleRecurrence. (#144031)
This also patches HashRecognize to avoid it mishandling some opcodes.
Added:
Modified:
llvm/lib/Analysis/HashRecognize.cpp
llvm/lib/Analysis/ValueTracking.cpp
llvm/test/Analysis/HashRecognize/cyclic-redundancy-check.ll
Removed:
################################################################################
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<bool> isBigEndianBitShift(const SCEV *E) {
+static std::optional<bool> 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<bool> 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 e7a1f07c0270d..d39efb2859747 100644
--- a/llvm/lib/Analysis/ValueTracking.cpp
+++ b/llvm/lib/Analysis/ValueTracking.cpp
@@ -9071,6 +9071,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;
@@ -9081,35 +9082,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
+}
More information about the llvm-commits
mailing list