Patchwork [wide-int] Remove cst_fits_*

login
register
mail settings
Submitter Richard Sandiford
Date Nov. 20, 2013, 3:31 p.m.
Message ID <87y54jf5sv.fsf@sandifor-thinkpad.stglab.manchester.uk.ibm.com>
Download mbox | patch
Permalink /patch/292802/
State New
Headers show

Comments

Richard Sandiford - Nov. 20, 2013, 3:31 p.m.
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
Mike Stump - Nov. 20, 2013, 7:01 p.m.
On Nov 20, 2013, at 7:31 AM, Richard Sandiford <rsandifo@linux.vnet.ibm.com> wrote:
> 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.

So the entire patch seems fine, except for one hunk I'll punt to Kenny to weigh in and those are the changes of the form:

-      if (!cst_fits_shwi_p (tdiff))
+      if (!cst_and_fits_in_hwi (tiff))

Patch

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.  */