[Patch] GVN fold conditional-branch on-the-fly

Shuxin Yang shuxin.llvm at gmail.com
Thu Sep 19 09:54:51 PDT 2013


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




More information about the llvm-commits mailing list