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:
parent
1c2b53ce8b
commit
0e36a9c691
2 changed files with 51 additions and 20 deletions
|
@ -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))))])
|
||||
|
||||
|
|
26
gcc/testsuite/gcc.target/i386/pr107172.c
Normal file
26
gcc/testsuite/gcc.target/i386/pr107172.c
Normal 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;
|
||||
}
|
Loading…
Add table
Reference in a new issue