public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH, ifcvt] Fix PR63917
@ 2014-11-20 10:47 Zhenqiang Chen
  2014-11-20 12:33 ` H.J. Lu
  2014-11-20 18:58 ` Richard Henderson
  0 siblings, 2 replies; 6+ messages in thread
From: Zhenqiang Chen @ 2014-11-20 10:47 UTC (permalink / raw)
  To: gcc-patches

Hi,

r217646 enhances ifcvt to handle cbranchcc4 instruction. But ifcvt does not
strictly check the dependence before moving instructions before IF. Then
some instructions, which clobber CC, are inserted before the cbranchcc4
instruction.

For the case in the patch, ifcvt transfers code from

   5: r87:SI=r117:SI
   22: pc={(flags:CCGOC>=0)?L26:pc}
   25: {r87:SI=-r117:SI;clobber flags:CC;}

to
   5: r87:SI=r117:SI
  136: {r145:SI=-r117:SI;clobber flags:CC;} // CC is clobbered
  137: r87:SI={(flags:CCGOC<0)?r145:SI:r117:SI}

The patch skips moving insns, which clobber CC, before cbranchcc4.

Bootstrap and no make check regression on X86-64 and i686.
All the failed cases in PR63917 PASS.

OK for trunk?
Thanks!
-Zhenqiang

ChangeLog:
2014-11-20  Zhenqiang Chen  <zhenqiang.chen@arm.com>

	PR rtl-optimization/63917
	* ifcvt.c (clobber_cc_p, use_cc_p): New functions.
	(noce_process_if_block, check_cond_move_block): Check CC references.

testsuite/ChangeLog:
2014-11-20  Zhenqiang Chen  <zhenqiang.chen@arm.com>

	* gcc.target/i386/floatsitf.c: New test.

diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 21f08c2..760eeb6 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -2528,6 +2528,34 @@ noce_can_store_speculate_p (basic_block top_bb,
const_rtx mem)
   return false;
 }
 
+/* Check X clobber CC reg or not.  */
+
+static bool
+clobber_cc_p (rtx x)
+{
+  RTX_CODE code = GET_CODE (x);
+  int i;
+
+  if (code == CLOBBER
+      && REG_P (XEXP (x, 0))
+      && (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) == MODE_CC))
+    return TRUE;
+  else if (code == PARALLEL)
+    for (i = 0; i < XVECLEN (x, 0); i++)
+      if (clobber_cc_p (XVECEXP (x, 0, i)))
+	return TRUE;
+  return FALSE;
+}
+
+/* Check CC reg is used in COND or not.  */
+
+static bool
+use_cc_p (rtx cond)
+{
+  return (HAVE_cbranchcc4)
+	  && (GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC);
+}
+
 /* Given a simple IF-THEN-JOIN or IF-THEN-ELSE-JOIN block, attempt to
convert
    it without using conditional execution.  Return TRUE if we were
successful
    at converting the block.  */
@@ -2655,6 +2683,12 @@ noce_process_if_block (struct noce_if_info *if_info)
   if_info->a = a;
   if_info->b = b;
 
+  /* Skip it if the instruction to be moved might clobber CC.  */
+  if (use_cc_p (if_info->cond)
+      && (clobber_cc_p (PATTERN (insn_a))
+	  || (insn_b && clobber_cc_p (PATTERN (insn_b)))))
+    return FALSE;
+
   /* Try optimizations in some approximation of a useful order.  */
   /* ??? Should first look to see if X is live incoming at all.  If it
      isn't, we don't need anything but an unconditional set.  */
@@ -2868,6 +2902,10 @@ check_cond_move_block (basic_block bb,
 	  && modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
 	return FALSE;
 
+      /* Skip it if the instruction to be moved might clobber CC.  */
+      if (use_cc_p (cond) && clobber_cc_p (PATTERN (insn)))
+	return FALSE;
+
       vals->put (dest, src);
 
       regs->safe_push (dest);

diff --git a/gcc/testsuite/gcc.target/i386/floatsitf.c
b/gcc/testsuite/gcc.target/i386/floatsitf.c
new file mode 100644
index 0000000..6b249cc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/floatsitf.c
@@ -0,0 +1,48 @@
+/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
+/* { dg-options "-O2 -fdump-rtl-ce2"  } */
+
+typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
+void __sfp_handle_exceptions (int);
+
+typedef int QItype __attribute__ ((mode (QI)));
+typedef int SItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int UQItype __attribute__ ((mode (QI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+
+typedef unsigned int UHWtype __attribute__ ((mode (HI)));
+extern const UQItype __clz_tab[256] ;
+
+extern void abort (void);
+typedef float TFtype __attribute__ ((mode (TF)));
+
+union _FP_UNION_Q
+{
+  TFtype flt;
+  struct
+  {
+    unsigned long frac0 : 32;
+    unsigned long frac1 : 32;
+    unsigned long frac2 : 32;
+    unsigned long frac3 : 113 - (((unsigned int) 1 << (113 -1) % 32) !=
0)-(32 * 3);
+    unsigned exp : 15;
+    unsigned sign : 1;
+
+  } bits __attribute__ ((packed));
+};
+
+TFtype
+__floatsitf (SItype i)
+{
+  int A_c __attribute__ ((unused)); int A_s __attribute__ ((unused)); int
A_e __attribute__ ((unused)); unsigned int A_f[4];
+  TFtype a;
+
+  do { if ((i)) { USItype _FP_FROM_INT_ur; if ((A_s = (((i)) < 0))) ((i)) =
-(USItype) ((i)); _FP_FROM_INT_ur = (USItype) ((i)); (void) (((((8 * (int)
sizeof (SItype)))) <= 32) ? ({ int _FP_FROM_INT_lz; do { if (sizeof
(unsigned int) == sizeof (unsigned int)) (_FP_FROM_INT_lz) = __builtin_clz
((unsigned int) _FP_FROM_INT_ur); else if (sizeof (unsigned int) == sizeof
(unsigned long)) (_FP_FROM_INT_lz) = __builtin_clzl ((unsigned int)
_FP_FROM_INT_ur); else if (sizeof (unsigned int) == sizeof (unsigned long
long)) (_FP_FROM_INT_lz) = __builtin_clzll ((unsigned int) _FP_FROM_INT_ur);
else abort (); } while (0); A_e = (16383 + 32 - 1 - _FP_FROM_INT_lz); }) :
(((((8 * (int) sizeof (SItype)))) <= 2 * 32) ? ({ int _FP_FROM_INT_lz; do {
if ((unsigned int) (_FP_FROM_INT_ur >> 32)) do { if (sizeof (unsigned int)
== sizeof (unsigned int)) ((_FP_FROM_INT_lz)) = __builtin_clz ((unsigned
int) (_FP_FROM_INT_ur >> 32)); else if (sizeof (unsigned int) == sizeof
(unsigned long)) ((_FP_FROM_INT_lz)) = __builtin_clzl ((unsigned int)
(_FP_FROM_INT_ur >> 32)); else if (sizeof (unsigned int) == sizeof (unsigned
long long)) ((_FP_FROM_INT_lz)) = __builtin_clzll ((unsigned int)
(_FP_FROM_INT_ur >> 32)); else abort (); } while (0); else { do { if (sizeof
(unsigned int) == sizeof (unsigned int)) ((_FP_FROM_INT_lz)) = __builtin_clz
((unsigned int) _FP_FROM_INT_ur); else if (sizeof (unsigned int) == sizeof
(unsigned long)) ((_FP_FROM_INT_lz)) = __builtin_clzl ((unsigned int)
_FP_FROM_INT_ur); else if (sizeof (unsigned int) == sizeof (unsigned long
long)) ((_FP_FROM_INT_lz)) = __builtin_clzll ((unsigned int)
_FP_FROM_INT_ur); else abort (); } while (0); (_FP_FROM_INT_lz) += 32; } }
while (0); A_e = (16383 + 2 * 32 - 1 - _FP_FROM_INT_lz); }) : (abort (),
0))); if ((((8 * (int) sizeof (SItype)))) - 1 + 16383 >= 32767 && A_e >=
32767) { do { if (0xc00 == 0 || (0xc00 == 0x800 && !A_s) || (0xc00 == 0x400
&& A_s)) { A_e = 32767; (A_f[3] = 0, A_f[2] = 0, A_f[1] = 0, A_f[0] = 0); }
else { A_e = 32767 - 1; (A_f[3] = (~(signed int) 0), A_f[2] = (~(signed int)
0), A_f[1] = (~(signed int) 0), A_f[0] = (~(signed int) 0)); } do {} while
(0); do {} while (0); } while (0); goto pack_semiraw; } if ((((8 * (int)
sizeof (SItype)))) <= 113 || A_e < 16383 + 113) { do { A_f[0] =
(_FP_FROM_INT_ur); A_f[1] = (((((8 * (int) sizeof (SItype))))) <= 32 ? 0 :
(_FP_FROM_INT_ur) >> 32); A_f[2] = (((((8 * (int) sizeof (SItype))))) <=
2*32 ? 0 : (_FP_FROM_INT_ur) >> 2*32); A_f[3] = (((((8 * (int) sizeof
(SItype))))) <= 3*32 ? 0 : (_FP_FROM_INT_ur) >> 3*32); } while (0); if
(16383 + 113 - 1 - A_e > 0) do { int _FP_FRAC_SLL_4_up, _FP_FRAC_SLL_4_down;
int _FP_FRAC_SLL_4_skip, _FP_FRAC_SLL_4_i; _FP_FRAC_SLL_4_skip = ((16383 +
113 - 1 - A_e)) / 32; _FP_FRAC_SLL_4_up = ((16383 + 113 - 1 - A_e)) % 32;
_FP_FRAC_SLL_4_down = 32 - _FP_FRAC_SLL_4_up; if (!_FP_FRAC_SLL_4_up) for
(_FP_FRAC_SLL_4_i = 3; _FP_FRAC_SLL_4_i >= _FP_FRAC_SLL_4_skip;
--_FP_FRAC_SLL_4_i) A_f[_FP_FRAC_SLL_4_i] =
A_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip]; else { for (_FP_FRAC_SLL_4_i = 3;
_FP_FRAC_SLL_4_i > _FP_FRAC_SLL_4_skip; --_FP_FRAC_SLL_4_i)
A_f[_FP_FRAC_SLL_4_i] = ((A_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip] <<
_FP_FRAC_SLL_4_up) | (A_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip-1] >>
_FP_FRAC_SLL_4_down)); A_f[_FP_FRAC_SLL_4_i--] = A_f[0] <<
_FP_FRAC_SLL_4_up; } for (; _FP_FRAC_SLL_4_i >= 0; --_FP_FRAC_SLL_4_i)
A_f[_FP_FRAC_SLL_4_i] = 0; } while (0); } else { if (16383 + (3 + 113) - 1 <
A_e) _FP_FROM_INT_ur = ((_FP_FROM_INT_ur >> (A_e - 16383 - (3 + 113) + 1)) |
((_FP_FROM_INT_ur << ((((8 * (int) sizeof (SItype)))) - (A_e - 16383 - (3 +
113) + 1))) != 0)); do { A_f[0] = (_FP_FROM_INT_ur); A_f[1] = (((((8 * (int)
sizeof (SItype))))) <= 32 ? 0 : (_FP_FROM_INT_ur) >> 32); A_f[2] = (((((8 *
(int) sizeof (SItype))))) <= 2*32 ? 0 : (_FP_FROM_INT_ur) >> 2*32); A_f[3] =
(((((8 * (int) sizeof (SItype))))) <= 3*32 ? 0 : (_FP_FROM_INT_ur) >> 3*32);
} while (0); if ((16383 + (3 + 113) - 1 - A_e) > 0) do { int
_FP_FRAC_SLL_4_up, _FP_FRAC_SLL_4_down; int _FP_FRAC_SLL_4_skip,
_FP_FRAC_SLL_4_i; _FP_FRAC_SLL_4_skip = ((16383 + (3 + 113) - 1 - A_e)) /
32; _FP_FRAC_SLL_4_up = ((16383 + (3 + 113) - 1 - A_e)) % 32;
_FP_FRAC_SLL_4_down = 32 - _FP_FRAC_SLL_4_up; if (!_FP_FRAC_SLL_4_up) for
(_FP_FRAC_SLL_4_i = 3; _FP_FRAC_SLL_4_i >= _FP_FRAC_SLL_4_skip;
--_FP_FRAC_SLL_4_i) A_f[_FP_FRAC_SLL_4_i] =
A_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip]; else { for (_FP_FRAC_SLL_4_i = 3;
_FP_FRAC_SLL_4_i > _FP_FRAC_SLL_4_skip; --_FP_FRAC_SLL_4_i)
A_f[_FP_FRAC_SLL_4_i] = ((A_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip] <<
_FP_FRAC_SLL_4_up) | (A_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip-1] >>
_FP_FRAC_SLL_4_down)); A_f[_FP_FRAC_SLL_4_i--] = A_f[0] <<
_FP_FRAC_SLL_4_up; } for (; _FP_FRAC_SLL_4_i >= 0; --_FP_FRAC_SLL_4_i)
A_f[_FP_FRAC_SLL_4_i] = 0; } while (0); (A_f[3]) &= ~(unsigned int)
((unsigned int) 1 << (113 -1+3) % 32); pack_semiraw: do { int
_FP_PACK_SEMIRAW_is_tiny = A_e == 0 && !((A_f[0] | A_f[1] | A_f[2] | A_f[3])
== 0); if (0 && _FP_PACK_SEMIRAW_is_tiny) { int _FP_PACK_SEMIRAW_T_c
__attribute__ ((unused)); int _FP_PACK_SEMIRAW_T_s __attribute__ ((unused));
int _FP_PACK_SEMIRAW_T_e __attribute__ ((unused)); unsigned int
_FP_PACK_SEMIRAW_T_f[4]; (_FP_PACK_SEMIRAW_T_f[0] = A_f[0],
_FP_PACK_SEMIRAW_T_f[1] = A_f[1], _FP_PACK_SEMIRAW_T_f[2] = A_f[2],
_FP_PACK_SEMIRAW_T_f[3] = A_f[3]); _FP_PACK_SEMIRAW_T_s = A_s;
_FP_PACK_SEMIRAW_T_e = A_e; do { int _FP_FRAC_SLL_4_up, _FP_FRAC_SLL_4_down;
int _FP_FRAC_SLL_4_skip, _FP_FRAC_SLL_4_i; _FP_FRAC_SLL_4_skip = (1) / 32;
_FP_FRAC_SLL_4_up = (1) % 32; _FP_FRAC_SLL_4_down = 32 - _FP_FRAC_SLL_4_up;
if (!_FP_FRAC_SLL_4_up) for (_FP_FRAC_SLL_4_i = 3; _FP_FRAC_SLL_4_i >=
_FP_FRAC_SLL_4_skip; --_FP_FRAC_SLL_4_i)
_FP_PACK_SEMIRAW_T_f[_FP_FRAC_SLL_4_i] =
_FP_PACK_SEMIRAW_T_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip]; else { for
(_FP_FRAC_SLL_4_i = 3; _FP_FRAC_SLL_4_i > _FP_FRAC_SLL_4_skip;
--_FP_FRAC_SLL_4_i) _FP_PACK_SEMIRAW_T_f[_FP_FRAC_SLL_4_i] =
((_FP_PACK_SEMIRAW_T_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip] <<
_FP_FRAC_SLL_4_up) |
(_FP_PACK_SEMIRAW_T_f[_FP_FRAC_SLL_4_i-_FP_FRAC_SLL_4_skip-1] >>
_FP_FRAC_SLL_4_down)); _FP_PACK_SEMIRAW_T_f[_FP_FRAC_SLL_4_i--] =
_FP_PACK_SEMIRAW_T_f[0] << _FP_FRAC_SLL_4_up; } for (; _FP_FRAC_SLL_4_i >=
0; --_FP_FRAC_SLL_4_i) _FP_PACK_SEMIRAW_T_f[_FP_FRAC_SLL_4_i] = 0; } while
(0); do { if ((_FP_PACK_SEMIRAW_T_f[0]) & 7) { do {} while (0); switch
(0xc00) { case 0: do { if (((_FP_PACK_SEMIRAW_T_f[0]) & 15) != ((unsigned
int) 1 << 2)) __asm__ ("add{l} {%4,%3|%3,%4}\n\t" "adc{l} {$0,%2|%2,0}\n\t"
"adc{l} {$0,%1|%1,0}\n\t" "adc{l} {$0,%0|%0,0}" : "+r" ((USItype)
(_FP_PACK_SEMIRAW_T_f[3])), "+&r" ((USItype) (_FP_PACK_SEMIRAW_T_f[2])),
"+&r" ((USItype) (_FP_PACK_SEMIRAW_T_f[1])), "+&r" ((USItype)
(_FP_PACK_SEMIRAW_T_f[0])) : "g" ((USItype) (((unsigned int) 1 << 2)))); }
while (0); break; case 0xc00: (void) 0; break; case 0x800: do { if
(!_FP_PACK_SEMIRAW_T_s && ((_FP_PACK_SEMIRAW_T_f[0]) & 7)) __asm__ ("add{l}
{%4,%3|%3,%4}\n\t" "adc{l} {$0,%2|%2,0}\n\t" "adc{l} {$0,%1|%1,0}\n\t"
"adc{l} {$0,%0|%0,0}" : "+r" ((USItype) (_FP_PACK_SEMIRAW_T_f[3])), "+&r"
((USItype) (_FP_PACK_SEMIRAW_T_f[2])), "+&r" ((USItype)
(_FP_PACK_SEMIRAW_T_f[1])), "+&r" ((USItype) (_FP_PACK_SEMIRAW_T_f[0])) :
"g" ((USItype) (((unsigned int) 1 << 3)))); } while (0); break; case 0x400:
do { if (_FP_PACK_SEMIRAW_T_s && ((_FP_PACK_SEMIRAW_T_f[0]) & 7)) __asm__
("add{l} {%4,%3|%3,%4}\n\t" "adc{l} {$0,%2|%2,0}\n\t" "adc{l}
{$0,%1|%1,0}\n\t" "adc{l} {$0,%0|%0,0}" : "+r" ((USItype)
(_FP_PACK_SEMIRAW_T_f[3])), "+&r" ((USItype) (_FP_PACK_SEMIRAW_T_f[2])),
"+&r" ((USItype) (_FP_PACK_SEMIRAW_T_f[1])), "+&r" ((USItype)
(_FP_PACK_SEMIRAW_T_f[0])) : "g" ((USItype) (((unsigned int) 1 << 3)))); }
while (0); break; } } } while (0); if (((_FP_PACK_SEMIRAW_T_f[3]) &
((unsigned int) 1 << ((3 + 113) % 32)))) _FP_PACK_SEMIRAW_is_tiny = 0; } do
{ if ((A_f[0]) & 7) { do {} while (0); switch (0xc00) { case 0: do { if
(((A_f[0]) & 15) != ((unsigned int) 1 << 2)) __asm__ ("add{l}
{%4,%3|%3,%4}\n\t" "adc{l} {$0,%2|%2,0}\n\t" "adc{l} {$0,%1|%1,0}\n\t"
"adc{l} {$0,%0|%0,0}" : "+r" ((USItype) (A_f[3])), "+&r" ((USItype)
(A_f[2])), "+&r" ((USItype) (A_f[1])), "+&r" ((USItype) (A_f[0])) : "g"
((USItype) (((unsigned int) 1 << 2)))); } while (0); break; case 0xc00:
(void) 0; break; case 0x800: do { if (!A_s && ((A_f[0]) & 7)) __asm__
("add{l} {%4,%3|%3,%4}\n\t" "adc{l} {$0,%2|%2,0}\n\t" "adc{l}
{$0,%1|%1,0}\n\t" "adc{l} {$0,%0|%0,0}" : "+r" ((USItype) (A_f[3])), "+&r"
((USItype) (A_f[2])), "+&r" ((USItype) (A_f[1])), "+&r" ((USItype) (A_f[0]))
: "g" ((USItype) (((unsigned int) 1 << 3)))); } while (0); break; case
0x400: do { if (A_s && ((A_f[0]) & 7)) __asm__ ("add{l} {%4,%3|%3,%4}\n\t"
"adc{l} {$0,%2|%2,0}\n\t" "adc{l} {$0,%1|%1,0}\n\t" "adc{l} {$0,%0|%0,0}" :
"+r" ((USItype) (A_f[3])), "+&r" ((USItype) (A_f[2])), "+&r" ((USItype)
(A_f[1])), "+&r" ((USItype) (A_f[0])) : "g" ((USItype) (((unsigned int) 1 <<
3)))); } while (0); break; } } } while (0); if (_FP_PACK_SEMIRAW_is_tiny) {
if ((0 & 0x20) || (0 & 0x10)) do {} while (0); } if ((A_f[3]) & (((unsigned
int) 1 << ((3 + 113) % 32)) >> 1)) { (A_f[3]) &= ~(((unsigned int) 1 << ((3
+ 113) % 32)) >> 1); A_e++; if (A_e == 32767) do { if (0xc00 == 0 || (0xc00
== 0x800 && !A_s) || (0xc00 == 0x400 && A_s)) { A_e = 32767; (A_f[3] = 0,
A_f[2] = 0, A_f[1] = 0, A_f[0] = 0); } else { A_e = 32767 - 1; (A_f[3] =
(~(signed int) 0), A_f[2] = (~(signed int) 0), A_f[1] = (~(signed int) 0),
A_f[0] = (~(signed int) 0)); } do {} while (0); do {} while (0); } while
(0); } do { int _FP_FRAC_SRL_4_up, _FP_FRAC_SRL_4_down; int
_FP_FRAC_SRL_4_skip, _FP_FRAC_SRL_4_i; _FP_FRAC_SRL_4_skip = (3) / 32;
_FP_FRAC_SRL_4_down = (3) % 32; _FP_FRAC_SRL_4_up = 32 -
_FP_FRAC_SRL_4_down; if (!_FP_FRAC_SRL_4_down) for (_FP_FRAC_SRL_4_i = 0;
_FP_FRAC_SRL_4_i <= 3-_FP_FRAC_SRL_4_skip; ++_FP_FRAC_SRL_4_i)
A_f[_FP_FRAC_SRL_4_i] = A_f[_FP_FRAC_SRL_4_i+_FP_FRAC_SRL_4_skip]; else {
for (_FP_FRAC_SRL_4_i = 0; _FP_FRAC_SRL_4_i < 3-_FP_FRAC_SRL_4_skip;
++_FP_FRAC_SRL_4_i) A_f[_FP_FRAC_SRL_4_i] =
((A_f[_FP_FRAC_SRL_4_i+_FP_FRAC_SRL_4_skip] >> _FP_FRAC_SRL_4_down) |
(A_f[_FP_FRAC_SRL_4_i+_FP_FRAC_SRL_4_skip+1] << _FP_FRAC_SRL_4_up));
A_f[_FP_FRAC_SRL_4_i++] = A_f[3] >> _FP_FRAC_SRL_4_down; } for (;
_FP_FRAC_SRL_4_i < 4; ++_FP_FRAC_SRL_4_i) A_f[_FP_FRAC_SRL_4_i] = 0; } while
(0); if (A_e == 32767 && !((A_f[0] | A_f[1] | A_f[2] | A_f[3]) == 0)) { if
(!1) { (A_f[3] = ((unsigned int) 1 << (113 -2) % 32), A_f[2] = 0, A_f[1] =
0, A_f[0] = 0); A_s = 1; } else do { if (0) { (A_f[3]) &= ((unsigned int) 1
<< (113 -2) % 32) - 1; if (((A_f[0] | A_f[1] | A_f[2] | A_f[3]) == 0)) { A_s
= 1; (A_f[3] = ((unsigned int) 1 << (113 -2) % 32), A_f[2] = 0, A_f[1] = 0,
A_f[0] = 0); } } else (A_f[3]) |= ((unsigned int) 1 << (113 -2) % 32); }
while (0); } } while (0); } } else { A_s = 0; A_e = 0; (A_f[3] = 0, A_f[2] =
0, A_f[1] = 0, A_f[0] = 0); } } while (0);
+  do { union _FP_UNION_Q _FP_PACK_RAW_4_flo; _FP_PACK_RAW_4_flo.bits.frac0
= A_f[0]; _FP_PACK_RAW_4_flo.bits.frac1 = A_f[1];
_FP_PACK_RAW_4_flo.bits.frac2 = A_f[2]; _FP_PACK_RAW_4_flo.bits.frac3 =
A_f[3]; _FP_PACK_RAW_4_flo.bits.exp = A_e; _FP_PACK_RAW_4_flo.bits.sign =
A_s; ((a)) = _FP_PACK_RAW_4_flo.flt; } while (0);
+
+  return a;
+}
+
+/* { dg-final { scan-rtl-dump "0 IF blocks converted" "ce2"  } } */
+/* { dg-final { cleanup-rtl-dump "ce2" } } */



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH, ifcvt] Fix PR63917
  2014-11-20 10:47 [PATCH, ifcvt] Fix PR63917 Zhenqiang Chen
@ 2014-11-20 12:33 ` H.J. Lu
  2014-11-20 18:58 ` Richard Henderson
  1 sibling, 0 replies; 6+ messages in thread
From: H.J. Lu @ 2014-11-20 12:33 UTC (permalink / raw)
  To: Zhenqiang Chen; +Cc: GCC Patches

On Thu, Nov 20, 2014 at 1:48 AM, Zhenqiang Chen <zhenqiang.chen@arm.com> wrote:
> Hi,
>
> r217646 enhances ifcvt to handle cbranchcc4 instruction. But ifcvt does not
> strictly check the dependence before moving instructions before IF. Then
> some instructions, which clobber CC, are inserted before the cbranchcc4
> instruction.
>
> For the case in the patch, ifcvt transfers code from
>
>    5: r87:SI=r117:SI
>    22: pc={(flags:CCGOC>=0)?L26:pc}
>    25: {r87:SI=-r117:SI;clobber flags:CC;}
>
> to
>    5: r87:SI=r117:SI
>   136: {r145:SI=-r117:SI;clobber flags:CC;} // CC is clobbered
>   137: r87:SI={(flags:CCGOC<0)?r145:SI:r117:SI}
>
> The patch skips moving insns, which clobber CC, before cbranchcc4.
>
> Bootstrap and no make check regression on X86-64 and i686.
> All the failed cases in PR63917 PASS.
>
> OK for trunk?
> Thanks!
> -Zhenqiang
>
> ChangeLog:
> 2014-11-20  Zhenqiang Chen  <zhenqiang.chen@arm.com>
>
>         PR rtl-optimization/63917
>         * ifcvt.c (clobber_cc_p, use_cc_p): New functions.
>         (noce_process_if_block, check_cond_move_block): Check CC references.
>
> testsuite/ChangeLog:
> 2014-11-20  Zhenqiang Chen  <zhenqiang.chen@arm.com>
>
>         * gcc.target/i386/floatsitf.c: New test.
>

Why do you need a new testcase?  There are many failures with the
existing testcases.

-- 
H.J.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH, ifcvt] Fix PR63917
  2014-11-20 10:47 [PATCH, ifcvt] Fix PR63917 Zhenqiang Chen
  2014-11-20 12:33 ` H.J. Lu
@ 2014-11-20 18:58 ` Richard Henderson
  2014-11-24  4:12   ` Zhenqiang Chen
  1 sibling, 1 reply; 6+ messages in thread
From: Richard Henderson @ 2014-11-20 18:58 UTC (permalink / raw)
  To: Zhenqiang Chen, gcc-patches

On 11/20/2014 10:48 AM, Zhenqiang Chen wrote:
> +/* Check X clobber CC reg or not.  */
> +
> +static bool
> +clobber_cc_p (rtx x)
> +{
> +  RTX_CODE code = GET_CODE (x);
> +  int i;
> +
> +  if (code == CLOBBER
> +      && REG_P (XEXP (x, 0))
> +      && (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) == MODE_CC))
> +    return TRUE;
> +  else if (code == PARALLEL)
> +    for (i = 0; i < XVECLEN (x, 0); i++)
> +      if (clobber_cc_p (XVECEXP (x, 0, i)))
> +	return TRUE;
> +  return FALSE;
> +}

Why would you need something like this when modified_between_p or one of its
kin ought to do the job?


r~

^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [PATCH, ifcvt] Fix PR63917
  2014-11-20 18:58 ` Richard Henderson
@ 2014-11-24  4:12   ` Zhenqiang Chen
  2014-11-28 15:15     ` H.J. Lu
  0 siblings, 1 reply; 6+ messages in thread
From: Zhenqiang Chen @ 2014-11-24  4:12 UTC (permalink / raw)
  To: 'Richard Henderson'; +Cc: gcc-patches


> -----Original Message-----
> From: Richard Henderson [mailto:rth@redhat.com]
> Sent: Friday, November 21, 2014 2:27 AM
> To: Zhenqiang Chen; gcc-patches@gcc.gnu.org
> Subject: Re: [PATCH, ifcvt] Fix PR63917
> 
> On 11/20/2014 10:48 AM, Zhenqiang Chen wrote:
> > +/* Check X clobber CC reg or not.  */
> > +
> > +static bool
> > +clobber_cc_p (rtx x)
> > +{
> > +  RTX_CODE code = GET_CODE (x);
> > +  int i;
> > +
> > +  if (code == CLOBBER
> > +      && REG_P (XEXP (x, 0))
> > +      && (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) == MODE_CC))
> > +    return TRUE;
> > +  else if (code == PARALLEL)
> > +    for (i = 0; i < XVECLEN (x, 0); i++)
> > +      if (clobber_cc_p (XVECEXP (x, 0, i)))
> > +	return TRUE;
> > +  return FALSE;
> > +}
> 
> Why would you need something like this when modified_between_p or one
> of its kin ought to do the job?

Thanks for the comments. Patch is updated to use set_of.

And it is also enhanced to make sure that the new generated insns can not
clobber CC.

Bootstrap and no make check regression on X86-64 and IA32.

OK for trunk?

Thanks!
-Zhenqiang

ChangeLog:
2014-11-24  Zhenqiang Chen  <zhenqiang.chen@arm.com>

	PR rtl-optimization/63917
	* ifcvt.c (cc_in_cond): New function.
	(end_ifcvt_sequence): Make sure new generated insns do not clobber
CC.
	(noce_process_if_block, check_cond_move_block): Check CC references.

testsuite/ChangeLog:
2014-11-24  Zhenqiang Chen  <zhenqiang.chen@arm.com>

	* gcc.dg/pr63917.c: New test.

diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 21f08c2..1acd0ff 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -1016,6 +1016,18 @@ noce_emit_move_insn (rtx x, rtx y)
 		   0, 0, outmode, y);
 }
 
+/* Return the CC reg if it is used in COND.  */
+
+static rtx
+cc_in_cond (rtx cond)
+{
+  if ((HAVE_cbranchcc4) && cond
+      && (GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC))
+    return XEXP (cond, 0);
+
+  return NULL_RTX;
+}
+
 /* Return sequence of instructions generated by if conversion.  This
    function calls end_sequence() to end the current stream, ensures
    that are instructions are unshared, recognizable non-jump insns.
@@ -1026,6 +1038,7 @@ end_ifcvt_sequence (struct noce_if_info *if_info)
 {
   rtx_insn *insn;
   rtx_insn *seq = get_insns ();
+  rtx cc = cc_in_cond (if_info->cond);
 
   set_used_flags (if_info->x);
   set_used_flags (if_info->cond);
@@ -1040,7 +1053,9 @@ end_ifcvt_sequence (struct noce_if_info *if_info)
      allows proper placement of required clobbers.  */
   for (insn = seq; insn; insn = NEXT_INSN (insn))
     if (JUMP_P (insn)
-	|| recog_memoized (insn) == -1)
+	|| recog_memoized (insn) == -1
+	   /* Make sure new generated code does not clobber CC.  */
+	|| (cc && set_of (cc, insn)))
       return NULL;
 
   return seq;
@@ -2544,6 +2559,7 @@ noce_process_if_block (struct noce_if_info *if_info)
   rtx_insn *insn_a, *insn_b;
   rtx set_a, set_b;
   rtx orig_x, x, a, b;
+  rtx cc;
 
   /* We're looking for patterns of the form
 
@@ -2655,6 +2671,13 @@ noce_process_if_block (struct noce_if_info *if_info)
   if_info->a = a;
   if_info->b = b;
 
+  /* Skip it if the instruction to be moved might clobber CC.  */
+  cc = cc_in_cond (cond);
+  if (cc)
+    if (set_of (cc, insn_a)
+	|| (insn_b && set_of (XEXP (cond, 0), insn_b)))
+      return FALSE;
+
   /* Try optimizations in some approximation of a useful order.  */
   /* ??? Should first look to see if X is live incoming at all.  If it
      isn't, we don't need anything but an unconditional set.  */
@@ -2811,6 +2834,7 @@ check_cond_move_block (basic_block bb,
 		       rtx cond)
 {
   rtx_insn *insn;
+  rtx cc = cc_in_cond (cond);
 
    /* We can only handle simple jumps at the end of the basic block.
       It is almost impossible to update the CFG otherwise.  */
@@ -2868,6 +2892,10 @@ check_cond_move_block (basic_block bb,
 	  && modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
 	return FALSE;
 
+      /* Skip it if the instruction to be moved might clobber CC.  */
+      if (cc && set_of (cc, insn))
+	return FALSE;
+
       vals->put (dest, src);
 
       regs->safe_push (dest);
diff --git a/gcc/testsuite/gcc.dg/pr63917.c b/gcc/testsuite/gcc.dg/pr63917.c
new file mode 100644
index 0000000..422b15d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr63917.c
@@ -0,0 +1,45 @@
+/* { dg-options " -O3 " } */
+
+int d, i;
+
+struct S
+{
+  int f0;
+} *b, c, e, h, **g = &b;
+
+static struct S *f = &e;
+
+int
+fn1 (int p)
+{
+  int a = 0;
+  return a || p < 0 || p >= 2 || 1 >> p;
+}
+
+int
+main ()
+{
+  int k = 1, l, *m = &c.f0;
+
+  for (;;)
+    {
+      l = fn1 (i);
+      *m = k && i;
+      if (l)
+	{
+	  int n[1] = {0};
+	}
+      break;
+    }
+
+  *g = &h;
+
+  if (d)
+    (*m)--;
+  d = (f != 0) | (i >= 0);
+
+  if (c.f0 != 0)
+    __builtin_abort ();
+
+  return 0;
+}



^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH, ifcvt] Fix PR63917
  2014-11-24  4:12   ` Zhenqiang Chen
@ 2014-11-28 15:15     ` H.J. Lu
  2014-12-01  7:13       ` Zhenqiang Chen
  0 siblings, 1 reply; 6+ messages in thread
From: H.J. Lu @ 2014-11-28 15:15 UTC (permalink / raw)
  To: Zhenqiang Chen; +Cc: Richard Henderson, GCC Patches

On Sun, Nov 23, 2014 at 7:47 PM, Zhenqiang Chen <zhenqiang.chen@arm.com> wrote:
>
>> -----Original Message-----
>> From: Richard Henderson [mailto:rth@redhat.com]
>> Sent: Friday, November 21, 2014 2:27 AM
>> To: Zhenqiang Chen; gcc-patches@gcc.gnu.org
>> Subject: Re: [PATCH, ifcvt] Fix PR63917
>>
>> On 11/20/2014 10:48 AM, Zhenqiang Chen wrote:
>> > +/* Check X clobber CC reg or not.  */
>> > +
>> > +static bool
>> > +clobber_cc_p (rtx x)
>> > +{
>> > +  RTX_CODE code = GET_CODE (x);
>> > +  int i;
>> > +
>> > +  if (code == CLOBBER
>> > +      && REG_P (XEXP (x, 0))
>> > +      && (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) == MODE_CC))
>> > +    return TRUE;
>> > +  else if (code == PARALLEL)
>> > +    for (i = 0; i < XVECLEN (x, 0); i++)
>> > +      if (clobber_cc_p (XVECEXP (x, 0, i)))
>> > +   return TRUE;
>> > +  return FALSE;
>> > +}
>>
>> Why would you need something like this when modified_between_p or one
>> of its kin ought to do the job?
>
> Thanks for the comments. Patch is updated to use set_of.
>
> And it is also enhanced to make sure that the new generated insns can not
> clobber CC.
>
> Bootstrap and no make check regression on X86-64 and IA32.
>
> OK for trunk?
>
> Thanks!
> -Zhenqiang
>
> ChangeLog:
> 2014-11-24  Zhenqiang Chen  <zhenqiang.chen@arm.com>
>
>         PR rtl-optimization/63917
>         * ifcvt.c (cc_in_cond): New function.
>         (end_ifcvt_sequence): Make sure new generated insns do not clobber
> CC.
>         (noce_process_if_block, check_cond_move_block): Check CC references.
>
> testsuite/ChangeLog:
> 2014-11-24  Zhenqiang Chen  <zhenqiang.chen@arm.com>
>
>         * gcc.dg/pr63917.c: New test.
>
> diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
> index 21f08c2..1acd0ff 100644
> --- a/gcc/ifcvt.c
> +++ b/gcc/ifcvt.c
> @@ -1016,6 +1016,18 @@ noce_emit_move_insn (rtx x, rtx y)
>                    0, 0, outmode, y);
>  }
>
> +/* Return the CC reg if it is used in COND.  */
> +
> +static rtx
> +cc_in_cond (rtx cond)
> +{
> +  if ((HAVE_cbranchcc4) && cond
> +      && (GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC))
> +    return XEXP (cond, 0);
> +
> +  return NULL_RTX;
> +}
> +
>  /* Return sequence of instructions generated by if conversion.  This
>     function calls end_sequence() to end the current stream, ensures
>     that are instructions are unshared, recognizable non-jump insns.
> @@ -1026,6 +1038,7 @@ end_ifcvt_sequence (struct noce_if_info *if_info)
>  {
>    rtx_insn *insn;
>    rtx_insn *seq = get_insns ();
> +  rtx cc = cc_in_cond (if_info->cond);
>
>    set_used_flags (if_info->x);
>    set_used_flags (if_info->cond);
> @@ -1040,7 +1053,9 @@ end_ifcvt_sequence (struct noce_if_info *if_info)
>       allows proper placement of required clobbers.  */
>    for (insn = seq; insn; insn = NEXT_INSN (insn))
>      if (JUMP_P (insn)
> -       || recog_memoized (insn) == -1)
> +       || recog_memoized (insn) == -1
> +          /* Make sure new generated code does not clobber CC.  */
> +       || (cc && set_of (cc, insn)))
>        return NULL;
>
>    return seq;
> @@ -2544,6 +2559,7 @@ noce_process_if_block (struct noce_if_info *if_info)
>    rtx_insn *insn_a, *insn_b;
>    rtx set_a, set_b;
>    rtx orig_x, x, a, b;
> +  rtx cc;
>
>    /* We're looking for patterns of the form
>
> @@ -2655,6 +2671,13 @@ noce_process_if_block (struct noce_if_info *if_info)
>    if_info->a = a;
>    if_info->b = b;
>
> +  /* Skip it if the instruction to be moved might clobber CC.  */
> +  cc = cc_in_cond (cond);
> +  if (cc)
> +    if (set_of (cc, insn_a)
> +       || (insn_b && set_of (XEXP (cond, 0), insn_b)))
> +      return FALSE;
> +
>    /* Try optimizations in some approximation of a useful order.  */
>    /* ??? Should first look to see if X is live incoming at all.  If it
>       isn't, we don't need anything but an unconditional set.  */
> @@ -2811,6 +2834,7 @@ check_cond_move_block (basic_block bb,
>                        rtx cond)
>  {
>    rtx_insn *insn;
> +  rtx cc = cc_in_cond (cond);
>
>     /* We can only handle simple jumps at the end of the basic block.
>        It is almost impossible to update the CFG otherwise.  */
> @@ -2868,6 +2892,10 @@ check_cond_move_block (basic_block bb,
>           && modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
>         return FALSE;
>
> +      /* Skip it if the instruction to be moved might clobber CC.  */
> +      if (cc && set_of (cc, insn))
> +       return FALSE;
> +
>        vals->put (dest, src);
>
>        regs->safe_push (dest);
> diff --git a/gcc/testsuite/gcc.dg/pr63917.c b/gcc/testsuite/gcc.dg/pr63917.c
> new file mode 100644
> index 0000000..422b15d
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/pr63917.c

It should be pr64007.c.

> @@ -0,0 +1,45 @@
> +/* { dg-options " -O3 " } */

You need

/* { dg-do run } */

since it is a run-time test.

> +
> +int d, i;
> +
> +struct S
> +{
> +  int f0;
> +} *b, c, e, h, **g = &b;
> +
> +static struct S *f = &e;
> +
> +int
> +fn1 (int p)
> +{
> +  int a = 0;
> +  return a || p < 0 || p >= 2 || 1 >> p;
> +}
> +
> +int
> +main ()
> +{
> +  int k = 1, l, *m = &c.f0;
> +
> +  for (;;)
> +    {
> +      l = fn1 (i);
> +      *m = k && i;
> +      if (l)
> +       {
> +         int n[1] = {0};
> +       }
> +      break;
> +    }
> +
> +  *g = &h;
> +
> +  if (d)
> +    (*m)--;
> +  d = (f != 0) | (i >= 0);
> +
> +  if (c.f0 != 0)
> +    __builtin_abort ();
> +
> +  return 0;
> +}
>

You test doesn't fail without the fix since your test is a little
bit different from the test at

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64007

You missed:

assert (b);

Without it, the bug won't be triggered.

-- 
H.J.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* RE: [PATCH, ifcvt] Fix PR63917
  2014-11-28 15:15     ` H.J. Lu
@ 2014-12-01  7:13       ` Zhenqiang Chen
  0 siblings, 0 replies; 6+ messages in thread
From: Zhenqiang Chen @ 2014-12-01  7:13 UTC (permalink / raw)
  To: 'H.J. Lu'; +Cc: Richard Henderson, GCC Patches


> -----Original Message-----
> From: H.J. Lu [mailto:hjl.tools@gmail.com]
> Sent: Friday, November 28, 2014 10:45 PM
> To: Zhenqiang Chen
> Cc: Richard Henderson; GCC Patches
> Subject: Re: [PATCH, ifcvt] Fix PR63917
> 
> On Sun, Nov 23, 2014 at 7:47 PM, Zhenqiang Chen
> <zhenqiang.chen@arm.com> wrote:
> >
> >> -----Original Message-----
> >> From: Richard Henderson [mailto:rth@redhat.com]
> >> Sent: Friday, November 21, 2014 2:27 AM
> >> To: Zhenqiang Chen; gcc-patches@gcc.gnu.org
> >> Subject: Re: [PATCH, ifcvt] Fix PR63917
> >>
> >> On 11/20/2014 10:48 AM, Zhenqiang Chen wrote:
> >> > +/* Check X clobber CC reg or not.  */
> >> > +
> >> > +static bool
> >> > +clobber_cc_p (rtx x)
> >> > +{
> >> > +  RTX_CODE code = GET_CODE (x);
> >> > +  int i;
> >> > +
> >> > +  if (code == CLOBBER
> >> > +      && REG_P (XEXP (x, 0))
> >> > +      && (GET_MODE_CLASS (GET_MODE (XEXP (x, 0))) == MODE_CC))
> >> > +    return TRUE;
> >> > +  else if (code == PARALLEL)
> >> > +    for (i = 0; i < XVECLEN (x, 0); i++)
> >> > +      if (clobber_cc_p (XVECEXP (x, 0, i)))
> >> > +   return TRUE;
> >> > +  return FALSE;
> >> > +}
> >>
> >> Why would you need something like this when modified_between_p or
> one
> >> of its kin ought to do the job?
> >
> > Thanks for the comments. Patch is updated to use set_of.
> >
> > And it is also enhanced to make sure that the new generated insns can
> > not clobber CC.
> >
> > Bootstrap and no make check regression on X86-64 and IA32.
> >
> > OK for trunk?
> >
> > Thanks!
> > -Zhenqiang
> >
> > ChangeLog:
> > 2014-11-24  Zhenqiang Chen  <zhenqiang.chen@arm.com>
> >
> >         PR rtl-optimization/63917
> >         * ifcvt.c (cc_in_cond): New function.
> >         (end_ifcvt_sequence): Make sure new generated insns do not
> > clobber CC.
> >         (noce_process_if_block, check_cond_move_block): Check CC
> references.
> >
> > testsuite/ChangeLog:
> > 2014-11-24  Zhenqiang Chen  <zhenqiang.chen@arm.com>
> >
> >         * gcc.dg/pr63917.c: New test.
> >
> > diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c index 21f08c2..1acd0ff 100644
> > --- a/gcc/ifcvt.c
> > +++ b/gcc/ifcvt.c
> > @@ -1016,6 +1016,18 @@ noce_emit_move_insn (rtx x, rtx y)
> >                    0, 0, outmode, y);
> >  }
> >
> > +/* Return the CC reg if it is used in COND.  */
> > +
> > +static rtx
> > +cc_in_cond (rtx cond)
> > +{
> > +  if ((HAVE_cbranchcc4) && cond
> > +      && (GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC))
> > +    return XEXP (cond, 0);
> > +
> > +  return NULL_RTX;
> > +}
> > +
> >  /* Return sequence of instructions generated by if conversion.  This
> >     function calls end_sequence() to end the current stream, ensures
> >     that are instructions are unshared, recognizable non-jump insns.
> > @@ -1026,6 +1038,7 @@ end_ifcvt_sequence (struct noce_if_info
> > *if_info)  {
> >    rtx_insn *insn;
> >    rtx_insn *seq = get_insns ();
> > +  rtx cc = cc_in_cond (if_info->cond);
> >
> >    set_used_flags (if_info->x);
> >    set_used_flags (if_info->cond);
> > @@ -1040,7 +1053,9 @@ end_ifcvt_sequence (struct noce_if_info *if_info)
> >       allows proper placement of required clobbers.  */
> >    for (insn = seq; insn; insn = NEXT_INSN (insn))
> >      if (JUMP_P (insn)
> > -       || recog_memoized (insn) == -1)
> > +       || recog_memoized (insn) == -1
> > +          /* Make sure new generated code does not clobber CC.  */
> > +       || (cc && set_of (cc, insn)))
> >        return NULL;
> >
> >    return seq;
> > @@ -2544,6 +2559,7 @@ noce_process_if_block (struct noce_if_info
> *if_info)
> >    rtx_insn *insn_a, *insn_b;
> >    rtx set_a, set_b;
> >    rtx orig_x, x, a, b;
> > +  rtx cc;
> >
> >    /* We're looking for patterns of the form
> >
> > @@ -2655,6 +2671,13 @@ noce_process_if_block (struct noce_if_info
> *if_info)
> >    if_info->a = a;
> >    if_info->b = b;
> >
> > +  /* Skip it if the instruction to be moved might clobber CC.  */  cc
> > + = cc_in_cond (cond);  if (cc)
> > +    if (set_of (cc, insn_a)
> > +       || (insn_b && set_of (XEXP (cond, 0), insn_b)))
> > +      return FALSE;
> > +
> >    /* Try optimizations in some approximation of a useful order.  */
> >    /* ??? Should first look to see if X is live incoming at all.  If it
> >       isn't, we don't need anything but an unconditional set.  */ @@
> > -2811,6 +2834,7 @@ check_cond_move_block (basic_block bb,
> >                        rtx cond)
> >  {
> >    rtx_insn *insn;
> > +  rtx cc = cc_in_cond (cond);
> >
> >     /* We can only handle simple jumps at the end of the basic block.
> >        It is almost impossible to update the CFG otherwise.  */ @@
> > -2868,6 +2892,10 @@ check_cond_move_block (basic_block bb,
> >           && modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
> >         return FALSE;
> >
> > +      /* Skip it if the instruction to be moved might clobber CC.  */
> > +      if (cc && set_of (cc, insn))
> > +       return FALSE;
> > +
> >        vals->put (dest, src);
> >
> >        regs->safe_push (dest);
> > diff --git a/gcc/testsuite/gcc.dg/pr63917.c
> > b/gcc/testsuite/gcc.dg/pr63917.c new file mode 100644 index
> > 0000000..422b15d
> > --- /dev/null
> > +++ b/gcc/testsuite/gcc.dg/pr63917.c
> 
> It should be pr64007.c.
> 
> > @@ -0,0 +1,45 @@
> > +/* { dg-options " -O3 " } */
> 
> You need
> 
> /* { dg-do run } */
> 
> since it is a run-time test.
> 
> > +
> > +int d, i;
> > +
> > +struct S
> > +{
> > +  int f0;
> > +} *b, c, e, h, **g = &b;
> > +
> > +static struct S *f = &e;
> > +
> > +int
> > +fn1 (int p)
> > +{
> > +  int a = 0;
> > +  return a || p < 0 || p >= 2 || 1 >> p; }
> > +
> > +int
> > +main ()
> > +{
> > +  int k = 1, l, *m = &c.f0;
> > +
> > +  for (;;)
> > +    {
> > +      l = fn1 (i);
> > +      *m = k && i;
> > +      if (l)
> > +       {
> > +         int n[1] = {0};
> > +       }
> > +      break;
> > +    }
> > +
> > +  *g = &h;
> > +
> > +  if (d)
> > +    (*m)--;
> > +  d = (f != 0) | (i >= 0);
> > +
> > +  if (c.f0 != 0)
> > +    __builtin_abort ();
> > +
> > +  return 0;
> > +}
> >
> 
> You test doesn't fail without the fix since your test is a little bit different from
> the test at
> 
> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64007
> 
> You missed:
> 
> assert (b);
> 
> Without it, the bug won't be triggered.

Thanks for the comments. Test case in the patch is updated.

diff --git a/gcc/ifcvt.c b/gcc/ifcvt.c
index 21f08c2..1acd0ff 100644
--- a/gcc/ifcvt.c
+++ b/gcc/ifcvt.c
@@ -1016,6 +1016,18 @@ noce_emit_move_insn (rtx x, rtx y)
 		   0, 0, outmode, y);
 }
 
+/* Return the CC reg if it is used in COND.  */
+
+static rtx
+cc_in_cond (rtx cond)
+{
+  if ((HAVE_cbranchcc4) && cond
+      && (GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC))
+    return XEXP (cond, 0);
+
+  return NULL_RTX;
+}
+
 /* Return sequence of instructions generated by if conversion.  This
    function calls end_sequence() to end the current stream, ensures
    that are instructions are unshared, recognizable non-jump insns.
@@ -1026,6 +1038,7 @@ end_ifcvt_sequence (struct noce_if_info *if_info)
 {
   rtx_insn *insn;
   rtx_insn *seq = get_insns ();
+  rtx cc = cc_in_cond (if_info->cond);
 
   set_used_flags (if_info->x);
   set_used_flags (if_info->cond);
@@ -1040,7 +1053,9 @@ end_ifcvt_sequence (struct noce_if_info *if_info)
      allows proper placement of required clobbers.  */
   for (insn = seq; insn; insn = NEXT_INSN (insn))
     if (JUMP_P (insn)
-	|| recog_memoized (insn) == -1)
+	|| recog_memoized (insn) == -1
+	   /* Make sure new generated code does not clobber CC.  */
+	|| (cc && set_of (cc, insn)))
       return NULL;
 
   return seq;
@@ -2544,6 +2559,7 @@ noce_process_if_block (struct noce_if_info *if_info)
   rtx_insn *insn_a, *insn_b;
   rtx set_a, set_b;
   rtx orig_x, x, a, b;
+  rtx cc;
 
   /* We're looking for patterns of the form
 
@@ -2655,6 +2671,13 @@ noce_process_if_block (struct noce_if_info *if_info)
   if_info->a = a;
   if_info->b = b;
 
+  /* Skip it if the instruction to be moved might clobber CC.  */
+  cc = cc_in_cond (cond);
+  if (cc)
+    if (set_of (cc, insn_a)
+	|| (insn_b && set_of (XEXP (cond, 0), insn_b)))
+      return FALSE;
+
   /* Try optimizations in some approximation of a useful order.  */
   /* ??? Should first look to see if X is live incoming at all.  If it
      isn't, we don't need anything but an unconditional set.  */
@@ -2811,6 +2834,7 @@ check_cond_move_block (basic_block bb,
 		       rtx cond)
 {
   rtx_insn *insn;
+  rtx cc = cc_in_cond (cond);
 
    /* We can only handle simple jumps at the end of the basic block.
       It is almost impossible to update the CFG otherwise.  */
@@ -2868,6 +2892,10 @@ check_cond_move_block (basic_block bb,
 	  && modified_between_p (src, insn, NEXT_INSN (BB_END (bb))))
 	return FALSE;
 
+      /* Skip it if the instruction to be moved might clobber CC.  */
+      if (cc && set_of (cc, insn))
+	return FALSE;
+
       vals->put (dest, src);
 
       regs->safe_push (dest);
diff --git a/gcc/testsuite/gcc.dg/pr64007.c b/gcc/testsuite/gcc.dg/pr64007.c
new file mode 100644
index 0000000..cb0e50f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr64007.c
@@ -0,0 +1,50 @@
+/* { dg-options " -O3 " } */
+/* { dg-do run } */
+
+#include <assert.h>
+
+int d, i;
+
+struct S
+{
+  int f0;
+} *b, c, e, h, **g = &b;
+
+static struct S *f = &e;
+
+int
+fn1 (int p)
+{
+  int a = 0;
+  return a || p < 0 || p >= 2 || 1 >> p;
+}
+
+int
+main ()
+{
+  int k = 1, l, *m = &c.f0;
+
+  for (;;)
+    {
+      l = fn1 (i);
+      *m = k && i;
+      if (l)
+	{
+	  int n[1] = {0};
+	}
+      break;
+    }
+
+  *g = &h;
+
+  assert (b);
+
+  if (d)
+    (*m)--;
+  d = (f != 0) | (i >= 0);
+
+  if (c.f0 != 0)
+    __builtin_abort ();
+
+  return 0;
+}



^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2014-12-01  7:13 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-20 10:47 [PATCH, ifcvt] Fix PR63917 Zhenqiang Chen
2014-11-20 12:33 ` H.J. Lu
2014-11-20 18:58 ` Richard Henderson
2014-11-24  4:12   ` Zhenqiang Chen
2014-11-28 15:15     ` H.J. Lu
2014-12-01  7:13       ` Zhenqiang Chen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).