Page MenuHomePhabricator

[GVN] do not repeat PRE on failure to split critical edge
ClosedPublic

Authored by nickdesaulniers on Jan 19 2021, 12:50 PM.

Details

Summary

Fixes an infinite loop encountered in GVN.

GVN will delay PRE if it encounters critical edges, attempt to split
them later via calls to SplitCriticalEdge(), then restart.

The caller of GVN::splitCriticalEdges() assumed a return value of true
meant that critical edges were split, that the IR had changed, and that
PRE should be re-attempted, upon which we loop infinitely.

This was exposed after D88438, by compiling the Linux kernel for s390,
but the test case is reproducible on x86.

Fixes: https://github.com/ClangBuiltLinux/linux/issues/1261

Diff Detail

Event Timeline

nickdesaulniers requested review of this revision.Jan 19 2021, 12:50 PM
Herald added a project: Restricted Project. · View Herald TranscriptJan 19 2021, 12:50 PM
nickdesaulniers edited the summary of this revision. (Show Details)Jan 19 2021, 12:51 PM
  • fix comment in test
  • drop test metadata and fn attrs, unnecessary.
fhahn added a subscriber: fhahn.Jan 20 2021, 6:56 AM
fhahn added inline comments.
llvm/lib/Transforms/Scalar/GVN.cpp
2693–2695

do we need !! here?

2698

This code seems redundant, right, because it is already done by splitCriticalEdges?

llvm/test/Transforms/GVN/critical-edge-split-failure.ll
14

is this function needed?

nickdesaulniers marked an inline comment as done.
  • remove dead function from test
nickdesaulniers added inline comments.
llvm/lib/Transforms/Scalar/GVN.cpp
2693–2695

unless you'd prefer a comparison != nullptr? Otherwise:

../lib/Transforms/Scalar/GVN.cpp:2695:13: error: invalid operands to binary expression ('bool' and 'llvm::BasicBlock *')
    Changed |= SplitCriticalEdge(Edge.first, Edge.second,
    ~~~~~~~ ^  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2698

Different code paths; the method GVN::splitCriticalEdges that accepts arguments is called from different places at different points during GVN.

That method is used to splitting individual edges eagerly, then invalidating cached predecessors.

This method is for splitting a list of edges that were deferred, then invalidating cached predecessors.

llvm/test/Transforms/GVN/critical-edge-split-failure.ll
3

This is yet another case where NPM test passes before/after a patch that would be red with LPM. cc @aeubanks

I don't know if this test should be under

llvm/test/Transforms/GVN/PRE/
rather than
llvm/test/Transforms/GVN/
?

14

This is what was produced by running both llvm-reduce and bugpoint; I wonder if they don't remove functions referred to by block addresses? (Cycle counter/cycle breaker problem). Removed.

aeubanks added inline comments.Jan 20 2021, 10:56 AM
llvm/test/Transforms/GVN/critical-edge-split-failure.ll
3

This one is much more surprising, I can't think of anything off the top of my head that would cause the output of running GVN to change between the two pass managers.

@nathanchance verified this patch fixes the regression and doesn't appear to regress any of our other builds in https://github.com/ClangBuiltLinux/linux/issues/1261#issuecomment-763904779.

llvm/lib/Transforms/Scalar/GVN.cpp
2698

The other method probably shouldn't be plural. s/splitCriticalEdges/splitCriticalEdge/

fhahn added inline comments.Jan 21 2021, 2:35 AM
llvm/lib/Transforms/Scalar/GVN.cpp
2693–2695

oh right, != nullptr seems clearer to me.

2698

ah right, this doesn't actually call GVN::splitCriticalEdges. Nevermind then.

llvm/test/Transforms/GVN/critical-edge-split-failure.ll
3

missing aa-pipeline option?

aeubanks added inline comments.Jan 21 2021, 10:43 AM
llvm/test/Transforms/GVN/critical-edge-split-failure.ll
3

Haha I just sent out https://reviews.llvm.org/D95117 to use the "default" AA pipeline by default and still forgot about it here. Seems like the likely culprit.

nickdesaulniers marked 2 inline comments as done.
  • replace double negation with explicit not nullptr comparison
nickdesaulniers marked 2 inline comments as done.Jan 21 2021, 11:57 AM
nickdesaulniers added inline comments.
llvm/test/Transforms/GVN/critical-edge-split-failure.ll
3

Adding -aa-pipeline=default (or -aa-pipeline=) doesn't seem to cause the NPM RUN line to fail (before adding this patch). Am I holding it wrong, or is there still more to this difference?

void accepted this revision.Jan 21 2021, 3:55 PM
This revision is now accepted and ready to land.Jan 21 2021, 3:55 PM