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