aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAldy Hernandez <aldyh@redhat.com>2021-05-13 13:47:41 -0400
committerAldy Hernandez <aldyh@redhat.com>2021-06-17 12:10:41 +0200
commitf1555d4013ed3cae2589270436387063d1c2f1a3 (patch)
treece352c9735b2095b6952b2b84a660240dd8be3b8 /gcc
parent8eac92a07e386301f7b09f7ef6146e6e3ac6b6cd (diff)
downloadgcc-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.cc42
-rw-r--r--gcc/testsuite/gcc.dg/pr100790.c4
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; }