diff mbox

Add force option to find_best_rename_reg in regrename pass

Message ID 002901d00011$3b2726d0$b1757470$@arm.com
State New
Headers show

Commit Message

Thomas Preud'homme Nov. 14, 2014, 1:45 p.m. UTC
We are planning to introduce a new optimization in aarch64 backend, similar to the FP load balancing pass in the LLVM project [1]. This pass would be core specific and involve doing some register renaming. An RFC version of this patch should be posted later today. As part of this pass, we want to rename a register to any register following some specific constraints. We wanted to reuse the global (non static) find_best_rename_reg function as does the c6x backend but this function is a bit too specific to the register renaming pass.

[1] http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/AArch64/AArch64A57FPLoadBalancing.cpp?view=markup

It looks at register that respect the constraints of all the instructions in the set and tries to pick one in the preferred class for all the instructions involved. This is generally useful for any pass that wants to do register renaming. However it also contains some logic to only select the register that also haven't been used for a longer time than the register that should be replaced. This bit is specific to the register renaming pass and makes the function unusable for this new pass as a result which forces us to do a copy of the function.

This patch adds an extra parameter to skip this check and only consider the constraints and tries to pick a register in the preferred class.


ChangeLog entry is as follows:

2014-11-14  Thomas Preud'homme  <thomas.preudhomme@arm.com>

        * regrename.c (find_best_rename_reg): Rename to ...
        (find_rename_reg): This. Also add a parameter to skip tick check.
        * regrename.h: Likewise.
        * config/c6x/c6x.c: Adapt to above renaming.



=== Testing ===

c6x backend is the only user beyond regrename itself to use this API.
* Therefore a tic6x-none-elf cross-compiler was built with this patch to check that the change doesn't break that target.
* Testsuite run on a bootstrapped x86_64-linux-gnu GCC with -frename-register shows no regression

Is this ok for trunk?

Best regards,

Thomas

Comments

Eric Botcazou Nov. 15, 2014, 11:45 a.m. UTC | #1
> It looks at register that respect the constraints of all the instructions in
> the set and tries to pick one in the preferred class for all the
> instructions involved. This is generally useful for any pass that wants to
> do register renaming. However it also contains some logic to only select
> the register that also haven't been used for a longer time than the
> register that should be replaced. This bit is specific to the register
> renaming pass and makes the function unusable for this new pass as a result
> which forces us to do a copy of the function.
>
> This patch adds an extra parameter to skip this check and only consider the
> constraints and tries to pick a register in the preferred class.

OK on principle but...

> 2014-11-14  Thomas Preud'homme  <thomas.preudhomme@arm.com>
> 
>         * regrename.c (find_best_rename_reg): Rename to ...
>         (find_rename_reg): This. Also add a parameter to skip tick check.
>         * regrename.h: Likewise.
>         * config/c6x/c6x.c: Adapt to above renaming.

Missing function in config/c6x/c6x.c entry.

> @@ -408,8 +410,13 @@ find_best_rename_reg (du_head_p this_head, enum
> reg_class super_class, && ((pass == 0
>  		   && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
>  					  best_new_reg))
> -		  || tick[best_new_reg] > tick[new_reg]))
> -	    best_new_reg = new_reg;
> +		  || !best_rename || tick[best_new_reg] > tick[new_reg]))
> +	    {
> +	      if (best_rename)
> +		best_new_reg = new_reg;
> +	      else
> +		return new_reg;
> +	    }
>  	}
>        if (pass == 0 && best_new_reg != old_reg)
>  	break;

Please write it like so:

	  if (!check_new_reg_p (old_reg, new_reg, this_head, *unavailable))
	    continue;

	  if (!best_rename)
	    return new_reg;

	  /* In the first pass, we force the renaming of registers that
	     don't belong to PREFERRED_CLASS to registers that do, even
	     though the latters were used not very long ago.  *
	  if ((pass == 0
		 && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
					  best_new_reg))
		  || tick[best_new_reg] > tick[new_reg]))
	    best_new_reg = new_reg;
diff mbox

Patch

diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index 06319d0..6aca1e3 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -3513,7 +3513,8 @@  try_rename_operands (rtx_insn *head, rtx_insn *tail, unit_req_table reqs,
   COMPL_HARD_REG_SET (unavailable, reg_class_contents[(int) super_class]);
 
   old_reg = this_head->regno;
-  best_reg = find_best_rename_reg (this_head, super_class, &unavailable, old_reg);
+  best_reg = find_rename_reg (this_head, super_class, &unavailable, old_reg,
+			      true);
 
   regrename_do_replace (this_head, best_reg);
 
diff --git a/gcc/regrename.h b/gcc/regrename.h
index 03b7164..05c78ad 100644
--- a/gcc/regrename.h
+++ b/gcc/regrename.h
@@ -89,8 +89,8 @@  extern void regrename_init (bool);
 extern void regrename_finish (void);
 extern void regrename_analyze (bitmap);
 extern du_head_p regrename_chain_from_id (unsigned int);
-extern int find_best_rename_reg (du_head_p, enum reg_class, HARD_REG_SET *,
-				 int);
+extern int find_rename_reg (du_head_p, enum reg_class, HARD_REG_SET *, int,
+			    bool);
 extern void regrename_do_replace (du_head_p, int);
 
 #endif
diff --git a/gcc/regrename.c b/gcc/regrename.c


index 66f562b..5de7826 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -357,11 +357,13 @@  check_new_reg_p (int reg ATTRIBUTE_UNUSED, int new_reg,
 /* For the chain THIS_HEAD, compute and return the best register to
    rename to.  SUPER_CLASS is the superunion of register classes in
    the chain.  UNAVAILABLE is a set of registers that cannot be used.
-   OLD_REG is the register currently used for the chain.  */
+   OLD_REG is the register currently used for the chain.  BEST_RENAME
+   controls whether the register chosen must be better than the
+   current one or just respect the given constraint.  */
 
 int
-find_best_rename_reg (du_head_p this_head, enum reg_class super_class,
-		      HARD_REG_SET *unavailable, int old_reg)
+find_rename_reg (du_head_p this_head, enum reg_class super_class,
+		 HARD_REG_SET *unavailable, int old_reg, bool best_rename)
 {
   bool has_preferred_class;
   enum reg_class preferred_class;
@@ -408,8 +410,13 @@  find_best_rename_reg (du_head_p this_head, enum reg_class super_class,
 	      && ((pass == 0
 		   && !TEST_HARD_REG_BIT (reg_class_contents[preferred_class],
 					  best_new_reg))
-		  || tick[best_new_reg] > tick[new_reg]))
-	    best_new_reg = new_reg;
+		  || !best_rename || tick[best_new_reg] > tick[new_reg]))
+	    {
+	      if (best_rename)
+		best_new_reg = new_reg;
+	      else
+		return new_reg;
+	    }
 	}
       if (pass == 0 && best_new_reg != old_reg)
 	break;
@@ -480,8 +487,8 @@  rename_chains (void)
       if (n_uses < 2)
 	continue;
 
-      best_new_reg = find_best_rename_reg (this_head, super_class,
-					   &this_unavailable, reg);
+      best_new_reg = find_rename_reg (this_head, super_class,
+				      &this_unavailable, reg, true);
 
       if (dump_file)
 	{