<html>
  <head>
    <meta content="text/html; charset=ISO-8859-1"
      http-equiv="Content-Type">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    Hi, Daniel:<br>
    <br>
       Thank you so much for your time and expertise!<br>
    <br>
    <div class="moz-cite-prefix">On 9/19/13 10:15 AM, Daniel Berlin
      wrote:<br>
    </div>
    <blockquote
cite="mid:CAF4BwTXazuXEO+O3H-i6txUQtxNdRq2cd0We30xnve-OaDEzhw@mail.gmail.com"
      type="cite">
      <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 moz-do-not-send="true"
                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>
                -----------------------------------------------------<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>
               -----------------------------------------------------<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>
              ===============================<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>
    </blockquote>
    <br>
  </body>
</html>