[30/32] Remove global call sets: sel-sched.c
diff mbox series

Message ID mptv9tytzf3.fsf@arm.com
State New
Headers show
Series
  • Support multiple ABIs in the same translation unit
Related show

Commit Message

Richard Sandiford Sept. 11, 2019, 7:18 p.m. UTC
The main change here is to replace a crosses_call boolean with
a bitmask of the ABIs used by the crossed calls.  For space reasons,
I didn't also add a HARD_REG_SET that tracks the set of registers
that are actually clobbered, which means that this is the one part
of the series that doesn't benefit from -fipa-ra.  The existing
FIXME suggests that the current structures aren't the preferred
way of representing this anyhow, and the pass already makes
conservative assumptions about call-crossing registers.


2019-09-11  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* sel-sched-ir.h (_def::crosses_call): Replace with...
	(_def::crossed_call_abis): ..this new field.
	(def_list_add): Take a mask of ABIs instead of a crosses_call
	boolean.
	* sel-sched-ir.c (def_list_add): Likewise.  Update initialization
	of _def accordingly.
	* sel-sched.c: Include function-abi.h.
	(hard_regs_data::regs_for_call_clobbered): Delete.
	(reg_rename::crosses_call): Replace with...
	(reg_rename::crossed_call_abis): ...this new field.
	(fur_static_params::crosses_call): Replace with...
	(fur_static_params::crossed_call_abis): ...this new field.
	(init_regs_for_mode): Don't initialize sel_hrd.regs_for_call_clobbered.
	(init_hard_regs_data): Use crtl->abi to test which registers the
	current function would need to save before it uses them.
	(mark_unavailable_hard_regs): Update handling of call-clobbered
	registers, using call_clobbers_in_region to find out which registers
	might be call-clobbered (but without taking -fipa-ra into account
	for now).  Remove separate handling of partially call-clobbered
	registers.
	(verify_target_availability): Use crossed_call_abis instead of
	crosses_call.
	(get_spec_check_type_for_insn, find_used_regs): Likewise.
	(fur_orig_expr_found, fur_on_enter, fur_orig_expr_not_found): Likewise.

Patch
diff mbox series

Index: gcc/sel-sched-ir.h
===================================================================
--- gcc/sel-sched-ir.h	2019-07-10 19:41:26.359898316 +0100
+++ gcc/sel-sched-ir.h	2019-09-11 19:49:11.673506894 +0100
@@ -188,12 +188,12 @@  struct _def
 {
   insn_t orig_insn;
 
-  /* FIXME: Get rid of CROSSES_CALL in each def, since if we're moving up
+  /* FIXME: Get rid of CROSSED_CALL_ABIS in each def, since if we're moving up
      rhs from two different places, but only one of the code motion paths
      crosses a call, we can't use any of the call_used_regs, no matter which
-     path or whether all paths crosses a call.  Thus we should move CROSSES_CALL
-     to static params.  */
-  bool crosses_call;
+     path or whether all paths crosses a call.  Thus we should move
+     CROSSED_CALL_ABIS to static params.  */
+  unsigned int crossed_call_abis;
 };
 typedef struct _def *def_t;
 
@@ -1510,7 +1510,7 @@  extern void flist_tail_init (flist_tail_
 
 extern fence_t flist_lookup (flist_t, insn_t);
 extern void flist_clear (flist_t *);
-extern void def_list_add (def_list_t *, insn_t, bool);
+extern void def_list_add (def_list_t *, insn_t, unsigned int);
 
 /* Target context functions.  */
 extern tc_t create_target_context (bool);
Index: gcc/sel-sched-ir.c
===================================================================
--- gcc/sel-sched-ir.c	2019-09-09 19:01:40.375078244 +0100
+++ gcc/sel-sched-ir.c	2019-09-11 19:49:11.673506894 +0100
@@ -311,9 +311,10 @@  flist_clear (flist_t *lp)
     flist_remove (lp);
 }
 
-/* Add ORIGINAL_INSN the def list DL honoring CROSSES_CALL.  */
+/* Add ORIGINAL_INSN the def list DL honoring CROSSED_CALL_ABIS.  */
 void
-def_list_add (def_list_t *dl, insn_t original_insn, bool crosses_call)
+def_list_add (def_list_t *dl, insn_t original_insn,
+	      unsigned int crossed_call_abis)
 {
   def_t d;
 
@@ -321,7 +322,7 @@  def_list_add (def_list_t *dl, insn_t ori
   d = DEF_LIST_DEF (*dl);
 
   d->orig_insn = original_insn;
-  d->crosses_call = crosses_call;
+  d->crossed_call_abis = crossed_call_abis;
 }
 
 
Index: gcc/sel-sched.c
===================================================================
--- gcc/sel-sched.c	2019-09-11 19:47:32.902202887 +0100
+++ gcc/sel-sched.c	2019-09-11 19:49:11.673506894 +0100
@@ -46,6 +46,7 @@  Software Foundation; either version 3, o
 #include "sel-sched-dump.h"
 #include "sel-sched.h"
 #include "dbgcnt.h"
+#include "function-abi.h"
 
 /* Implementation of selective scheduling approach.
    The below implementation follows the original approach with the following
@@ -302,10 +303,6 @@  struct hard_regs_data
      that the whole set is not computed yet.  */
   HARD_REG_SET regs_for_rename[FIRST_PSEUDO_REGISTER];
 
-  /* For every mode, this stores registers not available due to
-     call clobbering.  */
-  HARD_REG_SET regs_for_call_clobbered[NUM_MACHINE_MODES];
-
   /* All registers that are used or call used.  */
   HARD_REG_SET regs_ever_used;
 
@@ -325,8 +322,8 @@  struct reg_rename
   /* These are *available* for renaming.  */
   HARD_REG_SET available_for_renaming;
 
-  /* Whether this code motion path crosses a call.  */
-  bool crosses_call;
+  /* The set of ABIs used by calls that the code motion path crosses.  */
+  unsigned int crossed_call_abis : NUM_ABI_IDS;
 };
 
 /* A global structure that contains the needed information about harg
@@ -390,8 +387,8 @@  struct fur_static_params
   /* Pointer to the list of original insns definitions.  */
   def_list_t *original_insns;
 
-  /* True if a code motion path contains a CALL insn.  */
-  bool crosses_call;
+  /* The set of ABIs used by calls that the code motion path crosses.  */
+  unsigned int crossed_call_abis : NUM_ABI_IDS;
 };
 
 typedef struct fur_static_params *fur_static_params_p;
@@ -1067,7 +1064,6 @@  init_regs_for_mode (machine_mode mode)
   int cur_reg;
 
   CLEAR_HARD_REG_SET (sel_hrd.regs_for_mode[mode]);
-  CLEAR_HARD_REG_SET (sel_hrd.regs_for_call_clobbered[mode]);
 
   for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++)
     {
@@ -1102,10 +1098,6 @@  init_regs_for_mode (machine_mode mode)
       if (i >= 0)
         continue;
 
-      if (targetm.hard_regno_call_part_clobbered (0, cur_reg, mode))
-        SET_HARD_REG_BIT (sel_hrd.regs_for_call_clobbered[mode],
-                          cur_reg);
-
       /* If the CUR_REG passed all the checks above,
          then it's ok.  */
       SET_HARD_REG_BIT (sel_hrd.regs_for_mode[mode], cur_reg);
@@ -1123,7 +1115,8 @@  init_hard_regs_data (void)
 
   CLEAR_HARD_REG_SET (sel_hrd.regs_ever_used);
   for (cur_reg = 0; cur_reg < FIRST_PSEUDO_REGISTER; cur_reg++)
-    if (df_regs_ever_live_p (cur_reg) || call_used_or_fixed_reg_p (cur_reg))
+    if (df_regs_ever_live_p (cur_reg)
+	|| crtl->abi->clobbers_full_reg_p (cur_reg))
       SET_HARD_REG_BIT (sel_hrd.regs_ever_used, cur_reg);
 
   /* Initialize registers that are valid based on mode when this is
@@ -1193,7 +1186,7 @@  mark_unavailable_hard_regs (def_t def, s
       SET_HARD_REG_SET (reg_rename_p->unavailable_hard_regs);
 
       /* Give a chance for original register, if it isn't in used_regs.  */
-      if (!def->crosses_call)
+      if (!def->crossed_call_abis)
         CLEAR_HARD_REG_BIT (reg_rename_p->unavailable_hard_regs, regno);
 
       return;
@@ -1224,13 +1217,20 @@  mark_unavailable_hard_regs (def_t def, s
     reg_rename_p->unavailable_hard_regs |= sel_hrd.stack_regs;
 #endif
 
-  /* If there's a call on this path, make regs from call_used_or_fixed_regs
-     unavailable.  */
-  if (def->crosses_call)
-    reg_rename_p->unavailable_hard_regs |= call_used_or_fixed_regs;
+  mode = GET_MODE (orig_dest);
+
+  /* If there's a call on this path, make regs from full_reg_clobbers
+     unavailable.
 
-  /* Stop here before reload: we need FRAME_REGS, STACK_REGS, and crosses_call,
-     but not register classes.  */
+     ??? It would be better to track the set of clobbered registers
+     directly, but that would be quite expensive in a def_t.  */
+  if (def->crossed_call_abis)
+    reg_rename_p->unavailable_hard_regs
+      |= call_clobbers_in_region (def->crossed_call_abis,
+				  reg_class_contents[ALL_REGS], mode);
+
+  /* Stop here before reload: we need FRAME_REGS, STACK_REGS, and
+     crossed_call_abis, but not register classes.  */
   if (!reload_completed)
     return;
 
@@ -1238,19 +1238,11 @@  mark_unavailable_hard_regs (def_t def, s
      register class.  */
   reg_rename_p->available_for_renaming = reg_class_contents[cl];
 
-  mode = GET_MODE (orig_dest);
-
   /* Leave only registers available for this mode.  */
   if (!sel_hrd.regs_for_mode_ok[mode])
     init_regs_for_mode (mode);
   reg_rename_p->available_for_renaming &= sel_hrd.regs_for_mode[mode];
 
-  /* Exclude registers that are partially call clobbered.  */
-  if (def->crosses_call
-      && !targetm.hard_regno_call_part_clobbered (0, regno, mode))
-    reg_rename_p->available_for_renaming
-      &= ~sel_hrd.regs_for_call_clobbered[mode];
-
   /* Leave only those that are ok to rename.  */
   EXECUTE_IF_SET_IN_HARD_REG_SET (reg_rename_p->available_for_renaming,
                                   0, cur_reg, hrsi)
@@ -1481,7 +1473,7 @@  choose_best_pseudo_reg (regset used_regs
 	      /* Don't let register cross a call if it doesn't already
 		 cross one.  This condition is written in accordance with
 		 that in sched-deps.c sched_analyze_reg().  */
-	      if (!reg_rename_p->crosses_call
+	      if (!reg_rename_p->crossed_call_abis
 		  || REG_N_CALLS_CROSSED (orig_regno) > 0)
 		return gen_rtx_REG (mode, orig_regno);
 	    }
@@ -1508,7 +1500,8 @@  choose_best_pseudo_reg (regset used_regs
 
     max_regno = max_reg_num ();
     maybe_extend_reg_info_p ();
-    REG_N_CALLS_CROSSED (REGNO (new_reg)) = reg_rename_p->crosses_call ? 1 : 0;
+    REG_N_CALLS_CROSSED (REGNO (new_reg))
+      = reg_rename_p->crossed_call_abis ? 1 : 0;
 
     return new_reg;
   }
@@ -1560,7 +1553,8 @@  verify_target_availability (expr_t expr,
        as well.  */
     gcc_assert (scheduled_something_on_previous_fence || !live_available
 		|| !hard_available
-		|| (!reload_completed && reg_rename_p->crosses_call
+		|| (!reload_completed
+		    && reg_rename_p->crossed_call_abis
 		    && REG_N_CALLS_CROSSED (regno) == 0));
 }
 
@@ -3248,7 +3242,7 @@  get_spec_check_type_for_insn (insn_t ins
    All the original operations found during the traversal are saved in the
    ORIGINAL_INSNS list.
 
-   REG_RENAME_P->CROSSES_CALL is true, if there is a call insn on the path
+   REG_RENAME_P->CROSSED_CALL_ABIS is true, if there is a call insn on the path
    from INSN to original insn. In this case CALL_USED_REG_SET will be added
    to unavailable hard regs at the point original operation is found.  */
 
@@ -3269,7 +3263,7 @@  find_used_regs (insn_t insn, av_set_t or
   bitmap_clear (code_motion_visited_blocks);
 
   /* Init parameters for code_motion_path_driver.  */
-  sparams.crosses_call = false;
+  sparams.crossed_call_abis = 0;
   sparams.original_insns = original_insns;
   sparams.used_regs = used_regs;
 
@@ -3278,7 +3272,7 @@  find_used_regs (insn_t insn, av_set_t or
 
   res = code_motion_path_driver (insn, orig_ops, NULL, &lparams, &sparams);
 
-  reg_rename_p->crosses_call |= sparams.crosses_call;
+  reg_rename_p->crossed_call_abis |= sparams.crossed_call_abis;
 
   gcc_assert (res == 1);
   gcc_assert (original_insns && *original_insns);
@@ -6006,7 +6000,7 @@  move_op_orig_expr_found (insn_t insn, ex
 
 /* The function is called when original expr is found.
    INSN - current insn traversed, EXPR - the corresponding expr found,
-   crosses_call and original_insns in STATIC_PARAMS are updated.  */
+   crossed_call_abis and original_insns in STATIC_PARAMS are updated.  */
 static void
 fur_orig_expr_found (insn_t insn, expr_t expr ATTRIBUTE_UNUSED,
                      cmpd_local_params_p lparams ATTRIBUTE_UNUSED,
@@ -6016,9 +6010,9 @@  fur_orig_expr_found (insn_t insn, expr_t
   regset tmp;
 
   if (CALL_P (insn))
-    params->crosses_call = true;
+    params->crossed_call_abis |= 1 << call_insn_abi (insn).id ();
 
-  def_list_add (params->original_insns, insn, params->crosses_call);
+  def_list_add (params->original_insns, insn, params->crossed_call_abis);
 
   /* Mark the registers that do not meet the following condition:
     (2) not among the live registers of the point
@@ -6176,10 +6170,10 @@  fur_on_enter (insn_t insn ATTRIBUTE_UNUS
 	 least one insn in ORIGINAL_INSNS.  */
       gcc_assert (*sparams->original_insns);
 
-      /* Adjust CROSSES_CALL, since we may have come to this block along
+      /* Adjust CROSSED_CALL_ABIS, since we may have come to this block along
 	 different path.  */
-      DEF_LIST_DEF (*sparams->original_insns)->crosses_call
-	  |= sparams->crosses_call;
+      DEF_LIST_DEF (*sparams->original_insns)->crossed_call_abis
+	|= sparams->crossed_call_abis;
     }
   else
     local_params->old_original_insns = *sparams->original_insns;
@@ -6233,7 +6227,7 @@  fur_orig_expr_not_found (insn_t insn, av
   fur_static_params_p sparams = (fur_static_params_p) static_params;
 
   if (CALL_P (insn))
-    sparams->crosses_call = true;
+    sparams->crossed_call_abis |= 1 << call_insn_abi (insn).id ();
   else if (DEBUG_INSN_P (insn))
     return true;