diff mbox

[ifcvt] Fix PR63917

Message ID 000001d004a7$2248cbb0$66da6310$@arm.com
State New
Headers show

Commit Message

Zhenqiang Chen Nov. 20, 2014, 9:48 a.m. UTC
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.

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

Comments

H.J. Lu Nov. 20, 2014, 12:25 p.m. UTC | #1
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.
Richard Henderson Nov. 20, 2014, 6:27 p.m. UTC | #2
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~
diff mbox

Patch

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