diff mbox

patch for correct mode use by LRA for save/restore generation

Message ID 52040636.8060601@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov Aug. 8, 2013, 8:57 p.m. UTC
The following patch implements correct mode use for save/restore generation.

The patch was successfully bootstrapped and tested on x86/x86-64, ppc64, 
s390.

The patch also makes some tuning in alternative matching and adds more 
debugging printing.

Committed as rev. 201611.

2013-08-08  Vladimir Makarov  <vmakarov@redhat.com>

         * lra-constraints.c (emit_spill_move): Remove assert.
         (process_alt_operands): Add more debugging
         output.  Increase reject for spilling into memory.  Decrease
         reject for reloading scratch.
         (split_reg): Use HARD_REGNO_CALLER_SAVE_MODE.
diff mbox

Patch

Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 201544)
+++ lra-constraints.c	(working copy)
@@ -859,8 +859,9 @@ 
 {
   if (GET_MODE (mem_pseudo) != GET_MODE (val))
     {
-      lra_assert (GET_MODE_SIZE (GET_MODE (mem_pseudo))
-		  >= GET_MODE_SIZE (GET_MODE (val)));
+      /* Usually size of mem_pseudo is greater than val size but in
+	 rare cases it can be less as it can be defined by target
+	 dependent macro HARD_REGNO_CALLER_SAVE_MODE.  */
       if (! MEM_P (val))
 	{
 	  val = gen_rtx_SUBREG (GET_MODE (mem_pseudo),
@@ -1423,8 +1424,14 @@ 
             
       overall = losers = reject = reload_nregs = reload_sum = 0;
       for (nop = 0; nop < n_operands; nop++)
-	reject += (curr_static_id
-		   ->operand_alternative[nalt * n_operands + nop].reject);
+	{
+	  int inc = (curr_static_id
+		     ->operand_alternative[nalt * n_operands + nop].reject);
+	  if (lra_dump_file != NULL && inc != 0)
+	    fprintf (lra_dump_file,
+		     "            Staticly defined alt reject+=%d\n", inc);
+	  reject += inc;
+	}
       early_clobbered_regs_num = 0;
 
       for (nop = 0; nop < n_operands; nop++)
@@ -1598,7 +1605,14 @@ 
 			    || (find_regno_note (curr_insn, REG_DEAD,
 						 REGNO (operand_reg[nop]))
 				 == NULL_RTX))
-			  reject += 2;
+			  {
+			    if (lra_dump_file != NULL)
+			      fprintf
+				(lra_dump_file,
+				 "            %d Matching alt: reject+=2\n",
+				 nop);
+			    reject += 2;
+			  }
 		      }
 		    /* If we have to reload this operand and some
 		       previous operand also had to match the same
@@ -1854,16 +1868,35 @@ 
 		    {
 		      if (in_hard_reg_set_p (this_costly_alternative_set,
 					     mode, hard_regno[nop]))
-			reject++;
+			{
+			  if (lra_dump_file != NULL)
+			    fprintf (lra_dump_file,
+				     "            %d Costly set: reject++\n",
+				     nop);
+			  reject++;
+			}
 		    }
 		  else
 		    {
 		      /* Prefer won reg to spilled pseudo under other equal
 			 conditions.  */
+		      if (lra_dump_file != NULL)
+			fprintf
+			  (lra_dump_file,
+			   "            %d Non pseudo reload: reject++\n",
+			   nop);
 		      reject++;
 		      if (in_class_p (operand_reg[nop],
 				      this_costly_alternative, NULL))
-			reject++;
+			{
+			  if (lra_dump_file != NULL)
+			    fprintf
+			      (lra_dump_file,
+			       "            %d Non pseudo costly reload:"
+			       " reject++\n",
+			       nop);
+			  reject++;
+			}
 		    }
 		  /* We simulate the behaviour of old reload here.
 		     Although scratches need hard registers and it
@@ -1872,7 +1905,13 @@ 
 		     might cost something but probably less than old
 		     reload pass believes.  */
 		  if (lra_former_scratch_p (REGNO (operand_reg[nop])))
-		    reject += LRA_LOSER_COST_FACTOR;
+		    {
+		      if (lra_dump_file != NULL)
+			fprintf (lra_dump_file,
+				 "            %d Scratch win: reject+=3\n",
+				 nop);
+		      reject += 3;
+		    }
 		}
 	    }
 	  else if (did_match)
@@ -1914,7 +1953,12 @@ 
 
 	      this_alternative_offmemok = offmemok;
 	      if (this_costly_alternative != NO_REGS)
-		reject++;
+		{
+		  if (lra_dump_file != NULL)
+		    fprintf (lra_dump_file,
+			     "            %d Costly loser: reject++\n", nop);
+		  reject++;
+		}
 	      /* If the operand is dying, has a matching constraint,
 		 and satisfies constraints of the matched operand
 		 which failed to satisfy the own constraints, we do
@@ -1996,7 +2040,13 @@ 
 		      || (curr_static_id->operand[nop].type == OP_OUT
 			  && (targetm.preferred_output_reload_class
 			      (op, this_alternative) == NO_REGS))))
-		reject += LRA_MAX_REJECT;
+		{
+		  if (lra_dump_file != NULL)
+		    fprintf (lra_dump_file,
+			     "            %d Non-prefered reload: reject+=%d\n",
+			     nop, LRA_MAX_REJECT);
+		  reject += LRA_MAX_REJECT;
+		}
 
 	      if (! (MEM_P (op) && offmemok)
 		  && ! (const_to_mem && constmemok))
@@ -2009,22 +2059,43 @@ 
 		     we don't want to have a different alternative
 		     match then.  */
 		  if (! (REG_P (op) && REGNO (op) >= FIRST_PSEUDO_REGISTER))
-		    reject += 2;
+		    {
+		      if (lra_dump_file != NULL)
+			fprintf
+			  (lra_dump_file,
+			   "            %d Non-pseudo reload: reject+=2\n",
+			   nop);
+		      reject += 2;
+		    }
 
 		  if (! no_regs_p)
 		    reload_nregs
 		      += ira_reg_class_max_nregs[this_alternative][mode];
 
 		  if (SMALL_REGISTER_CLASS_P (this_alternative))
-		    reject += LRA_LOSER_COST_FACTOR / 2;
+		    {
+		      if (lra_dump_file != NULL)
+			fprintf
+			  (lra_dump_file,
+			   "            %d Small class reload: reject+=%d\n",
+			   nop, LRA_LOSER_COST_FACTOR / 2);
+		      reject += LRA_LOSER_COST_FACTOR / 2;
+		    }
 		}
 
 	      /* We are trying to spill pseudo into memory.  It is
 		 usually more costly than moving to a hard register
 		 although it might takes the same number of
 		 reloads.  */
-	      if (no_regs_p && REG_P (op))
-		reject += 2;
+	      if (no_regs_p && REG_P (op) && hard_regno[nop] >= 0)
+		{
+		  if (lra_dump_file != NULL)
+		    fprintf
+		      (lra_dump_file,
+		       "            %d Spill pseudo in memory: reject+=3\n",
+		       nop);
+		  reject += 3;
+		}
 
 #ifdef SECONDARY_MEMORY_NEEDED
 	      /* If reload requires moving value through secondary
@@ -2043,12 +2114,23 @@ 
 		 reloads can be removed, so penalize output
 		 reloads.  */
 	      if (!REG_P (op) || curr_static_id->operand[nop].type != OP_IN)
-		reject++;
-
+		{
+		  if (lra_dump_file != NULL)
+		    fprintf
+		      (lra_dump_file,
+		       "            %d Non input pseudo reload: reject++\n",
+		       nop);
+		  reject++;
+		}
 	    }
 
 	  if (early_clobber_p)
-	    reject++;
+	    {
+	      if (lra_dump_file != NULL)
+		fprintf (lra_dump_file,
+			 "            %d Early clobber: reject++\n", nop);
+	      reject++;
+	    }
 	  /* ??? We check early clobbers after processing all operands
 	     (see loop below) and there we update the costs more.
 	     Should we update the cost (may be approximately) here
@@ -2059,7 +2141,7 @@ 
             {
               if (lra_dump_file != NULL)
 		fprintf (lra_dump_file,
-			 "          alt=%d,overall=%d,losers=%d -- reject\n",
+			 "            alt=%d,overall=%d,losers=%d -- refuse\n",
 			 nalt, overall, losers);
               goto fail;
             }
@@ -2102,10 +2184,12 @@ 
 		     insn we can transform it into an add still by
 		     using this alternative.  */
 		  && GET_CODE (no_subreg_reg_operand[1]) != PLUS)))
-	/* We have a move insn and a new reload insn will be similar
-	   to the current insn.  We should avoid such situation as it
-	   results in LRA cycling.  */
-	overall += LRA_MAX_REJECT;
+	{
+	  /* We have a move insn and a new reload insn will be similar
+	     to the current insn.  We should avoid such situation as it
+	     results in LRA cycling.  */
+	  overall += LRA_MAX_REJECT;
+	}
       ok_p = true;
       curr_alt_dont_inherit_ops_num = 0;
       for (nop = 0; nop < early_clobbered_regs_num; nop++)
@@ -2159,6 +2243,11 @@ 
 	      losers++;
 	      /* Early clobber was already reflected in REJECT. */
 	      lra_assert (reject > 0);
+	      if (lra_dump_file != NULL)
+		fprintf
+		  (lra_dump_file,
+		   "            %d Conflict early clobber reload: reject--\n",
+		   i);
 	      reject--;
 	      overall += LRA_LOSER_COST_FACTOR - 1;
 	    }
@@ -2186,6 +2275,12 @@ 
 	      losers++;
 	      /* Early clobber was already reflected in REJECT. */
 	      lra_assert (reject > 0);
+	      if (lra_dump_file != NULL)
+		fprintf
+		  (lra_dump_file,
+		   "            %d Matched conflict early clobber reloads:"
+		   "reject--\n",
+		   i);
 	      reject--;
 	      overall += LRA_LOSER_COST_FACTOR - 1;
 	    }
@@ -4386,15 +4481,12 @@ 
 	     "	  ((((((((((((((((((((((((((((((((((((((((((((((((\n");
   if (call_save_p)
     {
-      enum machine_mode sec_mode;
+      enum machine_mode mode = GET_MODE (original_reg);
 
-#ifdef SECONDARY_MEMORY_NEEDED_MODE
-      sec_mode = SECONDARY_MEMORY_NEEDED_MODE (GET_MODE (original_reg));
-#else
-      sec_mode = GET_MODE (original_reg);
-#endif
-      new_reg = lra_create_new_reg (sec_mode, NULL_RTX,
-				    NO_REGS, "save");
+      mode = HARD_REGNO_CALLER_SAVE_MODE (hard_regno,
+					  hard_regno_nregs[hard_regno][mode],
+					  mode);
+      new_reg = lra_create_new_reg (mode, NULL_RTX, NO_REGS, "save");
     }
   else
     {