@@ -58,6 +58,9 @@ typedef const struct rtx_def *const_rtx;
struct rtvec_def;
typedef struct rtvec_def *rtvec;
typedef const struct rtvec_def *const_rtvec;
+struct hwivec_def;
+typedef struct hwivec_def *hwivec;
+typedef const struct hwivec_def *const_hwivec;
union tree_node;
typedef union tree_node *tree;
typedef const union tree_node *const_tree;
@@ -692,88 +692,39 @@ stabstr_U (unsigned HOST_WIDE_INT num)
static void
stabstr_O (tree cst)
{
- unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (cst);
- unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
-
- char buf[128];
- char *p = buf + sizeof buf;
-
- /* GDB wants constants with no extra leading "1" bits, so
- we need to remove any sign-extension that might be
- present. */
- {
- const unsigned int width = TYPE_PRECISION (TREE_TYPE (cst));
- if (width == HOST_BITS_PER_DOUBLE_INT)
- ;
- else if (width > HOST_BITS_PER_WIDE_INT)
- high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);
- else if (width == HOST_BITS_PER_WIDE_INT)
- high = 0;
- else
- high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
- }
+ int prec = TYPE_PRECISION (TREE_TYPE (cst));
+ int res_pres = prec % 3;
+ int i;
+ unsigned int digit;
/* Leading zero for base indicator. */
stabstr_C ('0');
/* If the value is zero, the base indicator will serve as the value
all by itself. */
- if (high == 0 && low == 0)
+ if (wi::eq_p (cst, 0))
return;
- /* If the high half is zero, we need only print the low half normally. */
- if (high == 0)
- NUMBER_FMT_LOOP (p, low, 8);
- else
+ /* GDB wants constants with no extra leading "1" bits, so
+ we need to remove any sign-extension that might be
+ present. */
+ if (res_pres == 1)
{
- /* When high != 0, we need to print enough zeroes from low to
- give the digits from high their proper place-values. Hence
- NUMBER_FMT_LOOP cannot be used. */
- const int n_digits = HOST_BITS_PER_WIDE_INT / 3;
- int i;
-
- for (i = 1; i <= n_digits; i++)
- {
- unsigned int digit = low % 8;
- low /= 8;
- *--p = '0' + digit;
- }
-
- /* Octal digits carry exactly three bits of information. The
- width of a HOST_WIDE_INT is not normally a multiple of three.
- Therefore, the next digit printed probably needs to carry
- information from both low and high. */
- if (HOST_BITS_PER_WIDE_INT % 3 != 0)
- {
- const int n_leftover_bits = HOST_BITS_PER_WIDE_INT % 3;
- const int n_bits_from_high = 3 - n_leftover_bits;
-
- const unsigned HOST_WIDE_INT
- low_mask = (((unsigned HOST_WIDE_INT)1) << n_leftover_bits) - 1;
- const unsigned HOST_WIDE_INT
- high_mask = (((unsigned HOST_WIDE_INT)1) << n_bits_from_high) - 1;
-
- unsigned int digit;
-
- /* At this point, only the bottom n_leftover_bits bits of low
- should be set. */
- gcc_assert (!(low & ~low_mask));
-
- digit = (low | ((high & high_mask) << n_leftover_bits));
- high >>= n_bits_from_high;
-
- *--p = '0' + digit;
- }
-
- /* Now we can format high in the normal manner. However, if
- the only bits of high that were set were handled by the
- digit split between low and high, high will now be zero, and
- we don't want to print extra digits in that case. */
- if (high)
- NUMBER_FMT_LOOP (p, high, 8);
+ digit = wi::extract_uhwi (cst, prec - 1, 1);
+ stabstr_C ('0' + digit);
+ }
+ else if (res_pres == 2)
+ {
+ digit = wi::extract_uhwi (cst, prec - 2, 2);
+ stabstr_C ('0' + digit);
}
- obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
+ prec -= res_pres;
+ for (i = prec - 3; i <= 0; i = i - 3)
+ {
+ digit = wi::extract_uhwi (cst, i, 3);
+ stabstr_C ('0' + digit);
+ }
}
/* Called whenever it is safe to break a stabs string into multiple
@@ -2301,10 +2252,7 @@ dbxout_type (tree type, int full)
if (TREE_CODE (value) == CONST_DECL)
value = DECL_INITIAL (value);
- if (TREE_INT_CST_HIGH (value) == 0)
- stabstr_D (TREE_INT_CST_LOW (value));
- else if (TREE_INT_CST_HIGH (value) == -1
- && (HOST_WIDE_INT) TREE_INT_CST_LOW (value) < 0)
+ if (cst_and_fits_in_hwi (value))
stabstr_D (TREE_INT_CST_LOW (value));
else
stabstr_O (value);
@@ -1392,6 +1392,14 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define SWITCHABLE_TARGET 0
#endif
+/* If the target supports integers that are wider than two
+ HOST_WIDE_INTs on the host compiler, then the target should define
+ TARGET_SUPPORTS_WIDE_INT and make the appropriate fixups.
+ Otherwise the compiler really is not robust. */
+#ifndef TARGET_SUPPORTS_WIDE_INT
+#define TARGET_SUPPORTS_WIDE_INT 0
+#endif
+
#endif /* GCC_INSN_FLAGS_H */
#endif /* ! GCC_DEFAULTS_H */
@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see
#ifndef DOUBLE_INT_H
#define DOUBLE_INT_H
+#include "wide-int.h"
+
/* A large integer is currently represented as a pair of HOST_WIDE_INTs.
It therefore represents a number with precision of
2 * HOST_BITS_PER_WIDE_INT bits (it is however possible that the
@@ -435,4 +437,36 @@ void mpz_set_double_int (mpz_t, double_int, bool);
double_int mpz_get_double_int (const_tree, mpz_t, bool);
#endif
+namespace wi
+{
+ template <>
+ struct int_traits <double_int>
+ {
+ static const enum precision_type precision_type = CONST_PRECISION;
+ static const bool host_dependent_precision = true;
+ static const unsigned int precision = HOST_BITS_PER_DOUBLE_INT;
+ static unsigned int get_precision (const double_int &);
+ static wi::storage_ref decompose (HOST_WIDE_INT *, unsigned int,
+ const double_int &);
+ };
+}
+
+inline unsigned int
+wi::int_traits <double_int>::get_precision (const double_int &)
+{
+ return precision;
+}
+
+inline wi::storage_ref
+wi::int_traits <double_int>::decompose (HOST_WIDE_INT *scratch, unsigned int p,
+ const double_int &x)
+{
+ gcc_checking_assert (precision == p);
+ scratch[0] = x.low;
+ if ((x.high == 0 && scratch[0] >= 0) || (x.high == -1 && scratch[0] < 0))
+ return wi::storage_ref (scratch, 1, precision);
+ scratch[1] = x.high;
+ return wi::storage_ref (scratch, 2, precision);
+}
+
#endif /* DOUBLE_INT_H */
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm.h"
#include "tree.h"
#include "diagnostic-core.h"
+#include "wide-int.h"
/* Compare two fixed objects for bitwise identity. */
@@ -113,6 +114,7 @@ fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, enum machine_mode mode)
REAL_VALUE_TYPE real_value, fixed_value, base_value;
unsigned int fbit;
enum fixed_value_range_code temp;
+ bool fail;
f->mode = mode;
fbit = GET_MODE_FBIT (mode);
@@ -127,8 +129,10 @@ fixed_from_string (FIXED_VALUE_TYPE *f, const char *str, enum machine_mode mode)
"large fixed-point constant implicitly truncated to fixed-point type");
real_2expN (&base_value, fbit, mode);
real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
- real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high,
- &fixed_value);
+ wide_int w = real_to_integer (&fixed_value, &fail,
+ GET_MODE_PRECISION (mode));
+ f->data.low = w.elt (0);
+ f->data.high = w.elt (1);
if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode))
{
@@ -153,9 +157,12 @@ fixed_to_decimal (char *str, const FIXED_VALUE_TYPE *f_orig,
{
REAL_VALUE_TYPE real_value, base_value, fixed_value;
+ signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode) ? UNSIGNED : SIGNED;
real_2expN (&base_value, GET_MODE_FBIT (f_orig->mode), f_orig->mode);
- real_from_integer (&real_value, VOIDmode, f_orig->data.low, f_orig->data.high,
- UNSIGNED_FIXED_POINT_MODE_P (f_orig->mode));
+ real_from_integer (&real_value, VOIDmode,
+ wide_int::from (f_orig->data,
+ GET_MODE_PRECISION (f_orig->mode), sgn),
+ sgn);
real_arithmetic (&fixed_value, RDIV_EXPR, &real_value, &base_value);
real_to_decimal (str, &fixed_value, buf_size, 0, 1);
}
@@ -1041,12 +1048,17 @@ fixed_convert_from_real (FIXED_VALUE_TYPE *f, enum machine_mode mode,
int i_f_bits = GET_MODE_IBIT (mode) + GET_MODE_FBIT (mode);
unsigned int fbit = GET_MODE_FBIT (mode);
enum fixed_value_range_code temp;
+ bool fail;
real_value = *a;
f->mode = mode;
real_2expN (&base_value, fbit, mode);
real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
- real_to_integer2 ((HOST_WIDE_INT *)&f->data.low, &f->data.high, &fixed_value);
+
+ wide_int w = real_to_integer (&fixed_value, &fail,
+ GET_MODE_PRECISION (mode));
+ f->data.low = w.elt (0);
+ f->data.high = w.elt (1);
temp = check_real_for_fixed_mode (&real_value, mode);
if (temp == FIXED_UNDERFLOW) /* Minimum. */
{
@@ -1091,9 +1103,11 @@ real_convert_from_fixed (REAL_VALUE_TYPE *r, enum machine_mode mode,
{
REAL_VALUE_TYPE base_value, fixed_value, real_value;
+ signop sgn = UNSIGNED_FIXED_POINT_MODE_P (f->mode) ? UNSIGNED : SIGNED;
real_2expN (&base_value, GET_MODE_FBIT (f->mode), f->mode);
- real_from_integer (&fixed_value, VOIDmode, f->data.low, f->data.high,
- UNSIGNED_FIXED_POINT_MODE_P (f->mode));
+ real_from_integer (&fixed_value, VOIDmode,
+ wide_int::from (f->data, GET_MODE_PRECISION (f->mode),
+ sgn), sgn);
real_arithmetic (&real_value, RDIV_EXPR, &fixed_value, &base_value);
real_convert (r, mode, &real_value);
}
@@ -1310,76 +1310,58 @@ predict_iv_comparison (struct loop *loop, basic_block bb,
&& tree_fits_shwi_p (compare_base))
{
int probability;
- bool of, overflow = false;
- double_int mod, compare_count, tem, loop_count;
+ bool overflow, overall_overflow = false;
+ widest_int compare_count, tem;
- double_int loop_bound = tree_to_double_int (loop_bound_var);
- double_int compare_bound = tree_to_double_int (compare_var);
- double_int base = tree_to_double_int (compare_base);
- double_int compare_step = tree_to_double_int (compare_step_var);
+ widest_int loop_bound = wi::to_widest (loop_bound_var);
+ widest_int compare_bound = wi::to_widest (compare_var);
+ widest_int base = wi::to_widest (compare_base);
+ widest_int compare_step = wi::to_widest (compare_step_var);
/* (loop_bound - base) / compare_step */
- tem = loop_bound.sub_with_overflow (base, &of);
- overflow |= of;
- loop_count = tem.divmod_with_overflow (compare_step,
- 0, TRUNC_DIV_EXPR,
- &mod, &of);
- overflow |= of;
-
- if ((!compare_step.is_negative ())
+ tem = wi::sub (loop_bound, base, SIGNED, &overflow);
+ overall_overflow |= overflow;
+ widest_int loop_count = wi::div_trunc (tem, compare_step, SIGNED,
+ &overflow);
+ overall_overflow |= overflow;
+
+ if (!wi::neg_p (compare_step)
^ (compare_code == LT_EXPR || compare_code == LE_EXPR))
{
/* (loop_bound - compare_bound) / compare_step */
- tem = loop_bound.sub_with_overflow (compare_bound, &of);
- overflow |= of;
- compare_count = tem.divmod_with_overflow (compare_step,
- 0, TRUNC_DIV_EXPR,
- &mod, &of);
- overflow |= of;
+ tem = wi::sub (loop_bound, compare_bound, SIGNED, &overflow);
+ overall_overflow |= overflow;
+ compare_count = wi::div_trunc (tem, compare_step, SIGNED, &overflow);
+ overall_overflow |= overflow;
}
else
{
/* (compare_bound - base) / compare_step */
- tem = compare_bound.sub_with_overflow (base, &of);
- overflow |= of;
- compare_count = tem.divmod_with_overflow (compare_step,
- 0, TRUNC_DIV_EXPR,
- &mod, &of);
- overflow |= of;
+ tem = wi::sub (compare_bound, base, SIGNED, &overflow);
+ overall_overflow |= overflow;
+ compare_count = wi::div_trunc (tem, compare_step, SIGNED, &overflow);
+ overall_overflow |= overflow;
}
if (compare_code == LE_EXPR || compare_code == GE_EXPR)
++compare_count;
if (loop_bound_code == LE_EXPR || loop_bound_code == GE_EXPR)
++loop_count;
- if (compare_count.is_negative ())
- compare_count = double_int_zero;
- if (loop_count.is_negative ())
- loop_count = double_int_zero;
- if (loop_count.is_zero ())
+ if (wi::neg_p (compare_count))
+ compare_count = 0;
+ if (wi::neg_p (loop_count))
+ loop_count = 0;
+ if (loop_count == 0)
probability = 0;
- else if (compare_count.scmp (loop_count) == 1)
+ else if (wi::cmps (compare_count, loop_count) == 1)
probability = REG_BR_PROB_BASE;
else
{
- /* If loop_count is too big, such that REG_BR_PROB_BASE * loop_count
- could overflow, shift both loop_count and compare_count right
- a bit so that it doesn't overflow. Note both counts are known not
- to be negative at this point. */
- int clz_bits = clz_hwi (loop_count.high);
- gcc_assert (REG_BR_PROB_BASE < 32768);
- if (clz_bits < 16)
- {
- loop_count.arshift (16 - clz_bits, HOST_BITS_PER_DOUBLE_INT);
- compare_count.arshift (16 - clz_bits, HOST_BITS_PER_DOUBLE_INT);
- }
- tem = compare_count.mul_with_sign (double_int::from_shwi
- (REG_BR_PROB_BASE), true, &of);
- gcc_assert (!of);
- tem = tem.divmod (loop_count, true, TRUNC_DIV_EXPR, &mod);
+ tem = compare_count * REG_BR_PROB_BASE;
+ tem = wi::udiv_trunc (tem, loop_count);
probability = tem.to_uhwi ();
}
- if (!overflow)
+ if (!overall_overflow)
predict_edge (then_edge, PRED_LOOP_IV_COMPARE, probability);
return;
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see
#include "obstack.h"
#include "input.h"
+#include "wide-int-print.h"
/* Maximum number of format string arguments. */
#define PP_NL_ARGMAX 30
@@ -261,6 +262,13 @@ pp_get_prefix (const pretty_printer *pp) { return pp->prefix; }
#define pp_decimal_int(PP, I) pp_scalar (PP, "%d", I)
#define pp_unsigned_wide_integer(PP, I) \
pp_scalar (PP, HOST_WIDE_INT_PRINT_UNSIGNED, (unsigned HOST_WIDE_INT) I)
+#define pp_wide_int(PP, W, SGN) \
+ do \
+ { \
+ print_dec (W, pp_buffer (PP)->digit_buffer, SGN); \
+ pp_string (PP, pp_buffer (PP)->digit_buffer); \
+ } \
+ while (0)
#define pp_wide_integer(PP, I) \
pp_scalar (PP, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) I)
#define pp_widest_integer(PP, I) \
new file mode 100644
@@ -0,0 +1,35 @@
+/* Operations with SIGNED and UNSIGNED. -*- C++ -*-
+ Copyright (C) 2012-2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 3, or (at your option) any
+later version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT
+ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef SIGNOP_H
+#define SIGNOP_H
+
+/* This type is used for the large number of functions that produce
+ different results depending on if the operands are signed types or
+ unsigned types. The signedness of a tree type can be found by
+ using the TYPE_SIGN macro. */
+
+enum signop_e {
+ SIGNED,
+ UNSIGNED
+};
+
+typedef enum signop_e signop;
+
+#endif
@@ -711,6 +711,16 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
#define gcc_unreachable() (fancy_abort (__FILE__, __LINE__, __FUNCTION__))
#endif
+#if GCC_VERSION >= 3001
+#define STATIC_CONSTANT_P(X) (__builtin_constant_p (X) && (X))
+#else
+#define STATIC_CONSTANT_P(X) (false && (X))
+#endif
+
+/* Until we can use STATIC_ASSERT. */
+#define STATIC_ASSERT(X) \
+ typedef int assertion1[(X) ? 1 : -1] ATTRIBUTE_UNUSED
+
/* Provide a fake boolean type. We make no attempt to use the
C99 _Bool, as it may not be available in the bootstrap compiler,
and even if it is, it is liable to be buggy.
@@ -3610,9 +3610,9 @@ loop is only entered from the top.\n\
This hook is only used if @code{doloop_end} is available. The default\n\
implementation returns true. You can use @code{can_use_doloop_if_innermost}\n\
if the loop must be the innermost, and if there are no other restrictions.",
- bool, (double_int iterations, double_int iterations_max,
+ bool, (const widest_int &iterations, const widest_int &iterations_max,
unsigned int loop_depth, bool entered_at_top),
- hook_bool_dint_dint_uint_bool_true)
+ hook_bool_wint_wint_uint_bool_true)
/* Returns NULL if target supports the insn within a doloop block,
otherwise it returns an error message. */
@@ -50,7 +50,7 @@
#include "insn-modes.h"
#include "insn-codes.h"
-#include "double-int.h"
+#include "wide-int.h"
#ifdef ENABLE_CHECKING