This fixes a fallout that actually goes back to 5.0 but went unnoticed.
authorOleg Endo <olegendo@gcc.gnu.org>
Sun, 25 Sep 2016 06:59:37 +0000 (06:59 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Sun, 25 Sep 2016 06:59:37 +0000 (06:59 +0000)
The costs for movt and movrt type of insns were not correctly reported
and ifcvt thus made some bad choices for SH.  A new cset_zero pattern
variant is also required to fix the matching for some recent changes
in the middle end.

gcc/
PR target/51244
* config/sh/sh.c (sh_movt_set_dest, sh_movrt_set_dest): Add overloads.
(sh_rtx_costs): Handle SET of movt and movrt patterns.
* cnofig/sh/sh-protos.h (sh_movt_set_dest, sh_movrt_set_dest): Forward
declare new overloads.
* config/sh/sh.md (*cset_zero): Add variant that takes a treg_set_expr
operand.

gcc/testsuite/
PR target/51244
* gcc.target/sh/pr51244-11.c: Add more detailed expected insn matching.

From-SVN: r240471

gcc/ChangeLog
gcc/config/sh/sh-protos.h
gcc/config/sh/sh.c
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr51244-11.c

index ab5e5adfdd3c5c3901daebdcacf879ade5a8ceb9..ce6841b6894f6c7e85f6c1b7f93162ea9aaa4a8b 100644 (file)
@@ -1,3 +1,13 @@
+2016-09-25  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/51244
+       * config/sh/sh.c (sh_movt_set_dest, sh_movrt_set_dest): Add overloads.
+       (sh_rtx_costs): Handle SET of movt and movrt patterns.
+       * cnofig/sh/sh-protos.h (sh_movt_set_dest, sh_movrt_set_dest): Forward
+       declare new overloads.
+       * config/sh/sh.md (*cset_zero): Add variant that takes a treg_set_expr
+       operand.
+
 2016-09-24  Aaron Sawdey  <acsawdey@linux.vnet.ibm.com>
 
        * config/rs6000/rs6000.c (expand_block_compare, do_load_for_compare):
index f611dabd6ad0761b0ee3985b4992d6bca1791aa0..1bac4030d0b84c1aaf418ee918a90b18bde28f33 100644 (file)
@@ -235,7 +235,9 @@ extern void sh_split_tst_subregs (rtx_insn* curr_insn,
 
 extern bool sh_is_nott_insn (const rtx_insn* i);
 extern rtx sh_movt_set_dest (const rtx_insn* i);
+extern rtx sh_movt_set_dest (const_rtx i);
 extern rtx sh_movrt_set_dest (const rtx_insn* i);
+extern rtx sh_movrt_set_dest (const_rtx i);
 
 inline bool sh_is_movt_insn (const rtx_insn* i)
 {
index a9b5a14e21101a3e6ddc951a8a41c0813136b4a5..bfa248d56df1dfb4a3e836db47282efc880f91b5 100644 (file)
@@ -3208,6 +3208,10 @@ sh_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
                                  / mov_insn_size (mode, TARGET_SH2A));
          return true;
         }
+
+      if (sh_movt_set_dest (x) != NULL || sh_movrt_set_dest (x) != NULL)
+       return COSTS_N_INSNS (1);
+
       return false;
 
     /* The cost of a mem access is mainly the cost of the address mode.  */
@@ -11703,13 +11707,15 @@ sh_is_nott_insn (const rtx_insn* i)
 rtx
 sh_movt_set_dest (const rtx_insn* i)
 {
-  if (i == NULL)
-    return NULL;
+  return i == NULL ? NULL : sh_movt_set_dest (PATTERN (i));
+}
 
-  const_rtx p = PATTERN (i);
-  return GET_CODE (p) == SET
-        && arith_reg_dest (XEXP (p, 0), SImode)
-        && t_reg_operand (XEXP (p, 1), VOIDmode) ? XEXP (p, 0) : NULL;
+rtx
+sh_movt_set_dest (const_rtx pat)
+{
+  return GET_CODE (pat) == SET
+        && arith_reg_dest (XEXP (pat, 0), SImode)
+        && t_reg_operand (XEXP (pat, 1), VOIDmode) ? XEXP (pat, 0) : NULL;
 }
 
 /* Given an insn, check whether it's a 'movrt' kind of insn, i.e. an insn
@@ -11718,18 +11724,20 @@ sh_movt_set_dest (const rtx_insn* i)
 rtx
 sh_movrt_set_dest (const rtx_insn* i)
 {
-  if (i == NULL)
-    return NULL;
-
-  const_rtx p = PATTERN (i);
+  return i == NULL ? NULL : sh_movrt_set_dest (PATTERN (i));
+}
 
+rtx
+sh_movrt_set_dest (const_rtx pat)
+{
   /* The negc movrt replacement is inside a parallel.  */
-  if (GET_CODE (p) == PARALLEL)
-    p = XVECEXP (p, 0, 0);
+  if (GET_CODE (pat) == PARALLEL)
+    pat = XVECEXP (pat, 0, 0);
+
+  return GET_CODE (pat) == SET
+        && arith_reg_dest (XEXP (pat, 0), SImode)
+        && negt_reg_operand (XEXP (pat, 1), VOIDmode) ? XEXP (pat, 0) : NULL;
 
-  return GET_CODE (p) == SET
-        && arith_reg_dest (XEXP (p, 0), SImode)
-        && negt_reg_operand (XEXP (p, 1), VOIDmode) ? XEXP (p, 0) : NULL;
 }
 
 /* Given an insn and a reg number, tell whether the reg dies or is unused
index 25e03efc313d3df6cfabbac9be273c33085eba62..dcb31eb3a0944d55e0d8477666dac073b243955f 100644 (file)
   [(set_attr "type" "arith") ;; poor approximation
    (set_attr "length" "4")])
 
+(define_insn_and_split "*cset_zero"
+  [(set (match_operand:SI 0 "arith_reg_dest")
+       (if_then_else:SI (match_operand 1 "treg_set_expr_not_const01")
+                        (match_dup 0) (const_int 0)))
+   (clobber (reg:SI T_REG))]
+  "TARGET_SH1 && TARGET_ZDCBRANCH && can_create_pseudo_p ()"
+  "#"
+  "&& 1"
+  [(set (match_dup 0)
+       (if_then_else:SI (match_dup 1) (match_dup 0) (const_int 0)))]
+{
+  sh_treg_insns ti = sh_split_treg_set_expr (operands[1], curr_insn);
+  if (ti.remove_trailing_nott ())
+    operands[1] = gen_rtx_EQ (SImode, get_t_reg_rtx (), const0_rtx);
+  else
+    operands[1] = gen_rtx_EQ (SImode, get_t_reg_rtx (), const1_rtx);
+})
+
 (define_expand "cstoresf4"
   [(set (match_operand:SI 0 "register_operand")
        (match_operator:SI 1 "ordered_comparison_operator"
index ae952cb69fd9d8de13ec5d07aeddb79a0801e680..4fc22c4e65f1362f59a671da763d9a50053d9421 100644 (file)
@@ -1,3 +1,8 @@
+2016-09-25  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/51244
+       * gcc.target/sh/pr51244-11.c: Add more detailed expected insn matching.
+
 2016-09-24  Dominique d'Humieres  <dominiq@lps.ens.fr>
 
        * gfortran.dg/coarray_lib_comm_1.f90: Really fix test
index fea7f6cfa856dff1f4ec20d664af9a313bfc6c7e..f0582692d8eb3cfa345a5c542c136fceb6e44f9e 100644 (file)
@@ -1,8 +1,11 @@
 /* Check that zero-displacement branches are used instead of branch-free
-   execution patterns.  */
+   execution patterns.
+   This is usually handled by the *cset_zero patterns.  */
 /* { dg-do compile }  */
-/* { dg-options "-O1 -mzdcbranch" } */
-/* { dg-final { scan-assembler-not "subc|and" } } */
+/* { dg-options "-O1 -mzdcbranch" }  */
+/* { dg-final { scan-assembler-not "subc|and|bra" } }  */
+/* { dg-final { scan-assembler-times "bf\t0f" 1 } }  */
+/* { dg-final { scan-assembler-times "bt\t0f" 1 } }  */
 
 int*
 test_00 (int* s)