x86: Replace ne:CCC/ne:CCO with UNSPEC_CC_NE in neg patterns

In i386.md, neg patterns which set MODE_CC register like

(set (reg:CCC FLAGS_REG)
     (ne:CCC (match_operand:SWI48 1 "general_reg_operand") (const_int 0)))

can lead to errors when operand 1 is a constant value.  If FLAGS_REG in

(set (reg:CCC FLAGS_REG)
     (ne:CCC (const_int 2) (const_int 0)))

is set to 1, RTX simplifiers may simplify

(set (reg:SI 93)
     (neg:SI (ltu:SI (reg:CCC 17 flags) (const_int 0 [0]))))

as

(set (reg:SI 93)
     (neg:SI (ltu:SI (const_int 1) (const_int 0 [0]))))

which leads to incorrect results since LTU on MODE_CC register isn't the
same as "unsigned less than" in x86 backend.  To prevent RTL optimizers
from setting MODE_CC register to a constant, use UNSPEC_CC_NE to replace
ne:CCC/ne:CCO when setting FLAGS_REG in neg patterns.

gcc/

	PR target/107172
	* config/i386/i386.md (UNSPEC_CC_NE): New.
	Replace ne:CCC/ne:CCO with UNSPEC_CC_NE in neg patterns.

gcc/testsuite/

	PR target/107172
	* gcc.target/i386/pr107172.c: New test.
This commit is contained in:
H.J. Lu 2022-10-20 11:55:19 -07:00
parent 1c2b53ce8b
commit 0e36a9c691
2 changed files with 51 additions and 20 deletions

View file

@ -113,6 +113,7 @@
UNSPEC_PEEPSIB
UNSPEC_INSN_FALSE_DEP
UNSPEC_SBB
UNSPEC_CC_NE
;; For SSE/MMX support:
UNSPEC_FIX_NOTRUNC
@ -11470,7 +11471,7 @@
"&& reload_completed"
[(parallel
[(set (reg:CCC FLAGS_REG)
(ne:CCC (match_dup 1) (const_int 0)))
(unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 0) (neg:DWIH (match_dup 1)))])
(parallel
[(set (match_dup 2)
@ -11499,7 +11500,8 @@
(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)))
(unspec:CCC [(match_operand:SWI48 2 "general_reg_operand")
(const_int 0)] UNSPEC_CC_NE))
(set (match_dup 2) (neg:SWI48 (match_dup 2)))])
(parallel
[(set (match_dup 0)
@ -11517,7 +11519,7 @@
&& !reg_mentioned_p (operands[2], operands[1])"
[(parallel
[(set (reg:CCC FLAGS_REG)
(ne:CCC (match_dup 2) (const_int 0)))
(unspec:CCC [(match_dup 2) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 2) (neg:SWI48 (match_dup 2)))])
(parallel
[(set (match_dup 0)
@ -11543,7 +11545,8 @@
(clobber (reg:CC FLAGS_REG))])
(parallel
[(set (reg:CCC FLAGS_REG)
(ne:CCC (match_operand:SWI48 1 "general_reg_operand") (const_int 0)))
(unspec:CCC [(match_operand:SWI48 1 "general_reg_operand")
(const_int 0)] UNSPEC_CC_NE))
(set (match_dup 1) (neg:SWI48 (match_dup 1)))])
(parallel
[(set (match_dup 0)
@ -11559,7 +11562,7 @@
"REGNO (operands[0]) != REGNO (operands[1])"
[(parallel
[(set (reg:CCC FLAGS_REG)
(ne:CCC (match_dup 1) (const_int 0)))
(unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 1) (neg:SWI48 (match_dup 1)))])
(parallel
[(set (match_dup 0)
@ -11635,9 +11638,9 @@
(define_insn "*neg<mode>_ccc_1"
[(set (reg:CCC FLAGS_REG)
(ne:CCC
(match_operand:SWI 1 "nonimmediate_operand" "0")
(const_int 0)))
(unspec:CCC
[(match_operand:SWI 1 "nonimmediate_operand" "0")
(const_int 0)] UNSPEC_CC_NE))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
(neg:SWI (match_dup 1)))]
""
@ -11647,9 +11650,9 @@
(define_insn "*neg<mode>_ccc_2"
[(set (reg:CCC FLAGS_REG)
(ne:CCC
(match_operand:SWI 1 "nonimmediate_operand" "0")
(const_int 0)))
(unspec:CCC
[(match_operand:SWI 1 "nonimmediate_operand" "0")
(const_int 0)] UNSPEC_CC_NE))
(clobber (match_scratch:SWI 0 "=<r>"))]
""
"neg{<imodesuffix>}\t%0"
@ -11659,8 +11662,8 @@
(define_expand "x86_neg<mode>_ccc"
[(parallel
[(set (reg:CCC FLAGS_REG)
(ne:CCC (match_operand:SWI48 1 "register_operand")
(const_int 0)))
(unspec:CCC [(match_operand:SWI48 1 "register_operand")
(const_int 0)] UNSPEC_CC_NE))
(set (match_operand:SWI48 0 "register_operand")
(neg:SWI48 (match_dup 1)))])])
@ -11686,8 +11689,9 @@
;; Negate with jump on overflow.
(define_expand "negv<mode>3"
[(parallel [(set (reg:CCO FLAGS_REG)
(ne:CCO (match_operand:SWI 1 "register_operand")
(match_dup 3)))
(unspec:CCO
[(match_operand:SWI 1 "register_operand")
(match_dup 3)] UNSPEC_CC_NE))
(set (match_operand:SWI 0 "register_operand")
(neg:SWI (match_dup 1)))])
(set (pc) (if_then_else
@ -11703,8 +11707,9 @@
(define_insn "*negv<mode>3"
[(set (reg:CCO FLAGS_REG)
(ne:CCO (match_operand:SWI 1 "nonimmediate_operand" "0")
(match_operand:SWI 2 "const_int_operand")))
(unspec:CCO [(match_operand:SWI 1 "nonimmediate_operand" "0")
(match_operand:SWI 2 "const_int_operand")]
UNSPEC_CC_NE))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m")
(neg:SWI (match_dup 1)))]
"ix86_unary_operator_ok (NEG, <MODE>mode, operands)
@ -11770,7 +11775,7 @@
"&& 1"
[(parallel
[(set (reg:CCC FLAGS_REG)
(ne:CCC (match_dup 1) (const_int 0)))
(unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 2) (neg:DWIH (match_dup 1)))])
(parallel
[(set (match_dup 5)
@ -11814,7 +11819,7 @@
"&& 1"
[(parallel
[(set (reg:CCC FLAGS_REG)
(ne:CCC (match_dup 1) (const_int 0)))
(unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 2) (neg:DWIH (match_dup 1)))])
(parallel
[(set (match_dup 5)
@ -21456,7 +21461,7 @@
(const_int 0))))]
""
[(set (reg:CCC FLAGS_REG)
(ne:CCC (match_dup 1) (const_int 0)))
(unspec:CCC [(match_dup 1) (const_int 0)] UNSPEC_CC_NE))
(set (match_dup 0)
(neg:SWI (ltu:SWI (reg:CCC FLAGS_REG) (const_int 0))))])

View file

@ -0,0 +1,26 @@
/* { dg-do run } */
/* { dg-options "-O1 -ftree-vrp" } */
int a, c, d;
int
main()
{
long e = 1;
int f = a = 1;
L1:
if (a)
a = 2;
int h = e = ~e;
c = -1;
if (e >= a)
goto L2;
if (-1 > a)
goto L1;
if (a)
f = -1;
L2:
d = (-f + d) & h;
if (d)
__builtin_abort();
return 0;
}