[SimplifyCFG] Handle tail-sinking of more than 2 incoming branches
authorJames Molloy <james.molloy@arm.com>
Thu, 1 Sep 2016 12:58:13 +0000 (12:58 +0000)
committerJames Molloy <james.molloy@arm.com>
Thu, 1 Sep 2016 12:58:13 +0000 (12:58 +0000)
commit88cad7e5cf465fdb995424058e0e111a65493f6e
tree63c10e700ddf02c75cb921d4d075b3e2214a710b
parentf1fb439d31fb0634cb48c836b4d7ab60b3e814e2
[SimplifyCFG] Handle tail-sinking of more than 2 incoming branches

This was a real restriction in the original version of SinkIfThenCodeToEnd. Now it's been rewritten, the restriction can be lifted.

As part of this, we handle a very common and useful case where one of the incoming branches is actually conditional. Consider:

   if (a)
     x(1);
   else if (b)
     x(2);

This produces the following CFG:

         [if]
        /    \
      [x(1)] [if]
        |     | \
        |     |  \
        |  [x(2)] |
         \    |  /
          [ end ]

[end] has two unconditional predecessor arcs and one conditional. The conditional refers to the implicit empty 'else' arc. This same pattern can also be caused by an empty default block in a switch.

We can't sink the call to x() down to end because no call to x() happens on the third incoming arc (assume that x() has sideeffects for the sake of argument; if something is safe to speculate we could indeed sink nevertheless but this cannot happen in the general case and causes many extra selects).

We are now able to detect this case and split off the unconditional arcs to a common successor:

         [if]
        /    \
      [x(1)] [if]
        |     | \
        |     |  \
        |  [x(2)] |
         \   /    |
     [sink.split] |
           \     /
           [ end ]

Now we can sink the call to x() into %sink.split. This can cause significant code simplification in many testcases.

llvm-svn: 280364
llvm/lib/Transforms/Utils/SimplifyCFG.cpp
llvm/test/CodeGen/AArch64/arm64-jumptable.ll
llvm/test/CodeGen/AArch64/branch-folder-merge-mmos.ll
llvm/test/CodeGen/AArch64/ifcvt-select.ll
llvm/test/CodeGen/AArch64/rm_redundant_cmp.ll
llvm/test/MC/ARM/data-in-code.ll
llvm/test/Transforms/SimplifyCFG/sink-common-code.ll