re PR tree-optimization/59747 (wrong code at -Os and above on x86_64-linux-gnu in 64-bit mode)

PR tree-optimization/59747
	* ree.c (find_and_remove_re): Properly handle case where a second
	eliminated extension requires widening a copy created for elimination
	of a prior extension.
	(combine_set_extension): Ensure that the number of hard regs needed
	for a destination register does not change when we widen it.

	PR tree-optimization/59747
	* gcc.c-torture/execute/pr59747.c: New test.

From-SVN: r206638
This commit is contained in:
Jeff Law 2014-01-15 11:13:52 -07:00 committed by Jeff Law
parent aefe4056bb
commit a6a2d67b0a
4 changed files with 59 additions and 3 deletions

View File

@ -1,3 +1,12 @@
2014-01-15 Jeff Law <law@redhat.com>
PR tree-optimization/59747
* ree.c (find_and_remove_re): Properly handle case where a second
eliminated extension requires widening a copy created for elimination
of a prior extension.
(combine_set_extension): Ensure that the number of hard regs needed
for a destination register does not change when we widen it.
2014-01-15 Sebastian Huber <sebastian.huber@embedded-brains.de>
* config.gcc (*-*-rtems*): Add t-rtems to tmake_file.

View File

@ -297,6 +297,12 @@ combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set)
else
new_reg = gen_rtx_REG (cand->mode, REGNO (SET_DEST (*orig_set)));
/* We're going to be widening the result of DEF_INSN, ensure that doing so
doesn't change the number of hard registers needed for the result. */
if (HARD_REGNO_NREGS (REGNO (new_reg), cand->mode)
!= HARD_REGNO_NREGS (REGNO (orig_src), GET_MODE (SET_DEST (*orig_set))))
return false;
/* Merge constants by directly moving the constant into the register under
some conditions. Recall that RTL constants are sign-extended. */
if (GET_CODE (orig_src) == CONST_INT
@ -1017,11 +1023,20 @@ find_and_remove_re (void)
for (unsigned int i = 0; i < reinsn_copy_list.length (); i += 2)
{
rtx curr_insn = reinsn_copy_list[i];
rtx def_insn = reinsn_copy_list[i + 1];
/* Use the mode of the destination of the defining insn
for the mode of the copy. This is necessary if the
defining insn was used to eliminate a second extension
that was wider than the first. */
rtx sub_rtx = *get_sub_rtx (def_insn);
rtx pat = PATTERN (curr_insn);
rtx new_reg = gen_rtx_REG (GET_MODE (SET_DEST (pat)),
rtx new_dst = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
REGNO (XEXP (SET_SRC (pat), 0)));
rtx set = gen_rtx_SET (VOIDmode, new_reg, SET_DEST (pat));
emit_insn_after (set, reinsn_copy_list[i + 1]);
rtx new_src = gen_rtx_REG (GET_MODE (SET_DEST (sub_rtx)),
REGNO (SET_DEST (pat)));
rtx set = gen_rtx_SET (VOIDmode, new_dst, new_src);
emit_insn_after (set, def_insn);
}
/* Delete all useless extensions here in one sweep. */

View File

@ -1,3 +1,8 @@
2014-01-15 Jeff Law <law@redhat.com>
PR tree-optimization/59747
* gcc.c-torture/execute/pr59747.c: New test.
2014-01-15 H.J. Lu <hongjiu.lu@intel.com>
PR target/59794

View File

@ -0,0 +1,27 @@
extern void abort (void);
extern void exit (int);
int a[6], b, c = 1, d;
short e;
int __attribute__ ((noinline))
fn1 (int p)
{
b = a[p];
}
int
main ()
{
if (sizeof (long long) != 8)
exit (0);
a[0] = 1;
if (c)
e--;
d = e;
long long f = e;
if (fn1 ((f >> 56) & 1) != 0)
abort ();
exit (0);
}