Patchwork LRA patch for powerpc

login
register
mail settings
Submitter Vladimir Makarov
Date May 7, 2013, 7:18 p.m.
Message ID <51895393.50303@redhat.com>
Download mbox | patch
Permalink /patch/242435/
State New
Headers show

Comments

Vladimir Makarov - May 7, 2013, 7:18 p.m.
The following patch contains some work for porting LRA to PPC.  The 
patch adds code analogous to recent changes made for 
reload.c::find_reloads (it permits to fix a lot testsuite failures for 
32-bit ppc), improves address code generation for targets with 
constraints on address displacement, improves equivalence handling which 
permits to decrease stack frame for ppc.

   The patch was successfully bootstrapped and tested on ppc and x86/x86-64.

   Committed as rev. 198695.

2013-05-07  Vladimir Makarov  <vmakarov@redhat.com>

         * ira.c (update_equiv_regs): Add insn having equiv memory even if
         it is not lhs of the insn.
         (setup_reg_equiv): Remove insn having equiv memory which it is not
         lhs of the insn.
         * lra-constraints.c (process_address): Try to improve generation
         code for address base + disp.
         (lra_constraints): Make correct the code for checking insn setting
         up backward equivalence.  Remove insn only if it is in the init
         insn list.
         * lra-eliminations.c (update_reg_eliminate): Change return value.
         (lra_eliminate): Use the result.
Steven Bosscher - May 7, 2013, 7:32 p.m.
On Tue, May 7, 2013 at 9:18 PM, Vladimir Makarov wrote:
>   The following patch contains some work for porting LRA to PPC.  The patch
> adds code analogous to recent changes made for reload.c::find_reloads (it
> permits to fix a lot testsuite failures for 32-bit ppc), improves address
> code generation for targets with constraints on address displacement,
> improves equivalence handling which permits to decrease stack frame for ppc.
>
>   The patch was successfully bootstrapped and tested on ppc and x86/x86-64.

Can you please put it on the ira-improv branch or lra-branch too, so
that my autotesters can pick it up?

Ciao!
Steven
Vladimir Makarov - May 9, 2013, 7:22 p.m.
On 05/07/2013 03:32 PM, Steven Bosscher wrote:
> On Tue, May 7, 2013 at 9:18 PM, Vladimir Makarov wrote:
>>    The following patch contains some work for porting LRA to PPC.  The patch
>> adds code analogous to recent changes made for reload.c::find_reloads (it
>> permits to fix a lot testsuite failures for 32-bit ppc), improves address
>> code generation for targets with constraints on address displacement,
>> improves equivalence handling which permits to decrease stack frame for ppc.
>>
>>    The patch was successfully bootstrapped and tested on ppc and x86/x86-64.
> Can you please put it on the ira-improv branch or lra-branch too, so
> that my autotesters can pick it up?
>
I've just merged trunk into lra and ira-improv branches.

Patch

Index: ira.c
===================================================================
--- ira.c	(revision 198685)
+++ ira.c	(working copy)
@@ -2188,7 +2188,7 @@  ira_update_equiv_info_by_shuffle_insn (i
       && (! ira_reg_equiv[to_regno].defined_p
 	  || ((x = ira_reg_equiv[to_regno].memory) != NULL_RTX
 	      && ! MEM_READONLY_P (x))))
-      return;
+    return;
   insn = insns;
   if (NEXT_INSN (insn) != NULL_RTX)
     {
@@ -2971,8 +2971,12 @@  update_equiv_regs (void)
 		 register.  */
 	      reg_equiv[regno].is_arg_equivalence = 1;
 
-	      /* Record for reload that this is an equivalencing insn.  */
-	      if (rtx_equal_p (src, XEXP (note, 0)))
+	      /* The insn result can have equivalence memory although
+		 the equivalence is not set up by the insn.  We add
+		 this insn to init insns as it is a flag for now that
+		 regno has an equivalence.  We will remove the insn
+		 from init insn list later.  */
+	      if (rtx_equal_p (src, XEXP (note, 0)) || MEM_P (XEXP (note, 0)))
 		ira_reg_equiv[regno].init_insns
 		  = gen_rtx_INSN_LIST (VOIDmode, insn,
 				       ira_reg_equiv[regno].init_insns);
@@ -3368,11 +3372,14 @@  static void
 setup_reg_equiv (void)
 {
   int i;
-  rtx elem, insn, set, x;
+  rtx elem, prev_elem, next_elem, insn, set, x;
 
   for (i = FIRST_PSEUDO_REGISTER; i < ira_reg_equiv_len; i++)
-    for (elem = ira_reg_equiv[i].init_insns; elem; elem = XEXP (elem, 1))
+    for (prev_elem = NULL, elem = ira_reg_equiv[i].init_insns;
+	 elem;
+	 prev_elem = elem, elem = next_elem)
       {
+	next_elem = XEXP (elem, 1);
 	insn = XEXP (elem, 0);
 	set = single_set (insn);
 	
@@ -3381,7 +3388,22 @@  setup_reg_equiv (void)
 	if (set != 0 && (REG_P (SET_DEST (set)) || REG_P (SET_SRC (set))))
 	  {
 	    if ((x = find_reg_note (insn, REG_EQUIV, NULL_RTX)) != NULL)
-	      x = XEXP (x, 0);
+	      {
+		x = XEXP (x, 0);
+		if (REG_P (SET_DEST (set))
+		    && REGNO (SET_DEST (set)) == (unsigned int) i
+		    && ! rtx_equal_p (SET_SRC (set), x) && MEM_P (x))
+		  {
+		    /* This insn reporting the equivalence but
+		       actually not setting it.  Remove it from the
+		       list.  */
+		    if (prev_elem == NULL)
+		      ira_reg_equiv[i].init_insns = next_elem;
+		    else
+		      XEXP (prev_elem, 1) = next_elem;
+		    elem = prev_elem;
+		  }
+	      }
 	    else if (REG_P (SET_DEST (set))
 		     && REGNO (SET_DEST (set)) == (unsigned int) i)
 	      x = SET_SRC (set);
Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 198685)
+++ lra-constraints.c	(working copy)
@@ -1680,14 +1680,13 @@  process_alt_operands (int only_alternati
 
 		case 'G':
 		case 'H':
-		  if (GET_CODE (op) == CONST_DOUBLE
+		  if (CONST_DOUBLE_AS_FLOAT_P (op)
 		      && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, c, p))
 		    win = true;
 		  break;
 
 		case 's':
-		  if (CONST_INT_P (op)
-		      || (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode))
+		  if (CONST_SCALAR_INT_P (op))
 		    break;
 
 		case 'i':
@@ -1696,8 +1695,7 @@  process_alt_operands (int only_alternati
 		  break;
 
 		case 'n':
-		  if (CONST_INT_P (op)
-		      || (GET_CODE (op) == CONST_DOUBLE && mode == VOIDmode))
+		  if (CONST_SCALAR_INT_P (op))
 		    win = true;
 		  break;
 
@@ -2411,18 +2409,18 @@  equiv_address_substitution (struct addre
 /* Major function to make reloads for an address in operand NOP.
    The supported cases are:
 
-   1) an address that existed before LRA started, at which point it must
-      have been valid.  These addresses are subject to elimination and
-      may have become invalid due to the elimination offset being out
-      of range.
-
-   2) an address created by forcing a constant to memory (force_const_to_mem).
-      The initial form of these addresses might not be valid, and it is this
-      function's job to make them valid.
+   1) an address that existed before LRA started, at which point it
+   must have been valid.  These addresses are subject to elimination
+   and may have become invalid due to the elimination offset being out
+   of range.
+
+   2) an address created by forcing a constant to memory
+   (force_const_to_mem).  The initial form of these addresses might
+   not be valid, and it is this function's job to make them valid.
 
    3) a frame address formed from a register and a (possibly zero)
-      constant offset.  As above, these addresses might not be valid
-      and this function must make them so.
+   constant offset.  As above, these addresses might not be valid and
+   this function must make them so.
 
    Add reloads to the lists *BEFORE and *AFTER.  We might need to add
    reloads to *AFTER because of inc/dec, {pre, post} modify in the
@@ -2478,11 +2476,11 @@  process_address (int nop, rtx *before, r
   /* There are three cases where the shape of *AD.INNER may now be invalid:
 
      1) the original address was valid, but either elimination or
-	equiv_address_substitution was applied and that made
-	the address invalid.
+     equiv_address_substitution was applied and that made
+     the address invalid.
 
      2) the address is an invalid symbolic address created by
-	force_const_to_mem.
+     force_const_to_mem.
 
      3) the address is a frame address with an invalid offset.
 
@@ -2564,13 +2562,43 @@  process_address (int nop, rtx *before, r
     }
   else if (ad.index == NULL)
     {
+      int regno;
+      enum reg_class cl;
+      rtx set, insns, last_insn;
       /* base + disp => new base, cases (1) and (3) above.  */
       /* Another option would be to reload the displacement into an
 	 index register.  However, postreload has code to optimize
 	 address reloads that have the same base and different
 	 displacements, so reloading into an index register would
 	 not necessarily be a win.  */
+      start_sequence ();
       new_reg = base_plus_disp_to_reg (&ad);
+      insns = get_insns ();
+      last_insn = get_last_insn ();
+      /* If we generated at least two insns, try last insn source as
+	 an address.  If we succeed, we generate one less insn.  */
+      if (last_insn != insns && (set = single_set (last_insn)) != NULL_RTX
+	  && GET_CODE (SET_SRC (set)) == PLUS
+	  && REG_P (XEXP (SET_SRC (set), 0))
+	  && CONSTANT_P (XEXP (SET_SRC (set), 1)))
+	{
+	  *ad.inner = SET_SRC (set);
+	  if (valid_address_p (ad.mode, *ad.outer, ad.as))
+	    {
+	      *ad.base_term = XEXP (SET_SRC (set), 0);
+	      *ad.disp_term = XEXP (SET_SRC (set), 1);
+	      cl = base_reg_class (ad.mode, ad.as, ad.base_outer_code,
+				   get_index_code (&ad));
+	      regno = REGNO (*ad.base_term);
+	      if (regno >= FIRST_PSEUDO_REGISTER
+		  && cl != lra_get_allocno_class (regno))
+		change_class (regno, cl, "      Change", true);
+	      new_reg = SET_SRC (set);
+	      delete_insns_since (PREV_INSN (last_insn));
+	    }
+	}
+      end_sequence ();
+      emit_insn (insns);
       *ad.inner = new_reg;
     }
   else
@@ -3560,7 +3588,7 @@  lra_constraints (bool first_p)
 	else if ((x = get_equiv_substitution (reg)) != reg)
 	  {
 	    bool pseudo_p = contains_reg_p (x, false, false);
-	    rtx set, insn;
+	    rtx set, insns;
 
 	    /* After RTL transformation, we can not guarantee that
 	       pseudo in the substitution was not reloaded which might
@@ -3592,11 +3620,12 @@  lra_constraints (bool first_p)
 		   removed the insn.  When the equiv can be a
 		   constant, the right hand side of the init insn can
 		   be a pseudo.  */
-		|| (! ((insn = ira_reg_equiv[i].init_insns) != NULL_RTX
-		       && INSN_P (insn)
-		       && (set = single_set (insn)) != NULL_RTX
-		       && REG_P (SET_DEST (set))
-		       && (int) REGNO (SET_DEST (set)) == i)
+		|| (! ((insns = ira_reg_equiv[i].init_insns) != NULL_RTX
+		       && INSN_P (XEXP (insns, 0))
+		       && XEXP (insns, 1) == NULL_RTX
+		       && (set = single_set (XEXP (insns, 0))) != NULL_RTX
+		       && REG_P (SET_SRC (set))
+		       && (int) REGNO (SET_SRC (set)) == i)
 		    && init_insn_rhs_dead_pseudo_p (i))
 		/* Prevent access beyond equivalent memory for
 		   paradoxical subregs.  */
@@ -3669,11 +3698,23 @@  lra_constraints (bool first_p)
 		dest_reg = SUBREG_REG (dest_reg);
 	      if ((REG_P (dest_reg)
 		   && (x = get_equiv_substitution (dest_reg)) != dest_reg
+		   /* Check that this is actually an insn setting up
+		      the equivalence.  */
+		   && (in_list_p (curr_insn,
+				  ira_reg_equiv
+				  [REGNO (dest_reg)].init_insns)
+		       /* Init insns may contain not all insns setting
+			  up equivalence as we have live range
+			  splitting.  So here we use another condition
+			  to check insn setting up the equivalence
+			  which should be removed, e.g. in case when
+			  the equivalence is a constant.  */
+		       || ! MEM_P (x))
 		   /* Remove insns which set up a pseudo whose value
 		      can not be changed.  Such insns might be not in
 		      init_insns because we don't update equiv data
 		      during insn transformations.
-
+		      
 		      As an example, let suppose that a pseudo got
 		      hard register and on the 1st pass was not
 		      changed to equivalent constant.  We generate an
Index: lra-eliminations.c
===================================================================
--- lra-eliminations.c	(revision 198685)
+++ lra-eliminations.c	(working copy)
@@ -1042,11 +1042,12 @@  spill_pseudos (HARD_REG_SET set)
    registers.  Spill pseudos assigned to registers which became
    uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET.  Add
    insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard
-   registers whose offsets should be changed.  */
-static void
+   registers whose offsets should be changed.  Return true if any
+   elimination offset changed.  */
+static bool
 update_reg_eliminate (bitmap insns_with_changed_offsets)
 {
-  bool prev;
+  bool prev, result;
   struct elim_table *ep, *ep1;
   HARD_REG_SET temp_hard_reg_set;
 
@@ -1122,6 +1123,7 @@  update_reg_eliminate (bitmap insns_with_
   AND_COMPL_HARD_REG_SET (eliminable_regset, temp_hard_reg_set);
   spill_pseudos (temp_hard_reg_set);
   setup_elimination_map ();
+  result = false;
   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     if (elimination_map[ep->from] == ep && ep->previous_offset != ep->offset)
       {
@@ -1132,7 +1134,9 @@  update_reg_eliminate (bitmap insns_with_
 	   changed.  */
 	lra_update_reg_val_offset (lra_reg_info[ep->from].val,
 				   ep->offset - ep->previous_offset);
+	result = true;
       }
+  return result;
 }
 
 /* Initialize the table of hard registers to eliminate.
@@ -1273,12 +1277,8 @@  lra_eliminate (bool final_p)
 	  bitmap_ior_into (&insns_with_changed_offsets,
 			   &lra_reg_info[ep->from].insn_bitmap);
     }
-  else
-    {
-      update_reg_eliminate (&insns_with_changed_offsets);
-      if (bitmap_empty_p (&insns_with_changed_offsets))
-	goto lra_eliminate_done;
-    }
+  else if (! update_reg_eliminate (&insns_with_changed_offsets))
+    goto lra_eliminate_done;
   if (lra_dump_file != NULL)
     {
       fprintf (lra_dump_file, "New elimination table:\n");