diff options
author | Oleg Endo <olegendo@gcc.gnu.org> | 2014-12-01 06:50:06 +0000 |
---|---|---|
committer | Oleg Endo <olegendo@gcc.gnu.org> | 2014-12-01 06:50:06 +0000 |
commit | 9270a54f3841ab4a3b0facd6e23d7b3063a30fbe (patch) | |
tree | 0957f6d2755068f1e1ddc55033246c83b34176e8 /gcc | |
parent | 975fbd84776bc813d2c6cc020682b1e692400d38 (diff) | |
download | gcc-9270a54f3841ab4a3b0facd6e23d7b3063a30fbe.zip gcc-9270a54f3841ab4a3b0facd6e23d7b3063a30fbe.tar.gz gcc-9270a54f3841ab4a3b0facd6e23d7b3063a30fbe.tar.bz2 |
re PR target/63986 ([SH] gcc.target/sh/pr51244-15.c failures)
gcc/
PR target/63986
PR target/51244
* config/sh/sh.c (sh_unspec_insn_p,
sh_insn_operands_modified_between_p): New functions.
(sh_split_movrt_negc_to_movt_xor): Do not delete insn if its operands
are modified or if it has side effects, may trap or is volatile.
From-SVN: r218200
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/config/sh/sh.c | 50 |
2 files changed, 58 insertions, 1 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 075ccbf..a428bf0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2014-12-01 Oleg Endo <olegendo@gcc.gnu.org> + + PR target/63986 + PR target/51244 + * config/sh/sh.c (sh_unspec_insn_p, + sh_insn_operands_modified_between_p): New functions. + (sh_split_movrt_negc_to_movt_xor): Do not delete insn if its operands + are modified or if it has side effects, may trap or is volatile. + 2014-11-29 Jakub Jelinek <jakub@redhat.com> * gimple-expr.h (create_tmp_var_raw, create_tmp_var, diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index f578b43..4012c9a 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -13503,6 +13503,47 @@ sh_find_equiv_gbr_addr (rtx_insn* insn, rtx mem) Manual insn combine support code. */ +/* Return true if the specified insn contains any UNSPECs or + UNSPEC_VOLATILEs. */ +static bool +sh_unspec_insn_p (rtx_insn* insn) +{ + bool result = false; + + struct note_uses_func + { + static void + func (rtx* x, void* data) + { + if (GET_CODE (*x) == UNSPEC || GET_CODE (*x) == UNSPEC_VOLATILE) + *(static_cast<bool*> (data)) = true; + } + }; + + note_uses (&PATTERN (insn), note_uses_func::func, &result); + return result; +} + +/* Return true if the register operands of the specified insn are modified + between the specified from and to insns (exclusive of those two). */ +static bool +sh_insn_operands_modified_between_p (rtx_insn* operands_insn, + const rtx_insn* from, + const rtx_insn* to) +{ + /* FIXME: Return true for multiple sets for now. */ + rtx s = single_set (operands_insn); + if (s == NULL_RTX) + return true; + + subrtx_iterator::array_type array; + FOR_EACH_SUBRTX (i, array, SET_SRC (s), ALL) + if ((REG_P (*i) || SUBREG_P (*i)) && reg_set_between_p (*i, from, to)) + return true; + + return false; +} + /* Given an op rtx and an insn, try to find out whether the result of the specified op consists only of logical operations on T bit stores. */ bool @@ -13598,7 +13639,14 @@ sh_split_movrt_negc_to_movt_xor (rtx_insn* curr_insn, rtx operands[]) if (t_before_negc.set_rtx != NULL_RTX && t_after_negc.set_rtx != NULL_RTX && rtx_equal_p (t_before_negc.set_rtx, t_after_negc.set_rtx) - && !reg_used_between_p (get_t_reg_rtx (), curr_insn, t_after_negc.insn)) + && !reg_used_between_p (get_t_reg_rtx (), curr_insn, t_after_negc.insn) + && !sh_insn_operands_modified_between_p (t_before_negc.insn, + t_before_negc.insn, + t_after_negc.insn) + && !sh_unspec_insn_p (t_after_negc.insn) + && !volatile_insn_p (PATTERN (t_after_negc.insn)) + && !side_effects_p (PATTERN (t_after_negc.insn)) + && !may_trap_or_fault_p (PATTERN (t_after_negc.insn))) { emit_insn (gen_movrt_xor (operands[0], get_t_reg_rtx ())); set_insn_deleted (t_after_negc.insn); |