aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Bizjak <ubizjak@gmail.com>2020-05-06 17:33:51 +0200
committerUros Bizjak <ubizjak@gmail.com>2020-05-06 17:33:51 +0200
commit7c2879301d3b027a1ba427a5d5c7557decb8a7ab (patch)
tree88de4ce841571a83a2dba3f013b5d79b2768a4f0
parent1266778548e20de82983b6446f3cb685068cfb1e (diff)
downloadgcc-7c2879301d3b027a1ba427a5d5c7557decb8a7ab.zip
gcc-7c2879301d3b027a1ba427a5d5c7557decb8a7ab.tar.gz
gcc-7c2879301d3b027a1ba427a5d5c7557decb8a7ab.tar.bz2
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.
-rw-r--r--gcc/ChangeLog6
-rw-r--r--gcc/config/i386/i386.md35
-rw-r--r--gcc/config/i386/predicates.md3
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/i386/pr94913-1.c21
-rw-r--r--gcc/testsuite/gcc.target/i386/pr94913-2.c24
6 files changed, 95 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9e5a434..bc27083 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,9 @@
+2020-05-06 Uroš Bizjak <ubizjak@gmail.com>
+
+ 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 <rguenther@suse.de>
* tree-vectorizer.h (vect_transform_slp_perm_load): Adjust.
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 911ef7a..5fe851e 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -12326,6 +12326,21 @@
(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"
[(match_operand:DI 2 "register_operand")
(match_operand 3 "const_int_operand")]))]
@@ -12521,6 +12536,26 @@
(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
(match_operator 1 "shr_comparison_operator"
[(match_operand:DI 2 "register_operand")
(match_operand 3 "const_int_operand")])
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 1a5e221..8d8bcb1 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 a3cf68d..ccdbf98 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2020-05-06 Uroš Bizjak <ubizjak@gmail.com>
+
+ PR target/94913
+ * gcc.target/i386/pr94913-1.c: New test.
+ * gcc.target/i386/pr94913-2.c: Ditto.
+
2020-05-06 Richard Biener <rguenther@suse.de>
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 0000000..f21032d
--- /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 0000000..22bca2b
--- /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 } } */