Skip to content
  • Chandler Carruth's avatar
    [LPM] Fix PR18643, another scary place where loop transforms failed to · d4be9dc0
    Chandler Carruth authored
    preserve loop simplify of enclosing loops.
    
    The problem here starts with LoopRotation which ends up cloning code out
    of the latch into the new preheader it is buidling. This can create
    a new edge from the preheader into the exit block of the loop which
    breaks LoopSimplify form. The code tries to fix this by splitting the
    critical edge between the latch and the exit block to get a new exit
    block that only the latch dominates. This sadly isn't sufficient.
    
    The exit block may be an exit block for multiple nested loops. When we
    clone an edge from the latch of the inner loop to the new preheader
    being built in the outer loop, we create an exiting edge from the outer
    loop to this exit block. Despite breaking the LoopSimplify form for the
    inner loop, this is fine for the outer loop. However, when we split the
    edge from the inner loop to the exit block, we create a new block which
    is in neither the inner nor outer loop as the new exit block. This is
    a predecessor to the old exit block, and so the split itself takes the
    outer loop out of LoopSimplify form. We need to split every edge
    entering the exit block from inside a loop nested more deeply than the
    exit block in order to preserve all of the loop simplify constraints.
    
    Once we try to do that, a problem with splitting critical edges
    surfaces. Previously, we tried a very brute force to update LoopSimplify
    form by re-computing it for all exit blocks. We don't need to do this,
    and doing this much will sometimes but not always overlap with the
    LoopRotate bug fix. Instead, the code needs to specifically handle the
    cases which can start to violate LoopSimplify -- they aren't that
    common. We need to see if the destination of the split edge was a loop
    exit block in simplified form for the loop of the source of the edge.
    For this to be true, all the predecessors need to be in the exact same
    loop as the source of the edge being split. If the dest block was
    originally in this form, we have to split all of the deges back into
    this loop to recover it. The old mechanism of doing this was
    conservatively correct because at least *one* of the exiting blocks it
    rewrote was the DestBB and so the DestBB's predecessors were fixed. But
    this is a much more targeted way of doing it. Making it targeted is
    important, because ballooning the set of edges touched prevents
    LoopRotate from being able to split edges *it* needs to split to
    preserve loop simplify in a coherent way -- the critical edge splitting
    would sometimes find the other edges in need of splitting but not
    others.
    
    Many, *many* thanks for help from Nick reducing these test cases
    mightily. And helping lots with the analysis here as this one was quite
    tricky to track down.
    
    llvm-svn: 200393
    d4be9dc0
Loading