Account for prologue spills in reg_pressure scheduling
authorMaxim Kuvyrkov <maxim.kuvyrkov@gmail.com>
Fri, 24 Oct 2014 08:22:12 +0000 (08:22 +0000)
committerMaxim Kuvyrkov <mkuvyrkov@gcc.gnu.org>
Fri, 24 Oct 2014 08:22:12 +0000 (08:22 +0000)
* haifa-sched.c (sched_class_regs_num, call_used_regs_num): New static
arrays.  Use sched_class_regs_num instead of ira_class_hard_regs_num.
(print_curr_reg_pressure, setup_insn_reg_pressure_info,)
(model_update_pressure, model_spill_cost): Use sched_class_regs_num.
(model_start_schedule): Update.
(sched_pressure_start_bb): New static function.  Calculate
sched_class_regs_num.
(schedule_block): Use it.
(alloc_global_sched_pressure_data): Calculate call_used_regs_num.

From-SVN: r216620

gcc/ChangeLog
gcc/haifa-sched.c

index ee7a0fd0c1a55a0087673d1ad9723ada6765a2f6..084fa812a45c4ade22507af1686b4fc4de7bbbf7 100644 (file)
@@ -1,3 +1,15 @@
+2014-10-24  Maxim Kuvyrkov  <maxim.kuvyrkov@gmail.com>
+
+       * haifa-sched.c (sched_class_regs_num, call_used_regs_num): New static
+       arrays.  Use sched_class_regs_num instead of ira_class_hard_regs_num.
+       (print_curr_reg_pressure, setup_insn_reg_pressure_info,)
+       (model_update_pressure, model_spill_cost): Use sched_class_regs_num.
+       (model_start_schedule): Update.
+       (sched_pressure_start_bb): New static function.  Calculate
+       sched_class_regs_num.
+       (schedule_block): Use it.
+       (alloc_global_sched_pressure_data): Calculate call_used_regs_num.
+
 2014-10-24  Richard Biener  <rguenther@suse.de>
 
        * Makefile.in (BUILD_CPPLIB): When in stage2+ use the
index db8a45cf5ecc2f5eeeb59dbbe20434a0815112c5..6cc34b20ab2a34d579a07f97f51e7820faf2539d 100644 (file)
@@ -933,6 +933,13 @@ static bitmap saved_reg_live;
 /* Registers mentioned in the current region.  */
 static bitmap region_ref_regs;
 
+/* Effective number of available registers of a given class (see comment
+   in sched_pressure_start_bb).  */
+static int sched_class_regs_num[N_REG_CLASSES];
+/* Number of call_used_regs.  This is a helper for calculating of
+   sched_class_regs_num.  */
+static int call_used_regs_num[N_REG_CLASSES];
+
 /* Initiate register pressure relative info for scheduling the current
    region.  Currently it is only clearing register mentioned in the
    current region.  */
@@ -1116,7 +1123,7 @@ print_curr_reg_pressure (void)
       gcc_assert (curr_reg_pressure[cl] >= 0);
       fprintf (sched_dump, "  %s:%d(%d)", reg_class_names[cl],
               curr_reg_pressure[cl],
-              curr_reg_pressure[cl] - ira_class_hard_regs_num[cl]);
+              curr_reg_pressure[cl] - sched_class_regs_num[cl]);
     }
   fprintf (sched_dump, "\n");
 }
@@ -1731,9 +1738,9 @@ setup_insn_reg_pressure_info (rtx_insn *insn)
       cl = ira_pressure_classes[i];
       gcc_assert (curr_reg_pressure[cl] >= 0);
       change = (int) pressure_info[i].set_increase - death[cl];
-      before = MAX (0, max_reg_pressure[i] - ira_class_hard_regs_num[cl]);
+      before = MAX (0, max_reg_pressure[i] - sched_class_regs_num[cl]);
       after = MAX (0, max_reg_pressure[i] + change
-                  - ira_class_hard_regs_num[cl]);
+                  - sched_class_regs_num[cl]);
       hard_regno = ira_class_hard_regs[cl][0];
       gcc_assert (hard_regno >= 0);
       mode = reg_raw_mode[hard_regno];
@@ -2070,7 +2077,7 @@ model_update_pressure (struct model_pressure_group *group,
 
       /* Check whether the maximum pressure in the overall schedule
         has increased.  (This means that the MODEL_MAX_PRESSURE of
-        every point <= POINT will need to increae too; see below.)  */
+        every point <= POINT will need to increase too; see below.)  */
       if (group->limits[pci].pressure < ref_pressure)
        group->limits[pci].pressure = ref_pressure;
 
@@ -2347,7 +2354,7 @@ must_restore_pattern_p (rtx_insn *next, dep_t dep)
 /* Return the cost of increasing the pressure in class CL from FROM to TO.
 
    Here we use the very simplistic cost model that every register above
-   ira_class_hard_regs_num[CL] has a spill cost of 1.  We could use other
+   sched_class_regs_num[CL] has a spill cost of 1.  We could use other
    measures instead, such as one based on MEMORY_MOVE_COST.  However:
 
       (1) In order for an instruction to be scheduled, the higher cost
@@ -2371,7 +2378,7 @@ must_restore_pattern_p (rtx_insn *next, dep_t dep)
 static int
 model_spill_cost (int cl, int from, int to)
 {
-  from = MAX (from, ira_class_hard_regs_num[cl]);
+  from = MAX (from, sched_class_regs_num[cl]);
   return MAX (to, from) - from;
 }
 
@@ -2477,7 +2484,7 @@ model_set_excess_costs (rtx_insn **insns, int count)
   bool print_p;
 
   /* Record the baseECC value for each instruction in the model schedule,
-     except that negative costs are converted to zero ones now rather thatn
+     except that negative costs are converted to zero ones now rather than
      later.  Do not assign a cost to debug instructions, since they must
      not change code-generation decisions.  Experiments suggest we also
      get better results by not assigning a cost to instructions from
@@ -3727,15 +3734,13 @@ model_dump_pressure_summary (void)
    scheduling region.  */
 
 static void
-model_start_schedule (void)
+model_start_schedule (basic_block bb)
 {
-  basic_block bb;
-
   model_next_priority = 1;
   model_schedule.create (sched_max_luid);
   model_insns = XCNEWVEC (struct model_insn_info, sched_max_luid);
 
-  bb = BLOCK_FOR_INSN (NEXT_INSN (current_sched_info->prev_head));
+  gcc_assert (bb == BLOCK_FOR_INSN (NEXT_INSN (current_sched_info->prev_head)));
   initiate_reg_pressure_info (df_get_live_in (bb));
 
   model_analyze_insns ();
@@ -3773,6 +3778,53 @@ model_end_schedule (void)
   model_finalize_pressure_group (&model_before_pressure);
   model_schedule.release ();
 }
+
+/* Prepare reg pressure scheduling for basic block BB.  */
+static void
+sched_pressure_start_bb (basic_block bb)
+{
+  /* Set the number of available registers for each class taking into account
+     relative probability of current basic block versus function prologue and
+     epilogue.
+     * If the basic block executes much more often than the prologue/epilogue
+     (e.g., inside a hot loop), then cost of spill in the prologue is close to
+     nil, so the effective number of available registers is
+     (ira_class_hard_regs_num[cl] - 0).
+     * If the basic block executes as often as the prologue/epilogue,
+     then spill in the block is as costly as in the prologue, so the effective
+     number of available registers is
+     (ira_class_hard_regs_num[cl] - call_used_regs_num[cl]).
+     Note that all-else-equal, we prefer to spill in the prologue, since that
+     allows "extra" registers for other basic blocks of the function.
+     * If the basic block is on the cold path of the function and executes
+     rarely, then we should always prefer to spill in the block, rather than
+     in the prologue/epilogue.  The effective number of available register is
+     (ira_class_hard_regs_num[cl] - call_used_regs_num[cl]).  */
+  {
+    int i;
+    int entry_freq = ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency;
+    int bb_freq = bb->frequency;
+
+    if (bb_freq == 0)
+      {
+       if (entry_freq == 0)
+         entry_freq = bb_freq = 1;
+      }
+    if (bb_freq < entry_freq)
+      bb_freq = entry_freq;
+
+    for (i = 0; i < ira_pressure_classes_num; ++i)
+      {
+       enum reg_class cl = ira_pressure_classes[i];
+       sched_class_regs_num[cl] = ira_class_hard_regs_num[cl];
+       sched_class_regs_num[cl]
+         -= (call_used_regs_num[cl] * entry_freq) / bb_freq;
+      }
+  }
+
+  if (sched_pressure == SCHED_PRESSURE_MODEL)
+    model_start_schedule (bb);
+}
 \f
 /* A structure that holds local state for the loop in schedule_block.  */
 struct sched_block_state
@@ -6053,8 +6105,8 @@ schedule_block (basic_block *target_bb, state_t init_state)
      in try_ready () (which is called through init_ready_list ()).  */
   (*current_sched_info->init_ready_list) ();
 
-  if (sched_pressure == SCHED_PRESSURE_MODEL)
-    model_start_schedule ();
+  if (sched_pressure)
+    sched_pressure_start_bb (*target_bb);
 
   /* The algorithm is O(n^2) in the number of ready insns at any given
      time in the worst case.  Before reload we are more likely to have
@@ -6701,6 +6753,19 @@ alloc_global_sched_pressure_data (void)
          saved_reg_live = BITMAP_ALLOC (NULL);
          region_ref_regs = BITMAP_ALLOC (NULL);
        }
+
+      /* Calculate number of CALL_USED_REGS in register classes that
+        we calculate register pressure for.  */
+      for (int c = 0; c < ira_pressure_classes_num; ++c)
+       {
+         enum reg_class cl = ira_pressure_classes[c];
+
+         call_used_regs_num[cl] = 0;
+
+         for (int i = 0; i < ira_class_hard_regs_num[cl]; ++i)
+           if (call_used_regs[ira_class_hard_regs[cl][i]])
+             ++call_used_regs_num[cl];
+       }
     }
 }