fold-const.c (add_double): Rename to add_double_with_sign.
* fold-const.c (add_double): Rename to add_double_with_sign. Add 'unsigned_p' parameter and take it into account for the overflow. (mul_double): Rename to mul_double_with_sign. Add 'unsigned_p' parameter and take it into account for the overflow. (fold_div_compare): Call add_double_with_sign instead of add_double and mul_double_with_sign instead of mul_double, passing them the unsignedness of the type. * tree.h (add_double): Macroize. (add_double_with_sign): New prototype. (mul_double): Macroize. (mul_double_with_sign): New prototype. From-SVN: r117887
This commit is contained in:
parent
93ef7c1f7e
commit
6b7283ac66
|
@ -1,3 +1,17 @@
|
|||
2006-10-19 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* fold-const.c (add_double): Rename to add_double_with_sign.
|
||||
Add 'unsigned_p' parameter and take it into account for the overflow.
|
||||
(mul_double): Rename to mul_double_with_sign.
|
||||
Add 'unsigned_p' parameter and take it into account for the overflow.
|
||||
(fold_div_compare): Call add_double_with_sign instead of add_double
|
||||
and mul_double_with_sign instead of mul_double, passing them the
|
||||
unsignedness of the type.
|
||||
* tree.h (add_double): Macroize.
|
||||
(add_double_with_sign): New prototype.
|
||||
(mul_double): Macroize.
|
||||
(mul_double_with_sign): New prototype.
|
||||
|
||||
2006-10-19 Chen Liqin <liqin@sunnorth.com.cn>
|
||||
|
||||
* config/score/crti.asm: New file.
|
||||
|
|
|
@ -291,14 +291,16 @@ force_fit_type (tree t, int overflowable,
|
|||
}
|
||||
|
||||
/* Add two doubleword integers with doubleword result.
|
||||
Return nonzero if the operation overflows according to UNSIGNED_P.
|
||||
Each argument is given as two `HOST_WIDE_INT' pieces.
|
||||
One argument is L1 and H1; the other, L2 and H2.
|
||||
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
|
||||
|
||||
int
|
||||
add_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
||||
unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
|
||||
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
|
||||
add_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
||||
unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
|
||||
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
|
||||
bool unsigned_p)
|
||||
{
|
||||
unsigned HOST_WIDE_INT l;
|
||||
HOST_WIDE_INT h;
|
||||
|
@ -308,7 +310,11 @@ add_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
|||
|
||||
*lv = l;
|
||||
*hv = h;
|
||||
return OVERFLOW_SUM_SIGN (h1, h2, h);
|
||||
|
||||
if (unsigned_p)
|
||||
return (unsigned HOST_WIDE_INT) h < (unsigned HOST_WIDE_INT) h1;
|
||||
else
|
||||
return OVERFLOW_SUM_SIGN (h1, h2, h);
|
||||
}
|
||||
|
||||
/* Negate a doubleword integer with doubleword result.
|
||||
|
@ -335,15 +341,16 @@ neg_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
|||
}
|
||||
|
||||
/* Multiply two doubleword integers with doubleword result.
|
||||
Return nonzero if the operation overflows, assuming it's signed.
|
||||
Return nonzero if the operation overflows according to UNSIGNED_P.
|
||||
Each argument is given as two `HOST_WIDE_INT' pieces.
|
||||
One argument is L1 and H1; the other, L2 and H2.
|
||||
The value is stored as two `HOST_WIDE_INT' pieces in *LV and *HV. */
|
||||
|
||||
int
|
||||
mul_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
||||
unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
|
||||
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv)
|
||||
mul_double_with_sign (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
||||
unsigned HOST_WIDE_INT l2, HOST_WIDE_INT h2,
|
||||
unsigned HOST_WIDE_INT *lv, HOST_WIDE_INT *hv,
|
||||
bool unsigned_p)
|
||||
{
|
||||
HOST_WIDE_INT arg1[4];
|
||||
HOST_WIDE_INT arg2[4];
|
||||
|
@ -374,11 +381,15 @@ mul_double (unsigned HOST_WIDE_INT l1, HOST_WIDE_INT h1,
|
|||
prod[i + 4] = carry;
|
||||
}
|
||||
|
||||
decode (prod, lv, hv); /* This ignores prod[4] through prod[4*2-1] */
|
||||
|
||||
/* Check for overflow by calculating the top half of the answer in full;
|
||||
it should agree with the low half's sign bit. */
|
||||
decode (prod, lv, hv);
|
||||
decode (prod + 4, &toplow, &tophigh);
|
||||
|
||||
/* Unsigned overflow is immediate. */
|
||||
if (unsigned_p)
|
||||
return (toplow | tophigh) != 0;
|
||||
|
||||
/* Check for signed overflow by calculating the signed representation of the
|
||||
top half of the result; it should agree with the low half's sign bit. */
|
||||
if (h1 < 0)
|
||||
{
|
||||
neg_double (l2, h2, &neglow, &neghigh);
|
||||
|
@ -6083,30 +6094,32 @@ fold_div_compare (enum tree_code code, tree type, tree arg0, tree arg1)
|
|||
tree arg01 = TREE_OPERAND (arg0, 1);
|
||||
unsigned HOST_WIDE_INT lpart;
|
||||
HOST_WIDE_INT hpart;
|
||||
bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (arg0));
|
||||
bool neg_overflow;
|
||||
int overflow;
|
||||
|
||||
/* We have to do this the hard way to detect unsigned overflow.
|
||||
prod = int_const_binop (MULT_EXPR, arg01, arg1, 0); */
|
||||
overflow = mul_double (TREE_INT_CST_LOW (arg01),
|
||||
TREE_INT_CST_HIGH (arg01),
|
||||
TREE_INT_CST_LOW (arg1),
|
||||
TREE_INT_CST_HIGH (arg1), &lpart, &hpart);
|
||||
overflow = mul_double_with_sign (TREE_INT_CST_LOW (arg01),
|
||||
TREE_INT_CST_HIGH (arg01),
|
||||
TREE_INT_CST_LOW (arg1),
|
||||
TREE_INT_CST_HIGH (arg1),
|
||||
&lpart, &hpart, unsigned_p);
|
||||
prod = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
|
||||
prod = force_fit_type (prod, -1, overflow, false);
|
||||
neg_overflow = false;
|
||||
|
||||
if (TYPE_UNSIGNED (TREE_TYPE (arg0)))
|
||||
if (unsigned_p)
|
||||
{
|
||||
tmp = int_const_binop (MINUS_EXPR, arg01, integer_one_node, 0);
|
||||
lo = prod;
|
||||
|
||||
/* Likewise hi = int_const_binop (PLUS_EXPR, prod, tmp, 0). */
|
||||
overflow = add_double (TREE_INT_CST_LOW (prod),
|
||||
TREE_INT_CST_HIGH (prod),
|
||||
TREE_INT_CST_LOW (tmp),
|
||||
TREE_INT_CST_HIGH (tmp),
|
||||
&lpart, &hpart);
|
||||
overflow = add_double_with_sign (TREE_INT_CST_LOW (prod),
|
||||
TREE_INT_CST_HIGH (prod),
|
||||
TREE_INT_CST_LOW (tmp),
|
||||
TREE_INT_CST_HIGH (tmp),
|
||||
&lpart, &hpart, unsigned_p);
|
||||
hi = build_int_cst_wide (TREE_TYPE (arg00), lpart, hpart);
|
||||
hi = force_fit_type (hi, -1, overflow | TREE_OVERFLOW (prod),
|
||||
TREE_CONSTANT_OVERFLOW (prod));
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
2006-10-19 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gcc.dg/div-compare-1.c: New test.
|
||||
|
||||
2006-10-19 Paul Thomas <pault@gcc.gnu.org>
|
||||
|
||||
PR fortran/29216
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/* { dg-do run } */
|
||||
/* { dg-options "-std=c99" } */
|
||||
|
||||
extern void abort(void);
|
||||
|
||||
typedef unsigned long long uint64;
|
||||
|
||||
int very_large_value (uint64 t)
|
||||
{
|
||||
return (t / 1000000000ULL) > 9223372037ULL;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uint64 t = 0xC000000000000000ULL;
|
||||
|
||||
if (!very_large_value (t))
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
18
gcc/tree.h
18
gcc/tree.h
|
@ -4210,14 +4210,20 @@ extern tree fold_indirect_ref_1 (tree, tree);
|
|||
|
||||
extern tree force_fit_type (tree, int, bool, bool);
|
||||
|
||||
extern int add_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
|
||||
extern int add_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
|
||||
bool);
|
||||
#define add_double(l1,h1,l2,h2,lv,hv) \
|
||||
add_double_with_sign (l1, h1, l2, h2, lv, hv, false)
|
||||
extern int neg_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
|
||||
extern int mul_double (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *);
|
||||
extern int mul_double_with_sign (unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT, HOST_WIDE_INT,
|
||||
unsigned HOST_WIDE_INT *, HOST_WIDE_INT *,
|
||||
bool);
|
||||
#define mul_double(l1,h1,l2,h2,lv,hv) \
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue