https://gcc.gnu.org/g:3cca524e337a886d479e630c7a3e6aef4656b425

commit r17-2335-g3cca524e337a886d479e630c7a3e6aef4656b425
Author: MITSUNARI Shigeo <[email protected]>
Date:   Sat Jul 11 22:38:41 2026 -0600

    i386: Add BMI2 MULX pattern for highpart-only multiplication
    
    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.
    
    Signed-off-by: MITSUNARI Shigeo <[email protected]>

Diff:
---
 gcc/config/i386/i386.md                            | 15 ++++++++++++++
 .../gcc.target/i386/bmi2-mulx-highpart-1.c         | 23 ++++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index d4107739250a..3244bc6240de 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -11895,6 +11895,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 000000000000..8b3b6725d1b2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/bmi2-mulx-highpart-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -mbmi2" } */
+/* { dg-final { check-function-bodies "**" "" "" { target *-*-linux* *-*-gnu* 
} } } */
+
+/* %edx is fixed by the ISA (implicit mulx source) and %edi by the ABI
+   (first argument).  The highpart MULX pattern uses the same operand
+   for both result registers, and that result is the return value, so
+   both are %rax.  Only the magic-constant register is chosen by the
+   register allocator, so match it generically.  */
+/*
+**div7:
+**     movabsq \$2635249153617166336, (%r[a-z0-9]+)
+**     movl    %edi, %edx
+**     mulx    \1, %rax, %rax
+**     ret
+**...
+*/
+
+unsigned int
+div7 (unsigned int x)
+{
+  return x / 7;
+}

Reply via email to