[ConstantRange] Add sdiv() support
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 3 Jun 2019 18:19:54 +0000 (18:19 +0000)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 3 Jun 2019 18:19:54 +0000 (18:19 +0000)
commitc061b99c5b6234ff2442eee847491286633d9e92
treedf95f2235ba56cd60545f07aceda7bbc6ba2555d
parent221e604d6f92af075f22e38ca2fe71432bb1b3c1
[ConstantRange] Add sdiv() support

The implementation is conceptually simple: We separate the LHS and
RHS into positive and negative components and then also compute the
positive and negative components of the result, taking into account
that e.g. only pos/pos and neg/neg will give a positive result.

However, there's one significant complication: SignedMin / -1 is UB
for sdiv, and we can't just ignore it, because the APInt result of
SignedMin would break the sign segregation. Instead we drop SignedMin
or -1 from the corresponding ranges, taking into account some edge
cases with wrapped ranges.

Because of the sign segregation, the implementation ends up being
nearly fully precise even for wrapped ranges (the remaining
imprecision is due to ranges that are both signed and unsigned
wrapping and are divided by a trivial divisor like 1). This means
that the testing cannot just check the signed envelope as we
usually do. Instead we collect all possible results in a bitvector
and construct a better sign wrapped range (than the full envelope).

Differential Revision: https://reviews.llvm.org/D61238

llvm-svn: 362430
llvm/include/llvm/IR/ConstantRange.h
llvm/lib/IR/ConstantRange.cpp
llvm/unittests/IR/ConstantRangeTest.cpp