PR rtl-optimization/37273
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Mar 2011 20:08:01 +0000 (20:08 +0000)
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 17 Mar 2011 20:08:01 +0000 (20:08 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@171111 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/ira-costs.c

index 887e014..5182971 100644 (file)
@@ -1,3 +1,10 @@
+2011-03-16  Jeff Law  <law@redhat.com>
+
+       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.
+
 2011-03-17  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR debug/48160
index 2329613..6db5bf2 100644 (file)
@@ -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];
       }