From: Lulu Cheng Date: Tue, 5 Sep 2023 03:09:03 +0000 (+0800) Subject: LoongArch: Optimized multiply instruction generation. X-Git-Tag: basepoints/gcc-15~6319 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f83d6fc222040febf510af81eeeb87670a2fc4d8;p=thirdparty%2Fgcc.git LoongArch: Optimized multiply instruction generation. 1. Can generate mulh.w[u] instruction. 2. Can generate mulw.d.wu instruction. gcc/ChangeLog: * config/loongarch/loongarch.md (mulsidi3_64bit): Field unsigned extension support. (muldi3_highpart): Modify template name. (mulsi3_highpart): Likewise. (mulsidi3_64bit): Field unsigned extension support. (muldi3_highpart): Modify muldi3_highpart to smuldi3_highpart. (mulsi3_highpart): Modify mulsi3_highpart to smulsi3_highpart. gcc/testsuite/ChangeLog: * gcc.target/loongarch/mulw_d_wu.c: New test. * gcc.target/loongarch/smuldi3_highpart.c: New test. * gcc.target/loongarch/smulsi3_highpart.c: New test. * gcc.target/loongarch/umulsi3_highpart.c: New test. --- diff --git a/gcc/config/loongarch/loongarch.md b/gcc/config/loongarch/loongarch.md index 75f641b38ee7..1dc6b5244167 100644 --- a/gcc/config/loongarch/loongarch.md +++ b/gcc/config/loongarch/loongarch.md @@ -750,15 +750,6 @@ [(set_attr "type" "imul") (set_attr "mode" "")]) -(define_insn "mulsidi3_64bit" - [(set (match_operand:DI 0 "register_operand" "=r") - (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r")) - (sign_extend:DI (match_operand:SI 2 "register_operand" "r"))))] - "TARGET_64BIT" - "mulw.d.w\t%0,%1,%2" - [(set_attr "type" "imul") - (set_attr "mode" "DI")]) - (define_insn "*mulsi3_extended" [(set (match_operand:DI 0 "register_operand" "=r") (sign_extend:DI @@ -787,14 +778,14 @@ emit_insn (gen_muldi3 (low, operands[1], operands[2])); rtx high = gen_reg_rtx (DImode); - emit_insn (gen_muldi3_highpart (high, operands[1], operands[2])); + emit_insn (gen_muldi3_highpart (high, operands[1], operands[2])); emit_move_insn (gen_lowpart (DImode, operands[0]), low); emit_move_insn (gen_highpart (DImode, operands[0]), high); DONE; }) -(define_insn "muldi3_highpart" +(define_insn "muldi3_highpart" [(set (match_operand:DI 0 "register_operand" "=r") (truncate:DI (lshiftrt:TI @@ -809,22 +800,34 @@ (set_attr "mode" "DI")]) (define_expand "mulsidi3" - [(set (match_operand:DI 0 "register_operand" "=r") + [(set (match_operand:DI 0 "register_operand") (mult:DI (any_extend:DI - (match_operand:SI 1 "register_operand" " r")) + (match_operand:SI 1 "register_operand")) (any_extend:DI - (match_operand:SI 2 "register_operand" " r"))))] - "!TARGET_64BIT" + (match_operand:SI 2 "register_operand"))))] + "" { - rtx temp = gen_reg_rtx (SImode); - emit_insn (gen_mulsi3 (temp, operands[1], operands[2])); - emit_insn (gen_mulsi3_highpart (loongarch_subword (operands[0], true), - operands[1], operands[2])); - emit_insn (gen_movsi (loongarch_subword (operands[0], false), temp)); - DONE; + if (!TARGET_64BIT) + { + rtx temp = gen_reg_rtx (SImode); + emit_insn (gen_mulsi3 (temp, operands[1], operands[2])); + emit_insn (gen_mulsi3_highpart (loongarch_subword (operands[0], true), + operands[1], operands[2])); + emit_insn (gen_movsi (loongarch_subword (operands[0], false), temp)); + DONE; + } }) -(define_insn "mulsi3_highpart" +(define_insn "mulsidi3_64bit" + [(set (match_operand:DI 0 "register_operand" "=r") + (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "r")) + (any_extend:DI (match_operand:SI 2 "register_operand" "r"))))] + "TARGET_64BIT" + "mulw.d.w\t%0,%1,%2" + [(set_attr "type" "imul") + (set_attr "mode" "DI")]) + +(define_insn "mulsi3_highpart" [(set (match_operand:SI 0 "register_operand" "=r") (truncate:SI (lshiftrt:DI @@ -833,11 +836,28 @@ (any_extend:DI (match_operand:SI 2 "register_operand" " r"))) (const_int 32))))] - "!TARGET_64BIT" + "" "mulh.w\t%0,%1,%2" [(set_attr "type" "imul") (set_attr "mode" "SI")]) +;; Under the LoongArch architecture, the mulh.w[u] instruction performs +;; sign extension by default, so the sign extension instruction can be +;; eliminated. +(define_peephole + [(set (match_operand:SI 0 "register_operand") + (truncate:SI + (lshiftrt:DI + (mult:DI (any_extend:DI + (match_operand:SI 1 "register_operand")) + (any_extend:DI + (match_operand:SI 2 "register_operand"))) + (const_int 32)))) + (set (match_operand:DI 3 "register_operand") + (sign_extend:DI (match_dup 0)))] + "TARGET_64BIT && REGNO (operands[0]) == REGNO (operands[3])" + "mulh.w\t%0,%1,%2") + ;; ;; .................... ;; diff --git a/gcc/testsuite/gcc.target/loongarch/mulw_d_wu.c b/gcc/testsuite/gcc.target/loongarch/mulw_d_wu.c new file mode 100644 index 000000000000..16163d6675d0 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/mulw_d_wu.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -mabi=lp64d" } */ +/* { dg-final { scan-assembler "mulw.d.wu" } } */ + +__attribute__((noipa, noinline)) unsigned long +f(unsigned long a, unsigned long b) +{ + return (unsigned long)(unsigned int)a * (unsigned long)(unsigned int)b; +} diff --git a/gcc/testsuite/gcc.target/loongarch/smuldi3_highpart.c b/gcc/testsuite/gcc.target/loongarch/smuldi3_highpart.c new file mode 100644 index 000000000000..6f5c686ca38e --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/smuldi3_highpart.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-mabi=lp64d -O2 -fdump-rtl-expand-all" } */ + +typedef int TI __attribute ((mode(TI))); +typedef int DI __attribute__((mode(DI))); + +DI +test (DI x, DI y) +{ + return ((TI)x * y) >> 64; +} + +/* { dg-final { scan-rtl-dump "highparttmp" "expand" } } */ diff --git a/gcc/testsuite/gcc.target/loongarch/smulsi3_highpart.c b/gcc/testsuite/gcc.target/loongarch/smulsi3_highpart.c new file mode 100644 index 000000000000..c4dbf8afc245 --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/smulsi3_highpart.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-rtl-expand-all" } */ + +typedef unsigned int DI __attribute__((mode(DI))); +typedef unsigned int SI __attribute__((mode(SI))); + +SI +f (SI x, SI y) +{ + return ((DI) x * y) >> 32; +} + +/* { dg-final { scan-rtl-dump "highparttmp" "expand" } } */ +/* { dg-final { scan-assembler "mulh\\.w" } } */ +/* { dg-final { scan-assembler-not "slli\\.w" } } */ diff --git a/gcc/testsuite/gcc.target/loongarch/umulsi3_highpart.c b/gcc/testsuite/gcc.target/loongarch/umulsi3_highpart.c new file mode 100644 index 000000000000..e208803e2d0d --- /dev/null +++ b/gcc/testsuite/gcc.target/loongarch/umulsi3_highpart.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef unsigned int DI __attribute__((mode(DI))); +typedef unsigned int SI __attribute__((mode(SI))); + +SI +f (SI x, SI y) +{ + return ((DI) x * y) >> 32; +} + +/* { dg-final { scan-assembler "mulh\\.wu" } } */ +/* { dg-final { scan-assembler-not "slli\\.w" } } */