Patchwork [lra] a patch to fix s390 bootstrap

login
register
mail settings
Submitter Vladimir Makarov
Date March 1, 2012, 6:05 p.m.
Message ID <4F4FBA73.1010305@redhat.com>
Download mbox | patch
Permalink /patch/144083/
State New
Headers show

Comments

Vladimir Makarov - March 1, 2012, 6:05 p.m.
The following patch finally fixes s390 bootstrap.

The patch was successfully bootstrapped on s390x, x86/x86-64, power7, 
arm, sparc64, and ia64.

Committed as rev. 184749.

2012-03-01  Vladimir Makarov <vmakarov@redhat.com>

         * lra-lives.c (pseudos_live_through_calls): New sparseset.
         (pseudos_live_through_setjumps): Ditto.
         (check_pseudos_live_through_calls): New function.
         (process_bb_lives): Use the sparsesets and the function.
         (lra_create_live_ranges): Allocate and free sparsesets
         pseudos_live_through_calls and pseudos_live_through_setjumps.

         * lra-constraints.c (check_and_process_move): Try secondary reload
         for source and destination.

         * jump.c (true_regnum): Use hard_regno for subreg_get_info when
         lra is in progress.

Patch

Index: lra-lives.c
===================================================================
--- lra-lives.c	(revision 184177)
+++ lra-lives.c	(working copy)
@@ -69,6 +69,16 @@  static int curr_point;
 /* Pseudos live at current point in the scan.  */
 static sparseset pseudos_live;
 
+/* Pseudos probably living through calls and setjumps.  As setjump is
+   a call too, if a bit in PSEUDOS_LIVE_THROUGH_SETJUMPS is set up
+   then the corresponding bit in PSEUDOS_LIVE_THROUGH_CALLS is set up
+   too.  These data are necessary for cases when only one subreg of a
+   multi-reg pseudo is set up after a call.  So we decide it is
+   probably live when traversing bb backward.  We are sure about
+   living when we see its usage or definition of the pseudo.  */
+static sparseset pseudos_live_through_calls;
+static sparseset pseudos_live_through_setjumps;
+
 /* Set of hard regs (except eliminable ones) currently live.  */
 static HARD_REG_SET hard_regs_live;
 
@@ -466,6 +476,28 @@  lra_setup_reload_pseudo_preferenced_hard
     }
 }
 
+/* Check that REGNO living through calls and setjumps, set up conflict
+   regs, and clear corresponding bits in PSEUDOS_LIVE_THROUGH_CALLS and
+   PSEUDOS_LIVE_THROUGH_SETJUMPS.  */
+static inline void
+check_pseudos_live_through_calls (int regno)
+{
+  if (! sparseset_bit_p (pseudos_live_through_calls, regno))
+    return;
+  sparseset_clear_bit (pseudos_live_through_calls, regno);
+  IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs,
+		    call_used_reg_set);
+#ifdef ENABLE_CHECKING
+  lra_reg_info[regno].call_p = true;
+#endif
+  if (! sparseset_bit_p (pseudos_live_through_setjumps, regno))
+    return;
+  sparseset_clear_bit (pseudos_live_through_setjumps, regno);
+  /* Don't allocate pseudos that cross setjmps or any call, if this
+     function receives a nonlocal goto.  */
+  SET_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs);
+}
+
 /* Process insns of the basic block BB to update pseudo live ranges,
    pseudo hard register conflicts.  */
 static void
@@ -480,6 +512,8 @@  process_bb_lives (basic_block bb)
 
   reg_live_out = DF_LR_OUT (bb);
   sparseset_clear (pseudos_live);
+  sparseset_clear (pseudos_live_through_calls);
+  sparseset_clear (pseudos_live_through_setjumps);
   REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out);
   AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset);
   AND_COMPL_HARD_REG_SET (hard_regs_live, lra_no_alloc_regs);
@@ -571,7 +605,10 @@  process_bb_lives (basic_block bb)
 	 that are live at the time of the definition.  */
       for (reg = curr_id->regs; reg != NULL; reg = reg->next)
 	if (reg->type != OP_IN)
-	  mark_regno_live (reg->regno, reg->biggest_mode);
+	  {
+	    mark_regno_live (reg->regno, reg->biggest_mode);
+	    check_pseudos_live_through_calls (reg->regno);
+	  }
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
 	if (reg->type != OP_IN)
@@ -596,22 +633,13 @@  process_bb_lives (basic_block bb)
 
       if (call_p)
 	{
-	  /* The current set of live pseudos are live across the
-	     call.  */
-	  EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
-	    {
-	      /* Don't allocate pseudos that cross setjmps or any
-		 call, if this function receives a nonlocal goto.  */
-	      if (cfun->has_nonlocal_label
-		  || find_reg_note (curr_insn, REG_SETJMP,
-				    NULL_RTX) != NULL_RTX)
-		SET_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
-	      IOR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs,
-				call_used_reg_set);
-#ifdef ENABLE_CHECKING
-	      lra_reg_info[i].call_p = true;
-#endif
-	    }
+	  sparseset_ior (pseudos_live_through_calls,
+			 pseudos_live_through_calls, pseudos_live);
+	  if (cfun->has_nonlocal_label
+	      || find_reg_note (curr_insn, REG_SETJMP,
+				NULL_RTX) != NULL_RTX)
+	    sparseset_ior (pseudos_live_through_setjumps,
+			   pseudos_live_through_setjumps, pseudos_live);
 	}
       
       incr_curr_point (freq);
@@ -621,7 +649,10 @@  process_bb_lives (basic_block bb)
       /* Mark each used value as live.  */
       for (reg = curr_id->regs; reg != NULL; reg = reg->next)
 	if (reg->type == OP_IN)
-	  mark_regno_live (reg->regno, reg->biggest_mode);
+	  {
+	    mark_regno_live (reg->regno, reg->biggest_mode);
+	    check_pseudos_live_through_calls (reg->regno);
+	  }
 
       for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
 	if (reg->type == OP_IN)
@@ -711,6 +742,10 @@  process_bb_lives (basic_block bb)
   
   EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
     mark_pseudo_dead (i);
+
+  EXECUTE_IF_SET_IN_SPARSESET (pseudos_live_through_calls, i)
+    if (bitmap_bit_p (DF_LR_IN (bb), i))
+      check_pseudos_live_through_calls (i);
   
   incr_curr_point (freq);
 }
@@ -943,6 +978,8 @@  lra_create_live_ranges (bool all_p)
     }
   lra_free_copies ();
   pseudos_live = sparseset_alloc (max_regno);
+  pseudos_live_through_calls = sparseset_alloc (max_regno);
+  pseudos_live_through_setjumps = sparseset_alloc (max_regno);
   start_living = sparseset_alloc (max_regno);
   start_dying = sparseset_alloc (max_regno);
   dead_set = sparseset_alloc (max_regno);
@@ -961,6 +998,8 @@  lra_create_live_ranges (bool all_p)
   sparseset_free (dead_set);
   sparseset_free (start_dying);
   sparseset_free (start_living);
+  sparseset_free (pseudos_live_through_calls);
+  sparseset_free (pseudos_live_through_setjumps);
   sparseset_free (pseudos_live);
   compress_live_ranges ();
 }
Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 184637)
+++ lra-constraints.c	(working copy)
@@ -1042,11 +1042,11 @@  emit_spill_move (bool to_p, rtx mem_pseu
 static bool
 check_and_process_move (bool *change_p, bool *sec_mem_p)
 {
-  int regno;
-  rtx set, dest, src, dreg, sr, dr, sreg, new_reg, before, x, scratch_reg;
-  enum reg_class dclass, sclass, xclass, rclass, secondary_class;
+  int sregno, dregno;
+  rtx set, dest, src, dreg, sr, dr, sreg, new_reg, before, scratch_reg;
+  enum reg_class dclass, sclass, secondary_class;
+  enum machine_mode sreg_mode;
   secondary_reload_info sri;
-  bool in_p, temp_assign_p;
 
   *sec_mem_p = *change_p = false;
   if ((set = single_set (curr_insn)) == NULL || side_effects_p (set))
@@ -1081,6 +1081,7 @@  check_and_process_move (bool *change_p, 
        work with such classes through their implementation of
        machine-dependent hooks like secondary_memory_needed.  */
     return false;
+  sreg_mode = GET_MODE (sreg);
   sr = get_equiv_substitution (sreg);
   if (sr != sreg)
     sreg = copy_rtx (sr);
@@ -1100,44 +1101,44 @@  check_and_process_move (bool *change_p, 
   sri.prev_sri = NULL;
   sri.icode = CODE_FOR_nothing;
   sri.extra_cost = 0;
-  if (sclass != NO_REGS)
-    {
-      in_p = false;
-      rclass = sclass;
-      x = dreg;
-      xclass = dclass;
-    }
-  else if (dclass != NO_REGS)
-    {
-      in_p = true;
-      rclass = dclass;
-      x = sreg;
-      xclass = sclass;
-    }
-  else
-    return false;
-  temp_assign_p = false;
+  secondary_class = NO_REGS;
   /* Set up hard register for a reload pseudo for hook
      secondary_reload because some targets just ignore pseudos in the
      hook.  */
-  if (xclass != NO_REGS
-      && REG_P (x) && (regno = REGNO (x)) >= new_regno_start
-      && lra_get_regno_hard_regno (regno) < 0)
-    {
-      reg_renumber[regno] = ira_class_hard_regs[xclass][0];
-      temp_assign_p = true;
-    }
-  secondary_class
-    = (enum reg_class) targetm.secondary_reload (in_p, x, (reg_class_t) rclass,
-						 GET_MODE (src), &sri);
-  if (temp_assign_p)
-    reg_renumber [REGNO (x)] = -1;
+  if (dclass != NO_REGS
+      && REG_P (dreg) && (dregno = REGNO (dreg)) >= new_regno_start
+      && lra_get_regno_hard_regno (dregno) < 0)
+    reg_renumber[dregno] = ira_class_hard_regs[dclass][0];
+  else
+    dregno = -1;
+  if (sclass != NO_REGS
+      && REG_P (sreg) && (sregno = REGNO (sreg)) >= new_regno_start
+      && lra_get_regno_hard_regno (sregno) < 0)
+    reg_renumber[sregno] = ira_class_hard_regs[sclass][0];
+  else
+    sregno = -1;
+  if (sclass != NO_REGS)
+    secondary_class
+      = (enum reg_class) targetm.secondary_reload (false, dest,
+						   (reg_class_t) sclass,
+						   GET_MODE (src), &sri);
+  if (sclass == NO_REGS
+      || ((secondary_class != NO_REGS || sri.icode != CODE_FOR_nothing)
+	  && dclass != NO_REGS))
+    secondary_class
+      = (enum reg_class) targetm.secondary_reload (true, sreg,
+						   (reg_class_t) dclass,
+						   sreg_mode, &sri);
+  if (sregno >= 0)
+    reg_renumber [sregno] = -1;
+  if (dregno >= 0)
+    reg_renumber [dregno] = -1;
   if (secondary_class == NO_REGS && sri.icode == CODE_FOR_nothing)
     return false;
   *change_p = true;
   new_reg = NULL_RTX;
   if (secondary_class != NO_REGS)
-    new_reg = lra_create_new_reg_with_unique_value (GET_MODE (sreg), NULL_RTX,
+    new_reg = lra_create_new_reg_with_unique_value (sreg_mode, NULL_RTX,
 						    secondary_class,
 						    "secondary");
   start_sequence ();
@@ -1160,8 +1161,8 @@  check_and_process_move (bool *change_p, 
   lra_process_new_insns (curr_insn, before, NULL_RTX, "Inserting the move");
   if (new_reg != NULL_RTX)
     {
-      if (GET_CODE (SET_SRC (set)) == SUBREG)
-	SUBREG_REG (SET_SRC (set)) = new_reg;
+      if (GET_CODE (src) == SUBREG)
+	SUBREG_REG (src) = new_reg;
       else
 	SET_SRC (set) = new_reg;
     }
Index: jump.c
===================================================================
--- jump.c	(revision 184146)
+++ jump.c	(working copy)
@@ -1866,7 +1866,8 @@  true_regnum (const_rtx x)
 	{
 	  struct subreg_info info;
 
-	  subreg_get_info (REGNO (SUBREG_REG (x)),
+	  subreg_get_info (lra_in_progress
+			   ? (unsigned) base : REGNO (SUBREG_REG (x)),
 			   GET_MODE (SUBREG_REG (x)),
 			   SUBREG_BYTE (x), GET_MODE (x), &info);