diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index eb4121b..a314f1a 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -9747,13 +9747,37 @@ (match_operand:DWIH 3 "nonimmediate_operand" "rm"))) (set (match_operand:DWIH 1 "register_operand" "=r") (umul_highpart:DWIH (match_dup 2) (match_dup 3)))] - "TARGET_BMI2 - && !(MEM_P (operands[2]) && MEM_P (operands[3]))" + "TARGET_BMI2" "mulx\t{%3, %0, %1|%1, %0, %3}" [(set_attr "type" "imulx") (set_attr "prefix" "vex") (set_attr "mode" "")]) +;; Tweak *bmi2_umul3_1 to eliminate following mov. +(define_peephole2 + [(parallel [(set (match_operand:DWIH 0 "general_reg_operand") + (mult:DWIH (match_operand:DWIH 2 "register_operand") + (match_operand:DWIH 3 "nonimmediate_operand"))) + (set (match_operand:DWIH 1 "general_reg_operand") + (umul_highpart:DWIH (match_dup 2) (match_dup 3)))]) + (set (match_operand:DWIH 4 "general_reg_operand") + (match_operand:DWIH 5 "general_reg_operand"))] + "TARGET_BMI2 + && ((REGNO (operands[5]) == REGNO (operands[0]) + && REGNO (operands[1]) != REGNO (operands[4])) + || (REGNO (operands[5]) == REGNO (operands[1]) + && REGNO (operands[0]) != REGNO (operands[4]))) + && peep2_reg_dead_p (2, operands[5])" + [(parallel [(set (match_dup 0) (mult:DWIH (match_dup 2) (match_dup 3))) + (set (match_dup 1) + (umul_highpart:DWIH (match_dup 2) (match_dup 3)))])] +{ + if (REGNO (operands[5]) == REGNO (operands[0])) + operands[0] = operands[4]; + else + operands[1] = operands[4]; +}) + (define_insn "*umul3_1" [(set (match_operand: 0 "register_operand" "=r,A") (mult: diff --git a/gcc/testsuite/gcc.target/i386/pr110551-2.c b/gcc/testsuite/gcc.target/i386/pr110551-2.c new file mode 100644 index 0000000..4936adf --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr110551-2.c @@ -0,0 +1,12 @@ +/* { dg-do compile { target int128 } } */ +/* { dg-options "-O2 -march=haswell" } */ + +typedef unsigned long long uint64_t; + +uint64_t mulx64(uint64_t x) +{ + __uint128_t r = (__uint128_t)x * 0x9E3779B97F4A7C15ull; + return (uint64_t)r ^ (uint64_t)( r >> 64 ); +} + +/* { dg-final { scan-assembler-not "movq" } } */