[Committed] [PATCH, ifcvt] Fix PR63917

2014-12-11 Thread Zhenqiang Chen


 -Original Message-
 From: Richard Henderson [mailto:r...@redhat.com]
 Sent: Wednesday, December 10, 2014 8:55 AM
 To: Zhenqiang Chen
 Cc: gcc-patches@gcc.gnu.org
 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;
+}





Re: [Ping] [PATCH, ifcvt] Fix PR63917

2014-12-09 Thread Richard Henderson
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.

 +   (GET_MODE_CLASS (GET_MODE (XEXP (cond, 0))) == MODE_CC))

More silly parens around the ==.

 +  /* 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.


r~


[Ping] [PATCH, ifcvt] Fix PR63917

2014-12-04 Thread Zhenqiang Chen
Ping?

Thanks!
-Zhenqiang

-Original Message-
From: gcc-patches-ow...@gcc.gnu.org [mailto:gcc-patches-ow...@gcc.gnu.org] On 
Behalf Of Zhenqiang Chen
Sent: Monday, December 01, 2014 3:14 PM
To: 'H.J. Lu'
Cc: Richard Henderson; GCC Patches
Subject: RE: [PATCH, ifcvt] Fix PR63917


 -Original Message-
 From: H.J. Lu [mailto:hjl.to...@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.c...@arm.com wrote:
 
  -Original Message-
  From: Richard Henderson [mailto:r...@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.c...@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.c...@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

RE: [PATCH, ifcvt] Fix PR63917

2014-11-30 Thread Zhenqiang Chen

 -Original Message-
 From: H.J. Lu [mailto:hjl.to...@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.c...@arm.com wrote:
 
  -Original Message-
  From: Richard Henderson [mailto:r...@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.c...@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.c...@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
  000..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

Re: [PATCH, ifcvt] Fix PR63917

2014-11-28 Thread H.J. Lu
On Sun, Nov 23, 2014 at 7:47 PM, Zhenqiang Chen zhenqiang.c...@arm.com wrote:

 -Original Message-
 From: Richard Henderson [mailto:r...@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.c...@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.c...@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 000..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

RE: [PATCH, ifcvt] Fix PR63917

2014-11-23 Thread Zhenqiang Chen

 -Original Message-
 From: Richard Henderson [mailto:r...@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.c...@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.c...@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 000..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;
+}





[PATCH, ifcvt] Fix PR63917

2014-11-20 Thread Zhenqiang Chen
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:CCGOC0)?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.c...@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.c...@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 000..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) = 

Re: [PATCH, ifcvt] Fix PR63917

2014-11-20 Thread H.J. Lu
On Thu, Nov 20, 2014 at 1:48 AM, Zhenqiang Chen zhenqiang.c...@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:CCGOC0)?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.c...@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.c...@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.


Re: [PATCH, ifcvt] Fix PR63917

2014-11-20 Thread Richard Henderson
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~