At the moment, ranger punts entirely on POLY_INT_CSTs. Numerical ranges are a bit difficult, unless we do start modelling bounds on the indeterminates. But we can at least track the nonzero bits.
gcc/ * value-query.cc (range_query::get_tree_range): Use get_nonzero_bits to populate the irange_bitmask of a POLY_INT_CST. gcc/testsuite/ * gcc.target/aarch64/sve/cnt_fold_6.c: New test. --- .../gcc.target/aarch64/sve/cnt_fold_6.c | 75 +++++++++++++++++++ gcc/value-query.cc | 7 ++ 2 files changed, 82 insertions(+) create mode 100644 gcc/testsuite/gcc.target/aarch64/sve/cnt_fold_6.c diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cnt_fold_6.c b/gcc/testsuite/gcc.target/aarch64/sve/cnt_fold_6.c new file mode 100644 index 00000000000..9d9e1ca9330 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/cnt_fold_6.c @@ -0,0 +1,75 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +#include <arm_sve.h> + +/* +** f1: +** ... +** cntb (x[0-9]+) +** ... +** add x[0-9]+, \1, #?16 +** ... +** csel [^\n]+ +** ret +*/ +uint64_t +f1 (int x) +{ + uint64_t y = x ? svcnth () : svcnth () + 8; + y >>= 3; + y <<= 4; + return y; +} + +/* +** f2: +** ... +** (?:and|[al]sr) [^\n]+ +** ... +** ret +*/ +uint64_t +f2 (int x) +{ + uint64_t y = x ? svcnth () : svcnth () + 8; + y >>= 4; + y <<= 5; + return y; +} + +/* +** f3: +** ... +** cntw (x[0-9]+) +** ... +** add x[0-9]+, \1, #?16 +** ... +** csel [^\n]+ +** ret +*/ +uint64_t +f3 (int x) +{ + uint64_t y = x ? svcntd () : svcntd () + 8; + y >>= 1; + y <<= 2; + return y; +} + +/* +** f4: +** ... +** (?:and|[al]sr) [^\n]+ +** ... +** ret +*/ +uint64_t +f4 (int x) +{ + uint64_t y = x ? svcntd () : svcntd () + 8; + y >>= 2; + y <<= 3; + return y; +} diff --git a/gcc/value-query.cc b/gcc/value-query.cc index cac2cb5b2bc..34499da1a98 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -375,6 +375,13 @@ range_query::get_tree_range (vrange &r, tree expr, gimple *stmt, } default: + if (POLY_INT_CST_P (expr)) + { + unsigned int precision = TYPE_PRECISION (type); + r.set_varying (type); + r.update_bitmask ({ wi::zero (precision), get_nonzero_bits (expr) }); + return true; + } break; } if (BINARY_CLASS_P (expr) || COMPARISON_CLASS_P (expr)) -- 2.25.1