diff --git a/gcc/ChangeLog b/gcc/ChangeLog index fee14941bc88123fce744df546f2f6bde875c671..20a2d09c31aa9cd504fbf47aafd386c8000c87b0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,14 @@ +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. diff --git a/gcc/config/mips/mips-protos.h b/gcc/config/mips/mips-protos.h index 716b7acad82cfed956108cfbb5917bc65fe711a8..e4fbb32b9591223e8979e123e5195601f3484900 100644 --- a/gcc/config/mips/mips-protos.h +++ b/gcc/config/mips/mips-protos.h @@ -346,4 +346,9 @@ extern void mips_final_prescan_insn (rtx, rtx *, int); 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 */ diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index c8c1dca25ce37a26cde44951b738db583513eaef..eeff72d4b3378c4b055c551cb09a0d65f927c2f0 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -15982,6 +15982,39 @@ mips_final_postscan_insn (FILE *file ATTRIBUTE_UNUSED, rtx insn, 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; + } +} /* Return the size in bytes of the trampoline code, padded to TRAMPOLINE_ALIGNMENT bits. The static chain pointer and target diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index 76fc37bd479a74e7b949839897a5b54f7863efe2..2179b8a46c68469445fb7da395660fe2397d8d4c 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -1847,15 +1847,10 @@ [(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; }) @@ -1885,7 +1880,7 @@ (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") @@ -1961,6 +1956,17 @@ [(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") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 009b3335d285f24b689494068ccd380748c2a6c2..445691ab939ae036c77987f02ade7b7c717c1380 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +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. diff --git a/gcc/testsuite/gcc.target/mips/mult-1.c b/gcc/testsuite/gcc.target/mips/mult-1.c index d82a47782636bd6d4719e5175492f51d8ec5dcb7..43dd08c0b52177f024d5a856a13bb901fe0174a3 100644 --- a/gcc/testsuite/gcc.target/mips/mult-1.c +++ b/gcc/testsuite/gcc.target/mips/mult-1.c @@ -1,6 +1,6 @@ /* 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" } } */ diff --git a/gcc/testsuite/gcc.target/mips/octeon-dmul-3.c b/gcc/testsuite/gcc.target/mips/octeon-dmul-3.c new file mode 100644 index 0000000000000000000000000000000000000000..01f0eefca8001260ac577b7ef051cdc119a40d1f --- /dev/null +++ b/gcc/testsuite/gcc.target/mips/octeon-dmul-3.c @@ -0,0 +1,19 @@ +/* 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; +}