> -----Original Message-----
> From: Richard Henderson [mailto:[email protected]]
> Sent: Wednesday, December 10, 2014 8:55 AM
> To: Zhenqiang Chen
> Cc: [email protected]
> Subject: Re: [Ping] [PATCH, ifcvt] Fix PR63917
>
> On 12/04/2014 05:16 PM, Zhenqiang Chen wrote:
> > +static rtx
> > +cc_in_cond (rtx cond)
> > +{
> > + if ((HAVE_cbranchcc4) && cond
>
> Silly parens around the HAVE_cbranchcc4.
Removed.
> > + && (GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC))
>
> More silly parens around the ==.
Removed.
> > + /* 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;
>
> Don't nest if's when an && will do; if the && won't do, always use braces.
>
> It looks like the insn_b test can be simpler, since the non-null return from
> cc_in_cond is always XEXP (cond, 0).
>
> So:
>
> if (cc
> && (set_of (cc, insn_a)
> || (insn_b && set_of (cc, insn_b)))
> return FALSE;
>
> Ok with those changes.
Updated and committed @r218658.
Here is the final patch.
Index: gcc/ifcvt.c
===================================================================
--- gcc/ifcvt.c (revision 218657)
+++ gcc/ifcvt.c (working copy)
@@ -1016,6 +1016,18 @@
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 @@
{
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 @@
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 @@
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 @@
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
+ && (set_of (cc, insn_a)
+ || (insn_b && set_of (cc, 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 @@
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 @@
&& 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);
Index: gcc/testsuite/gcc.dg/pr64007.c
===================================================================
--- gcc/testsuite/gcc.dg/pr64007.c (revision 0)
+++ gcc/testsuite/gcc.dg/pr64007.c (revision 0)
@@ -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;
+}