diff options
author | Aldy Hernandez <aldyh@redhat.com> | 2021-05-13 13:47:41 -0400 |
---|---|---|
committer | Aldy Hernandez <aldyh@redhat.com> | 2021-06-17 12:10:41 +0200 |
commit | f1555d4013ed3cae2589270436387063d1c2f1a3 (patch) | |
tree | ce352c9735b2095b6952b2b84a660240dd8be3b8 /gcc | |
parent | 8eac92a07e386301f7b09f7ef6146e6e3ac6b6cd (diff) | |
download | gcc-f1555d4013ed3cae2589270436387063d1c2f1a3.zip gcc-f1555d4013ed3cae2589270436387063d1c2f1a3.tar.gz gcc-f1555d4013ed3cae2589270436387063d1c2f1a3.tar.bz2 |
Cleanup clz and ctz code in range_of_builtin_call.
These are various cleanups to the clz/ctz code.
First, ranges from range_of_expr are always numeric so we
should adjust. Also, the checks for non-zero were assuming the argument
was unsigned, which in the PR's testcase is clearly not. I've cleaned
this up, so that it works either way.
I've also removed the following annoying idiom:
- int newmini = prec - 1 - wi::floor_log2 (r.upper_bound ());
- if (newmini == prec)
This is really a check for r.upper_bound() == 0, as floor_log2(0)
returns -1. It's confusing.
Tested on x86-64 Linux.
gcc/ChangeLog:
PR tree-optimization/100790
* gimple-range.cc (range_of_builtin_call): Cleanup clz and ctz
code.
gcc/testsuite/ChangeLog:
* gcc.dg/pr100790.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/gimple-range.cc | 42 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/pr100790.c | 4 |
2 files changed, 24 insertions, 22 deletions
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 5810970..15c65f1 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -960,32 +960,29 @@ fold_using_range::range_of_builtin_call (irange &r, gcall *call, src.get_operand (r, arg); // From clz of minimum we can compute result maximum. - if (r.constant_p () && !r.varying_p ()) + if (!r.undefined_p ()) { - int newmaxi = prec - 1 - wi::floor_log2 (r.lower_bound ()); - // Argument is unsigned, so do nothing if it is [0, ...] range. - if (newmaxi != prec) + // From clz of minimum we can compute result maximum. + if (wi::gt_p (r.lower_bound (), 0, TYPE_SIGN (r.type ()))) + { + maxi = prec - 1 - wi::floor_log2 (r.lower_bound ()); + if (mini == -2) + mini = 0; + } + else if (!range_includes_zero_p (&r)) { mini = 0; - maxi = newmaxi; + maxi = prec - 1; } - } - else if (!range_includes_zero_p (&r)) - { - maxi = prec - 1; - mini = 0; - } - if (mini == -2) - break; - // From clz of maximum we can compute result minimum. - if (r.constant_p ()) - { - int newmini = prec - 1 - wi::floor_log2 (r.upper_bound ()); - if (newmini == prec) + if (mini == -2) + break; + // From clz of maximum we can compute result minimum. + wide_int max = r.upper_bound (); + int newmini = prec - 1 - wi::floor_log2 (max); + if (max == 0) { - // Argument range is [0, 0]. If CLZ_DEFINED_VALUE_AT_ZERO - // is 2 with VALUE of prec, return [prec, prec], otherwise - // ignore the range. + // If CLZ_DEFINED_VALUE_AT_ZERO is 2 with VALUE of prec, + // return [prec, prec], otherwise ignore the range. if (maxi == prec) mini = prec; } @@ -1026,7 +1023,8 @@ fold_using_range::range_of_builtin_call (irange &r, gcall *call, src.get_operand (r, arg); if (!r.undefined_p ()) { - if (r.lower_bound () != 0) + // If arg is non-zero, then use [0, prec - 1]. + if (!range_includes_zero_p (&r)) { mini = 0; maxi = prec - 1; diff --git a/gcc/testsuite/gcc.dg/pr100790.c b/gcc/testsuite/gcc.dg/pr100790.c new file mode 100644 index 0000000..31e0eff --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr100790.c @@ -0,0 +1,4 @@ +// { dg-do compile } +// { dg-options "-O2 -w" } + +__builtin_clz(int x) { x ? __builtin_clz(x) : 32; } |