[Committed] [PATCH, ifcvt] Fix PR63917
-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
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
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
-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
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
-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
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
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
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~