OSDN Git Service

[SCEV] Add URem support to SCEV
authorAlexandre Isoard <alexandre.isoard@gmail.com>
Fri, 1 Sep 2017 14:59:59 +0000 (14:59 +0000)
committerAlexandre Isoard <alexandre.isoard@gmail.com>
Fri, 1 Sep 2017 14:59:59 +0000 (14:59 +0000)
commit3b88873b054cd2c541797062d653707c5689c265
treee4b7984466e389abd030cba773837076ccd150a6
parentd168a77ec3c791a1cf5db8bf613818eb41982300
[SCEV] Add URem support to SCEV

In LLVM IR the following code:

    %r = urem <ty> %t, %b

is equivalent to

    %q = udiv <ty> %t, %b
    %s = mul <ty> nuw %q, %b
    %r = sub <ty> nuw %t, %q ; (t / b) * b + (t % b) = t

As UDiv, Mul and Sub are already supported by SCEV, URem can be implemented
with minimal effort using that relation:

    %r --> (-%b * (%t /u %b)) + %t

We implement two special cases:

  - if %b is 1, the result is always 0
  - if %b is a power-of-two, we produce a zext/trunc based expression instead

That is, the following code:

    %r = urem i32 %t, 65536

Produces:

    %r --> (zext i16 (trunc i32 %a to i16) to i32)

Note that while this helps get a tighter bound on the range analysis and the
known-bits analysis, this exposes some normalization shortcoming of SCEVs:

    %div = udim i32 %a, 65536
    %mul = mul i32 %div, 65536
    %rem = urem i32 %a, 65536
    %add = add i32 %mul, %rem

Will usually not be reduced.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@312329 91177308-0d34-0410-b5e6-96231b3b80d8
include/llvm/Analysis/ScalarEvolution.h
lib/Analysis/ScalarEvolution.cpp
test/Analysis/ScalarEvolution/flattened-0.ll [new file with mode: 0644]
test/Analysis/ScalarEvolution/urem-0.ll [new file with mode: 0644]