------- Comment #12 from hjl at lucon dot org 2007-05-13 06:36 ------- find_reg computes the cost of moving to target register too high. This kludge adjusts the cost of moving to target register and seems to work for the testcase:
--- gcc/reload1.c.sse 2007-04-27 05:46:12.000000000 -0700 +++ gcc/reload1.c 2007-05-12 22:30:58.000000000 -0700 @@ -1723,6 +1723,20 @@ find_reg (struct insn_chain *chain, int HARD_REG_SET not_usable; HARD_REG_SET used_by_other_reload; reg_set_iterator rsi; + rtx body = PATTERN (chain->insn); + unsigned int dest_reg; + + if (GET_CODE (body) == SET) + { + rtx dest = SET_DEST (body); + + if ((REG_P (dest) + || (GET_CODE (dest) == SUBREG + && REG_P (SUBREG_REG (dest))))) + dest_reg = reg_or_subregno (dest); + } + else + dest_reg = FIRST_PSEUDO_REGISTER; COPY_HARD_REG_SET (not_usable, bad_spill_regs); IOR_HARD_REG_SET (not_usable, bad_spill_regs_global); @@ -1746,7 +1760,7 @@ find_reg (struct insn_chain *chain, int && ! TEST_HARD_REG_BIT (used_by_other_reload, regno) && HARD_REGNO_MODE_OK (regno, rl->mode)) { - int this_cost = spill_cost[regno]; + int this_cost = dest_reg == regno ? 0 : spill_cost[regno]; int ok = 1; unsigned int this_nregs = hard_regno_nregs[regno][rl->mode]; -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30961