Message ID | CACgzC7DftPOTvmh3wVfJ=jq5d1MbmSDeW6hq3p-ndo8LK3rQGQ@mail.gmail.com |
---|---|
State | New |
Headers | show |
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 --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)))