sh-protos.h (sh_cbranch_distance): Declare new function.
authorOleg Endo <olegendo@gcc.gnu.org>
Sat, 7 May 2016 01:43:12 +0000 (01:43 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Sat, 7 May 2016 01:43:12 +0000 (01:43 +0000)
gcc/
* config/sh/sh-protos.h (sh_cbranch_distance): Declare new function.
* config/sh/sh.c (sh_cbranch_distance): Implement it.
* config/sh/sh.md (branch_zero): Remove define_attr.
(define_delay): Disable delay slot if branch distance is one insn.

From-SVN: r235993

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

index 156359254af1ab8bf1cc9843ff924ee6e9394cd8..ce10e79d4e51f2c8ac892335d1dea643c950774b 100644 (file)
@@ -1,3 +1,10 @@
+2016-05-07  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       * config/sh/sh-protos.h (sh_cbranch_distance): Declare new function.
+       * config/sh/sh.c (sh_cbranch_distance): Implement it.
+       * config/sh/sh.md (branch_zero): Remove define_attr.
+       (define_delay): Disable delay slot if branch distance is one insn.
+
 2016-05-06  Uros Bizjak  <ubizjak@gmail.com>
 
        * config/i386/i386.md (LEAMODE): New mode attribute.
index c47e2eade1534134c27e9feae98cbbbbd34bed6a..d302394d52e46897ffdf57dfc8bf5dbe30e22239 100644 (file)
@@ -348,6 +348,18 @@ private:
 
 extern sh_treg_insns sh_split_treg_set_expr (rtx x, rtx_insn* curr_insn);
 
+enum
+{
+  /* An effective conditional branch distance of zero bytes is impossible.
+     Hence we can use it to designate an unknown value.  */
+  unknown_cbranch_distance = 0u,
+  infinite_cbranch_distance = ~0u
+};
+
+unsigned int
+sh_cbranch_distance (rtx_insn* cbranch_insn,
+                    unsigned int max_dist = infinite_cbranch_distance);
+
 #endif /* RTX_CODE */
 
 extern void sh_cpu_cpp_builtins (cpp_reader* pfile);
index 809f679f807162b23f2d6d1482bc4599d5c3ab56..6d1d1a38eeb7aff05bd83e2a2b050ff09720d042 100644 (file)
@@ -1928,6 +1928,52 @@ sh_fixed_condition_code_regs (unsigned int* p1, unsigned int* p2)
   return true;
 }
 
+/* Try to calculate the branch distance of a conditional branch in bytes.
+
+   FIXME: Because of PR 59189 we can't use the CFG here.  Instead just
+   walk from this insn into the next (fall-through) basic block and see if
+   we hit the label.  */
+unsigned int
+sh_cbranch_distance (rtx_insn* _cbranch_insn, unsigned int max_dist)
+{
+  rtx_jump_insn* cbranch_insn = safe_as_a<rtx_jump_insn*> (_cbranch_insn);
+
+  if (dump_file)
+    {
+      fprintf (dump_file, "sh_cbranch_distance insn = \n");
+      print_rtl_single (dump_file, cbranch_insn);
+    }
+
+  unsigned int dist = 0;
+
+  for (rtx_insn* i = next_nonnote_insn (cbranch_insn);
+       i != NULL && dist < max_dist; i = next_nonnote_insn (i))
+    {
+      const unsigned int i_len = get_attr_length (i);
+      dist += i_len;
+
+      if (dump_file)
+       fprintf (dump_file, "  insn %d  length = %u  dist = %u\n",
+                INSN_UID (i), i_len, dist);
+
+      if (rtx_code_label* l = dyn_cast<rtx_code_label*> (i))
+       {
+         if (l == cbranch_insn->jump_target ())
+           {
+             if (dump_file)
+               fprintf (dump_file, "  cbranch dist = %u\n", dist);
+             return dist;
+           }
+         break;
+       }
+    }
+
+  if (dump_file)
+    fprintf (dump_file, "  cbranch dist = unknown\n");
+
+  return unknown_cbranch_distance;
+}
+
 enum rtx_code
 prepare_cbranch_operands (rtx *operands, machine_mode mode,
                          enum rtx_code comparison)
index 39270ce8e92bccecd1ab90223650b7801af011cd..406721dc7369ff665f6001ee41f59d3025e63fab 100644 (file)
 (define_attr "is_sfunc" ""
   (if_then_else (eq_attr "type" "sfunc") (const_int 1) (const_int 0)))
 
-(define_attr "branch_zero" "yes,no"
-  (cond [(eq_attr "type" "!cbranch") (const_string "no")
-        (ne (symbol_ref "(next_active_insn (insn)\
-                          == (prev_active_insn\
-                              (XEXP (SET_SRC (PATTERN (insn)), 1))))\
-                         && get_attr_length (next_active_insn (insn)) == 2")
-            (const_int 0))
-        (const_string "yes")]
-       (const_string "no")))
-
 ;; SH4 Double-precision computation with double-precision result -
 ;; the two halves are ready at different times.
 (define_attr "dfp_comp" "yes,no"
        (eq_attr "type" "!pstore,prget")) (nil) (nil)])
 
 ;; Conditional branches with delay slots are available starting with SH2.
+;; If zero displacement conditional branches are fast, disable the delay
+;; slot if the branch jumps over only one 2-byte insn.
 (define_delay
-  (and (eq_attr "type" "cbranch") (match_test "TARGET_SH2"))
+  (and (eq_attr "type" "cbranch")
+       (match_test "TARGET_SH2")
+       (not (and (match_test "TARGET_ZDCBRANCH")
+                (match_test "sh_cbranch_distance (insn, 4) == 2"))))
   [(eq_attr "cond_delay_slot" "yes") (nil) (nil)])
 \f
 ;; -------------------------------------------------------------------------