FWIW this is the last change I had planned.  I thought it would be easier
to do once the host_integerp replacement was in mainline, but that means
it's a bit closer to the deadline than it should have been.

The branch adds two new functions, cst_fits_uhwi_p and cst_fits_shwi_p,
alongside the tree_fits_* variants.  AFAICT, all cst_fits_uhwi_p tests
replace trunk tests of the form:

    TREE_CODE (x) == INTEGER_CST && TREE_INT_CST_HIGH (x) == 0

But this is the same as host_integerp (x, 1), now tree_fits_uhwi_p,
so I think we should just use that instead.  FWIW host_integerp was:

int
host_integerp (const_tree t, int pos)
{
  if (t == NULL_TREE)
    return 0;

  return (TREE_CODE (t) == INTEGER_CST
          && ((TREE_INT_CST_HIGH (t) == 0
               && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) >= 0)
              || (! pos && TREE_INT_CST_HIGH (t) == -1
                  && (HOST_WIDE_INT) TREE_INT_CST_LOW (t) < 0
                  && !TYPE_UNSIGNED (TREE_TYPE (t)))
              || (pos && TREE_INT_CST_HIGH (t) == 0)));
}

which if you fold in "pos = 1" reduces to current trunk's:

bool
tree_fits_uhwi_p (const_tree t)
{
  return (t != NULL_TREE
          && TREE_CODE (t) == INTEGER_CST
          && TREE_INT_CST_HIGH (t) == 0);
}

cst_fits_shwi_p replaces cst_and_fits_in_hwi, but if cst_fits_uhwi_p
goes away then I think we might as well stick with the original name.
(We're already keeping the associated extraction function, int_cst_value.)

I did a bit of wide-intification of write_integer_cst, which showed
up a missing conversion in the abs routine (my fault).

Tested on x86_64-linux-gnu.  OK for wide-int?

Thanks,
Richard


Index: gcc/ada/gcc-interface/utils.c
===================================================================
--- gcc/ada/gcc-interface/utils.c       2013-11-20 14:00:54.151599452 +0000
+++ gcc/ada/gcc-interface/utils.c       2013-11-20 15:29:17.483262547 +0000
@@ -6065,7 +6065,7 @@ handle_novops_attribute (tree *node, tre
 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
 {
   /* Verify the arg number is a constant.  */
-  if (!cst_fits_uhwi_p (arg_num_expr))
+  if (!tree_fits_uhwi_p (arg_num_expr))
     return false;
 
   *valp = TREE_INT_CST_LOW (arg_num_expr);
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c     2013-11-20 14:00:54.151599452 +0000
+++ gcc/c-family/c-common.c     2013-11-20 15:29:17.486262535 +0000
@@ -8768,7 +8768,7 @@ check_nonnull_arg (void * ARG_UNUSED (ct
 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
 {
   /* Verify the arg number is a small constant.  */
-  if (cst_fits_uhwi_p (arg_num_expr))
+  if (tree_fits_uhwi_p (arg_num_expr))
     {
       *valp = TREE_INT_CST_LOW (arg_num_expr);
       return true;
Index: gcc/c-family/c-format.c
===================================================================
--- gcc/c-family/c-format.c     2013-11-20 14:00:54.151599452 +0000
+++ gcc/c-family/c-format.c     2013-11-20 15:29:17.487262531 +0000
@@ -227,7 +227,7 @@ check_format_string (tree fntype, unsign
 static bool
 get_constant (tree expr, unsigned HOST_WIDE_INT *value, int validated_p)
 {
-  if (!cst_fits_uhwi_p (expr))
+  if (!tree_fits_uhwi_p (expr))
     {
       gcc_assert (!validated_p);
       return false;
Index: gcc/config/sol2-c.c
===================================================================
--- gcc/config/sol2-c.c 2013-11-20 14:00:54.151599452 +0000
+++ gcc/config/sol2-c.c 2013-11-20 15:29:17.433262746 +0000
@@ -96,7 +96,7 @@ solaris_pragma_align (cpp_reader *pfile
     }
 
   low = TREE_INT_CST_LOW (x);
-  if (!cst_fits_uhwi_p (x)
+  if (!tree_fits_uhwi_p (x)
       || (low != 1 && low != 2 && low != 4 && low != 8 && low != 16
          && low != 32 && low != 64 && low != 128))
     {
Index: gcc/cp/mangle.c
===================================================================
--- gcc/cp/mangle.c     2013-11-20 14:00:54.151599452 +0000
+++ gcc/cp/mangle.c     2013-11-20 15:29:17.434262742 +0000
@@ -1505,8 +1505,8 @@ write_number (unsigned HOST_WIDE_INT num
 write_integer_cst (const tree cst)
 {
   int sign = tree_int_cst_sgn (cst);
-
-  if (!cst_fits_shwi_p (cst))
+  widest_int abs_value = wi::abs (wi::to_widest (cst));
+  if (!wi::fits_uhwi_p (abs_value))
     {
       /* A bignum. We do this in chunks, each of which fits in a
         HOST_WIDE_INT.  */
@@ -1559,14 +1559,9 @@ write_integer_cst (const tree cst)
   else
     {
       /* A small num.  */
-      unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
-
       if (sign < 0)
-       {
-         write_char ('n');
-         low = -low;
-       }
-      write_unsigned_number (low);
+       write_char ('n');
+      write_unsigned_number (abs_value.to_uhwi ());
     }
 }
 
Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c     2013-11-20 15:27:30.843688771 +0000
+++ gcc/dwarf2out.c     2013-11-20 15:29:17.438262726 +0000
@@ -16353,8 +16353,7 @@ add_bound_info (dw_die_ref subrange_die,
            add_AT_unsigned (subrange_die, bound_attr,
                             TREE_INT_CST_LOW (bound) & mask);
          }
-       else if (prec == HOST_BITS_PER_WIDE_INT
-                || (cst_fits_uhwi_p (bound) && wi::ges_p (bound, 0)))
+       else if (prec == HOST_BITS_PER_WIDE_INT || tree_fits_uhwi_p (bound))
          add_AT_unsigned (subrange_die, bound_attr,
                           TREE_INT_CST_LOW (bound));
        else
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c    2013-11-20 15:27:30.844688767 +0000
+++ gcc/fold-const.c    2013-11-20 15:29:17.440262718 +0000
@@ -16822,7 +16822,7 @@ ptr_difference_const (tree e1, tree e2,
        toffset2 = fold_convert (type, toffset2);
 
       tdiff = fold_build2 (MINUS_EXPR, type, toffset1, toffset2);
-      if (!cst_fits_shwi_p (tdiff))
+      if (!cst_and_fits_in_hwi (tdiff))
        return false;
 
       *diff = int_cst_value (tdiff);
Index: gcc/fortran/trans-const.c
===================================================================
--- gcc/fortran/trans-const.c   2013-11-20 14:00:54.151599452 +0000
+++ gcc/fortran/trans-const.c   2013-11-20 15:29:17.487262531 +0000
@@ -146,7 +146,7 @@ gfc_conv_string_init (tree length, gfc_e
 
   gcc_assert (expr->expr_type == EXPR_CONSTANT);
   gcc_assert (expr->ts.type == BT_CHARACTER);
-  gcc_assert (cst_fits_uhwi_p (length));
+  gcc_assert (tree_fits_uhwi_p (length));
 
   len = TREE_INT_CST_LOW (length);
   slen = expr->value.character.length;
Index: gcc/fortran/trans-decl.c
===================================================================
--- gcc/fortran/trans-decl.c    2013-11-20 14:00:54.151599452 +0000
+++ gcc/fortran/trans-decl.c    2013-11-20 15:29:17.441262714 +0000
@@ -409,7 +409,7 @@ gfc_can_put_var_on_stack (tree size)
   if (gfc_option.flag_max_stack_var_size < 0)
     return 1;
 
-  if (!cst_fits_uhwi_p (size))
+  if (!tree_fits_uhwi_p (size))
     return 0;
 
   low = TREE_INT_CST_LOW (size);
Index: gcc/fortran/trans-expr.c
===================================================================
--- gcc/fortran/trans-expr.c    2013-11-20 15:27:30.851688739 +0000
+++ gcc/fortran/trans-expr.c    2013-11-20 15:29:17.474262582 +0000
@@ -2629,7 +2629,7 @@ gfc_string_to_single_character (tree len
 {
 
   if (len == NULL
-      || !cst_fits_uhwi_p (len)
+      || !tree_fits_uhwi_p (len)
       || !POINTER_TYPE_P (TREE_TYPE (str)))
     return NULL_TREE;
 
Index: gcc/go/go-gcc.cc
===================================================================
--- gcc/go/go-gcc.cc    2013-11-20 14:00:54.151599452 +0000
+++ gcc/go/go-gcc.cc    2013-11-20 15:29:17.488262527 +0000
@@ -830,7 +830,7 @@ Gcc_backend::type_size(Btype* btype)
   if (t == error_mark_node)
     return 1;
   t = TYPE_SIZE_UNIT(t);
-  gcc_assert(cst_fits_uhwi_p (t));
+  gcc_assert(tree_fits_uhwi_p (t));
   unsigned HOST_WIDE_INT val_wide = TREE_INT_CST_LOW (t);
   size_t ret = static_cast<size_t>(val_wide);
   gcc_assert(ret == val_wide);
Index: gcc/lto/lto-lang.c
===================================================================
--- gcc/lto/lto-lang.c  2013-11-20 14:00:54.151599452 +0000
+++ gcc/lto/lto-lang.c  2013-11-20 15:29:17.475262578 +0000
@@ -318,7 +318,7 @@ handle_novops_attribute (tree *node, tre
 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
 {
   /* Verify the arg number is a constant.  */
-  if (!cst_fits_uhwi_p (arg_num_expr))
+  if (!tree_fits_uhwi_p (arg_num_expr))
     return false;
 
   *valp = TREE_INT_CST_LOW (arg_num_expr);
Index: gcc/tree-ssa-loop-ivopts.c
===================================================================
--- gcc/tree-ssa-loop-ivopts.c  2013-11-20 14:00:54.151599452 +0000
+++ gcc/tree-ssa-loop-ivopts.c  2013-11-20 15:29:17.480262559 +0000
@@ -2065,7 +2065,7 @@ strip_offset_1 (tree expr, bool inside_a
   switch (code)
     {
     case INTEGER_CST:
-      if (!cst_fits_shwi_p (expr)
+      if (!cst_and_fits_in_hwi (expr)
          || integer_zerop (expr))
        return orig_expr;
 
@@ -2102,7 +2102,7 @@ strip_offset_1 (tree expr, bool inside_a
 
     case MULT_EXPR:
       op1 = TREE_OPERAND (expr, 1);
-      if (!cst_fits_shwi_p (op1))
+      if (!cst_and_fits_in_hwi (op1))
        return orig_expr;
 
       op0 = TREE_OPERAND (expr, 0);
@@ -2124,7 +2124,7 @@ strip_offset_1 (tree expr, bool inside_a
        return orig_expr;
 
       step = array_ref_element_size (expr);
-      if (!cst_fits_shwi_p (step))
+      if (!cst_and_fits_in_hwi (step))
        break;
 
       st = int_cst_value (step);
@@ -2153,8 +2153,8 @@ strip_offset_1 (tree expr, bool inside_a
        tmp = component_ref_field_offset (expr);
        field = TREE_OPERAND (expr, 1);
        if (top_compref
-           && cst_fits_shwi_p (tmp)
-           && cst_fits_shwi_p (DECL_FIELD_BIT_OFFSET (field)))
+           && cst_and_fits_in_hwi (tmp)
+           && cst_and_fits_in_hwi (DECL_FIELD_BIT_OFFSET (field)))
          {
            HOST_WIDE_INT boffset, abs_off;
 
@@ -2417,7 +2417,7 @@ add_autoinc_candidates (struct ivopts_da
   if (use_bb->loop_father != data->current_loop
       || !dominated_by_p (CDI_DOMINATORS, data->current_loop->latch, use_bb)
       || stmt_could_throw_p (use->stmt)
-      || !cst_fits_shwi_p (step))
+      || !cst_and_fits_in_hwi (step))
     return;
 
   cstepi = int_cst_value (step);
@@ -3698,7 +3698,7 @@ force_expr_to_var_cost (tree expr, bool
             mult = op0;
 
           if (mult != NULL_TREE
-              && cst_fits_shwi_p (TREE_OPERAND (mult, 1))
+              && cst_and_fits_in_hwi (TREE_OPERAND (mult, 1))
               && get_shiftadd_cost (expr, mode, cost0, cost1, mult,
                                     speed, &sa_cost))
             return sa_cost;
@@ -3716,10 +3716,10 @@ force_expr_to_var_cost (tree expr, bool
       break;
 
     case MULT_EXPR:
-      if (cst_fits_shwi_p (op0))
+      if (cst_and_fits_in_hwi (op0))
        cost = new_cost (mult_by_coeff_cost (int_cst_value (op0),
                                             mode, speed), 0);
-      else if (cst_fits_shwi_p (op1))
+      else if (cst_and_fits_in_hwi (op1))
        cost = new_cost (mult_by_coeff_cost (int_cst_value (op1),
                                             mode, speed), 0);
       else
@@ -4119,7 +4119,7 @@ get_computation_cost_at (struct ivopts_d
      redundancy elimination is likely to transform the code so that
      it uses value of the variable before increment anyway,
      so it is not that much unrealistic.  */
-  if (cst_fits_shwi_p (cstep))
+  if (cst_and_fits_in_hwi (cstep))
     cstepi = int_cst_value (cstep);
   else
     cstepi = 0;
@@ -4144,7 +4144,7 @@ get_computation_cost_at (struct ivopts_d
 
      (also holds in the case ratio == -1, TODO.  */
 
-  if (cst_fits_shwi_p (cbase))
+  if (cst_and_fits_in_hwi (cbase))
     {
       offset = - ratio * int_cst_value (cbase);
       cost = difference_cost (data,
@@ -4597,7 +4597,7 @@ iv_elimination_compare_lt (struct ivopts
 
   /* We need to be able to decide whether candidate is increasing or decreasing
      in order to choose the right comparison operator.  */
-  if (!cst_fits_shwi_p (cand->iv->step))
+  if (!cst_and_fits_in_hwi (cand->iv->step))
     return false;
   step = int_cst_value (cand->iv->step);
 
Index: gcc/tree-ssa-loop-niter.c
===================================================================
--- gcc/tree-ssa-loop-niter.c   2013-11-20 14:00:54.151599452 +0000
+++ gcc/tree-ssa-loop-niter.c   2013-11-20 15:29:17.481262555 +0000
@@ -579,8 +579,8 @@ inverse (tree x, tree mask)
       unsigned HOST_WIDE_INT imask;
       unsigned HOST_WIDE_INT irslt = 1;
 
-      gcc_assert (cst_fits_shwi_p (x));
-      gcc_assert (cst_fits_shwi_p (mask));
+      gcc_assert (cst_and_fits_in_hwi (x));
+      gcc_assert (cst_and_fits_in_hwi (mask));
 
       ix = int_cst_value (x);
       imask = int_cst_value (mask);
Index: gcc/tree-ssa-loop-prefetch.c
===================================================================
--- gcc/tree-ssa-loop-prefetch.c        2013-11-20 14:00:54.151599452 +0000
+++ gcc/tree-ssa-loop-prefetch.c        2013-11-20 15:29:17.482262551 +0000
@@ -295,7 +295,7 @@ dump_mem_details (FILE *file, tree base,
   fprintf (file, "(base ");
   print_generic_expr (file, base, TDF_SLIM);
   fprintf (file, ", step ");
-  if (cst_fits_shwi_p (step))
+  if (cst_and_fits_in_hwi (step))
     fprintf (file, HOST_WIDE_INT_PRINT_DEC, int_cst_value (step));
   else
     print_generic_expr (file, step, TDF_TREE);
@@ -336,7 +336,7 @@ find_or_create_group (struct mem_ref_gro
 
       /* If step is an integer constant, keep the list of groups sorted
          by decreasing step.  */
-        if (cst_fits_shwi_p ((*groups)->step) && cst_fits_shwi_p (step)
+        if (cst_and_fits_in_hwi ((*groups)->step) && cst_and_fits_in_hwi (step)
             && int_cst_value ((*groups)->step) < int_cst_value (step))
        break;
     }
@@ -444,12 +444,12 @@ idx_analyze_ref (tree base, tree *index,
   step = iv.step;
 
   if (TREE_CODE (ibase) == POINTER_PLUS_EXPR
-      && cst_fits_shwi_p (TREE_OPERAND (ibase, 1)))
+      && cst_and_fits_in_hwi (TREE_OPERAND (ibase, 1)))
     {
       idelta = int_cst_value (TREE_OPERAND (ibase, 1));
       ibase = TREE_OPERAND (ibase, 0);
     }
-  if (cst_fits_shwi_p (ibase))
+  if (cst_and_fits_in_hwi (ibase))
     {
       idelta += int_cst_value (ibase);
       ibase = build_int_cst (TREE_TYPE (ibase), 0);
@@ -458,7 +458,7 @@ idx_analyze_ref (tree base, tree *index,
   if (TREE_CODE (base) == ARRAY_REF)
     {
       stepsize = array_ref_element_size (base);
-      if (!cst_fits_shwi_p (stepsize))
+      if (!cst_and_fits_in_hwi (stepsize))
        return false;
       imult = int_cst_value (stepsize);
       step = fold_build2 (MULT_EXPR, sizetype,
@@ -556,7 +556,7 @@ gather_memory_references_ref (struct loo
 
   /* Limit non-constant step prefetching only to the innermost loops and 
      only when the step is loop invariant in the entire loop nest. */
-  if (!cst_fits_shwi_p (step))
+  if (!cst_and_fits_in_hwi (step))
     {
       if (loop->inner != NULL)
         {
@@ -670,7 +670,7 @@ prune_ref_by_self_reuse (struct mem_ref
   bool backward;
 
   /* If the step size is non constant, we cannot calculate prefetch_mod.  */
-  if (!cst_fits_shwi_p (ref->group->step))
+  if (!cst_and_fits_in_hwi (ref->group->step))
     return;
 
   step = int_cst_value (ref->group->step);
@@ -780,7 +780,7 @@ prune_ref_by_group_reuse (struct mem_ref
   int align_unit;
 
   /* If the step is non constant we cannot calculate prefetch_before.  */
-  if (!cst_fits_shwi_p (ref->group->step)) {
+  if (!cst_and_fits_in_hwi (ref->group->step)) {
     return;
   }
 
@@ -1145,7 +1145,7 @@ issue_prefetch_ref (struct mem_ref *ref,
 
   for (ap = 0; ap < n_prefetches; ap++)
     {
-      if (cst_fits_shwi_p (ref->group->step))
+      if (cst_and_fits_in_hwi (ref->group->step))
         {
           /* Determine the address to prefetch.  */
           delta = (ahead + ap * ref->prefetch_mod) *
Index: gcc/tree.c
===================================================================
--- gcc/tree.c  2013-11-20 15:27:30.848688751 +0000
+++ gcc/tree.c  2013-11-20 15:29:17.478262567 +0000
@@ -1474,6 +1474,21 @@ build_low_bits_mask (tree type, unsigned
                                           TYPE_PRECISION (type)));
 }
 
+/* Checks that X is integer constant that can be expressed in (unsigned)
+   HOST_WIDE_INT without loss of precision.  */
+
+bool
+cst_and_fits_in_hwi (const_tree x)
+{
+  if (TREE_CODE (x) != INTEGER_CST)
+    return false;
+
+  if (TYPE_PRECISION (TREE_TYPE (x)) > HOST_BITS_PER_WIDE_INT)
+    return false;
+
+  return TREE_INT_CST_NUNITS (x) == 1;
+}
+
 /* Build a newly constructed TREE_VEC node of length LEN.  */
 
 tree
@@ -2669,7 +2684,7 @@ int_size_in_bytes (const_tree type)
   type = TYPE_MAIN_VARIANT (type);
   t = TYPE_SIZE_UNIT (type);
 
-  if (t && cst_fits_uhwi_p (t))
+  if (t && tree_fits_uhwi_p (t))
     return TREE_INT_CST_LOW (t);
   else
     return -1;
@@ -7235,7 +7250,7 @@ compare_tree_int (const_tree t, unsigned
 {
   if (tree_int_cst_sgn (t) < 0)
     return -1;
-  else if (!cst_fits_uhwi_p (t))
+  else if (!tree_fits_uhwi_p (t))
     return 1;
   else if (TREE_INT_CST_LOW (t) == u)
     return 0;
@@ -10473,7 +10488,7 @@ int_cst_value (const_tree x)
   unsigned HOST_WIDE_INT val = TREE_INT_CST_LOW (x);
 
   /* Make sure the sign-extended value will fit in a HOST_WIDE_INT.  */
-  gcc_assert (cst_fits_shwi_p (x));
+  gcc_assert (cst_and_fits_in_hwi (x));
 
   if (bits < HOST_BITS_PER_WIDE_INT)
     {
Index: gcc/tree.h
===================================================================
--- gcc/tree.h  2013-11-20 15:27:30.849688747 +0000
+++ gcc/tree.h  2013-11-20 15:29:17.479262563 +0000
@@ -3149,34 +3149,6 @@ omp_clause_elt_check (const_tree __t, in
 
 #endif
 
-/* Checks that X is an integer constant that can be expressed in a signed
-   HOST_WIDE_INT without loss of precision.  This function differs from
-   the tree_fits_* versions in that the signedness of the type of X is
-   not considered.  */
-
-static inline bool
-cst_fits_shwi_p (const_tree x)
-{
-  if (TREE_CODE (x) != INTEGER_CST)
-    return false;
-
-  return TREE_INT_CST_NUNITS (x) == 1;
-}
-
-/* Checks that X is an integer constant that can be expressed in an unsigned
-   HOST_WIDE_INT without loss of precision.  This function differs from
-   the tree_fits_* versions in that the signedness of the type of X is
-   not considered.  */
-
-static inline bool
-cst_fits_uhwi_p (const_tree x)
-{
-  if (TREE_CODE (x) != INTEGER_CST)
-    return false;
-
-  return TREE_INT_CST_NUNITS (x) == 1 && TREE_INT_CST_ELT (x, 0) >= 0;
-}
-
 /* Compute the number of operands in an expression node NODE.  For
    tcc_vl_exp nodes like CALL_EXPRs, this is stored in the node itself,
    otherwise it is looked up from the node's code.  */
@@ -3942,6 +3914,7 @@ extern int integer_pow2p (const_tree);
 
 extern int integer_nonzerop (const_tree);
 
+extern bool cst_and_fits_in_hwi (const_tree);
 extern tree num_ending_zeros (const_tree);
 
 /* fixed_zerop (tree x) is nonzero if X is a fixed-point constant of
Index: gcc/wide-int.h
===================================================================
--- gcc/wide-int.h      2013-11-20 14:00:54.151599452 +0000
+++ gcc/wide-int.h      2013-11-20 15:29:17.488262527 +0000
@@ -1775,7 +1775,7 @@ wi::neg (const T &x, bool *overflow)
 inline WI_UNARY_RESULT (T)
 wi::abs (const T &x)
 {
-  return neg_p (x) ? neg (x) : x;
+  return neg_p (x) ? neg (x) : WI_UNARY_RESULT (T) (x);
 }
 
 /* Return the result of sign-extending the low OFFSET bits of X.  */

Reply via email to