OSDN Git Service

PR target/49486
authorkkojima <kkojima@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Sep 2011 21:43:01 +0000 (21:43 +0000)
committerkkojima <kkojima@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Sep 2011 21:43:01 +0000 (21:43 +0000)
* config/sh/sh.md (negdi2): Move expansion into split to
allow more combination options.  Add T_REG clobber.
(abssi2): New expander.
(*negdi2, *abssi2, *negabssi2): New insns.
(cneg): Change from insn to insn_and_split.  Rename to
negsi_cond.  Add alternative for non-SH4.
* gcc.target/sh/pr49468-si.c: New.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@179320 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr49468-si.c [new file with mode: 0644]

index 98d926a..2aae5aa 100644 (file)
@@ -1,3 +1,13 @@
+2011-09-28  Oleg Endo  <oleg.endo@t-online.de>
+
+       PR target/49486
+       * config/sh/sh.md (negdi2): Move expansion into split to
+       allow more combination options.  Add T_REG clobber.
+       (abssi2): New expander.
+       (*negdi2, *abssi2, *negabssi2): New insns.
+       (cneg): Change from insn to insn_and_split.  Rename to
+       negsi_cond.  Add alternative for non-SH4.
+
 2011-09-28  Richard Sandiford  <richard.sandiford@linaro.org>
 
        * config/arm/neon.md (neon_move_lo_quad_<mode>): Delete.
index f2c4e55..63cb939 100644 (file)
@@ -4282,28 +4282,39 @@ label:
   "sub r63, %1, %0"
   [(set_attr "type" "arith_media")])
 
+
+
+;; Don't expand immediately because otherwise neg:DI (abs:DI) will not be
+;; combined.
 (define_expand "negdi2"
-  [(set (match_operand:DI 0 "arith_reg_operand" "")
-       (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))]
+  [(set (match_operand:DI 0 "arith_reg_dest" "")
+       (neg:DI (match_operand:DI 1 "arith_reg_operand" "")))
+   (clobber (reg:SI T_REG))]
   ""
+  "")
+
+(define_insn_and_split "*negdi2"
+  [(set (match_operand:DI 0 "arith_reg_dest" "=r")
+       (neg:DI (match_operand:DI 1 "arith_reg_operand" "r")))]
+  "TARGET_SH1"
+  "#"
+  "TARGET_SH1"
+  [(const_int 0)]
   "
 {
-  if (TARGET_SH1)
-    {
-      int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
-      int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
+  int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
+  int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
 
-      rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
-      rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
+  rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
+  rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
 
-      rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
-      rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
+  rtx low_dst = operand_subword (operands[0], low_word, 1, DImode);
+  rtx high_dst = operand_subword (operands[0], high_word, 1, DImode);
 
-      emit_insn (gen_clrt ());
-      emit_insn (gen_negc (low_dst, low_src));
-      emit_insn (gen_negc (high_dst, high_src));
-      DONE;
-    }
+  emit_insn (gen_clrt ());
+  emit_insn (gen_negc (low_dst, low_src));
+  emit_insn (gen_negc (high_dst, high_src));
+  DONE;
 }")
 
 (define_insn "negsi2"
@@ -4326,27 +4337,77 @@ label:
                (const_int -1)))]
   "TARGET_SHMEDIA" "")
 
-/* The SH4 202 can do zero-offset branches without pipeline stalls.
-   This can be used as some kind of conditional execution, which is useful
-   for abs.  */
-(define_split
+(define_expand "abssi2"
   [(set (match_operand:SI 0 "arith_reg_dest" "")
-       (plus:SI (xor:SI (neg:SI (reg:SI T_REG))
-                        (match_operand:SI 1 "arith_reg_operand" ""))
-                (reg:SI T_REG)))]
-  "TARGET_HARD_SH4"
+       (abs:SI (match_operand:SI 1 "arith_reg_operand" "")))
+   (clobber (reg:SI T_REG))]
+  ""
+  "")
+
+(define_insn_and_split "*abssi2"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+       (abs:SI (match_operand:SI 1 "arith_reg_operand" "r")))]
+  "TARGET_SH1"
+  "#"
+  "TARGET_SH1"
   [(const_int 0)]
-  "emit_insn (gen_movsi_i (operands[0], operands[1]));
-   emit_insn (gen_cneg (operands[0], operands[0], operands[0]));
-   DONE;")
+  "
+{
+  emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
+  emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
+                const1_rtx));
+  DONE;
+}")
 
-(define_insn "cneg"
+(define_insn_and_split "*negabssi2"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (if_then_else:SI (eq:SI (reg:SI T_REG) (const_int 0))
-                     (match_operand:SI 1 "arith_reg_operand" "0")
-                     (neg:SI (match_operand:SI 2 "arith_reg_operand" "r"))))]
+       (neg:SI (abs:SI (match_operand:SI 1 "arith_reg_operand" "r"))))]
+  "TARGET_SH1"
+  "#"
+  "TARGET_SH1"
+  [(const_int 0)]
+  "
+{
+  emit_insn (gen_cmpgesi_t (operands[1], const0_rtx));
+  emit_insn (gen_negsi_cond (operands[0], operands[1], operands[1],
+                const0_rtx));
+  DONE;
+}")
+
+
+;; The SH4 202 can do zero-offset branches without pipeline stalls.
+;; This can be used as some kind of conditional execution, which is useful
+;; for abs.
+;; Actually the instruction scheduling should decide whether to use a
+;; zero-offset branch or not for any generic case involving a single
+;; instruction on SH4 202.
+
+(define_insn_and_split "negsi_cond"
+  [(set (match_operand:SI 0 "arith_reg_dest" "=r,r")
+       (if_then_else:SI (eq:SI (reg:SI T_REG)
+                         (match_operand:SI 3 "const_int_operand" "M,N"))
+        (match_operand:SI 1 "arith_reg_operand" "0,0")
+        (neg:SI (match_operand:SI 2 "arith_reg_operand" "r,r"))))]
   "TARGET_HARD_SH4"
-  "bf 0f\;neg %2,%0\\n0:"
+  "@
+       bt\\t0f\;neg\\t%2,%0\\n0:
+       bf\\t0f\;neg\\t%2,%0\\n0:"
+  "!TARGET_HARD_SH4"
+  [(const_int 0)]
+  "
+{
+  rtx skip_neg_label = gen_label_rtx ();
+
+  emit_insn (gen_movsi (operands[0], operands[1]));
+
+  emit_jump_insn (INTVAL (operands[3])
+                 ? gen_branch_true (skip_neg_label)
+                 : gen_branch_false (skip_neg_label));
+
+  emit_label_after (skip_neg_label,
+                   emit_insn (gen_negsi2 (operands[0], operands[1])));
+  DONE;
+}"
   [(set_attr "type" "arith") ;; poor approximation
    (set_attr "length" "4")])
 
index b760725..d19933a 100644 (file)
@@ -1,3 +1,8 @@
+2011-09-28  Oleg Endo  <oleg.endo@t-online.de>
+
+       PR target/49486
+       * gcc.target/sh/pr49468-si.c: New.
+
 2011-09-28  Tom de Vries  <tom@codesourcery.com>
 
        PR testsuite/50485
diff --git a/gcc/testsuite/gcc.target/sh/pr49468-si.c b/gcc/testsuite/gcc.target/sh/pr49468-si.c
new file mode 100644 (file)
index 0000000..69fbe23
--- /dev/null
@@ -0,0 +1,22 @@
+/* Check that 32 bit integer abs is generated as neg instruction and
+   conditional branch instead of default branch-free code.  */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-final { scan-assembler-times "neg" 2 } } */
+
+
+/* Normal integer absolute value.  */
+int
+abs_0 (int i)
+{
+  return (i < 0) ? -i : i;
+}
+
+/*  Negated integer absolute value.
+    The generated code should be the same, except that the branch 
+    condition is inverted.  */
+int
+abs_1 (int i)
+{
+  return (i > 0) ? -i : i;
+}