From 7c2879301d3b027a1ba427a5d5c7557decb8a7ab Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Wed, 6 May 2020 17:33:51 +0200 Subject: [PATCH] i386: Use ADD to implement compares with negated operand [PR94913] Use carry flag from addition to implement GEU/LTU compares with negated operand, so e.g. ~x < y compiles to: addq %rsi, %rdi setc %al instead of: notq %rdi cmpq %rsi, %rdi setb %al PR target/94913 * config/i386/predicates.md (add_comparison_operator): New predicate. * config/i386/i386.md (compare->add splitter): New splitters. testsuite/ChangeLog: PR target/94913 * gcc.target/i386/pr94913-1.c: New test. * gcc.target/i386/pr94913-2.c: Ditto. --- gcc/ChangeLog | 6 ++++ gcc/config/i386/i386.md | 35 +++++++++++++++++++++++ gcc/config/i386/predicates.md | 3 ++ gcc/testsuite/ChangeLog | 6 ++++ gcc/testsuite/gcc.target/i386/pr94913-1.c | 21 ++++++++++++++ gcc/testsuite/gcc.target/i386/pr94913-2.c | 24 ++++++++++++++++ 6 files changed, 95 insertions(+) create mode 100644 gcc/testsuite/gcc.target/i386/pr94913-1.c create mode 100644 gcc/testsuite/gcc.target/i386/pr94913-2.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9e5a434a231..bc27083b7d3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-05-06 Uroš Bizjak + + PR target/94913 + * config/i386/predicates.md (add_comparison_operator): New predicate. + * config/i386/i386.md (compare->add splitter): New splitters. + 2020-05-06 Richard Biener * tree-vectorizer.h (vect_transform_slp_perm_load): Adjust. diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 911ef7a6c4c..5fe851e0312 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -12324,6 +12324,21 @@ ;; Store-flag instructions. +(define_split + [(set (match_operand:QI 0 "nonimmediate_operand") + (match_operator:QI 1 "add_comparison_operator" + [(not:SWI (match_operand:SWI 2 "register_operand")) + (match_operand:SWI 3 "nonimmediate_operand")]))] + "" + [(parallel + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:SWI (match_dup 2) (match_dup 3)) + (match_dup 2))) + (clobber (scratch:SWI))]) + (set (match_dup 0) + (match_op_dup 1 [(reg:CCC FLAGS_REG) (const_int 0)]))]) + (define_split [(set (match_operand:QI 0 "nonimmediate_operand") (match_operator:QI 1 "shr_comparison_operator" @@ -12518,6 +12533,26 @@ ;; Basic conditional jump instructions. +(define_split + [(set (pc) + (if_then_else + (match_operator 1 "add_comparison_operator" + [(not:SWI (match_operand:SWI 2 "register_operand")) + (match_operand:SWI 3 "nonimmediate_operand")]) + (label_ref (match_operand 0)) + (pc)))] + "" + [(parallel + [(set (reg:CCC FLAGS_REG) + (compare:CCC + (plus:SWI (match_dup 2) (match_dup 3)) + (match_dup 2))) + (clobber (scratch:SWI))]) + (set (pc) + (if_then_else (match_op_dup 1 [(reg:CCC FLAGS_REG) (const_int 0)]) + (label_ref (match_operand 0)) + (pc)))]) + (define_split [(set (pc) (if_then_else diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md index 1a5e2210eca..8d8bcb1a765 100644 --- a/gcc/config/i386/predicates.md +++ b/gcc/config/i386/predicates.md @@ -1293,6 +1293,9 @@ (define_predicate "shr_comparison_operator" (match_code "gtu,leu")) +(define_predicate "add_comparison_operator" + (match_code "geu,ltu")) + ;; Return true if OP is a valid comparison operator in valid mode. (define_predicate "ix86_comparison_operator" (match_operand 0 "comparison_operator") diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a3cf68d0a10..ccdbf989089 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2020-05-06 Uroš Bizjak + + PR target/94913 + * gcc.target/i386/pr94913-1.c: New test. + * gcc.target/i386/pr94913-2.c: Ditto. + 2020-05-06 Richard Biener PR tree-optimization/94963 diff --git a/gcc/testsuite/gcc.target/i386/pr94913-1.c b/gcc/testsuite/gcc.target/i386/pr94913-1.c new file mode 100644 index 00000000000..f21032d4522 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94913-1.c @@ -0,0 +1,21 @@ +/* PR target/94913 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +char fooc (unsigned char x, unsigned char y) +{ + return (unsigned char) ~x < y; +} + +short foos (unsigned short x, unsigned short y) +{ + return (unsigned short) ~x < y; +} + +long fooi (unsigned long x, unsigned long y) +{ + return (unsigned long) ~x < y; +} + +/* { dg-final { scan-assembler-not "cmp" } } */ +/* { dg-final { scan-assembler-times "add" 3 } } */ diff --git a/gcc/testsuite/gcc.target/i386/pr94913-2.c b/gcc/testsuite/gcc.target/i386/pr94913-2.c new file mode 100644 index 00000000000..22bca2bf27b --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr94913-2.c @@ -0,0 +1,24 @@ +/* PR target/94913 */ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void f1 (void); +void f2 (void); + +void fooc (unsigned char x, unsigned char y) +{ + if ((unsigned char) ~x < y) f1 (); else f2 (); +} + +void foos (unsigned short x, unsigned short y) +{ + if ((unsigned short) ~x < y) f1 (); else f2 (); +} + +void fooi (unsigned long x, unsigned long y) +{ + if ((unsigned long) ~x < y) f1 (); else f2 (); +} + +/* { dg-final { scan-assembler-not "cmp" } } */ +/* { dg-final { scan-assembler-times "add" 3 } } */ -- 2.30.2