public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Alan Lawrence <alan.lawrence@arm.com>
To: Jeff Law <law@redhat.com>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>,
	 Richard Biener <richard.guenther@gmail.com>
Subject: Re: [PATCH/RFC] Make loop-header-copying more aggressive, rerun before tree-if-conversion
Date: Fri, 19 Jun 2015 17:54:00 -0000	[thread overview]
Message-ID: <55845395.3020306@arm.com> (raw)
In-Reply-To: <5565E839.2090402@redhat.com>

Jeff Law wrote:
> On 05/22/2015 09:42 AM, Alan Lawrence wrote:
>> This patch does so (and makes slightly less conservative, to tackle the
>> example above). I found I had to make this a separate pass, so that the
>> phi nodes were cleaned up at the end of the pass before running
>> tree_if_conversion.
> What PHI node cleanup needs to be done?  I don't doubt something's 
> needed, but would like to understand the cleanup -- depending on what 
> needs to be done, it may be the case that we can cleanup on-the-fly or 
> it may point at a general issue we should be resolving prior to running 
> tree_if_conversion.

If I change pass_ch_vect to return 0 rather than TODO_update_cfg, my testcase gives:

foo ()
{
   int m;
   int i;
   unsigned int ivtmp_3;
   int _5;
   int _6;
   int _7;
   int _10;
   int _12;
   unsigned int ivtmp_13;
   int _15;
   unsigned int ivtmp_19;
   int _20;
   unsigned int ivtmp_23;
   unsigned int ivtmp_27;

   <bb 2>:
   _10 = A[0];

   <bb 8>:
   # m_11 = PHI <4(2)>
   # _12 = PHI <_10(2)>
   # i_1 = PHI <0(2)>
   # ivtmp_19 = PHI <16(2)>
   _20 = m_11 * _12;
   A[i_1] = _20;
   i_22 = i_1 + 1;
   ivtmp_23 = ivtmp_19 - 1;
   if (ivtmp_23 != 0)
     goto <bb 9>;
   else
     goto <bb 7>;

   <bb 9>:

   <bb 3>:
   # i_26 = PHI <i_9(10), i_22(9)>
   # ivtmp_27 = PHI <ivtmp_13(10), ivtmp_23(9)>
   _5 = A[i_26];
   _6 = _5 & i_26;
   if (_6 != 0)
     goto <bb 5>;
   else
     goto <bb 4>;

   <bb 4>:

   <bb 5>:
   # m_14 = PHI <5(3), 4(4)>

   <bb 6>:
   # m_2 = PHI <m_14(5)>
   # _15 = PHI <_5(5)>
   # i_16 = PHI <i_26(5)>
   # ivtmp_3 = PHI <ivtmp_27(5)>
   _7 = m_2 * _15;
   A[i_16] = _7;
   i_9 = i_16 + 1;
   ivtmp_13 = ivtmp_3 - 1;
   if (ivtmp_13 != 0)
     goto <bb 10>;
   else
     goto <bb 7>;

   <bb 10>:
   goto <bb 3>;

   <bb 7>:
   return;

}

if-conversion then bails out in if_convertible_phi_p, with a phi (whose result 
is a virtual operand, specifically an SSA name) used as operand to another phi 
("Difficult to handle this virtual phi" in tree-if-conv.c): see m_2, i_16. 
Returning TODO_update_cfg, causes merging of blocks 2 and 8, and blocks 5 and 6, 
giving instead:

foo ()
{
   int m;
   int i;
   int _5;
   int _6;
   int _7;
   int _10;
   unsigned int ivtmp_13;
   int _20;
   unsigned int ivtmp_23;
   unsigned int ivtmp_27;

   <bb 2>:
   _10 = A[0];
   _20 = _10 * 4;
   A[0] = _20;
   i_22 = 1;
   ivtmp_23 = 15;
   if (ivtmp_23 != 0)
     goto <bb 3>;
   else
     goto <bb 8>;

   <bb 3>:

   <bb 4>:
   # i_26 = PHI <i_9(7), i_22(3)>
   # ivtmp_27 = PHI <ivtmp_13(7), ivtmp_23(3)>
   _5 = A[i_26];
   _6 = _5 & i_26;
   if (_6 != 0)
     goto <bb 6>;
   else
     goto <bb 5>;

   <bb 5>:

   <bb 6>:
   # m_14 = PHI <5(4), 4(5)>
   _7 = _5 * m_14;
   A[i_26] = _7;
   i_9 = i_26 + 1;
   ivtmp_13 = ivtmp_27 + 4294967295;
   if (ivtmp_13 != 0)
     goto <bb 7>;
   else
     goto <bb 8>;

   <bb 7>:
   goto <bb 4>;

   <bb 8>:
   return;

}

and one can see that the troublesome phi's are gone.

> Don't we have a flag to turn off loop header copying?  If so, does 
> adding that flag to the test "fix" it  without resorting to something
> gross like preserving the old logic for the first pass and new logic for 
> the second pass.

Ah, yes, thanks, -fno-tree-ch works. In fact here the problem was caused by the 
second pass, which following Richard's suggestion, I've now gated with 
-ftree-vectorize also - which is turned off by default at -O2, so the test is 
passing without changes.

However, it turns out I was implicitly using different logic in the two passes: 
the 'if (!single_exit(loop)) return true' always bailed out in the first 
pass_ch, as single_exit-ness is not known in the absence of 
LOOPS_HAVE_RECORDED_EXITS, so the first pass_ch was still using the original 
logic anyway! I've now had to refactor the two classes to allow different code 
anyway, which makes the distinction clear.

(I also tried a more complicated version of do_while_loop_p that computed it's 
own single_exit criteria to have that in the first pass; this gave more test 
failures, which are fixable, but it's not really the purpose of this patch to do 
additional header-copying when we are not vectorizing.)

> My biggest worry would be cases where data initialized by 
> loop_optimizer_init gets invalidated by the header copying.  Have you 
> looked at all at that possibility?  I don't have anything specific in 
> mind to point you at -- just a general concern.

Well, this code from tree-ssa-loop-ch.c appears to update the preheader and loop 
latch (I've verified with printf's that loop->latch, loop->header, 
loop_preheader_edge(loop) and loop_latch_edge(loop) are all sensible after this):

/* Ensure that the latch and the preheader is simple (we know that they
	 are not now, since there was the loop exit condition.  */
       split_edge (loop_preheader_edge (loop));
       split_edge (loop_latch_edge (loop));

and I think the exit edges don't change (they get cloned outside the loop). The 
one remaining worry might be irreducible code, but I believe this should have 
been removed by the stage pass_ch_vect runs: I've also run an entire bootstrap + 
testsuite with both (a) an assertion in pass_ch_vect::process_loop_p that none 
of the blocks in the loop are BB_IRREDUCIBLE, and (b) a call to 
verify_loop_structure at the end of pass_ch_base::copy_headers.

I agree this isn't (/cannot be) totally definitive, so if you are not 
sufficiently reassured - would you be if I called loop_optimizer_init 
(LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS) at the end of pass_ch_vect, redoing 
the setup done in pass_tree_loop_init::execute?

Patch v2 at https://gcc.gnu.org/ml/gcc-patches/2015-06/msg01355.html .

Thanks for the review!

--Alan

  reply	other threads:[~2015-06-19 17:38 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-22 15:46 Alan Lawrence
2015-05-27 16:01 ` Jeff Law
2015-06-19 17:54   ` Alan Lawrence [this message]
2015-06-23 20:34     ` Jeff Law
2015-06-30 16:10       ` Alan Lawrence
2015-07-01 17:06         ` Jeff Law
2015-05-28 12:11 ` Richard Biener
2015-06-19 17:38   ` Alan Lawrence

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=55845395.3020306@arm.com \
    --to=alan.lawrence@arm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=law@redhat.com \
    --cc=richard.guenther@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).