re PR rtl-optimization/78546 (wrong code at -O2 and above)

PR rtl-optimization/78546
	* simplify-rtx.c (neg_const_int): When negating most negative
	number in mode wider than HOST_BITS_PER_WIDE_INT, use
	simplify_const_unary_operation to produce CONST_DOUBLE or
	CONST_WIDE_INT.
	(simplify_plus_minus): Hanlde the case where neg_const_int
	doesn't return a CONST_INT.

	* gcc.dg/torture/pr78546-1.c: New test.
	* gcc.dg/torture/pr78546-2.c: New test.

From-SVN: r242929
This commit is contained in:
Jakub Jelinek 2016-11-28 20:15:51 +01:00 committed by Jakub Jelinek
parent 82979abd86
commit d057004733
5 changed files with 66 additions and 6 deletions

View File

@ -1,3 +1,13 @@
2016-11-28 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/78546
* simplify-rtx.c (neg_const_int): When negating most negative
number in mode wider than HOST_BITS_PER_WIDE_INT, use
simplify_const_unary_operation to produce CONST_DOUBLE or
CONST_WIDE_INT.
(simplify_plus_minus): Hanlde the case where neg_const_int
doesn't return a CONST_INT.
2016-11-28 Markus Trippelsdorf <markus@trippelsdorf.de>
PR target/78556

View File

@ -56,12 +56,17 @@ static rtx simplify_unary_operation_1 (enum rtx_code, machine_mode, rtx);
static rtx simplify_binary_operation_1 (enum rtx_code, machine_mode,
rtx, rtx, rtx, rtx);
/* Negate a CONST_INT rtx, truncating (because a conversion from a
maximally negative number can overflow). */
/* Negate a CONST_INT rtx. */
static rtx
neg_const_int (machine_mode mode, const_rtx i)
{
return gen_int_mode (-(unsigned HOST_WIDE_INT) INTVAL (i), mode);
unsigned HOST_WIDE_INT val = -UINTVAL (i);
if (GET_MODE_PRECISION (mode) > HOST_BITS_PER_WIDE_INT
&& val == UINTVAL (i))
return simplify_const_unary_operation (NEG, mode, CONST_CAST_RTX (i),
mode);
return gen_int_mode (val, mode);
}
/* Test whether expression, X, is an immediate constant that represents
@ -4507,9 +4512,12 @@ simplify_plus_minus (enum rtx_code code, machine_mode mode, rtx op0,
rtx value = ops[n_ops - 1].op;
if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg)
value = neg_const_int (mode, value);
ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op,
INTVAL (value));
n_ops--;
if (CONST_INT_P (value))
{
ops[n_ops - 2].op = plus_constant (mode, ops[n_ops - 2].op,
INTVAL (value));
n_ops--;
}
}
/* Put a non-negated operand first, if possible. */

View File

@ -1,5 +1,9 @@
2016-11-28 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/78546
* gcc.dg/torture/pr78546-1.c: New test.
* gcc.dg/torture/pr78546-2.c: New test.
PR fortran/78298
* gfortran.dg/gomp/pr78298.f90: New test.

View File

@ -0,0 +1,22 @@
/* PR rtl-optimization/78546 */
/* { dg-do run { target int128 } } */
typedef unsigned __int128 u128;
u128 b;
static inline u128
foo (u128 p1)
{
p1 += ~b;
return -p1;
}
int
main ()
{
asm volatile ("" : : : "memory");
u128 x = foo (~0x7fffffffffffffffLL);
if (x != 0x8000000000000001ULL)
__builtin_abort ();
return 0;
}

View File

@ -0,0 +1,16 @@
/* PR rtl-optimization/78546 */
/* { dg-do run { target int128 } } */
typedef unsigned __int128 u128;
u128 b;
int
main ()
{
asm volatile ("" : : : "memory");
u128 x = ((u128) ~0x7fffffffffffffffLL) - b;
u128 y = 1 - x;
if (y != 0x8000000000000001ULL)
__builtin_abort ();
return 0;
}