(mips_mulsidi3_gen_fn): Declare new function.
* config/mips/mips.c (mips_mulsidi3_gen_fn): New function.
* config/mips/mips.md (<u>mulsidi3): Change condition to use
mips_mulsidi3_gen_fn. Use mips_mulsidi3_gen_fn to generate the
insn.
(<u>mulsidi3_64bit): Don't match for ISA_HAS_DMUL3.
(mulsidi3_64bit_dmul): New define_insn.
testsuite/
* gcc.target/mips/mult-1.c: Forbid octeon.
* gcc.target/mips/octeon-dmul-3.c: New test.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@154410
138bc75d-0d04-0410-961f-
82ee72b054a4
+2009-11-21 Adam Nemet <adambnemet@gmail.com>
+
+ * config/mips/mips-protos.h (mulsidi3_gen_fn): New typedef.
+ (mips_mulsidi3_gen_fn): Declare new function.
+ * config/mips/mips.c (mips_mulsidi3_gen_fn): New function.
+ * config/mips/mips.md (<u>mulsidi3): Change condition to use
+ mips_mulsidi3_gen_fn. Use mips_mulsidi3_gen_fn to generate the
+ insn.
+ (<u>mulsidi3_64bit): Don't match for ISA_HAS_DMUL3.
+ (mulsidi3_64bit_dmul): New define_insn.
+
2009-11-21 Ben Elliston <bje@au.ibm.com>
* gengtype-lex.l: Enable noinput flex option.
extern int mips_trampoline_code_size (void);
extern void mips_function_profiler (FILE *);
+typedef rtx (*mulsidi3_gen_fn) (rtx, rtx, rtx);
+#ifdef RTX_CODE
+extern mulsidi3_gen_fn mips_mulsidi3_gen_fn (enum rtx_code);
+#endif
+
#endif /* ! GCC_MIPS_PROTOS_H */
if (mips_need_noat_wrapper_p (insn, opvec, noperands))
mips_pop_asm_switch (&mips_noat);
}
+
+/* Return the function that is used to expand the <u>mulsidi3 pattern.
+ EXT_CODE is the code of the extension used. Return NULL if widening
+ multiplication shouldn't be used. */
+
+mulsidi3_gen_fn
+mips_mulsidi3_gen_fn (enum rtx_code ext_code)
+{
+ bool signed_p;
+
+ signed_p = ext_code == SIGN_EXTEND;
+ if (TARGET_64BIT)
+ {
+ /* Don't use widening multiplication with MULT when we have DMUL. Even
+ with the extension of its input operands DMUL is faster. Note that
+ the extension is not needed for signed multiplication. In order to
+ ensure that we always remove the redundant sign-extension in this
+ case we still expand mulsidi3 for DMUL. */
+ if (ISA_HAS_DMUL3)
+ return signed_p ? gen_mulsidi3_64bit_dmul : NULL;
+ if (TARGET_FIX_R4000)
+ return NULL;
+ return signed_p ? gen_mulsidi3_64bit : gen_umulsidi3_64bit;
+ }
+ else
+ {
+ if (TARGET_FIX_R4000)
+ return signed_p ? gen_mulsidi3_32bit_r4000 : gen_umulsidi3_32bit_r4000;
+ if (ISA_HAS_DSPR2)
+ return signed_p ? gen_mips_mult : gen_mips_multu;
+ return signed_p ? gen_mulsidi3_32bit : gen_umulsidi3_32bit;
+ }
+}
\f
/* Return the size in bytes of the trampoline code, padded to
TRAMPOLINE_ALIGNMENT bits. The static chain pointer and target
[(set (match_operand:DI 0 "register_operand")
(mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
(any_extend:DI (match_operand:SI 2 "register_operand"))))]
- "!TARGET_64BIT || !TARGET_FIX_R4000"
+ "mips_mulsidi3_gen_fn (<CODE>) != NULL"
{
- if (TARGET_64BIT)
- emit_insn (gen_<u>mulsidi3_64bit (operands[0], operands[1], operands[2]));
- else if (TARGET_FIX_R4000)
- emit_insn (gen_<u>mulsidi3_32bit_r4000 (operands[0], operands[1],
- operands[2]));
- else
- emit_insn (gen_<u>mulsidi3_32bit (operands[0], operands[1], operands[2]));
+ mulsidi3_gen_fn fn = mips_mulsidi3_gen_fn (<CODE>);
+ emit_insn (fn (operands[0], operands[1], operands[2]));
DONE;
})
(any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
(clobber (match_scratch:TI 3 "=x"))
(clobber (match_scratch:DI 4 "=d"))]
- "TARGET_64BIT && !TARGET_FIX_R4000"
+ "TARGET_64BIT && !TARGET_FIX_R4000 && !ISA_HAS_DMUL3"
"#"
[(set_attr "type" "imul")
(set_attr "mode" "SI")
[(set_attr "type" "imul")
(set_attr "mode" "SI")])
+;; See comment before the ISA_HAS_DMUL3 case in mips_mulsidi3_gen_fn.
+(define_insn "mulsidi3_64bit_dmul"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (sign_extend:DI (match_operand:SI 2 "register_operand" "d"))))
+ (clobber (match_scratch:DI 3 "=l"))]
+ "TARGET_64BIT && ISA_HAS_DMUL3"
+ "dmul\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "DI")])
+
;; Widening multiply with negation.
(define_insn "*muls<u>_di"
[(set (match_operand:DI 0 "register_operand" "=x")
+2009-11-21 Adam Nemet <adambnemet@gmail.com>
+
+ * gcc.target/mips/mult-1.c: Forbid octeon.
+ * gcc.target/mips/octeon-dmul-3.c: New test.
+
2009-11-21 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* gcc.dg/tree-ssa/vrp47.c: Fix target check.
/* For SI->DI widening multiplication we should use DINS to combine the two
- halves. */
-/* { dg-options "-O -mgp64 isa_rev>=2" } */
+ halves. For Octeon use DMUL with explicit widening. */
+/* { dg-options "-O -mgp64 isa_rev>=2 forbid_cpu=octeon" } */
/* { dg-final { scan-assembler "\tdins\t" } } */
/* { dg-final { scan-assembler-not "\tdsll\t" } } */
/* { dg-final { scan-assembler-not "\tdsrl\t" } } */
--- /dev/null
+/* Use DMUL for widening multiplication too. */
+/* { dg-options "-O -march=octeon -mgp64" } */
+/* { dg-final { scan-assembler-times "\tdmul\t" 2 } } */
+/* { dg-final { scan-assembler-not "\td?mult\t" } } */
+/* { dg-final { scan-assembler-times "\tdext\t" 2 } } */
+
+NOMIPS16 long long
+f (int i, int j)
+{
+ i++;
+ return (long long) i * j;
+}
+
+NOMIPS16 unsigned long long
+g (unsigned int i, unsigned int j)
+{
+ i++;
+ return (unsigned long long) i * j;
+}