re PR target/63986 ([SH] gcc.target/sh/pr51244-15.c failures)
authorOleg Endo <olegendo@gcc.gnu.org>
Sat, 22 Nov 2014 15:06:34 +0000 (15:06 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Sat, 22 Nov 2014 15:06:34 +0000 (15:06 +0000)
gcc/
PR target/63986
PR target/51244
* config/sh/sh.c (sh_is_logical_t_store_expr,
sh_try_omit_signzero_extend): Use rtx_insn* for insn argument.
(sh_split_movrt_negc_to_movt_xor): New function.
(sh_find_set_of_reg): Move to ...
* config/sh/sh-protos.h (sh_find_set_of_reg): ... here and convert
to template function.
(set_of_reg): Use rtx_insn* for insn member.
(sh_is_logical_t_store_expr, sh_try_omit_signzero_extend): Use
rtx_insn* for insn argument.
* config/sh/sh.md (movrt_negc, *movrt_negc): Split into movt-xor
sequence using new sh_split_movrt_negc_to_movt_xor function.
(movrt_xor): Allow also for SH2A.
(*movt_movrt): Delete insns and splits.

From-SVN: r217968

gcc/ChangeLog
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sh/sh.md

index 08ee16aa574ec364eb17885afdf9ac45d4364f6d..bbab5022ffd5e4f45641503adf8c13b76a1232fc 100644 (file)
@@ -1,3 +1,21 @@
+2014-11-22  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/63986
+       PR target/51244
+       * config/sh/sh.c (sh_is_logical_t_store_expr,
+       sh_try_omit_signzero_extend): Use rtx_insn* for insn argument.
+       (sh_split_movrt_negc_to_movt_xor): New function.
+       (sh_find_set_of_reg): Move to ...
+       * config/sh/sh-protos.h (sh_find_set_of_reg): ... here and convert
+       to template function.
+       (set_of_reg): Use rtx_insn* for insn member.
+       (sh_is_logical_t_store_expr, sh_try_omit_signzero_extend): Use
+       rtx_insn* for insn argument.
+       * config/sh/sh.md (movrt_negc, *movrt_negc): Split into movt-xor
+       sequence using new sh_split_movrt_negc_to_movt_xor function.
+       (movrt_xor): Allow also for SH2A.
+       (*movt_movrt): Delete insns and splits.
+
 2014-11-22  Marc Glisse  <marc.glisse@inria.fr>
 
        PR tree-optimization/60770
index e01b91e2db7946d9e7f41c00f0b710536e87c49f..262c4fb556add67ceb36079f32b022a7476ff686 100644 (file)
@@ -165,7 +165,7 @@ struct set_of_reg
 {
   /* The insn where sh_find_set_of_reg stopped looking.
      Can be NULL_RTX if the end of the insn list was reached.  */
-  rtx insn;
+  rtx_insn* insn;
 
   /* The set rtx of the specified reg if found, NULL_RTX otherwise.  */
   const_rtx set_rtx;
@@ -175,9 +175,47 @@ struct set_of_reg
   rtx set_src;
 };
 
-extern set_of_reg sh_find_set_of_reg (rtx reg, rtx insn, rtx_insn *(*stepfunc)(rtx));
-extern bool sh_is_logical_t_store_expr (rtx op, rtx insn);
-extern rtx sh_try_omit_signzero_extend (rtx extended_op, rtx insn);
+/* Given a reg rtx and a start insn, try to find the insn that sets the
+   specified reg by using the specified insn stepping function, such as 
+   'prev_nonnote_insn_bb'.  When the insn is found, try to extract the rtx
+   of the reg set.  */
+template <typename F> inline set_of_reg
+sh_find_set_of_reg (rtx reg, rtx_insn* insn, F stepfunc)
+{
+  set_of_reg result;
+  result.insn = insn;
+  result.set_rtx = NULL_RTX;
+  result.set_src = NULL_RTX;
+
+  if (!REG_P (reg) || insn == NULL_RTX)
+    return result;
+
+  for (result.insn = stepfunc (insn); result.insn != NULL_RTX;
+       result.insn = stepfunc (result.insn))
+    {
+      if (BARRIER_P (result.insn))
+       return result;
+      if (!NONJUMP_INSN_P (result.insn))
+       continue;
+      if (reg_set_p (reg, result.insn))
+       {
+         result.set_rtx = set_of (reg, result.insn);
+
+         if (result.set_rtx == NULL_RTX || GET_CODE (result.set_rtx) != SET)
+           return result;
+
+         result.set_src = XEXP (result.set_rtx, 1);
+         return result;
+       }
+    }
+
+  return result;
+}
+
+extern bool sh_is_logical_t_store_expr (rtx op, rtx_insn* insn);
+extern rtx sh_try_omit_signzero_extend (rtx extended_op, rtx_insn* insn);
+extern bool sh_split_movrt_negc_to_movt_xor (rtx_insn* curr_insn,
+                                            rtx operands[]);
 #endif /* RTX_CODE */
 
 extern void sh_cpu_cpp_builtins (cpp_reader* pfile);
index d6d50a4e8c1ef2746c92b32a23fb080e91923472..f578b43976b13bebb5334ec70ec9dae271003c51 100644 (file)
@@ -13503,47 +13503,10 @@ sh_find_equiv_gbr_addr (rtx_insn* insn, rtx mem)
   Manual insn combine support code.
 */
 
-/* Given a reg rtx and a start insn, try to find the insn that sets the
-   specified reg by using the specified insn stepping function, such as 
-   'prev_nonnote_insn_bb'.  When the insn is found, try to extract the rtx
-   of the reg set.  */
-set_of_reg
-sh_find_set_of_reg (rtx reg, rtx insn, rtx_insn *(*stepfunc)(rtx))
-{
-  set_of_reg result;
-  result.insn = insn;
-  result.set_rtx = NULL_RTX;
-  result.set_src = NULL_RTX;
-
-  if (!REG_P (reg) || insn == NULL_RTX)
-    return result;
-
-  for (result.insn = stepfunc (insn); result.insn != NULL_RTX;
-       result.insn = stepfunc (result.insn))
-    {
-      if (BARRIER_P (result.insn))
-       return result;
-      if (!NONJUMP_INSN_P (result.insn))
-       continue;
-      if (reg_set_p (reg, result.insn))
-       {
-         result.set_rtx = set_of (reg, result.insn);
-
-         if (result.set_rtx == NULL_RTX || GET_CODE (result.set_rtx) != SET)
-           return result;
-
-         result.set_src = XEXP (result.set_rtx, 1);
-         return result;
-       }
-    }
-
-  return result;
-}
-
 /* 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
-sh_is_logical_t_store_expr (rtx op, rtx insn)
+sh_is_logical_t_store_expr (rtx op, rtx_insn* insn)
 {
   if (!logical_operator (op, SImode))
     return false;
@@ -13579,7 +13542,7 @@ sh_is_logical_t_store_expr (rtx op, rtx insn)
    by a simple reg-reg copy.  If so, the replacement reg rtx is returned,
    NULL_RTX otherwise.  */
 rtx
-sh_try_omit_signzero_extend (rtx extended_op, rtx insn)
+sh_try_omit_signzero_extend (rtx extended_op, rtx_insn* insn)
 {
   if (REG_P (extended_op))
     extended_op = extended_op;
@@ -13609,6 +13572,42 @@ sh_try_omit_signzero_extend (rtx extended_op, rtx insn)
   return NULL_RTX;
 }
 
+/* Given the current insn, which is assumed to be a movrt_negc insn, try to
+   figure out whether it should be converted into a movt-xor sequence in
+   the movrt_negc splitter.
+   Returns true if insns have been modified and the splitter has succeeded.  */
+bool
+sh_split_movrt_negc_to_movt_xor (rtx_insn* curr_insn, rtx operands[])
+{
+  /* In cases such as
+       tst     r4,r4
+       mov     #-1,r1
+       negc    r1,r1
+       tst     r4,r4
+     we can replace the T bit clobbering negc with a movt-xor sequence and
+     eliminate the redundant comparison.
+     Because the xor insn depends on register allocation results, allow this
+     only before reload.  */
+  if (!can_create_pseudo_p ())
+    return false;
+
+  set_of_reg t_before_negc = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn,
+                                                prev_nonnote_insn_bb);
+  set_of_reg t_after_negc = sh_find_set_of_reg (get_t_reg_rtx (), curr_insn,
+                                               next_nonnote_insn_bb);
+
+  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))
+    {
+      emit_insn (gen_movrt_xor (operands[0], get_t_reg_rtx ()));
+      set_insn_deleted (t_after_negc.insn);
+      return true;
+    }
+  else
+    return false;
+}
+
 static void
 sh_emit_mode_set (int entity ATTRIBUTE_UNUSED, int mode,
                  int prev_mode, HARD_REG_SET regs_live ATTRIBUTE_UNUSED)
index 7b902953ac63fe21590d48fb16123c5b1876fd05..085a806e9f5a46c431f3a7449b210a688b925c52 100644 (file)
@@ -11445,13 +11445,21 @@ label:
   DONE;
 })
 
-(define_insn "movrt_negc"
+(define_insn_and_split "movrt_negc"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
+       (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
    (set (reg:SI T_REG) (const_int 1))
    (use (match_operand:SI 2 "arith_reg_operand" "r"))]
   "TARGET_SH1"
   "negc        %2,%0"
+  "&& 1"
+  [(const_int 0)]
+{
+  if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands))
+    DONE;
+  else
+    FAIL;
+}
   [(set_attr "type" "arith")])
 
 ;; The -1 constant will not be CSE-ed for the *movrt_negc pattern, but the
@@ -11460,17 +11468,25 @@ label:
 ;; generating a pseudo reg before reload.
 (define_insn_and_split "*movrt_negc"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (xor:SI (match_operand:SI 1 "t_reg_operand" "") (const_int 1)))
+       (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
    (clobber (match_scratch:SI 2 "=r"))
    (clobber (reg:SI T_REG))]
   "TARGET_SH1 && ! TARGET_SH2A"
   "#"
-  "&& reload_completed"
-  [(set (match_dup 2) (const_int -1))
-   (parallel
-       [(set (match_dup 0) (xor:SI (match_dup 1) (const_int 1)))
-       (set (reg:SI T_REG) (const_int 1))
-       (use (match_dup 2))])])
+  "&& 1"
+  [(const_int 0)]
+{
+  if (sh_split_movrt_negc_to_movt_xor (curr_insn, operands))
+    DONE;
+  else if (reload_completed)
+    {
+      emit_move_insn (operands[2], gen_int_mode (-1, SImode));
+      emit_insn (gen_movrt_negc (operands[0], operands[1], operands[2]));
+      DONE;
+    }
+  else
+    FAIL;
+})
 
 ;; Store the negated T bit in a reg using r0 and xor.  This one doesn't
 ;; clobber the T bit, which is useful when storing the T bit and the
@@ -11481,45 +11497,12 @@ label:
   [(set (match_operand:SI 0 "arith_reg_dest" "=z")
        (xor:SI (match_operand:SI 1 "t_reg_operand") (const_int 1)))
    (use (reg:SI T_REG))]
-  "TARGET_SH1 && !TARGET_SH2A"
+  "TARGET_SH1"
   "#"
   "&& reload_completed"
   [(set (match_dup 0) (reg:SI T_REG))
    (set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))])
 
-;; Store the T bit and the negated T bit in two regs in parallel.  There is
-;; no real insn to do that, but specifying this pattern will give combine
-;; some opportunities.
-(define_insn_and_split "*movt_movrt"
-  [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
-                  (match_operand:SI 1 "negt_reg_operand"))
-             (set (match_operand:SI 2 "arith_reg_dest")
-                  (match_operand:SI 3 "t_reg_operand"))])]
-  "TARGET_SH1"
-  "#"
-  "&& 1"
-  [(const_int 0)]
-{
-  rtx i = TARGET_SH2A
-         ? gen_movrt (operands[0], get_t_reg_rtx ())
-         : gen_movrt_xor (operands[0], get_t_reg_rtx ());
-  
-  emit_insn (i);
-  emit_insn (gen_movt (operands[2], get_t_reg_rtx ()));
-  DONE;
-})
-
-(define_insn_and_split "*movt_movrt"
-  [(parallel [(set (match_operand:SI 0 "arith_reg_dest")
-                  (match_operand:SI 1 "t_reg_operand"))
-             (set (match_operand:SI 2 "arith_reg_dest")
-                  (match_operand:SI 3 "negt_reg_operand"))])]
-  "TARGET_SH1"
-  "#"
-  "&& 1"
-  [(parallel [(set (match_dup 2) (match_dup 3))
-             (set (match_dup 0) (match_dup 1))])])
-
 ;; Use negc to store the T bit in a MSB of a reg in the following way:
 ;;     T = 1: 0x80000000 -> reg
 ;;     T = 0: 0x7FFFFFFF -> reg