[backport from gcc-4.8/trunk r191484, depends on reload-subreg-{1,2} patches ] gcc/ 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. gcc/testsuite/ 2012-09-19 Eric Botcazou * gcc.c-torture/execute/20120919-1.c: New test. --- gcc-4.7.2/gcc/reload1.c.~1~ 2012-09-22 15:12:42.000000000 +0200 +++ gcc-4.7.2/gcc/reload1.c 2012-09-22 15:12:55.000000000 +0200 @@ -6355,6 +6355,20 @@ choose_reload_regs_init (struct insn_cha 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. @@ -6945,7 +6959,7 @@ choose_reload_regs (struct insn_chain *c 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] @@ -6977,10 +6991,26 @@ choose_reload_regs (struct insn_chain *c 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 = 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 - && remove_address_replacements (rld[r].in) && pass) + && (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 } } @@ -8461,20 +8491,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. --- gcc-4.7.2/gcc/testsuite/gcc.c-torture/execute/20120919-1.c.~1~ 1970-01-01 01:00:00.000000000 +0100 +++ gcc-4.7.2/gcc/testsuite/gcc.c-torture/execute/20120919-1.c 2012-09-22 15:12:55.000000000 +0200 @@ -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; +}