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.preudho...@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.


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)
        {

=== 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



Reply via email to