re PR middle-end/78416 (wrong code for division by (u128)~INT64_MAX at -O0)
PR middle-end/78416 * expmed.c (expand_divmod): Use wide_int for computation of op1_is_pow2. Don't set it if op1 is 0. Formatting fixes. Use size <= HOST_BITS_PER_WIDE_INT instead of HOST_BITS_PER_WIDE_INT >= size. * gcc.dg/torture/pr78416.c: New test. From-SVN: r242690
This commit is contained in:
parent
9b28cb6f0a
commit
76a7314dc9
@ -1,5 +1,11 @@
|
|||||||
2016-11-22 Jakub Jelinek <jakub@redhat.com>
|
2016-11-22 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
PR middle-end/78416
|
||||||
|
* expmed.c (expand_divmod): Use wide_int for computation of
|
||||||
|
op1_is_pow2. Don't set it if op1 is 0. Formatting fixes.
|
||||||
|
Use size <= HOST_BITS_PER_WIDE_INT instead of
|
||||||
|
HOST_BITS_PER_WIDE_INT >= size.
|
||||||
|
|
||||||
PR tree-optimization/78445
|
PR tree-optimization/78445
|
||||||
* tree-if-conv.c (tree_if_conversion): If any_pred_load_store or
|
* tree-if-conv.c (tree_if_conversion): If any_pred_load_store or
|
||||||
any_complicated_phi, version loop even if flag_tree_loop_if_convert is
|
any_complicated_phi, version loop even if flag_tree_loop_if_convert is
|
||||||
|
54
gcc/expmed.c
54
gcc/expmed.c
@ -3994,11 +3994,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
op1_is_constant = CONST_INT_P (op1);
|
op1_is_constant = CONST_INT_P (op1);
|
||||||
if (op1_is_constant)
|
if (op1_is_constant)
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT ext_op1 = UINTVAL (op1);
|
wide_int ext_op1 = rtx_mode_t (op1, mode);
|
||||||
if (unsignedp)
|
op1_is_pow2 = (wi::popcount (ext_op1) == 1
|
||||||
ext_op1 &= GET_MODE_MASK (mode);
|
|| (! unsignedp
|
||||||
op1_is_pow2 = ((EXACT_POWER_OF_2_OR_ZERO_P (ext_op1)
|
&& wi::popcount (wi::neg (ext_op1)) == 1));
|
||||||
|| (! unsignedp && EXACT_POWER_OF_2_OR_ZERO_P (-ext_op1))));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4079,11 +4078,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
not straightforward to generalize this. Maybe we should make an array
|
not straightforward to generalize this. Maybe we should make an array
|
||||||
of possible modes in init_expmed? Save this for GCC 2.7. */
|
of possible modes in init_expmed? Save this for GCC 2.7. */
|
||||||
|
|
||||||
optab1 = ((op1_is_pow2 && op1 != const0_rtx)
|
optab1 = (op1_is_pow2
|
||||||
? (unsignedp ? lshr_optab : ashr_optab)
|
? (unsignedp ? lshr_optab : ashr_optab)
|
||||||
: (unsignedp ? udiv_optab : sdiv_optab));
|
: (unsignedp ? udiv_optab : sdiv_optab));
|
||||||
optab2 = ((op1_is_pow2 && op1 != const0_rtx)
|
optab2 = (op1_is_pow2 ? optab1
|
||||||
? optab1
|
|
||||||
: (unsignedp ? udivmod_optab : sdivmod_optab));
|
: (unsignedp ? udivmod_optab : sdivmod_optab));
|
||||||
|
|
||||||
for (compute_mode = mode; compute_mode != VOIDmode;
|
for (compute_mode = mode; compute_mode != VOIDmode;
|
||||||
@ -4139,10 +4137,15 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
/* convert_modes may have placed op1 into a register, so we
|
/* convert_modes may have placed op1 into a register, so we
|
||||||
must recompute the following. */
|
must recompute the following. */
|
||||||
op1_is_constant = CONST_INT_P (op1);
|
op1_is_constant = CONST_INT_P (op1);
|
||||||
op1_is_pow2 = (op1_is_constant
|
if (op1_is_constant)
|
||||||
&& ((EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
|
{
|
||||||
|| (! unsignedp
|
wide_int ext_op1 = rtx_mode_t (op1, compute_mode);
|
||||||
&& EXACT_POWER_OF_2_OR_ZERO_P (-UINTVAL (op1))))));
|
op1_is_pow2 = (wi::popcount (ext_op1) == 1
|
||||||
|
|| (! unsignedp
|
||||||
|
&& wi::popcount (wi::neg (ext_op1)) == 1));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
op1_is_pow2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If one of the operands is a volatile MEM, copy it into a register. */
|
/* If one of the operands is a volatile MEM, copy it into a register. */
|
||||||
@ -4182,10 +4185,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
unsigned HOST_WIDE_INT mh, ml;
|
unsigned HOST_WIDE_INT mh, ml;
|
||||||
int pre_shift, post_shift;
|
int pre_shift, post_shift;
|
||||||
int dummy;
|
int dummy;
|
||||||
unsigned HOST_WIDE_INT d = (INTVAL (op1)
|
wide_int wd = rtx_mode_t (op1, compute_mode);
|
||||||
& GET_MODE_MASK (compute_mode));
|
unsigned HOST_WIDE_INT d = wd.to_uhwi ();
|
||||||
|
|
||||||
if (EXACT_POWER_OF_2_OR_ZERO_P (d))
|
if (wi::popcount (wd) == 1)
|
||||||
{
|
{
|
||||||
pre_shift = floor_log2 (d);
|
pre_shift = floor_log2 (d);
|
||||||
if (rem_flag)
|
if (rem_flag)
|
||||||
@ -4325,7 +4328,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
else if (d == -1)
|
else if (d == -1)
|
||||||
quotient = expand_unop (compute_mode, neg_optab, op0,
|
quotient = expand_unop (compute_mode, neg_optab, op0,
|
||||||
tquotient, 0);
|
tquotient, 0);
|
||||||
else if (HOST_BITS_PER_WIDE_INT >= size
|
else if (size <= HOST_BITS_PER_WIDE_INT
|
||||||
&& abs_d == HOST_WIDE_INT_1U << (size - 1))
|
&& abs_d == HOST_WIDE_INT_1U << (size - 1))
|
||||||
{
|
{
|
||||||
/* This case is not handled correctly below. */
|
/* This case is not handled correctly below. */
|
||||||
@ -4335,6 +4338,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
goto fail1;
|
goto fail1;
|
||||||
}
|
}
|
||||||
else if (EXACT_POWER_OF_2_OR_ZERO_P (d)
|
else if (EXACT_POWER_OF_2_OR_ZERO_P (d)
|
||||||
|
&& (size <= HOST_BITS_PER_WIDE_INT || d >= 0)
|
||||||
&& (rem_flag
|
&& (rem_flag
|
||||||
? smod_pow2_cheap (speed, compute_mode)
|
? smod_pow2_cheap (speed, compute_mode)
|
||||||
: sdiv_pow2_cheap (speed, compute_mode))
|
: sdiv_pow2_cheap (speed, compute_mode))
|
||||||
@ -4348,7 +4352,9 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
compute_mode)
|
compute_mode)
|
||||||
!= CODE_FOR_nothing)))
|
!= CODE_FOR_nothing)))
|
||||||
;
|
;
|
||||||
else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d))
|
else if (EXACT_POWER_OF_2_OR_ZERO_P (abs_d)
|
||||||
|
&& (size <= HOST_BITS_PER_WIDE_INT
|
||||||
|
|| abs_d != (unsigned HOST_WIDE_INT) d))
|
||||||
{
|
{
|
||||||
if (rem_flag)
|
if (rem_flag)
|
||||||
{
|
{
|
||||||
@ -4483,7 +4489,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
case FLOOR_DIV_EXPR:
|
case FLOOR_DIV_EXPR:
|
||||||
case FLOOR_MOD_EXPR:
|
case FLOOR_MOD_EXPR:
|
||||||
/* We will come here only for signed operations. */
|
/* We will come here only for signed operations. */
|
||||||
if (op1_is_constant && HOST_BITS_PER_WIDE_INT >= size)
|
if (op1_is_constant && size <= HOST_BITS_PER_WIDE_INT)
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT mh, ml;
|
unsigned HOST_WIDE_INT mh, ml;
|
||||||
int pre_shift, lgup, post_shift;
|
int pre_shift, lgup, post_shift;
|
||||||
@ -4552,9 +4558,8 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
op0, constm1_rtx), NULL_RTX);
|
op0, constm1_rtx), NULL_RTX);
|
||||||
t2 = expand_binop (compute_mode, ior_optab, op0, t1, NULL_RTX,
|
t2 = expand_binop (compute_mode, ior_optab, op0, t1, NULL_RTX,
|
||||||
0, OPTAB_WIDEN);
|
0, OPTAB_WIDEN);
|
||||||
nsign = expand_shift
|
nsign = expand_shift (RSHIFT_EXPR, compute_mode, t2,
|
||||||
(RSHIFT_EXPR, compute_mode, t2,
|
size - 1, NULL_RTX, 0);
|
||||||
size - 1, NULL_RTX, 0);
|
|
||||||
t3 = force_operand (gen_rtx_MINUS (compute_mode, t1, nsign),
|
t3 = force_operand (gen_rtx_MINUS (compute_mode, t1, nsign),
|
||||||
NULL_RTX);
|
NULL_RTX);
|
||||||
t4 = expand_divmod (0, TRUNC_DIV_EXPR, compute_mode, t3, op1,
|
t4 = expand_divmod (0, TRUNC_DIV_EXPR, compute_mode, t3, op1,
|
||||||
@ -4663,7 +4668,10 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
case CEIL_MOD_EXPR:
|
case CEIL_MOD_EXPR:
|
||||||
if (unsignedp)
|
if (unsignedp)
|
||||||
{
|
{
|
||||||
if (op1_is_constant && EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1)))
|
if (op1_is_constant
|
||||||
|
&& EXACT_POWER_OF_2_OR_ZERO_P (INTVAL (op1))
|
||||||
|
&& (size <= HOST_BITS_PER_WIDE_INT
|
||||||
|
|| INTVAL (op1) >= 0))
|
||||||
{
|
{
|
||||||
rtx t1, t2, t3;
|
rtx t1, t2, t3;
|
||||||
unsigned HOST_WIDE_INT d = INTVAL (op1);
|
unsigned HOST_WIDE_INT d = INTVAL (op1);
|
||||||
@ -4876,7 +4884,7 @@ expand_divmod (int rem_flag, enum tree_code code, machine_mode mode,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case EXACT_DIV_EXPR:
|
case EXACT_DIV_EXPR:
|
||||||
if (op1_is_constant && HOST_BITS_PER_WIDE_INT >= size)
|
if (op1_is_constant && size <= HOST_BITS_PER_WIDE_INT)
|
||||||
{
|
{
|
||||||
HOST_WIDE_INT d = INTVAL (op1);
|
HOST_WIDE_INT d = INTVAL (op1);
|
||||||
unsigned HOST_WIDE_INT ml;
|
unsigned HOST_WIDE_INT ml;
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
2016-11-22 Jakub Jelinek <jakub@redhat.com>
|
2016-11-22 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
PR middle-end/78416
|
||||||
|
* gcc.dg/torture/pr78416.c: New test.
|
||||||
|
|
||||||
PR tree-optimization/78445
|
PR tree-optimization/78445
|
||||||
* gcc.dg/pr78445.c: New test.
|
* gcc.dg/pr78445.c: New test.
|
||||||
|
|
||||||
|
17
gcc/testsuite/gcc.dg/torture/pr78416.c
Normal file
17
gcc/testsuite/gcc.dg/torture/pr78416.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* PR middle-end/78416 */
|
||||||
|
/* { dg-do run { target int128 } } */
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
unsigned __int128 x;
|
||||||
|
x = 0xFFFFFFFFFFFFFFFFULL;
|
||||||
|
x /= ~0x7FFFFFFFFFFFFFFFLL;
|
||||||
|
if (x != 0)
|
||||||
|
__builtin_abort ();
|
||||||
|
x = ~0x7FFFFFFFFFFFFFFELL;
|
||||||
|
x /= ~0x7FFFFFFFFFFFFFFFLL;
|
||||||
|
if (x != 1)
|
||||||
|
__builtin_abort ();
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user