Fix LICM to avoid hoisting never-executed traps

It is legal for the optimizer to consider code after a loop always
reachable, but when a loop has no exits, or when the loops exits are
dominated by a conditional statement, we should not consider
conditional statements within the loop as dominating all possible
execution paths through the loop. At least not when there is at least
one path through the loop that contains a "synchronization point",
such as a function that may contain a memory barrier, perform I/O, or
exit the program.

Sadly, we still don't model synchronization points in the optimizer,
so we need to conservatively assume all loops have a synchronization
point and avoid hoisting conditional traps that may never be executed.

Fixes rdar://66791257 (Print statement provokes "Can't unsafeBitCast
between types of different sizes" when optimizations enabled)

Originated in 2014.
This commit is contained in:
Andrew Trick
2020-08-12 13:55:06 -07:00
parent 147274b6aa
commit 4ca3c232b7
3 changed files with 92 additions and 3 deletions

View File

@@ -214,8 +214,8 @@ static void getDominatingBlocks(SmallVectorImpl<SILBasicBlock *> &domBlocks,
SILLoop *Loop, DominanceInfo *DT) {
auto HeaderBB = Loop->getHeader();
auto DTRoot = DT->getNode(HeaderBB);
SmallVector<SILBasicBlock *, 8> ExitingBBs;
Loop->getExitingBlocks(ExitingBBs);
SmallVector<SILBasicBlock *, 8> ExitingAndLatchBBs;
Loop->getExitingAndLatchBlocks(ExitingAndLatchBBs);
for (llvm::df_iterator<DominanceInfoNode *> It = llvm::df_begin(DTRoot),
E = llvm::df_end(DTRoot);
It != E;) {
@@ -223,7 +223,7 @@ static void getDominatingBlocks(SmallVectorImpl<SILBasicBlock *> &domBlocks,
// Don't decent into control-dependent code. Only traverse into basic blocks
// that dominate all exits.
if (!std::all_of(ExitingBBs.begin(), ExitingBBs.end(),
if (!std::all_of(ExitingAndLatchBBs.begin(), ExitingAndLatchBBs.end(),
[=](SILBasicBlock *ExitBB) {
return DT->dominates(CurBB, ExitBB);
})) {