re PR target/63986 ([SH] gcc.target/sh/pr51244-15.c failures)
authorOleg Endo <olegendo@gcc.gnu.org>
Mon, 1 Dec 2014 06:50:06 +0000 (06:50 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Mon, 1 Dec 2014 06:50:06 +0000 (06:50 +0000)
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

gcc/ChangeLog
gcc/config/sh/sh.c

index 075ccbfca02e3fcfffc1de2ac4fa612b66c00e56..a428bf067328ea93d3c472027e817d9fabb84a58 100644 (file)
@@ -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,
index f578b43976b13bebb5334ec70ec9dae271003c51..4012c9a4f2428845dce40f4062621123a34087b0 100644 (file)
@@ -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);