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; +}
