From: Jeff Law Date: Wed, 15 Jan 2014 18:13:52 +0000 (-0700) Subject: re PR tree-optimization/59747 (wrong code at -Os and above on x86_64-linux-gnu in... X-Git-Tag: releases/gcc-4.9.0~1653 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=a6a2d67b0adf891b823b2b492a9d1cc98e09835a;p=thirdparty%2Fgcc.git 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 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1231e88b7359..856bd46ac525 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-01-15 Jeff Law + + 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 * config.gcc (*-*-rtems*): Add t-rtems to tmake_file. diff --git a/gcc/ree.c b/gcc/ree.c index 63cc8cc7c32e..19d821ce05af 100644 --- a/gcc/ree.c +++ b/gcc/ree.c @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4aadd851e852..dcfb67197f0b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2014-01-15 Jeff Law + + PR tree-optimization/59747 + * gcc.c-torture/execute/pr59747.c: New test. + 2014-01-15 H.J. Lu PR target/59794 diff --git a/gcc/testsuite/gcc.c-torture/execute/pr59747.c b/gcc/testsuite/gcc.c-torture/execute/pr59747.c new file mode 100644 index 000000000000..d45a9082b81a --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/pr59747.c @@ -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); +}