Commit 839380ee by Richard Sandiford Committed by Richard Sandiford

mips.md (*mul_acc_si): Remove middle alternative and its associated define_split.

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
parent 2cf1a19e
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> 2008-11-17 Jakub Jelinek <jakub@redhat.com>
PR middle-end/38140 PR middle-end/38140
......
...@@ -1474,34 +1474,50 @@ ...@@ -1474,34 +1474,50 @@
;; Multiply-accumulate patterns ;; Multiply-accumulate patterns
;; For processors that can copy the output to a general register: ;; This pattern is first matched by combine, which tries to use the
;; ;; pattern wherever it can. We don't know until later whether it
;; The all-d alternative is needed because the combiner will find this ;; is actually profitable to use MADD over a "MUL; ADDIU" sequence,
;; pattern and then register alloc/reload will move registers around to ;; so we need to keep both options open.
;; make them fit, and we don't want to trigger unnecessary loads to LO. ;;
;; ;; The second alternative has a "?" marker because it is generally
;; The last alternative should be made slightly less desirable, but adding ;; one instruction more costly than the first alternative. This "?"
;; "?" to the constraint is too strong, and causes values to be loaded into ;; marker is enough to convey the relative costs to the register
;; LO even when that's more costly. For now, using "*d" mostly does the ;; allocator.
;; trick. ;;
;; 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" (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") (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 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 4 "=X,3,l"))
(clobber (match_scratch:SI 5 "=X,X,&d"))] (clobber (match_scratch:SI 5 "=X,X,&d"))]
"(TARGET_MIPS3900 "TARGET_MIPS3900 && !TARGET_MIPS16"
|| GENERATE_MADD_MSUB) "@
&& !TARGET_MIPS16" madd\t%1,%2
{ madd\t%0,%1,%2
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];
}
[(set_attr "type" "imadd") [(set_attr "type" "imadd")
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "4,4,8")]) (set_attr "length" "4,4,8")])
...@@ -1522,23 +1538,6 @@ ...@@ -1522,23 +1538,6 @@
(set (match_dup 0) (plus:SI (match_dup 5) (match_dup 3)))] (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" (define_insn "*macc"
[(set (match_operand:SI 0 "register_operand" "=l,d") [(set (match_operand:SI 0 "register_operand" "=l,d")
(plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
...@@ -1718,21 +1717,21 @@ ...@@ -1718,21 +1717,21 @@
operands[2], operands[0]); operands[2], operands[0]);
}) })
;; See the comment above *mul_add_si for details.
(define_insn "*mul_sub_si" (define_insn "*mul_sub_si"
[(set (match_operand:SI 0 "register_operand" "=l,*d,*d") [(set (match_operand:SI 0 "register_operand" "=l*?*?,d?")
(minus:SI (match_operand:SI 1 "register_operand" "0,l,*d") (minus:SI (match_operand:SI 1 "register_operand" "0,d")
(mult:SI (match_operand:SI 2 "register_operand" "d,d,d") (mult:SI (match_operand:SI 2 "register_operand" "d,d")
(match_operand:SI 3 "register_operand" "d,d,d")))) (match_operand:SI 3 "register_operand" "d,d"))))
(clobber (match_scratch:SI 4 "=X,1,l")) (clobber (match_scratch:SI 4 "=X,l"))
(clobber (match_scratch:SI 5 "=X,X,&d"))] (clobber (match_scratch:SI 5 "=X,&d"))]
"GENERATE_MADD_MSUB" "GENERATE_MADD_MSUB"
"@ "@
msub\t%2,%3 msub\t%2,%3
#
#" #"
[(set_attr "type" "imadd") [(set_attr "type" "imadd")
(set_attr "mode" "SI") (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 ;; Split *mul_sub_si if both the source and destination accumulator
;; values are GPRs. ;; values are GPRs.
...@@ -1750,24 +1749,6 @@ ...@@ -1750,24 +1749,6 @@
(set (match_dup 0) (minus:SI (match_dup 1) (match_dup 5)))] (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" (define_insn "*muls"
[(set (match_operand:SI 0 "register_operand" "=l,d") [(set (match_operand:SI 0 "register_operand" "=l,d")
(neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
......
2008-11-17 Richard Sandiford <rdsandiford@googlemail.com> 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 * gcc.target/mips/no-smartmips-ror-1.c: Use -march=mips32 instead
of -march=mips32r2. of -march=mips32r2.
......
/* { 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]; }
/* { 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]; }
/* { 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;
}
/* { 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;
}
/* { 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]; }
/* { 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]; }
/* { 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;
}
/* { 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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment