The tree wi:: decompose routine wasn't asserting that the requested
precision matched the tree's precision.  This could make a difference
for unsigned trees that are exactly N HWIs wide and that have the upper
bit set, since we then need an extra zero HWI when extending it to wider
precisions (as for wi::to_widest).

This patch adds the assert and fixes the fallout shown by the testsuite.
Go seems to be unaffected.

Other fixed-precision decompose routines already had an assert.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu.
Also tested by comparing the testsuite assembly output on at least one
target per CPU directory.  OK to install?

Richard


2017-10-01  Richard Sandiford  <richard.sandif...@linaro.org>

gcc/
        * tree.h (wi::int_traits <const_tree>::decompose): Assert that the
        requested precision matches the type's.
        * calls.c (alloc_max_size): Calculate the new candidate size as
        a widest_int and use wi::to_widest when comparing it with the
        current candidate size.
        * gimple-ssa-warn-alloca.c (pass_walloca::execute): Compare with
        zero rather than integer_zero_node.
        * match.pd: Check for a no-op conversion before using wi::add
        rather than after.  Use tree_to_uhwi when summing small shift
        counts into an unsigned int.

gcc/c-family/
        * c-warn.c (warn_tautological_bitwise_comparison): Use wi::to_widest
        when combining the original unconverted comparison operands.

gcc/cp/
        * constexpr.c (cxx_eval_store_expression): Use wi::to_widest
        when comparing the array bounds with an ARRAY_REF index.

gcc/ada/
        * gcc-interface/decl.c (annotate_value): Use wi::to_widest when
        handling the form (plus/mult (convert @0) @1).

Index: gcc/tree.h
===================================================================
--- gcc/tree.h  2017-09-25 13:33:39.989814299 +0100
+++ gcc/tree.h  2017-10-01 17:08:55.827120507 +0100
@@ -5176,6 +5176,7 @@ wi::int_traits <const_tree>::get_precisi
 wi::int_traits <const_tree>::decompose (HOST_WIDE_INT *,
                                        unsigned int precision, const_tree x)
 {
+  gcc_checking_assert (precision == TYPE_PRECISION (TREE_TYPE (x)));
   return wi::storage_ref (&TREE_INT_CST_ELT (x, 0), TREE_INT_CST_NUNITS (x),
                          precision);
 }
Index: gcc/calls.c
===================================================================
--- gcc/calls.c 2017-09-21 12:13:48.336399601 +0100
+++ gcc/calls.c 2017-10-01 17:08:55.825112782 +0100
@@ -1252,9 +1252,8 @@ alloc_max_size (void)
 
              if (unit)
                {
-                 wide_int w = wi::uhwi (limit, HOST_BITS_PER_WIDE_INT + 64);
-                 w *= unit;
-                 if (wi::ltu_p (w, alloc_object_size_limit))
+                 widest_int w = wi::mul (limit, unit);
+                 if (w < wi::to_widest (alloc_object_size_limit))
                    alloc_object_size_limit = wide_int_to_tree (ssizetype, w);
                }
            }
Index: gcc/gimple-ssa-warn-alloca.c
===================================================================
--- gcc/gimple-ssa-warn-alloca.c        2017-03-28 16:19:28.000000000 +0100
+++ gcc/gimple-ssa-warn-alloca.c        2017-10-01 17:08:55.826116645 +0100
@@ -491,7 +491,7 @@ pass_walloca::execute (function *fun)
                              is_vla ? G_("argument to variable-length array "
                                          "may be too large")
                              : G_("argument to %<alloca%> may be too large"))
-                 && t.limit != integer_zero_node)
+                 && t.limit != 0)
                {
                  print_decu (t.limit, buff);
                  inform (loc, G_("limit is %u bytes, but argument "
@@ -504,7 +504,7 @@ pass_walloca::execute (function *fun)
                              is_vla ? G_("argument to variable-length array "
                                          "is too large")
                              : G_("argument to %<alloca%> is too large"))
-                 && t.limit != integer_zero_node)
+                 && t.limit != 0)
                {
                  print_decu (t.limit, buff);
                  inform (loc, G_("limit is %u bytes, but argument is %s"),
Index: gcc/match.pd
===================================================================
--- gcc/match.pd        2017-09-25 13:57:11.698158636 +0100
+++ gcc/match.pd        2017-10-01 17:08:55.827120507 +0100
@@ -358,8 +358,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
   (div (convert? (bit_and @0 INTEGER_CST@1)) INTEGER_CST@2)
   (if (integer_pow2p (@2)
        && tree_int_cst_sgn (@2) > 0
-       && wi::add (@2, @1) == 0
-       && tree_nop_conversion_p (type, TREE_TYPE (@0)))
+       && tree_nop_conversion_p (type, TREE_TYPE (@0))
+       && wi::add (@2, @1) == 0)
    (rshift (convert @0) { build_int_cst (integer_type_node,
                                         wi::exact_log2 (@2)); }))))
 
@@ -1871,7 +1871,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
         && wi::lt_p (@1, prec, TYPE_SIGN (TREE_TYPE (@1)))
         && wi::ge_p (@2, 0, TYPE_SIGN (TREE_TYPE (@2)))
        && wi::lt_p (@2, prec, TYPE_SIGN (TREE_TYPE (@2))))
-    (with { unsigned int low = wi::add (@1, @2).to_uhwi (); }
+    (with { unsigned int low = (tree_to_uhwi (@1)
+                               + tree_to_uhwi (@2)); }
      /* Deal with a OP (c1 + c2) being undefined but (a OP c1) OP c2
         being well defined.  */
      (if (low >= prec)
Index: gcc/c-family/c-warn.c
===================================================================
--- gcc/c-family/c-warn.c       2017-09-05 20:55:56.402037612 +0100
+++ gcc/c-family/c-warn.c       2017-10-01 17:08:55.824108920 +0100
@@ -355,15 +355,17 @@ warn_tautological_bitwise_comparison (lo
   else
     return;
 
-  wide_int res;
+  /* Note that the two operands are from before the usual integer
+     conversions, so their types might not be the same.  */
+  widest_int res;
   if (TREE_CODE (bitop) == BIT_AND_EXPR)
-    res = wi::bit_and (bitopcst, cst);
+    res = wi::to_widest (bitopcst) & wi::to_widest (cst);
   else
-    res = wi::bit_or (bitopcst, cst);
+    res = wi::to_widest (bitopcst) | wi::to_widest (cst);
 
   /* For BIT_AND only warn if (CST2 & CST1) != CST1, and
      for BIT_OR only if (CST2 | CST1) != CST1.  */
-  if (res == cst)
+  if (res == wi::to_widest (cst))
     return;
 
   if (code == EQ_EXPR)
Index: gcc/cp/constexpr.c
===================================================================
--- gcc/cp/constexpr.c  2017-09-16 21:38:21.073925724 +0100
+++ gcc/cp/constexpr.c  2017-10-01 17:08:55.826116645 +0100
@@ -3379,7 +3379,7 @@ cxx_eval_store_expression (const constex
          VERIFY_CONSTANT (nelts);
          gcc_assert (TREE_CODE (nelts) == INTEGER_CST
                      && TREE_CODE (TREE_OPERAND (probe, 1)) == INTEGER_CST);
-         if (wi::eq_p (TREE_OPERAND (probe, 1), nelts))
+         if (wi::to_widest (TREE_OPERAND (probe, 1)) == wi::to_widest (nelts))
            {
              diag_array_subscript (ctx, ary, TREE_OPERAND (probe, 1));
              *non_constant_p = true;
Index: gcc/ada/gcc-interface/decl.c
===================================================================
--- gcc/ada/gcc-interface/decl.c        2017-09-11 17:10:55.549140040 +0100
+++ gcc/ada/gcc-interface/decl.c        2017-10-01 17:08:55.823105057 +0100
@@ -8153,11 +8153,13 @@ annotate_value (tree gnu_size)
            {
              tree inner_op_op1 = TREE_OPERAND (inner_op, 1);
              tree gnu_size_op1 = TREE_OPERAND (gnu_size, 1);
-             wide_int op1;
+             widest_int op1;
              if (TREE_CODE (gnu_size) == MULT_EXPR)
-               op1 = wi::mul (inner_op_op1, gnu_size_op1);
+               op1 = (wi::to_widest (inner_op_op1)
+                      * wi::to_widest (gnu_size_op1));
              else
-               op1 = wi::add (inner_op_op1, gnu_size_op1);
+               op1 = (wi::to_widest (inner_op_op1)
+                      + wi::to_widest (gnu_size_op1));
              ops[1] = UI_From_gnu (wide_int_to_tree (sizetype, op1));
              ops[0] = annotate_value (TREE_OPERAND (inner_op, 0));
            }

Reply via email to