On Wed, Jun 10, 2026 at 7:33 AM <[email protected]> wrote:
>
> From: MITSUNARI Shigeo <[email protected]>
>
> Add a new instruction pattern that uses MULX to compute only the high
> part of an unsigned multiplication on BMI2 targets.  Previously, when
> only the high part was needed, GCC would emit MULQ followed by a MOV
> to retrieve the result from RDX.  With this pattern, MULX writes the
> high part directly to the destination register, saving one instruction.
>
> This benefits unsigned 32-bit integer division by constants that require
> 33-bit magic multipliers (e.g., division by 7), reducing the sequence
> from 4 instructions to 3 on BMI2 targets.
>
> Before:
>     movabsq $2635249153617166336, %rcx
>     movl    %edi, %eax
>     mulq    %rcx
>     movl    %edx, %eax
>
> After:
>     movabsq $2635249153617166336, %rax
>     movl    %edi, %edx
>     mulx    %rax, %rax, %rax
>
> gcc/ChangeLog:
>
>         * config/i386/i386.md (*bmi2_umul<mode>3_highpart): New pattern.
>
> gcc/testsuite/ChangeLog:
>
>         * gcc.target/i386/bmi2-mulx-highpart-1.c: New test.
>         * gcc.target/i386/bmi2-mulx-highpart-2.c: New test.

OK.

Thanks,
Uros.

>
> Signed-off-by: MITSUNARI Shigeo <[email protected]>
> ---
>  gcc/config/i386/i386.md                       | 15 +++++++++++++++
>  .../gcc.target/i386/bmi2-mulx-highpart-1.c    | 18 ++++++++++++++++++
>  .../gcc.target/i386/bmi2-mulx-highpart-2.c    | 19 +++++++++++++++++++
>  3 files changed, 52 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/i386/bmi2-mulx-highpart-1.c
>  create mode 100644 gcc/testsuite/gcc.target/i386/bmi2-mulx-highpart-2.c
>
> diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
> index e514809453d..5478ad5d632 100644
> --- a/gcc/config/i386/i386.md
> +++ b/gcc/config/i386/i386.md
> @@ -11507,6 +11507,21 @@
>               (set (match_dup 5)
>                    (umul_highpart:DWIH (match_dup 2) (match_dup 3)))])])
>
> +;; BMI2 MULX highpart-only pattern.  Uses MULX to get only the high part.
> +;; When both output operands are identical, MULX writes the high half to that
> +;; register, so no scratch register is needed.  This avoids the mov from rdx
> +;; after mulq when only the high part is needed.
> +(define_insn "*bmi2_umul<mode>3_highpart"
> +  [(set (match_operand:DWIH 0 "register_operand" "=r")
> +       (umul_highpart:DWIH
> +         (match_operand:DWIH 1 "register_operand" "d")
> +         (match_operand:DWIH 2 "nonimmediate_operand" "rm")))]
> +  "TARGET_BMI2"
> +  "mulx\t{%2, %0, %0|%0, %0, %2}"
> +  [(set_attr "type" "imulx")
> +   (set_attr "prefix" "vex")
> +   (set_attr "mode" "<MODE>")])
> +
>  ;; Highpart multiplication patterns
>  (define_insn "<s>mul<mode>3_highpart"
>    [(set (match_operand:DWIH 0 "register_operand" "=d")
> diff --git a/gcc/testsuite/gcc.target/i386/bmi2-mulx-highpart-1.c 
> b/gcc/testsuite/gcc.target/i386/bmi2-mulx-highpart-1.c
> new file mode 100644
> index 00000000000..0741ad0741b
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/bmi2-mulx-highpart-1.c
> @@ -0,0 +1,18 @@
> +/* { dg-do compile { target { ! ia32 } } } */
> +/* { dg-options "-O2 -mbmi2" } */
> +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* 
> *-*-gnu* } } } */
> +
> +/*
> +**div7:
> +**     movabsq \$2635249153617166336, %rax
> +**     movl    %edi, %edx
> +**     mulx    %rax, %rax, %rax
> +**     ret
> +**...
> +*/
> +
> +unsigned int
> +div7 (unsigned int x)
> +{
> +  return x / 7;
> +}
> diff --git a/gcc/testsuite/gcc.target/i386/bmi2-mulx-highpart-2.c 
> b/gcc/testsuite/gcc.target/i386/bmi2-mulx-highpart-2.c
> new file mode 100644
> index 00000000000..065c8e3f7dc
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/i386/bmi2-mulx-highpart-2.c
> @@ -0,0 +1,19 @@
> +/* { dg-do compile { target { ! ia32 } } } */
> +/* { dg-options "-O2 -mbmi2" } */
> +/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* 
> *-*-gnu* } } } */
> +
> +/*
> +**div7loop:
> +**...
> +**     mulx    %rsi, %rdx, %rdx
> +**...
> +*/
> +
> +unsigned int
> +div7loop (unsigned int x)
> +{
> +  for (int i = 0; i < 10000; i++) {
> +    x ^= (i ^ x) / 7;
> +  }
> +  return x;
> +}
> --
> 2.43.0
>

Reply via email to