From 59119253b3133b30114194a04171f9d353b5c7f7 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Fri, 29 Apr 2022 13:27:48 +0200 Subject: [PATCH] i386: Optimize double-word negation [PR51954] MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Introduce peephole2 pattern to convert from: mov %esi, %edx negl %eax adcl $0, %edx negl %edx to: xorl %edx, %edx negl %eax sbbl %esi, %edx This conversion is profitable only when initial move is found. Otherwise, additional move to a temporary together with clearing xor is needed. 2022-04-29 Uroš Bizjak gcc/ChangeLog: PR target/51954 * config/i386/i386.md (adcl/neg -> sbb peephole): New peephole2. gcc/testsuite/ChangeLog: PR target/51954 * gcc.target/i386/pr51954.c: New test. --- gcc/config/i386/i386.md | 44 +++++++++++++++++++++++++++++++++ gcc/testsuite/gcc.target/i386/pr51954.c | 15 +++++++++++ 2 files changed, 59 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr51954.c diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c74edd1..b321cda 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -10929,6 +10929,50 @@ (clobber (reg:CC FLAGS_REG))])] "split_double_mode (mode, &operands[0], 2, &operands[0], &operands[2]);") +;; Convert: +;; mov %esi, %edx +;; negl %eax +;; adcl $0, %edx +;; negl %edx +;; to: +;; xorl %edx, %edx +;; negl %eax +;; sbbl %esi, %edx + +(define_peephole2 + [(set (match_operand:SWI48 0 "general_reg_operand") + (match_operand:SWI48 1 "nonimmediate_gr_operand")) + (parallel + [(set (reg:CCC FLAGS_REG) + (ne:CCC (match_operand:SWI48 2 "general_reg_operand") (const_int 0))) + (set (match_dup 2) (neg:SWI48 (match_dup 2)))]) + (parallel + [(set (match_dup 0) + (plus:SWI48 (plus:SWI48 + (ltu:SWI48 (reg:CC FLAGS_REG) (const_int 0)) + (match_dup 0)) + (const_int 0))) + (clobber (reg:CC FLAGS_REG))]) + (parallel + [(set (match_dup 0) + (neg:SWI48 (match_dup 0))) + (clobber (reg:CC FLAGS_REG))])] + "REGNO (operands[0]) != REGNO (operands[2]) + && !reg_mentioned_p (operands[0], operands[1]) + && !reg_mentioned_p (operands[2], operands[1])" + [(parallel + [(set (reg:CCC FLAGS_REG) + (ne:CCC (match_dup 2) (const_int 0))) + (set (match_dup 2) (neg:SWI48 (match_dup 2)))]) + (parallel + [(set (match_dup 0) + (minus:SWI48 (minus:SWI48 + (match_dup 0) + (ltu:SWI48 (reg:CC FLAGS_REG) (const_int 0))) + (match_dup 1))) + (clobber (reg:CC FLAGS_REG))])] + "ix86_expand_clear (operands[0]);") + (define_insn "*neg_1" [(set (match_operand:SWI 0 "nonimmediate_operand" "=m") (neg:SWI (match_operand:SWI 1 "nonimmediate_operand" "0"))) diff --git a/gcc/testsuite/gcc.target/i386/pr51954.c b/gcc/testsuite/gcc.target/i386/pr51954.c new file mode 100644 index 0000000..5e757de --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr51954.c @@ -0,0 +1,15 @@ +/* PR target/51954 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* { dg-final { scan-assembler-not "adc" } } */ + +#ifdef __x86_64__ +#define TYPE __int128 +#else +#define TYPE long long +#endif + +TYPE bar (TYPE x) +{ + return -x; +} -- 2.7.4