double-int.h (HOST_BITS_PER_DOUBLE_INT): Define.

* double-int.h (HOST_BITS_PER_DOUBLE_INT): Define.
	(double_int_not, double_int_lshift, double_int_rshift): Declare.
	(double_int_negative_p): Convert to static inline function.
	* double-int.c (double_int_lshift, double_int_lshift): Add new function.
	(double_int_negative_p): Remove.
	* tree.h (lshift_double, rshift_double): 
	* tree.c (build_low_bits_mask): Clean up, use double_int_* functions.
	* fold-const.c (fold_convert_const_int_from_real,
	fold_convert_const_int_from_fixed, div_if_zero_remainder): (Ditto.).
	(lshift_double): Change type of arith argument to bool.
	(rshift_double): Change type of arith argument to bool. Correct
	comment.
	* expmed.c (mask_rtx, lshift_value): (Ditto.).

From-SVN: r158360
This commit is contained in:
Anatoly Sokolov 2010-04-15 02:05:32 +04:00 committed by Anatoly Sokolov
parent 8b9b8e9305
commit 2bd1333d62
7 changed files with 112 additions and 123 deletions

View File

@ -1,3 +1,19 @@
2010-04-15 Anatoly Sokolov <aesok@post.ru>
* double-int.h (HOST_BITS_PER_DOUBLE_INT): Define.
(double_int_not, double_int_lshift, double_int_rshift): Declare.
(double_int_negative_p): Convert to static inline function.
* double-int.c (double_int_lshift, double_int_lshift): Add new function.
(double_int_negative_p): Remove.
* tree.h (lshift_double, rshift_double):
* tree.c (build_low_bits_mask): Clean up, use double_int_* functions.
* fold-const.c (fold_convert_const_int_from_real,
fold_convert_const_int_from_fixed, div_if_zero_remainder): (Ditto.).
(lshift_double): Change type of arith argument to bool.
(rshift_double): Change type of arith argument to bool. Correct
comment.
* expmed.c (mask_rtx, lshift_value): (Ditto.).
2010-04-14 Bernd Schmidt <bernd.schmidt@codesourcery.com>
PR target/21803

View File

@ -1,5 +1,5 @@
/* Operations with long integers.
Copyright (C) 2006, 2007, 2009 Free Software Foundation, Inc.
Copyright (C) 2006, 2007, 2009, 2010 Free Software Foundation, Inc.
This file is part of GCC.
@ -290,6 +290,30 @@ double_int_umod (double_int a, double_int b, unsigned code)
return double_int_mod (a, b, true, code);
}
/* Shift A left by COUNT places keeping only PREC bits of result. Shift
right if COUNT is negative. ARITH true specifies arithmetic shifting;
otherwise use logical shift. */
double_int
double_int_lshift (double_int a, HOST_WIDE_INT count, unsigned int prec, bool arith)
{
double_int ret;
lshift_double (a.low, a.high, count, prec, &ret.low, &ret.high, arith);
return ret;
}
/* Shift A rigth by COUNT places keeping only PREC bits of result. Shift
left if COUNT is negative. ARITH true specifies arithmetic shifting;
otherwise use logical shift. */
double_int
double_int_rshift (double_int a, HOST_WIDE_INT count, unsigned int prec, bool arith)
{
double_int ret;
rshift_double (a.low, a.high, count, prec, &ret.low, &ret.high, arith);
return ret;
}
/* Constructs tree in type TYPE from with value given by CST. Signedness of CST
is assumed to be the same as the signedness of TYPE. */
@ -314,15 +338,6 @@ double_int_fits_to_tree_p (const_tree type, double_int cst)
return double_int_equal_p (cst, ext);
}
/* Returns true if CST is negative. Of course, CST is considered to
be signed. */
bool
double_int_negative_p (double_int cst)
{
return cst.high < 0;
}
/* Returns -1 if A < B, 0 if A == B and 1 if A > B. Signedness of the
comparison is given by UNS. */

View File

@ -1,5 +1,5 @@
/* Operations with long integers.
Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
Copyright (C) 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
This file is part of GCC.
@ -57,6 +57,8 @@ typedef struct
HOST_WIDE_INT high;
} double_int;
#define HOST_BITS_PER_DOUBLE_INT (2 * HOST_BITS_PER_WIDE_INT)
union tree_node;
/* Constructors and conversions. */
@ -127,7 +129,29 @@ double_int double_int_umod (double_int, double_int, unsigned);
double_int double_int_divmod (double_int, double_int, bool, unsigned, double_int *);
double_int double_int_sdivmod (double_int, double_int, unsigned, double_int *);
double_int double_int_udivmod (double_int, double_int, unsigned, double_int *);
bool double_int_negative_p (double_int);
/* Logical operations. */
static inline double_int
double_int_not (double_int a)
{
a.low = ~a.low;
a.high = ~ a.high;
return a;
}
/* Shift operations. */
double_int double_int_lshift (double_int, HOST_WIDE_INT, unsigned int, bool);
double_int double_int_rshift (double_int, HOST_WIDE_INT, unsigned int, bool);
/* Returns true if CST is negative. Of course, CST is considered to
be signed. */
static inline bool
double_int_negative_p (double_int cst)
{
return cst.high < 0;
}
int double_int_cmp (double_int, double_int, bool);
int double_int_scmp (double_int, double_int);
int double_int_ucmp (double_int, double_int);

View File

@ -1839,39 +1839,15 @@ extract_fixed_bit_field (enum machine_mode tmode, rtx op0,
static rtx
mask_rtx (enum machine_mode mode, int bitpos, int bitsize, int complement)
{
HOST_WIDE_INT masklow, maskhigh;
double_int mask;
if (bitsize == 0)
masklow = 0;
else if (bitpos < HOST_BITS_PER_WIDE_INT)
masklow = (HOST_WIDE_INT) -1 << bitpos;
else
masklow = 0;
if (bitpos + bitsize < HOST_BITS_PER_WIDE_INT)
masklow &= ((unsigned HOST_WIDE_INT) -1
>> (HOST_BITS_PER_WIDE_INT - bitpos - bitsize));
if (bitpos <= HOST_BITS_PER_WIDE_INT)
maskhigh = -1;
else
maskhigh = (HOST_WIDE_INT) -1 << (bitpos - HOST_BITS_PER_WIDE_INT);
if (bitsize == 0)
maskhigh = 0;
else if (bitpos + bitsize > HOST_BITS_PER_WIDE_INT)
maskhigh &= ((unsigned HOST_WIDE_INT) -1
>> (2 * HOST_BITS_PER_WIDE_INT - bitpos - bitsize));
else
maskhigh = 0;
mask = double_int_mask (bitsize);
mask = double_int_lshift (mask, bitpos, HOST_BITS_PER_DOUBLE_INT, false);
if (complement)
{
maskhigh = ~maskhigh;
masklow = ~masklow;
}
mask = double_int_not (mask);
return immed_double_const (masklow, maskhigh, mode);
return immed_double_const (mask.low, mask.high, mode);
}
/* Return a constant integer (CONST_INT or CONST_DOUBLE) rtx with the value
@ -1880,24 +1856,12 @@ mask_rtx (enum machine_mode mode, int bitpos, int bitsize, int complement)
static rtx
lshift_value (enum machine_mode mode, rtx value, int bitpos, int bitsize)
{
unsigned HOST_WIDE_INT v = INTVAL (value);
HOST_WIDE_INT low, high;
double_int val;
val = double_int_zext (uhwi_to_double_int (INTVAL (value)), bitsize);
val = double_int_lshift (val, bitpos, HOST_BITS_PER_DOUBLE_INT, false);
if (bitsize < HOST_BITS_PER_WIDE_INT)
v &= ~((HOST_WIDE_INT) -1 << bitsize);
if (bitpos < HOST_BITS_PER_WIDE_INT)
{
low = v << bitpos;
high = (bitpos > 0 ? (v >> (HOST_BITS_PER_WIDE_INT - bitpos)) : 0);
}
else
{
low = 0;
high = v << (bitpos - HOST_BITS_PER_WIDE_INT);
}
return immed_double_const (low, high, mode);
return immed_double_const (val.low, val.high, mode);
}
/* Extract a bit field that is split across two words

View File

@ -436,7 +436,7 @@ mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
void
lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
HOST_WIDE_INT count, unsigned int prec,
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, int arith)
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv, bool arith)
{
unsigned HOST_WIDE_INT signmask;
@ -491,7 +491,7 @@ lshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
}
/* Shift the doubleword integer in L1, H1 right by COUNT places
keeping only PREC bits of result. COUNT must be positive.
keeping only PREC bits of result. Shift left if COUNT is negative.
ARITH nonzero specifies arithmetic shifting; otherwise use logical shift.
Store the value as two `HOST_WIDE_INT' pieces in *LV and *HV. */
@ -499,7 +499,7 @@ void
rshift_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
HOST_WIDE_INT count, unsigned int prec,
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
int arith)
bool arith)
{
unsigned HOST_WIDE_INT signmask;
@ -881,10 +881,7 @@ div_and_round_double (enum tree_code code, int uns,
tree
div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
{
unsigned HOST_WIDE_INT int1l, int2l;
HOST_WIDE_INT int1h, int2h;
unsigned HOST_WIDE_INT quol, reml;
HOST_WIDE_INT quoh, remh;
double_int quo, rem;
int uns;
/* The sign of the division is according to operand two, that
@ -895,17 +892,14 @@ div_if_zero_remainder (enum tree_code code, const_tree arg1, const_tree arg2)
&& TYPE_IS_SIZETYPE (TREE_TYPE (arg2)))
uns = false;
int1l = TREE_INT_CST_LOW (arg1);
int1h = TREE_INT_CST_HIGH (arg1);
int2l = TREE_INT_CST_LOW (arg2);
int2h = TREE_INT_CST_HIGH (arg2);
quo = double_int_divmod (tree_to_double_int (arg1),
tree_to_double_int (arg2),
uns, code, &rem);
div_and_round_double (code, uns, int1l, int1h, int2l, int2h,
&quol, &quoh, &reml, &remh);
if (remh != 0 || reml != 0)
return NULL_TREE;
if (double_int_zero_p (rem))
return build_int_cst_wide (TREE_TYPE (arg1), quo.low, quo.high);
return build_int_cst_wide (TREE_TYPE (arg1), quol, quoh);
return NULL_TREE;
}
/* This is nonzero if we should defer warnings about undefined
@ -2279,7 +2273,7 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg
C and C++ standards that simply state that the behavior of
FP-to-integer conversion is unspecified upon overflow. */
HOST_WIDE_INT high, low;
double_int val;
REAL_VALUE_TYPE r;
REAL_VALUE_TYPE x = TREE_REAL_CST (arg1);
@ -2297,8 +2291,7 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg
if (REAL_VALUE_ISNAN (r))
{
overflow = 1;
high = 0;
low = 0;
val = double_int_zero;
}
/* See if R is less than the lower bound or greater than the
@ -2311,8 +2304,7 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg
if (REAL_VALUES_LESS (r, l))
{
overflow = 1;
high = TREE_INT_CST_HIGH (lt);
low = TREE_INT_CST_LOW (lt);
val = tree_to_double_int (lt);
}
}
@ -2325,16 +2317,15 @@ fold_convert_const_int_from_real (enum tree_code code, tree type, const_tree arg
if (REAL_VALUES_LESS (u, r))
{
overflow = 1;
high = TREE_INT_CST_HIGH (ut);
low = TREE_INT_CST_LOW (ut);
val = tree_to_double_int (ut);
}
}
}
if (! overflow)
REAL_VALUE_TO_INT (&low, &high, r);
real_to_integer2 ((HOST_WIDE_INT *) &val.low, &val.high, &r);
t = force_fit_type_double (type, low, high, -1,
t = force_fit_type_double (type, val.low, val.high, -1,
overflow | TREE_OVERFLOW (arg1));
return t;
}
@ -2354,39 +2345,32 @@ fold_convert_const_int_from_fixed (tree type, const_tree arg1)
mode = TREE_FIXED_CST (arg1).mode;
if (GET_MODE_FBIT (mode) < 2 * HOST_BITS_PER_WIDE_INT)
{
lshift_double (temp.low, temp.high,
- GET_MODE_FBIT (mode), 2 * HOST_BITS_PER_WIDE_INT,
&temp.low, &temp.high, SIGNED_FIXED_POINT_MODE_P (mode));
temp = double_int_rshift (temp, GET_MODE_FBIT (mode),
HOST_BITS_PER_DOUBLE_INT,
SIGNED_FIXED_POINT_MODE_P (mode));
/* Left shift temp to temp_trunc by fbit. */
lshift_double (temp.low, temp.high,
GET_MODE_FBIT (mode), 2 * HOST_BITS_PER_WIDE_INT,
&temp_trunc.low, &temp_trunc.high,
SIGNED_FIXED_POINT_MODE_P (mode));
temp_trunc = double_int_lshift (temp, GET_MODE_FBIT (mode),
HOST_BITS_PER_DOUBLE_INT,
SIGNED_FIXED_POINT_MODE_P (mode));
}
else
{
temp.low = 0;
temp.high = 0;
temp_trunc.low = 0;
temp_trunc.high = 0;
temp = double_int_zero;
temp_trunc = double_int_zero;
}
/* If FIXED_CST is negative, we need to round the value toward 0.
By checking if the fractional bits are not zero to add 1 to temp. */
if (SIGNED_FIXED_POINT_MODE_P (mode) && temp_trunc.high < 0
if (SIGNED_FIXED_POINT_MODE_P (mode)
&& double_int_negative_p (temp_trunc)
&& !double_int_equal_p (TREE_FIXED_CST (arg1).data, temp_trunc))
{
double_int one;
one.low = 1;
one.high = 0;
temp = double_int_add (temp, one);
}
temp = double_int_add (temp, double_int_one);
/* Given a fixed-point constant, make new constant with new type,
appropriately sign-extended or truncated. */
t = force_fit_type_double (type, temp.low, temp.high, -1,
(temp.high < 0
(double_int_negative_p (temp)
&& (TYPE_UNSIGNED (type)
< TYPE_UNSIGNED (TREE_TYPE (arg1))))
| TREE_OVERFLOW (arg1));

View File

@ -1221,32 +1221,18 @@ build_int_cst_wide (tree type, unsigned HOST_WIDE_INT low, HOST_WIDE_INT hi)
tree
build_low_bits_mask (tree type, unsigned bits)
{
unsigned HOST_WIDE_INT low;
HOST_WIDE_INT high;
unsigned HOST_WIDE_INT all_ones = ~(unsigned HOST_WIDE_INT) 0;
double_int mask;
gcc_assert (bits <= TYPE_PRECISION (type));
if (bits == TYPE_PRECISION (type)
&& !TYPE_UNSIGNED (type))
{
/* Sign extended all-ones mask. */
low = all_ones;
high = -1;
}
else if (bits <= HOST_BITS_PER_WIDE_INT)
{
low = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
high = 0;
}
/* Sign extended all-ones mask. */
mask = double_int_minus_one;
else
{
bits -= HOST_BITS_PER_WIDE_INT;
low = all_ones;
high = all_ones >> (HOST_BITS_PER_WIDE_INT - bits);
}
mask = double_int_mask (bits);
return build_int_cst_wide (type, low, high);
return build_int_cst_wide (type, mask.low, mask.high);
}
/* Checks that X is integer constant that can be expressed in (unsigned)

View File

@ -4841,10 +4841,10 @@ extern int mul_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
mul_double_with_sign (l1, h1, l2, h2, lv, hv, false)
extern void lshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
HOST_WIDE_INT, unsigned int,
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, int);
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool);
extern void rshift_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
HOST_WIDE_INT, unsigned int,
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, int);
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *, bool);
extern void lrotate_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
HOST_WIDE_INT, unsigned int,
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);