diff options
author | Jeff Law <law@redhat.com> | 2011-01-25 07:10:46 -0700 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 2011-01-25 07:10:46 -0700 |
commit | 7e6cb0221424399d27a07d3dadd09ad6967e41cd (patch) | |
tree | 1f0c96fac3818cfb4a85ccde3cf27fb2245a19db /gcc/ira-costs.c | |
parent | 315d905fd552d1ace2196310e527407f9b5bdbd8 (diff) | |
download | gcc-7e6cb0221424399d27a07d3dadd09ad6967e41cd.zip gcc-7e6cb0221424399d27a07d3dadd09ad6967e41cd.tar.gz gcc-7e6cb0221424399d27a07d3dadd09ad6967e41cd.tar.bz2 |
re PR rtl-optimization/37273 (IRA does not re-materializes addresses (loads from the TOC))
PR rtl-optimization/37273
* ira-costs.c (scan_one_insn): Detect constants living in memory and
handle them like argument loads from stack slots. Do not double
count memory for memory constants and argument loads from stack slots.
From-SVN: r169231
Diffstat (limited to 'gcc/ira-costs.c')
-rw-r--r-- | gcc/ira-costs.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 2329613..6db5bf2 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -1,5 +1,5 @@ /* IRA hard register and memory cost calculation for allocnos or pseudos. - Copyright (C) 2006, 2007, 2008, 2009, 2010 + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. Contributed by Vladimir Makarov <vmakarov@redhat.com>. @@ -1009,6 +1009,7 @@ scan_one_insn (rtx insn) enum rtx_code pat_code; rtx set, note; int i, k; + bool counted_mem; if (!NONDEBUG_INSN_P (insn)) return insn; @@ -1018,15 +1019,23 @@ scan_one_insn (rtx insn) || pat_code == ADDR_VEC || pat_code == ADDR_DIFF_VEC) return insn; + counted_mem = false; set = single_set (insn); extract_insn (insn); /* If this insn loads a parameter from its stack slot, then it represents a savings, rather than a cost, if the parameter is - stored in memory. Record this fact. */ + stored in memory. Record this fact. + + Similarly if we're loading other constants from memory (constant + pool, TOC references, small data areas, etc) and this is the only + assignment to the destination pseudo. */ if (set != 0 && REG_P (SET_DEST (set)) && MEM_P (SET_SRC (set)) && (note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != NULL_RTX - && MEM_P (XEXP (note, 0))) + && ((MEM_P (XEXP (note, 0))) + || (CONSTANT_P (XEXP (note, 0)) + && LEGITIMATE_CONSTANT_P (XEXP (note, 0)) + && REG_N_SETS (REGNO (SET_DEST (set))) == 1))) { enum reg_class cl = GENERAL_REGS; rtx reg = SET_DEST (set); @@ -1038,6 +1047,7 @@ scan_one_insn (rtx insn) -= ira_memory_move_cost[GET_MODE (reg)][cl][1] * frequency; record_address_regs (GET_MODE (SET_SRC (set)), XEXP (SET_SRC (set), 0), 0, MEM, SCRATCH, frequency * 2); + counted_mem = true; } record_operand_costs (insn, pref); @@ -1052,7 +1062,10 @@ scan_one_insn (rtx insn) struct costs *p = COSTS (costs, COST_INDEX (regno)); struct costs *q = op_costs[i]; - p->mem_cost += q->mem_cost; + /* If the already accounted for the memory "cost" above, don't + do so again. */ + if (!counted_mem) + p->mem_cost += q->mem_cost; for (k = 0; k < cost_classes_num; k++) p->cost[k] += q->cost[k]; } |