i386: Use ADD to implement compares with negated operand [PR94913]
authorUros Bizjak <ubizjak@gmail.com>
Wed, 6 May 2020 15:33:51 +0000 (17:33 +0200)
committerUros Bizjak <ubizjak@gmail.com>
Wed, 6 May 2020 15:33:51 +0000 (17:33 +0200)
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
gcc/config/i386/i386.md
gcc/config/i386/predicates.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr94913-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr94913-2.c [new file with mode: 0644]

index 9e5a434a231e27f65dda18812370edf6e4af4f2d..bc27083b7d3903a59fbee4ed1de63018fb1d03c8 100644 (file)
@@ -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.
index 911ef7a6c4c29d7ee037b5f72c6d86e42c45bdce..5fe851e0312849aea5ac1aa01e6c1dc9a1e5666e 100644 (file)
 \f
 ;; 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"
 \f
 ;; 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
index 1a5e2210eca8ba096122714624ad15f68b3840c9..8d8bcb1a765b2c8af22c0a087d2a1faffbd9332c 100644 (file)
 (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")
index a3cf68d0a10a6a3d9e5af9a9cee8e75f5976aab9..ccdbf989089ae3972ff545d9a16adaf963707243 100644 (file)
@@ -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 (file)
index 0000000..f21032d
--- /dev/null
@@ -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 (file)
index 0000000..22bca2b
--- /dev/null
@@ -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 } } */