diff mbox

[loop2_invariant] Pre-check invariants

Message ID CACgzC7DftPOTvmh3wVfJ=jq5d1MbmSDeW6hq3p-ndo8LK3rQGQ@mail.gmail.com
State New
Headers show

Commit Message

Zhenqiang Chen June 10, 2014, 9:55 a.m. UTC
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.

     return;

Comments

Steven Bosscher June 10, 2014, 11:01 a.m. UTC | #1
On Tue, Jun 10, 2014 at 11:55 AM, Zhenqiang Chen wrote:
>
>         * loop-invariant.c (find_invariant_insn): Skip invariants, which
>         can not make a valid insn during replacement in move_invariant_reg.
>
> --- 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)

Why only do this with (flag_ira_loop_pressure && df_live)? If the
invariant can't be moved, we should ignore it regardless of whether
register pressure is taken into account.


> +    {
> +      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;


Can you put your new check between "may_assign_reg_p (dest)" and
"check_maybe_invariant"? The may_assign_reg_p check is cheap and
triggers quite often.

Looks good to me otherwise.

Ciao!
Steven
diff mbox

Patch

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