mips.md (*mul_acc_si): Remove middle alternative and its associated define_split.
authorRichard Sandiford <rdsandiford@googlemail.com>
Mon, 17 Nov 2008 22:49:05 +0000 (22:49 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Mon, 17 Nov 2008 22:49:05 +0000 (22:49 +0000)
gcc/
* config/mips/mips.md (*mul_acc_si): Remove middle alternative
and its associated define_split.  Expose the all-d alternative
to the register allocator, but mark it with "?".  Mark the first
alternative with "*?*?".
(*mul_sub_si): Likewise.
(*mul_acc_si_r3900): New pattern.

gcc/testsuite/
* gcc.target/mips/madd-5.c: New test.
* gcc.target/mips/madd-6.c: Likewise.
* gcc.target/mips/madd-7.c: Likewise.
* gcc.target/mips/madd-8.c: Likewise.
* gcc.target/mips/msub-5.c: Likewise.
* gcc.target/mips/msub-6.c: Likewise.
* gcc.target/mips/msub-7.c: Likewise.
* gcc.target/mips/msub-8.c: Likewise.

From-SVN: r141954

gcc/ChangeLog
gcc/config/mips/mips.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/mips/madd-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/madd-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/madd-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/madd-8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/msub-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/msub-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/msub-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/mips/msub-8.c [new file with mode: 0644]

index ff38275..37bedc0 100644 (file)
@@ -1,3 +1,12 @@
+2008-11-17  Richard Sandiford  <rdsandiford@googlemail.com>
+
+       * config/mips/mips.md (*mul_acc_si): Remove middle alternative
+       and its associated define_split.  Expose the all-d alternative
+       to the register allocator, but mark it with "?".  Mark the first
+       alternative with "*?*?".
+       (*mul_sub_si): Likewise.
+       (*mul_acc_si_r3900): New pattern.
+
 2008-11-17  Jakub Jelinek  <jakub@redhat.com>
 
        PR middle-end/38140
index 222e41d..92e637c 100644 (file)
 
 ;; Multiply-accumulate patterns
 
-;; For processors that can copy the output to a general register:
-;;
-;; The all-d alternative is needed because the combiner will find this
-;; pattern and then register alloc/reload will move registers around to
-;; make them fit, and we don't want to trigger unnecessary loads to LO.
-;;
-;; The last alternative should be made slightly less desirable, but adding
-;; "?" to the constraint is too strong, and causes values to be loaded into
-;; LO even when that's more costly.  For now, using "*d" mostly does the
-;; trick.
+;; This pattern is first matched by combine, which tries to use the
+;; pattern wherever it can.  We don't know until later whether it
+;; is actually profitable to use MADD over a "MUL; ADDIU" sequence,
+;; so we need to keep both options open.
+;;
+;; The second alternative has a "?" marker because it is generally
+;; one instruction more costly than the first alternative.  This "?"
+;; marker is enough to convey the relative costs to the register
+;; allocator.
+;;
+;; However, reload counts reloads of operands 4 and 5 in the same way as
+;; reloads of the other operands, even though operands 4 and 5 need no
+;; copy instructions.  Reload therefore thinks that the second alternative
+;; is two reloads more costly than the first.  We add "*?*?" to the first
+;; alternative as a counterweight.
 (define_insn "*mul_acc_si"
-  [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
+  [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?")
+       (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
+                         (match_operand:SI 2 "register_operand" "d,d"))
+                (match_operand:SI 3 "register_operand" "0,d")))
+   (clobber (match_scratch:SI 4 "=X,l"))
+   (clobber (match_scratch:SI 5 "=X,&d"))]
+  "GENERATE_MADD_MSUB && !TARGET_MIPS16"
+  "@
+    madd\t%1,%2
+    #"
+  [(set_attr "type"    "imadd")
+   (set_attr "mode"    "SI")
+   (set_attr "length"  "4,8")])
+
+;; The same idea applies here.  The middle alternative needs one less
+;; clobber than the final alternative, so we add "*?" as a counterweight.
+(define_insn "*mul_acc_si_r3900"
+  [(set (match_operand:SI 0 "register_operand" "=l*?*?,d*?,d?")
        (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
                          (match_operand:SI 2 "register_operand" "d,d,d"))
-                (match_operand:SI 3 "register_operand" "0,l,*d")))
+                (match_operand:SI 3 "register_operand" "0,l,d")))
    (clobber (match_scratch:SI 4 "=X,3,l"))
    (clobber (match_scratch:SI 5 "=X,X,&d"))]
-  "(TARGET_MIPS3900
-   || GENERATE_MADD_MSUB)
-   && !TARGET_MIPS16"
-{
-  static const char *const madd[] = { "madd\t%1,%2", "madd\t%0,%1,%2" };
-  if (which_alternative == 2)
-    return "#";
-  if (GENERATE_MADD_MSUB && which_alternative != 0)
-    return "#";
-  return madd[which_alternative];
-}
+  "TARGET_MIPS3900 && !TARGET_MIPS16"
+  "@
+    madd\t%1,%2
+    madd\t%0,%1,%2
+    #"
   [(set_attr "type"    "imadd")
    (set_attr "mode"    "SI")
    (set_attr "length"  "4,4,8")])
    (set (match_dup 0) (plus:SI (match_dup 5) (match_dup 3)))]
   "")
 
-;; Split *mul_acc_si if the destination accumulator value is in a GPR
-;; and the source accumulator value is in LO.
-(define_split
-  [(set (match_operand:SI 0 "d_operand")
-        (plus:SI (mult:SI (match_operand:SI 1 "d_operand")
-                          (match_operand:SI 2 "d_operand"))
-                 (match_operand:SI 3 "lo_operand")))
-   (clobber (match_dup 3))
-   (clobber (scratch:SI))]
-  "reload_completed"
-  [(parallel [(set (match_dup 3)
-                   (plus:SI (mult:SI (match_dup 1) (match_dup 2))
-                            (match_dup 3)))
-              (clobber (scratch:SI))
-              (clobber (scratch:SI))])
-   (set (match_dup 0) (match_dup 3))])
-
 (define_insn "*macc"
   [(set (match_operand:SI 0 "register_operand" "=l,d")
        (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
                                operands[2], operands[0]);
 })
 
+;; See the comment above *mul_add_si for details.
 (define_insn "*mul_sub_si"
-  [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
-        (minus:SI (match_operand:SI 1 "register_operand" "0,l,*d")
-                  (mult:SI (match_operand:SI 2 "register_operand" "d,d,d")
-                           (match_operand:SI 3 "register_operand" "d,d,d"))))
-   (clobber (match_scratch:SI 4 "=X,1,l"))
-   (clobber (match_scratch:SI 5 "=X,X,&d"))]
+  [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?")
+        (minus:SI (match_operand:SI 1 "register_operand" "0,d")
+                  (mult:SI (match_operand:SI 2 "register_operand" "d,d")
+                           (match_operand:SI 3 "register_operand" "d,d"))))
+   (clobber (match_scratch:SI 4 "=X,l"))
+   (clobber (match_scratch:SI 5 "=X,&d"))]
   "GENERATE_MADD_MSUB"
   "@
    msub\t%2,%3
-   #
    #"
   [(set_attr "type"     "imadd")
    (set_attr "mode"     "SI")
-   (set_attr "length"   "4,8,8")])
+   (set_attr "length"   "4,8")])
 
 ;; Split *mul_sub_si if both the source and destination accumulator
 ;; values are GPRs.
    (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 5)))]
   "")
 
-;; Split *mul_acc_si if the destination accumulator value is in a GPR
-;; and the source accumulator value is in LO.
-(define_split
-  [(set (match_operand:SI 0 "d_operand")
-        (minus:SI (match_operand:SI 1 "lo_operand")
-                  (mult:SI (match_operand:SI 2 "d_operand")
-                           (match_operand:SI 3 "d_operand"))))
-   (clobber (match_dup 1))
-   (clobber (scratch:SI))]
-  "reload_completed"
-  [(parallel [(set (match_dup 1)
-                   (minus:SI (match_dup 1)
-                             (mult:SI (match_dup 2) (match_dup 3))))
-              (clobber (scratch:SI))
-              (clobber (scratch:SI))])
-   (set (match_dup 0) (match_dup 1))]
-  "")
-
 (define_insn "*muls"
   [(set (match_operand:SI 0 "register_operand" "=l,d")
         (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
index 2b90e3d..1d97976 100644 (file)
@@ -1,5 +1,16 @@
 2008-11-17  Richard Sandiford  <rdsandiford@googlemail.com>
 
+       * gcc.target/mips/madd-5.c: New test.
+       * gcc.target/mips/madd-6.c: Likewise.
+       * gcc.target/mips/madd-7.c: Likewise.
+       * gcc.target/mips/madd-8.c: Likewise.
+       * gcc.target/mips/msub-5.c: Likewise.
+       * gcc.target/mips/msub-6.c: Likewise.
+       * gcc.target/mips/msub-7.c: Likewise.
+       * gcc.target/mips/msub-8.c: Likewise.
+
+2008-11-17  Richard Sandiford  <rdsandiford@googlemail.com>
+
        * gcc.target/mips/no-smartmips-ror-1.c: Use -march=mips32 instead
        of -march=mips32r2.
 
diff --git a/gcc/testsuite/gcc.target/mips/madd-5.c b/gcc/testsuite/gcc.target/mips/madd-5.c
new file mode 100644 (file)
index 0000000..780194d
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-mips-options "-O2 -march=5kc" } */
+/* { dg-final { scan-assembler-times "\tmadd\t" 4 } } */
+/* { dg-final { scan-assembler-not "\tmtlo\t" } } */
+/* { dg-final { scan-assembler-times "\tmflo\t" 3 } } */
+
+NOMIPS16 void f1 (int *a) { a[0] = a[0] * a[1] + a[2] * a[3]; }
+NOMIPS16 void f2 (int *a) { a[0] = a[0] * a[1] + a[2] * a[3] + a[4]; }
+NOMIPS16 void f3 (int *a) { a[0] = a[0] * a[1] + a[2] * a[3] + a[4] * a[5]; }
diff --git a/gcc/testsuite/gcc.target/mips/madd-6.c b/gcc/testsuite/gcc.target/mips/madd-6.c
new file mode 100644 (file)
index 0000000..bbb6783
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-mips-options "-O2 -march=5kc" } */
+/* { dg-final { scan-assembler-not "\tmadd\t" } } */
+/* { dg-final { scan-assembler "\tmul\t" } } */
+/* { dg-final { scan-assembler "\taddu\t" } } */
+
+NOMIPS16 void f1 (int *a) { a[0] = a[0] * a[1] + a[2]; }
diff --git a/gcc/testsuite/gcc.target/mips/madd-7.c b/gcc/testsuite/gcc.target/mips/madd-7.c
new file mode 100644 (file)
index 0000000..25fd07d
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-mips-options "-O2 -march=5kc" } */
+/* { dg-final { scan-assembler-not "\tmul\t" } } */
+/* { dg-final { scan-assembler "\tmadd\t" } } */
+
+NOMIPS16 int
+f1 (int *a, int *b, int n)
+{
+  int x, i;
+
+  x = 0;
+  for (i = 0; i < n; i++)
+    x += a[i] * b[i];
+  return x;
+}
diff --git a/gcc/testsuite/gcc.target/mips/madd-8.c b/gcc/testsuite/gcc.target/mips/madd-8.c
new file mode 100644 (file)
index 0000000..0fc680e
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-mips-options "-O2 -march=5kc" } */
+/* { dg-final { scan-assembler "\tmul\t" } } */
+/* { dg-final { scan-assembler-not "\tmadd\t" } } */
+/* { dg-final { scan-assembler-not "\tmtlo\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+
+NOMIPS16 int
+f2 (int x, int y, int z)
+{
+  asm volatile ("" ::: "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",
+               "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17",
+               "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25",
+               "$31");
+  return x * y + z;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msub-5.c b/gcc/testsuite/gcc.target/mips/msub-5.c
new file mode 100644 (file)
index 0000000..675da64
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-mips-options "-O2 -march=5kc" } */
+/* { dg-final { scan-assembler-times "\tmsub\t" 4 } } */
+/* { dg-final { scan-assembler-not "\tmtlo\t" } } */
+/* { dg-final { scan-assembler-times "\tmflo\t" 3 } } */
+
+NOMIPS16 void f1 (int *a) { a[0] = a[0] * a[1] - a[2] * a[3]; }
+NOMIPS16 void f2 (int *a) { a[0] = a[0] * a[1] - a[2] * a[3] - a[4]; }
+NOMIPS16 void f3 (int *a) { a[0] = a[0] * a[1] - a[2] * a[3] - a[4] * a[5]; }
diff --git a/gcc/testsuite/gcc.target/mips/msub-6.c b/gcc/testsuite/gcc.target/mips/msub-6.c
new file mode 100644 (file)
index 0000000..afe01cb
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-mips-options "-O2 -march=5kc" } */
+/* { dg-final { scan-assembler-not "\tmsub\t" } } */
+/* { dg-final { scan-assembler "\tmul\t" } } */
+/* { dg-final { scan-assembler "\tsubu\t" } } */
+
+NOMIPS16 void f1 (int *a) { a[0] = a[0] - a[1] * a[2]; }
diff --git a/gcc/testsuite/gcc.target/mips/msub-7.c b/gcc/testsuite/gcc.target/mips/msub-7.c
new file mode 100644 (file)
index 0000000..9fff31d
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-mips-options "-O2 -march=5kc" } */
+/* { dg-final { scan-assembler-not "\tmul\t" } } */
+/* { dg-final { scan-assembler "\tmsub\t" } } */
+
+NOMIPS16 int
+f1 (int *a, int *b, int n)
+{
+  int x, i;
+
+  x = 100;
+  for (i = 0; i < n; i++)
+    x -= a[i] * b[i];
+  return x;
+}
diff --git a/gcc/testsuite/gcc.target/mips/msub-8.c b/gcc/testsuite/gcc.target/mips/msub-8.c
new file mode 100644 (file)
index 0000000..7517540
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-mips-options "-O2 -march=5kc" } */
+/* { dg-final { scan-assembler "\tmul\t" } } */
+/* { dg-final { scan-assembler-not "\tmsub\t" } } */
+/* { dg-final { scan-assembler-not "\tmtlo\t" } } */
+/* { dg-final { scan-assembler-not "\tmflo\t" } } */
+
+NOMIPS16 int
+f2 (int x, int y, int z)
+{
+  asm volatile ("" ::: "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",
+               "$10", "$11", "$12", "$13", "$14", "$15", "$16", "$17",
+               "$18", "$19", "$20", "$21", "$22", "$23", "$24", "$25",
+               "$31");
+  return x - y * z;
+}