diff options
author | Zhenqiang Chen <zhenqiang.chen@linaro.org> | 2014-06-23 02:47:54 +0000 |
---|---|---|
committer | Zhenqiang Chen <zqchen@gcc.gnu.org> | 2014-06-23 02:47:54 +0000 |
commit | 2c97f4728c9e92137401c5a16197b74f25bb1992 (patch) | |
tree | d52146a9a8d50d107fb3fd1d7fee7e2900245fdb /gcc | |
parent | 0001689b2edda047cbc5e6d057d8c1491282243b (diff) | |
download | gcc-2c97f4728c9e92137401c5a16197b74f25bb1992.zip gcc-2c97f4728c9e92137401c5a16197b74f25bb1992.tar.gz gcc-2c97f4728c9e92137401c5a16197b74f25bb1992.tar.bz2 |
loop-invariant.c (pre_check_invariant_p): New function.
2014-06-23 Zhenqiang Chen <zhenqiang.chen@linaro.org>
* loop-invariant.c (pre_check_invariant_p): New function.
(find_invariant_insn): Call pre_check_invariant_p.
From-SVN: r211885
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/loop-invariant.c | 36 |
2 files changed, 40 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bc72a7f..105f4ac 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2014-06-23 Zhenqiang Chen <zhenqiang.chen@linaro.org> + + * loop-invariant.c (pre_check_invariant_p): New function. + (find_invariant_insn): Call pre_check_invariant_p. + 2014-06-22 Richard Henderson <rth@redhat.com> PR target/61565 diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c index f683d8c..25e63e4 100644 --- a/gcc/loop-invariant.c +++ b/gcc/loop-invariant.c @@ -839,6 +839,39 @@ check_dependencies (rtx insn, bitmap depends_on) return true; } +/* Pre-check candidate DEST to skip the one which can not make a valid insn + during move_invariant_reg. SIMPLE is to skip HARD_REGISTER. */ +static bool +pre_check_invariant_p (bool simple, rtx dest) +{ + if (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_EACH_INSN_INFO_DEF (def_rec, insn_info) + if (DF_REF_REGNO (def_rec) == i) + { + /* Multi definitions at this stage, most likely are due to + instruction constraints, 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 false; + } + } + } + return true; +} + /* Finds invariant in INSN. ALWAYS_REACHED is true if the insn is always executed. ALWAYS_EXECUTED is true if the insn is always executed, unless the program ends due to a function call. */ @@ -868,7 +901,8 @@ find_invariant_insn (rtx insn, bool always_reached, bool always_executed) || HARD_REGISTER_P (dest)) simple = false; - if (!may_assign_reg_p (SET_DEST (set)) + if (!may_assign_reg_p (dest) + || !pre_check_invariant_p (simple, dest) || !check_maybe_invariant (SET_SRC (set))) return; |