diff options
author | Uros Bizjak <ubizjak@gmail.com> | 2022-04-29 13:27:48 +0200 |
---|---|---|
committer | Uros Bizjak <ubizjak@gmail.com> | 2022-04-29 13:31:12 +0200 |
commit | 59119253b3133b30114194a04171f9d353b5c7f7 (patch) | |
tree | 105aa73678b251a054964c0602875c73a40ef3f7 /gcc | |
parent | c090743b2ae0095f792371c7cbeb3cf6e2978f5d (diff) | |
download | gcc-59119253b3133b30114194a04171f9d353b5c7f7.zip gcc-59119253b3133b30114194a04171f9d353b5c7f7.tar.gz gcc-59119253b3133b30114194a04171f9d353b5c7f7.tar.bz2 |
i386: Optimize double-word negation [PR51954]
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 <ubizjak@gmail.com>
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386.md | 44 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr51954.c | 15 |
2 files changed, 59 insertions, 0 deletions
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 (<DWI>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<mode>_1" [(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>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; +} |