[PATCH] D34200: [PM/unswitch] Teach SimpleLoopUnswitch to do non-trivial unswitching, making it no longer even remotely simple.
Sanjoy Das via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Sun Jun 25 16:37:48 PDT 2017
sanjoy added a comment.
I did a quick scan and have a couple of low-level comments inline.
Do you think it is possible to split out the `LoopInfo` updating logic to a later patch, perhaps by using something more brute force initially? That will make later rounds of review a lot easier.
Finally, maybe I missed something, but I did not see the code handle something like this:
loop:
br i1 %us_cond, label %left, label %right
left:
br i1 %c, label %right, label %be
right:
br i1 %c, label %left, label %be
be:
br label %loop
where unswitching on `%us_cond` will create two subloops "out of thin air" by destroying unstructured control flow.
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:837
+ SmallVector<BasicBlock *, 16> Worklist;
+ SmallPtrSet<BasicBlock *, 16> ClonedLoopSet;
+ for (auto *Pred : predecessors(ClonedHeader)) {
----------------
I'd call this `ClonedLoopBlocksSet` to make it clear that this holds `BasicBlock *`s not `Loop *`s. Otherwise later `ClonedLoopSet.count(ClonedBB)` reads weird. Ditto for `PossibleClonedLoopSet`.
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1110
+ ExitLoops.push_back(ExitL);
+ ExitsInLoops.push_back(ExitBB);
+ if (!ParentL || (ParentL != ExitL && ParentL->contains(ExitL)))
----------------
Can this be common'ed up with the logic in `buildClonedLoops`?
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1165
+ // reverse.
+ LoopSet.insert(Header);
+ while (!Worklist.empty()) {
----------------
I'd suggest calling this `LoopBlocksSet`.
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1398
+///
+/// It also updates both dominator tree and loopinfo based on the unswitching.
+///
----------------
The commit message says you don't update the dom tree?
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1461
+ SmallPtrSet<BasicBlock *, 4> SkippedLoopAndExitBlocks;
+ if (ContinueSuccBB->getUniquePredecessor() ||
+ llvm::all_of(predecessors(ContinueSuccBB), [&](BasicBlock *PredBB) {
----------------
Again, I think you can just directly ask the domtree for this.
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1606
+ // Update any PHI nodes in the successors of the skipped blocks to not have
+ // spurrious incoming values.
+ for (auto *LoopBB : L.blocks())
----------------
s/spurrious/spurious/
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1740
+/// quadratic.
+int computeDomSubtreeCost(DomTreeNode &N,
+ const SmallDenseMap<BasicBlock *, int, 4> &BBCostMap,
----------------
`static`?
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1828
+ for (auto *BB : L.blocks()) {
+ int &Cost = BBCostMap[BB];
+ for (auto &I : *BB) {
----------------
I'd be a bit more comfortable if you did `int Const = 0`, and later `BBCostMap[BB] = Cost;`. Right now it isn't obvious that `Cost += TTI.getUserCost(&I);` is modifying a densemap value.
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1851
+ // 1) An unswitching cost below the threshold
+ // 2) The smallest number of duplicated unswitch candidates (to avoid
+ // creating redundant subsequent unswitching)
----------------
I may be missing something, but I only see (1). Also, a one liner on what "unswitching cost" and "cost after unswitching" mean will be helpful.
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1871
+ // Don't count successors more than once.
+ if (!Visited.insert(SuccBB).second)
+ continue;
----------------
Right now this is always true, right (since you're only unswitching `br` instructions that have different successors)?
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1879
+ if (SuccBB->getUniquePredecessor() ||
+ llvm::all_of(predecessors(SuccBB), [&](BasicBlock *PredBB) {
+ return PredBB == &BB || DT.dominates(SuccBB, PredBB);
----------------
Isn't this the same as edge domination?
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1901
+ << " for unswitch candidate: " << *CandidateTI << "\n");
+ if (!UnswitchTI || CandidateCost < UnswitchCost) {
+ UnswitchTI = CandidateTI;
----------------
Aren't you reading uninitialized memory here (for `UnswitchCost`)?
I'd also name `UnswitchCost` in a way that indicates it is the "best so far".
================
Comment at: lib/Transforms/Scalar/SimpleLoopUnswitch.cpp:1907
+
+ if (UnswitchCost < UnswitchThreshold) {
+ DEBUG(dbgs() << " Trying to unswitch non-trivial (cost = " << UnswitchCost
----------------
How about putting all of the logic up to this point into a `TerminatorInst *findNonTrivialUnswitchCandidate` function?
https://reviews.llvm.org/D34200
More information about the llvm-commits
mailing list