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.c...@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;