This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] i386: do not use SImode mul-highpart on 64-bit
- From: Uros Bizjak <ubizjak at gmail dot com>
- To: Alexander Monakov <amonakov at ispras dot ru>
- Cc: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 10 Aug 2018 07:53:34 +0200
- Subject: Re: [PATCH] i386: do not use SImode mul-highpart on 64-bit
- References: <alpine.LNX.2.20.13.1808091740340.7591@monopod.intra.ispras.ru>
On Thu, Aug 9, 2018 at 5:00 PM, Alexander Monakov <amonakov@ispras.ru> wrote:
> Hello,
>
> on x86-64, 32-bit division by constants uses mulsi3_highpart pattern that
> turns into 'mull <reg>' instruction with source implicitly in eax and
> result in edx:eax. However, using 64-bit multiplication with zero-extended
> source would be preferable, as the imulq instruction accepts the magic
> multiplier as immediate if it fits into 31 bits, has fewer register allocation
> constraints, and typically has better latency/throughput.
>
> Perhaps ideally we'd want expand_divmod to automatically choose this cheaper
> variant on x86, but changing that appears to be too complicated. On the other
> hand, we don't use mul_highpart patterns for anything else, so we can simply
> expose only the DImode mul_highpart on x86-64.
>
> This patch does that by changing mode iterator so we offer only SImode
> mul-highpart on 32-bit x86 and only DImode on 64-bit.
>
> Bootstrapped/regtested on x86-64, OK for trunk?
>
> Alexander
>
> PR target/82418
> * config/i386/i386.md (<s>mul<mode>3_highpart): Use DWIH mode iterator
> instead of SWI48.
>
> testsuite/
> * gcc.target/i386/pr82418.c: New test.
OK.
Thanks,
Uros.
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index 73948c12618..10783d305d2 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -7792,16 +7792,16 @@ (define_insn "*<u>mulqihi3_1"
> (set_attr "mode" "QI")])
>
> (define_expand "<s>mul<mode>3_highpart"
> - [(parallel [(set (match_operand:SWI48 0 "register_operand")
> - (truncate:SWI48
> + [(parallel [(set (match_operand:DWIH 0 "register_operand")
> + (truncate:DWIH
> (lshiftrt:<DWI>
> (mult:<DWI>
> (any_extend:<DWI>
> - (match_operand:SWI48 1 "nonimmediate_operand"))
> + (match_operand:DWIH 1 "nonimmediate_operand"))
> (any_extend:<DWI>
> - (match_operand:SWI48 2 "register_operand")))
> + (match_operand:DWIH 2 "register_operand")))
> (match_dup 3))))
> - (clobber (match_scratch:SWI48 4))
> + (clobber (match_scratch:DWIH 4))
> (clobber (reg:CC FLAGS_REG))])]
> ""
> "operands[3] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));")
> diff --git a/gcc/testsuite/gcc.target/i386/pr82418.c b/gcc/testsuite/gcc.target/i386/pr82418.c
> index e69de29bb2d..95a506d5ccd 100644
> --- a/gcc/testsuite/gcc.target/i386/pr82418.c
> +++ b/gcc/testsuite/gcc.target/i386/pr82418.c
> @@ -0,0 +1,10 @@
> +/* PR target/82418 */
> +/* { dg-do compile { target { ! ia32 } } } */
> +/* { dg-options "-O2" } */
> +/* { dg-final { scan-assembler "imul\[^\n\r]*1374389535" } } */
> +
> +unsigned
> +f1(unsigned x)
> +{
> + return x / 100;
> +}