[SimplifyCFG] Merge conditional stores
authorJames Molloy <james.molloy@arm.com>
Wed, 4 Nov 2015 15:28:04 +0000 (15:28 +0000)
committerJames Molloy <james.molloy@arm.com>
Wed, 4 Nov 2015 15:28:04 +0000 (15:28 +0000)
commit21ea6085dc581f8b6d4eb01617221185ce57dc42
tree0c0148e57fefe9eadc2a6704d6b48e7e9f580ccd
parentc3c89b471b2e30c85c37d17984e1260c56b6d06f
[SimplifyCFG] Merge conditional stores

We can often end up with conditional stores that cannot be speculated. They can come from fairly simple, idiomatic code:

  if (c & flag1)
    *a = x;
  if (c & flag2)
    *a = y;
  ...

There is no dominating or post-dominating store to a, so it is not legal to move the store unconditionally to the end of the sequence and cache the intermediate result in a register, as we would like to.

It is, however, legal to merge the stores together and do the store once:

  tmp = undef;
  if (c & flag1)
    tmp = x;
  if (c & flag2)
    tmp = y;
  if (c & flag1 || c & flag2)
    *a = tmp;

The real power in this optimization is that it allows arbitrary length ladders such as these to be completely and trivially if-converted. The typical code I'd expect this to trigger on often uses binary-AND with constants as the condition (as in the above example), which means the ending condition can simply be truncated into a single binary-AND too: 'if (c & (flag1|flag2))'. As in the general case there are bitwise operators here, the ladder can often be optimized further too.

This optimization involves potentially increasing register pressure. Even in the simplest case, the lifetime of the first predicate is extended. This can be elided in some cases such as using binary-AND on constants, but not in the general case. Threading 'tmp' through all branches can also increase register pressure.

The optimization as in this patch is enabled by default but kept in a very conservative mode. It will only optimize if it thinks the resultant code should be if-convertable, and additionally if it can thread 'tmp' through at least one existing PHI, so it will only ever in the worst case create one more PHI and extend the lifetime of a predicate.

This doesn't trigger much in LNT, unfortunately, but it does trigger in a big way in a third party test suite.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252051 91177308-0d34-0410-b5e6-96231b3b80d8
include/llvm/ADT/SetOperations.h
lib/Transforms/Utils/SimplifyCFG.cpp
test/Transforms/SimplifyCFG/merge-cond-stores.ll [new file with mode: 0644]