Hi!

My recent change broke Linux kernel build, where we ICE in get_nonzero_bits
which apparently assumes it must be called only on INTEGER_CSTs or
SSA_NAMEs, while during generic folding it can be called say with PLUS_EXPR
etc.

tree_nonzero_bits apparently can be called on any tree code, as it has the
return -1 fallback, but it doesn't really handle vector types, because it
uses TYPE_PRECISION instead of element_precision.
get_nonzero_bits also doesn't do anything useful for vector types,
INTEGER_CSTs aren't vectors and vector type SSA_NAMEs won't really have
range info (though, uses element_precision).  In theory for VECTOR_CSTs we
could or in get_nonzero_bits from all elements together or something
similar, but still for SSA_NAMEs as we don't track anything it won't be
useful, so this patch just punts on vector types if there is a widening
conversion from signed.  After all, a widening conversion for vectors
wouldn't be really a conversion, but VEC_UNPACK_{LO,HI}_EXPR.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2019-09-11  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/91725
        * match.pd ((A / (1 << B)) -> (A >> B)): Call tree_nonzero_bits instead
        of get_nonzero_bits, only call it for integral types.

        * gcc.c-torture/compile/pr91725.c: New test.

--- gcc/match.pd.jj     2019-09-10 10:13:29.723000308 +0200
+++ gcc/match.pd        2019-09-10 20:14:06.164054126 +0200
@@ -325,9 +325,11 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
              && (TYPE_UNSIGNED (TREE_TYPE (@1))
                  || (element_precision (type)
                      == element_precision (TREE_TYPE (@1)))
-                 || (get_nonzero_bits (@0)
-                     & wi::mask (element_precision (TREE_TYPE (@1)) - 1, true,
-                                 element_precision (type))) == 0))))
+                 || (INTEGRAL_TYPE_P (type)
+                     && (tree_nonzero_bits (@0)
+                         & wi::mask (element_precision (TREE_TYPE (@1)) - 1,
+                                     true,
+                                     element_precision (type))) == 0)))))
   (rshift @0 @2)))
 
 /* Preserve explicit divisions by 0: the C++ front-end wants to detect
--- gcc/testsuite/gcc.c-torture/compile/pr91725.c.jj    2019-09-10 
20:09:39.499987576 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr91725.c       2019-09-10 
20:08:21.302141038 +0200
@@ -0,0 +1,7 @@
+/* PR middle-end/91725 */
+
+unsigned long long
+foo (unsigned long long x, unsigned long long y, int z)
+{
+  return (x + y) / (1 << z);
+}

        Jakub

Reply via email to