[llvm] [HashRecognize] Fix LHS ConstantRange check for BE (PR #148620)

Ramkumar Ramachandra via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 22 04:08:50 PDT 2025


artagnon wrote:

Sorry for the delay, but the logic behind this patch is easy to see with examples.

Let us look at a big-endian example first:

```llvm
define i16 @crc16.be(i16 %crc.init) {
entry:
  br label %loop

loop:                                              ; preds = %loop, %entry
  %iv = phi i32 [ 0, %entry ], [ %iv.next, %loop ]
  %crc = phi i16 [ %crc.init, %entry ], [ %crc.next, %loop ]
  %crc.shl = shl i16 %crc, 1
  %crc.xor = xor i16 %crc.shl, 4129
  %check.sb = icmp sge i16 %crc, 0
  %crc.next = select i1 %check.sb, i16 %crc.shl, i16 %crc.xor
  %iv.next = add nuw nsw i32 %iv, 1
  %exit.cond = icmp samesign ult i32 %iv, 7
  br i1 %exit.cond, label %loop, label %exit

exit:                                              ; preds = %loop
  ret i16 %crc.next
}
```

Notice `%check.sb = icmp sge i16 %crc, 0`. All the big-endian sb-checks must be of this form. The RHS has range [0, smin), and the LHS has range [0, -1), [0, -3), [0, -7) etc. (as one bit is shifted every iteration). In this patch, we check LHS' range to prevent things like `%check.sb = icmp sge i16 %crc.shl, 0`.

See the little-endian case:

```llvm
define i32 @crc32.le(i32 %checksum, i32 %msg) {
entry:
  br label %loop

loop:                                              ; preds = %loop, %entry
  %crc = phi i32 [ %checksum, %entry ], [ %crc.next, %loop ]
  %data = phi i32 [ %msg, %entry ], [ %data.next, %loop ]
  %iv = phi i8 [ 0, %entry ], [ %iv.next, %loop ]
  %xor.crc.data = xor i32 %crc, %data
  %sb.crc.data = and i32 %xor.crc.data, 1
  %check.sb = icmp eq i32 %sb.crc.data, 0
  %crc.lshr = lshr i32 %crc, 1
  %crc.xor = xor i32 %crc.lshr, 33800
  %crc.next = select i1 %check.sb, i32 %crc.lshr, i32 %crc.xor
  %iv.next = add nuw nsw i8 %iv, 1
  %data.next = lshr i32 %data, 1
  %exit.cond = icmp samesign ult i8 %iv, 7
  br i1 %exit.cond, label %loop, label %exit

exit:                                              ; preds = %loop
  ret i32 %crc.next
}
```

Notice `%check.sb = icmp eq i32 %sb.crc.data, 0` where `%sb.crc.data = and i32 %xor.crc.data, 1`. All little-endian sb-checks must be of this form. The RHS has range [0, 1) and the LHS has range [0, 2). One bit is shifted every iteration, but we're only checking the least-significant-bit.

https://github.com/llvm/llvm-project/pull/148620


More information about the llvm-commits mailing list