re PR target/39423 ([SH] performance regression: lost mov @(disp,Rn))
authorOleg Endo <olegendo@gcc.gnu.org>
Thu, 9 Aug 2012 15:58:04 +0000 (15:58 +0000)
committerOleg Endo <olegendo@gcc.gnu.org>
Thu, 9 Aug 2012 15:58:04 +0000 (15:58 +0000)
PR target/39423
* config/sh/predicates.md (mem_index_disp_operand): New predicate.
* config/sh/sh.md (*movsi_index_disp): Rewrite insns to use the new
mem_index_disp_operand predicate.

PR target/39423
* gcc.target/sh/pr39423-1.c: New.

From-SVN: r190259

gcc/ChangeLog
gcc/config/sh/predicates.md
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/sh/pr39423-1.c [new file with mode: 0644]

index 318278a811a1187d0e73504c256273accf7611cd..dc96a3bad5821acb80811d82753420141e01f264 100644 (file)
@@ -1,3 +1,10 @@
+2012-08-09  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/39423
+       * config/sh/predicates.md (mem_index_disp_operand): New predicate.
+       * config/sh/sh.md (*movsi_index_disp): Rewrite insns to use the new
+       mem_index_disp_operand predicate.
+
 2012-08-09  Oleg Endo  <olegendo@gcc.gnu.org>
 
        PR target/51244
index 588e25c23fae98f97edec50d8cf9fa1c8f8fff39..209ff29e8b600e0b25e81afa40fdab8f3f8b21bd 100644 (file)
   return 0;
 })
 
+;; Returns 1 if OP is a MEM that can be used in "index_disp" combiner
+;; patterns.
+(define_predicate "mem_index_disp_operand"
+  (match_code "mem")
+{
+  rtx plus0_rtx, plus1_rtx, mult_rtx;
+
+  plus0_rtx = XEXP (op, 0);
+  if (GET_CODE (plus0_rtx) != PLUS)
+    return 0;
+
+  plus1_rtx = XEXP (plus0_rtx, 0);
+  if (GET_CODE (plus1_rtx) != PLUS)
+    return 0;
+
+  mult_rtx = XEXP (plus1_rtx, 0);
+  if (GET_CODE (mult_rtx) != MULT)
+    return 0;
+  return REG_P (XEXP (mult_rtx, 0)) && CONST_INT_P (XEXP (mult_rtx, 1))
+        && exact_log2 (INTVAL (XEXP (mult_rtx, 1))) > 0
+        && REG_P (XEXP (plus1_rtx, 1))
+        && sh_legitimate_index_p (mode, XEXP (plus0_rtx, 1), TARGET_SH2A, true);
+})
+
 ;; TODO: Add a comment here.
 
 (define_predicate "greater_comparison_operator"
index c95c904844ccd630b7a32102f80a1ccb4b7fafd9..e96ff7d40522b1b7b39904ccdb4ef42d84754536 100644 (file)
@@ -5119,114 +5119,116 @@ label:
 ;; FIXME: Combine never tries this kind of patterns for DImode.
 (define_insn_and_split "*movsi_index_disp"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (mem:SI
-         (plus:SI
-           (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
-                             (match_operand:SI 2 "const_int_operand"))
-                    (match_operand:SI 3 "arith_reg_operand" "r"))
-           (match_operand:SI 4 "const_int_operand"))))]
-  "TARGET_SH1 && sh_legitimate_index_p (SImode, operands[4], TARGET_SH2A, true)
-   && exact_log2 (INTVAL (operands[2])) > 0"
+       (match_operand:SI 1 "mem_index_disp_operand" "m"))]
+  "TARGET_SH1"
   "#"
   "&& can_create_pseudo_p ()"
   [(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
    (set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
-   (set (match_dup 0) (mem:SI (plus:SI (match_dup 6) (match_dup 4))))]
+   (set (match_dup 0) (match_dup 7))]
 {
+  rtx mem = operands[1];
+  rtx plus0_rtx = XEXP (mem, 0);
+  rtx plus1_rtx = XEXP (plus0_rtx, 0);
+  rtx mult_rtx = XEXP (plus1_rtx, 0);
+
+  operands[1] = XEXP (mult_rtx, 0);
+  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
+  operands[3] = XEXP (plus1_rtx, 1);
+  operands[4] = XEXP (plus0_rtx, 1);
   operands[5] = gen_reg_rtx (SImode);
   operands[6] = gen_reg_rtx (SImode);
-  operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+  operands[7] =
+    replace_equiv_address (mem,
+                          gen_rtx_PLUS (SImode, operands[6], operands[4]));
 })
 
 (define_insn_and_split "*movhi_index_disp"
   [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (sign_extend:SI
-         (mem:HI
-           (plus:SI
-             (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
-                               (match_operand:SI 2 "const_int_operand"))
-                      (match_operand:SI 3 "arith_reg_operand" "r"))
-             (match_operand:SI 4 "const_int_operand")))))]
-  "TARGET_SH1 && sh_legitimate_index_p (HImode, operands[4], TARGET_SH2A, true)
-   && exact_log2 (INTVAL (operands[2])) > 0"
+       (sign_extend:SI (match_operand:HI 1 "mem_index_disp_operand" "m")))]
+  "TARGET_SH1"
   "#"
   "&& can_create_pseudo_p ()"
   [(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
    (set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
-   (set (match_dup 0)
-       (sign_extend:SI (mem:HI (plus:SI (match_dup 6) (match_dup 4)))))]
+   (set (match_dup 0) (sign_extend:SI (match_dup 7)))]
 {
+  rtx mem = operands[1];
+  rtx plus0_rtx = XEXP (mem, 0);
+  rtx plus1_rtx = XEXP (plus0_rtx, 0);
+  rtx mult_rtx = XEXP (plus1_rtx, 0);
+
+  operands[1] = XEXP (mult_rtx, 0);
+  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
+  operands[3] = XEXP (plus1_rtx, 1);
+  operands[4] = XEXP (plus0_rtx, 1);
   operands[5] = gen_reg_rtx (SImode);
   operands[6] = gen_reg_rtx (SImode);
-  operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+  operands[7] =
+    replace_equiv_address (mem,
+                          gen_rtx_PLUS (SImode, operands[6], operands[4]));
 })
 
-(define_insn_and_split "*movhi_index_disp"
-  [(set (match_operand:SI 0 "arith_reg_dest" "=r")
-       (zero_extend:SI
-         (mem:HI
-           (plus:SI
-             (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
-                               (match_operand:SI 2 "const_int_operand"))
-                      (match_operand:SI 3 "arith_reg_operand" "r"))
-             (match_operand:SI 4 "const_int_operand")))))]
-  "TARGET_SH1 && sh_legitimate_index_p (HImode, operands[4], TARGET_SH2A, true)
-   && exact_log2 (INTVAL (operands[2])) > 0"
-  "#"
-  "&& can_create_pseudo_p ()"
-  [(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
-   (set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
-   (set (match_dup 7)
-       (sign_extend:SI (mem:HI (plus:SI (match_dup 6) (match_dup 4)))))
-   (set (match_dup 0) (zero_extend:SI (match_dup 8)))]
+(define_split
+  [(set (match_operand:SI 0 "arith_reg_dest")
+       (zero_extend:SI (match_operand:HI 1 "mem_index_disp_operand")))]
+  "TARGET_SH1"
+  [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
+   (set (match_dup 0) (zero_extend:SI (match_dup 2)))]
 {
-  operands[5] = gen_reg_rtx (SImode);
-  operands[6] = gen_reg_rtx (SImode);
-  operands[7] = gen_reg_rtx (SImode);
-  operands[8] = gen_lowpart (HImode, operands[7]);
-  operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+  operands[2] = gen_lowpart (HImode, operands[0]);
 })
 
 (define_insn_and_split "*movsi_index_disp"
-  [(set (mem:SI
-         (plus:SI
-           (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
-                             (match_operand:SI 2 "const_int_operand"))
-                    (match_operand:SI 3 "arith_reg_operand" "r"))
-         (match_operand:SI 4 "const_int_operand")))
-       (match_operand:SI 0 "arith_reg_operand" "r"))]
-  "TARGET_SH1 && sh_legitimate_index_p (SImode, operands[4], TARGET_SH2A, true)
-   && exact_log2 (INTVAL (operands[2])) > 0"
+  [(set (match_operand:SI 0 "mem_index_disp_operand" "=m")
+       (match_operand:SI 1 "arith_reg_operand" "r"))]
+  "TARGET_SH1"
   "#"
   "&& can_create_pseudo_p ()"
-  [(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
+  [(set (match_dup 5) (ashift:SI (match_dup 0) (match_dup 2)))
    (set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
-   (set (mem:SI (plus:SI (match_dup 6) (match_dup 4))) (match_dup 0))]
+   (set (match_dup 7) (match_dup 1))]
 {
+  rtx mem = operands[0];
+  rtx plus0_rtx = XEXP (mem, 0);
+  rtx plus1_rtx = XEXP (plus0_rtx, 0);
+  rtx mult_rtx = XEXP (plus1_rtx, 0);
+
+  operands[0] = XEXP (mult_rtx, 0);
+  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
+  operands[3] = XEXP (plus1_rtx, 1);
+  operands[4] = XEXP (plus0_rtx, 1);
   operands[5] = gen_reg_rtx (SImode);
   operands[6] = gen_reg_rtx (SImode);
-  operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+  operands[7] =
+    replace_equiv_address (mem,
+                          gen_rtx_PLUS (SImode, operands[6], operands[4]));
 })
 
-(define_insn_and_split "*movhi_index_disp"
-  [(set (mem:HI
-         (plus:SI
-           (plus:SI (mult:SI (match_operand:SI 1 "arith_reg_operand" "r")
-                             (match_operand:SI 2 "const_int_operand"))
-                    (match_operand:SI 3 "arith_reg_operand" "r"))
-         (match_operand:SI 4 "const_int_operand")))
-       (match_operand:HI 0 "arith_reg_operand" "r"))]
-  "TARGET_SH1 && sh_legitimate_index_p (HImode, operands[4], TARGET_SH2A, true)
-   && exact_log2 (INTVAL (operands[2])) > 0"
+(define_insn_and_split "*movsi_index_disp"
+  [(set (match_operand:HI 0 "mem_index_disp_operand" "=m")
+       (match_operand:HI 1 "arith_reg_operand" "r"))]
+  "TARGET_SH1"
   "#"
   "&& can_create_pseudo_p ()"
-  [(set (match_dup 5) (ashift:SI (match_dup 1) (match_dup 2)))
+  [(set (match_dup 5) (ashift:SI (match_dup 0) (match_dup 2)))
    (set (match_dup 6) (plus:SI (match_dup 5) (match_dup 3)))
-   (set (mem:HI (plus:SI (match_dup 6) (match_dup 4))) (match_dup 0))]
+   (set (match_dup 7) (match_dup 1))]
 {
+  rtx mem = operands[0];
+  rtx plus0_rtx = XEXP (mem, 0);
+  rtx plus1_rtx = XEXP (plus0_rtx, 0);
+  rtx mult_rtx = XEXP (plus1_rtx, 0);
+
+  operands[0] = XEXP (mult_rtx, 0);
+  operands[2] = GEN_INT (exact_log2 (INTVAL (XEXP (mult_rtx, 1))));
+  operands[3] = XEXP (plus1_rtx, 1);
+  operands[4] = XEXP (plus0_rtx, 1);
   operands[5] = gen_reg_rtx (SImode);
   operands[6] = gen_reg_rtx (SImode);
-  operands[2] = GEN_INT (exact_log2 (INTVAL (operands[2])));
+  operands[7] =
+    replace_equiv_address (mem,
+                          gen_rtx_PLUS (SImode, operands[6], operands[4]));
 })
 
 ;; Define additional pop for SH1 and SH2 so it does not get 
index cffdd0b183475fda6a63a2751033978ee6b85d71..790921fc14bb891cccfefe310d36805a2b85e2c7 100644 (file)
@@ -1,3 +1,8 @@
+2012-08-09  Oleg Endo  <olegendo@gcc.gnu.org>
+
+       PR target/39423
+       * gcc.target/sh/pr39423-1.c: New.
+
 2012-08-09  Oleg Endo  <olegendo@gcc.gnu.org>
 
        PR target/51244
diff --git a/gcc/testsuite/gcc.target/sh/pr39423-1.c b/gcc/testsuite/gcc.target/sh/pr39423-1.c
new file mode 100644 (file)
index 0000000..dac0f89
--- /dev/null
@@ -0,0 +1,48 @@
+/* Check that displacement addressing is used for indexed addresses with a
+   small offset, instead of re-calculating the index.  */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O2" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-final { scan-assembler-not "add\t#1" } } */
+
+int
+test_00 (int tab[], int index)
+{
+  return tab[index + 1];
+}
+
+int
+test_01 (short tab[], int index)
+{
+  return tab[index + 1];
+}
+
+int
+test_02 (unsigned short tab[], int index)
+{
+  return tab[index + 1];
+}
+
+int
+test_03 (long long tab[], int index)
+{
+  return (int)tab[index + 1];
+}
+
+void
+test_04 (int tab[], int index, int val)
+{
+  tab[index + 1] = val;
+}
+
+void
+test_05 (short tab[], int index, int val)
+{
+  tab[index + 1] = (short)val;
+}
+
+void
+test_06 (unsigned short tab[], int index, int val)
+{
+  tab[index + 1] = (unsigned short)val;
+}