]> gcc.gnu.org Git - gcc.git/commitdiff
Cleanup clz and ctz code in range_of_builtin_call.
authorAldy Hernandez <aldyh@redhat.com>
Thu, 13 May 2021 17:47:41 +0000 (13:47 -0400)
committerAldy Hernandez <aldyh@redhat.com>
Thu, 17 Jun 2021 10:10:41 +0000 (12:10 +0200)
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.

gcc/gimple-range.cc
gcc/testsuite/gcc.dg/pr100790.c [new file with mode: 0644]

index 58109701f2f06d54745252fdb8e3c40418d40415..15c65f16a32844c83f20fcff8a58730743941d4d 100644 (file)
@@ -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 (file)
index 0000000..31e0eff
--- /dev/null
@@ -0,0 +1,4 @@
+// { dg-do compile }
+// { dg-options "-O2 -w" }
+
+__builtin_clz(int x) { x ? __builtin_clz(x) : 32; }
This page took 0.070175 seconds and 5 git commands to generate.