Wrong Range of SCEV for URem

Dear all,

Hi! I noticed an interesting situation when using getUnsignedRange and getSignedRange of SCEV for URem instruction.
Here is an example with 2 IR instructions:

%rem.lhs.trunc = trunc i32 %i15.082 to i8 → getUnsignedRange → [1,50)
%rem81 = urem i8 %rem.lhs.trunc, 3 → getUnsignedRange → [-47,50)

The problems are:

  1. From my perspective, the getUnsignedRange() function should return non-negative range but it seems not so in the example. Is there anything wrong?
  2. The range of the IR %rem81 should be [0,3), considering the equation: X%3 < 3?

Thanks in advance for your time and suggestions!

1. There is nothing wrong about getUnsignedRange returning a range
with a negative value. "Signed" and "Unsigned" are merely hints, the
underlying ConstantRange representation does not have a concept of
sign. [A, B) represents all the values enumerated by "for (I = A; I
!= B; I++ /*wrapping addition*/) { yield(I); }"

2. I would guess this is because SCEV does not directly represent urem
but instead represents it as "%x urem %y == %x -<nuw> ((%x udiv %y)
*<nuw> %y)". This makes it difficult for SCEV to infer that the X
urem 3 is u< 3.

I feel that we maybe able to pattern match "%x -<nuw> ((%x udiv %y)
*<nuw> %y)" to infer that the results should be smaller than %y. But
not sure if this approach could scale well

Dear all,

Thanks a lot for your analysis and suggestion.
Currently, I walk around in a way similar to what Hongbin said, by treating SCEV of URem specially to get the range.
I guess maybe the rule of inference can be updated haha :slight_smile:
Thanks again for your time and answer!