This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH, loop2_invariant] Pre-check invariants


Hi,

During tests, I found some invariants could not be replaced at the
last stage. If we can identify such invariants earlier, we can skip
them and give the chance to other invariants.  So the patch pre-checks
candidates to skip the one which can not make a valid insn during
replacement in move_invariant_reg.

Bootstrap and no make check regression on X86-64.
Bootstrap and no make check regression on X86-64 with
flag_ira_loop_pressure = true.

OK for trunk?

Thanks!
-Zhenqiang

ChangeLog:
2014-06-10  Zhenqiang Chen  <zhenqiang.chen@linaro.org>

        * loop-invariant.c (find_invariant_insn): Skip invariants, which
        can not make a valid insn during replacement in move_invariant_reg.

diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index c43206a..7be4b29 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -881,6 +881,35 @@ find_invariant_insn (rtx insn, bool
always_reached, bool always_executed)
       || HARD_REGISTER_P (dest))
     simple = false;

+  /* Pre-check candidate to skip the one which can not make a valid insn
+     during move_invariant_reg.  */
+  if (flag_ira_loop_pressure && df_live && simple
+      && REG_P (dest) && DF_REG_DEF_COUNT (REGNO (dest)) > 1)
+    {
+      df_ref use;
+      rtx ref;
+      unsigned int i = REGNO (dest);
+      struct df_insn_info *insn_info;
+      df_ref *def_rec;
+
+      for (use = DF_REG_USE_CHAIN (i); use; use = DF_REF_NEXT_REG (use))
+       {
+         ref = DF_REF_INSN (use);
+         insn_info = DF_INSN_INFO_GET (ref);
+
+         for (def_rec = DF_INSN_INFO_DEFS (insn_info); *def_rec; def_rec++)
+           if (DF_REF_REGNO (*def_rec) == i)
+             {
+               /* Multi definitions at this stage, most likely are due to
+                  instruction constrain, which requires both read and write
+                  on the same register.  Since move_invariant_reg is not
+                  powerful enough to handle such cases, just ignore the INV
+                  and leave the chance to others.  */
+               return;
+             }
+       }
+    }
+
   if (!may_assign_reg_p (SET_DEST (set))
       || !check_maybe_invariant (SET_SRC (set)))
     return;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]