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.
This commit is contained in:
Uros Bizjak 2020-05-06 17:33:51 +02:00
parent 1266778548
commit 7c2879301d
6 changed files with 95 additions and 0 deletions

View 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.

View file

@ -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

View file

@ -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")

View 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

View file

@ -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 } } */

View file

@ -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 } } */