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