<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Wed, Sep 18, 2013 at 10:14 AM, Shuxin Yang <span dir="ltr"><<a href="mailto:shuxin.llvm@gmail.com" target="_blank">shuxin.llvm@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi, Daniel:<br>
<br>
  With the helper of Andy and Nadav, I manage to come up a much simpler fix.<br>
It no longer delete dead code on the fly, it just proceeds in the presence<br>
of dead code.<br>
<br>
  It is no longer complex both in terms of concept and LOC. In terms of LOC,<br>
it add 157 LOC with plenty of comments. In concept, it is almost "no-brainer",<br>
so to speak :-). </blockquote><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
 How does this patch look to you?<br>
<br></blockquote><div>Looks good to me.</div><div><br></div><div>Thank you so much or working through this :)<br> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

Thanks<br>
Shxuin<br>
<br>
How it work<br>
=======================<br>
  Here is baiscially how dead code are "ignored".<br>
<br>
  1) When a dead branch target, say block B, is identified, all the<br>
     blocks dominated by B is dead as well.<br>
  2) The phis of those blocks in dominance-frontier(B) is updated such<br>
     that the operands corresponding to dead predecessors are replaced<br>
     by "UndefVal".<br>
<br>
     Using lattice's jargon, the "UndefVal" is the "Top" in essence.<br>
     Phi node like this "phi(v1 bb1, undef xx)" will be optimized into<br>
     "v1" if v1 is constant, or v1 is an instruction which dominate this<br>
     phi node.<br>
   3) When analyzing the availability of a load L, all dead mem-ops which<br>
      L depends on disguise as a load which evaluate exactly same value as L.<br>
   4) The dead mem-ops will be materialized as "UndefVal" during code motion.<br>
<br>
example<br>
=======<br>
  Consider the e.g slightly generalized from the original motivating eg.<br>
<br>
  Fig 1<br>
  ------------------------------<u></u>-----------------------<br>
  BB1 :<br>
       = *p;   // s1<br>
     if (false) {<br>
        BB-then-dead:<br>
        puts("Shuxin is a pretty nice guy!lol"). // s2, alias with *p;<br>
     } else {<br>
       BB-else:<br>
        ...<br>
     }<br>
<br>
  BB-junk:<br>
     another if-then-else construct.<br>
<br>
  BB-last:<br>
        = *p; // s3;<br>
 ------------------------------<u></u>-----------------------<br>
<br>
  The load in S3 deps on s1 and s2; the later is dead. Now that s2 alias with s3,<br>
 due to the limit the Ld-PRE, it gives up.<br>
<br>
  The step-3) will modify the dep-info about s2 to disguise as a load<br>
producing the same value as s3, and hence enable the transformation.<br>
<br>
 Fig 2:<br>
 ------------------<br>
  BB1 :<br>
     v1 = *p;   // s1<br>
     if (false) {<br>
       BB-then-dead:<br>
       puts("Shuxin is a pretty nice guy!lol"). // s2, alias with *p;<br>
     } else {<br>
       BB-else:<br>
        ...<br>
     }<br>
<br>
  BB-junk:<br>
     v3 = phi(v1@BB-else, undef@BB-then-dead)<br>
     another if-then-else construct.<br>
<br>
  BB-last:<br>
        = v3; // s3;<br>
 ------------------<br>
<br>
LD-PRE Limitation<br>
=================<br>
  With a closer look of the original problem. I realize GVN fail to eliminate<br>
the redundant load due to the limit the of LD-PRE.<br>
<br>
  A typical whatever-PRE would pick up the "observation point" at the place<br>
available and unavailble path just meet (in this case, it would be the entry<br>
of BB-junk). However, GVN LD-PRE choose the point right before the load in<br>
question. In this case, it would be the entry point of BB-last, from that<br>
point of view, the load is unavilable in all the incoming pred. Hence give up.<br>
<br>
  That said, I don't want to blame GVN as choosing right "observation point"<br>
entails expensive data flow analysis. However, llvm users are pretty picky<br>
at compile time.<br>
<br>
The limitation of this approach<br>
==============================<u></u>=<br>
  The limitation comes from the fact that we are not able to simplify<br>
"v2 = phi(v1, undef)" into v if v neither dominate this phi nor is<br>
constant. By it machinary, val-num(v2) != val-num(v1) and hence obscure<br>
some opportunities.<br>
<br>
<br>
</blockquote></div><br></div></div>