diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e7f798049af3..48884d8ed623 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2012-09-19 Eric Botcazou + + PR rtl-optimization/54290 + * reload1.c (choose_reload_regs): Also take into account secondary MEMs + to remove address replacements for inherited reloads. + (replaced_subreg): Move around. + 2012-09-19 David Edelsohn * config/rs6000/aix61.h (TARGET_DEFAULT): Add MASK_PPC_GPOPT, diff --git a/gcc/reload1.c b/gcc/reload1.c index 1bcdfad9377e..4487ea83fa9e 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -6352,6 +6352,20 @@ choose_reload_regs_init (struct insn_chain *chain, rtx *save_reload_reg_rtx) rld[i].when_needed, rld[i].mode); } +#ifdef SECONDARY_MEMORY_NEEDED +/* If X is not a subreg, return it unmodified. If it is a subreg, + look up whether we made a replacement for the SUBREG_REG. Return + either the replacement or the SUBREG_REG. */ + +static rtx +replaced_subreg (rtx x) +{ + if (GET_CODE (x) == SUBREG) + return find_replacement (&SUBREG_REG (x)); + return x; +} +#endif + /* Assign hard reg targets for the pseudo-registers we must reload into hard regs for this insn. Also output the instructions to copy them in and out of the hard regs. @@ -6942,7 +6956,7 @@ choose_reload_regs (struct insn_chain *chain) for (j = 0; j < n_reloads; j++) { int r = reload_order[j]; - rtx check_reg; + rtx check_reg, tem; if (reload_inherited[r] && rld[r].reg_rtx) check_reg = rld[r].reg_rtx; else if (reload_override_in[r] @@ -6974,10 +6988,26 @@ choose_reload_regs (struct insn_chain *chain) If we succeeded removing some reload and we are doing a preliminary pass just to remove such reloads, make another pass, since the removal of one reload might allow us to inherit another one. */ - else if (rld[r].in + else if (pass + && rld[r].in && rld[r].out != rld[r].in - && remove_address_replacements (rld[r].in) && pass) + && remove_address_replacements (rld[r].in)) pass = 2; +#ifdef SECONDARY_MEMORY_NEEDED + /* If we needed a memory location for the reload, we also have to + remove its related reloads. */ + else if (pass + && rld[r].in + && rld[r].out != rld[r].in + && (tem = replaced_subreg (rld[r].in), REG_P (tem)) + && REGNO (tem) < FIRST_PSEUDO_REGISTER + && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (tem)), + rld[r].rclass, rld[r].inmode) + && remove_address_replacements + (get_secondary_mem (tem, rld[r].inmode, rld[r].opnum, + rld[r].when_needed))) + pass = 2; +#endif } } @@ -8458,20 +8488,6 @@ emit_insn_if_valid_for_reload (rtx insn) return NULL; } -#ifdef SECONDARY_MEMORY_NEEDED -/* If X is not a subreg, return it unmodified. If it is a subreg, - look up whether we made a replacement for the SUBREG_REG. Return - either the replacement or the SUBREG_REG. */ - -static rtx -replaced_subreg (rtx x) -{ - if (GET_CODE (x) == SUBREG) - return find_replacement (&SUBREG_REG (x)); - return x; -} -#endif - /* Emit code to perform a reload from IN (which may be a reload register) to OUT (which may also be a reload register). IN or OUT is from operand OPNUM with reload type TYPE. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 31069a0a2122..6c6fdf374122 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2012-09-19 Eric Botcazou + + * gcc.c-torture/execute/20120919-1.c: New test. + 2012-09-19 Richard Guenther * lib/c-torture.exp (TORTURE_OPTIONS): Add -Og -g. diff --git a/gcc/testsuite/gcc.c-torture/execute/20120919-1.c b/gcc/testsuite/gcc.c-torture/execute/20120919-1.c new file mode 100644 index 000000000000..e7f329538c01 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/20120919-1.c @@ -0,0 +1,37 @@ +/* PR rtl-optimization/54290 */ +/* Testcase by Eric Volk */ + +double vd[2] = {1., 0.}; +int vi[2] = {1234567890, 0}; +double *pd = vd; +int *pi = vi; + +extern void abort(void); + +void init (int *n, int *dummy) __attribute__ ((noinline,noclone)); + +void init (int *n, int *dummy) +{ + if(0 == n) dummy[0] = 0; +} + +int main (void) +{ + int dummy[1532]; + int i = -1, n = 1, s = 0; + init (&n, dummy); + while (i < n) { + if (i == 0) { + if (pd[i] > 0) { + if (pi[i] > 0) { + s += pi[i]; + } + } + pd[i] = pi[i]; + } + ++i; + } + if (s != 1234567890) + abort (); + return 0; +}