From: David Green Date: Thu, 26 Jul 2018 15:19:07 +0000 (+0000) Subject: [UnJ] Common some code. NFC X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0b19d8a7b1d23ab91612d42f3c3d1746854b0cf6;p=llvm [UnJ] Common some code. NFC Create a processHeaderPhiOperands for analysing the instructions in the aft blocks that must be moved before the loop. Differential Revision: https://reviews.llvm.org/D49061 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@338033 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Transforms/Utils/LoopUnrollAndJam.cpp b/lib/Transforms/Utils/LoopUnrollAndJam.cpp index 4d0d6f4b7cf..b919f73c381 100644 --- a/lib/Transforms/Utils/LoopUnrollAndJam.cpp +++ b/lib/Transforms/Utils/LoopUnrollAndJam.cpp @@ -81,15 +81,18 @@ static bool partitionOuterLoopBlocks(Loop *L, Loop *SubLoop, return true; } -// Move the phi operands of Header from Latch out of AftBlocks to InsertLoc. -static void moveHeaderPhiOperandsToForeBlocks(BasicBlock *Header, - BasicBlock *Latch, - Instruction *InsertLoc, - BasicBlockSet &AftBlocks) { - // We need to ensure we move the instructions in the correct order, - // starting with the earliest required instruction and moving forward. - std::vector Worklist; - std::vector Visited; +// Looks at the phi nodes in Header for values coming from Latch. For these +// instructions and all their operands calls Visit on them, keeping going for +// all the operands in AftBlocks. Returns false if Visit returns false, +// otherwise returns true. This is used to process the instructions in the +// Aft blocks that need to be moved before the subloop. It is used in two +// places. One to check that the required set of instructions can be moved +// before the loop. Then to collect the instructions to actually move in +// moveHeaderPhiOperandsToForeBlocks. +template +static bool processHeaderPhiOperands(BasicBlock *Header, BasicBlock *Latch, + BasicBlockSet &AftBlocks, T Visit) { + SmallVector Worklist; for (auto &Phi : Header->phis()) { Value *V = Phi.getIncomingValueForBlock(Latch); if (Instruction *I = dyn_cast(V)) @@ -99,15 +102,33 @@ static void moveHeaderPhiOperandsToForeBlocks(BasicBlock *Header, while (!Worklist.empty()) { Instruction *I = Worklist.back(); Worklist.pop_back(); - if (!AftBlocks.count(I->getParent())) - continue; + if (!Visit(I)) + return false; - Visited.push_back(I); - for (auto &U : I->operands()) - if (Instruction *II = dyn_cast(U)) - Worklist.push_back(II); + if (AftBlocks.count(I->getParent())) + for (auto &U : I->operands()) + if (Instruction *II = dyn_cast(U)) + Worklist.push_back(II); } + return true; +} + +// Move the phi operands of Header from Latch out of AftBlocks to InsertLoc. +static void moveHeaderPhiOperandsToForeBlocks(BasicBlock *Header, + BasicBlock *Latch, + Instruction *InsertLoc, + BasicBlockSet &AftBlocks) { + // We need to ensure we move the instructions in the correct order, + // starting with the earliest required instruction and moving forward. + std::vector Visited; + processHeaderPhiOperands(Header, Latch, AftBlocks, + [&Visited, &AftBlocks](Instruction *I) { + if (AftBlocks.count(I->getParent())) + Visited.push_back(I); + return true; + }); + // Move all instructions in program order to before the InsertLoc BasicBlock *InsertLocBB = InsertLoc->getParent(); for (Instruction *I : reverse(Visited)) { @@ -735,31 +756,24 @@ bool llvm::isSafeToUnrollAndJam(Loop *L, ScalarEvolution &SE, DominatorTree &DT, // ForeBlock phi operands before the subloop // Make sure we can move all instructions we need to before the subloop - SmallVector Worklist; - SmallPtrSet Visited; - for (auto &Phi : Header->phis()) { - Value *V = Phi.getIncomingValueForBlock(Latch); - if (Instruction *I = dyn_cast(V)) - Worklist.push_back(I); - } - while (!Worklist.empty()) { - Instruction *I = Worklist.back(); - Worklist.pop_back(); - if (Visited.insert(I).second) { - if (SubLoop->contains(I->getParent())) - return false; - if (AftBlocks.count(I->getParent())) { - // If we hit a phi node in afts we know we are done (probably LCSSA) - if (isa(I)) - return false; - if (I->mayHaveSideEffects() || I->mayReadOrWriteMemory()) - return false; - for (auto &U : I->operands()) - if (Instruction *II = dyn_cast(U)) - Worklist.push_back(II); - } - } - } + if (!processHeaderPhiOperands( + Header, Latch, AftBlocks, [&AftBlocks, &SubLoop](Instruction *I) { + if (SubLoop->contains(I->getParent())) + return false; + if (AftBlocks.count(I->getParent())) { + // If we hit a phi node in afts we know we are done (probably + // LCSSA) + if (isa(I)) + return false; + // Can't move instructions with side effects or memory + // reads/writes + if (I->mayHaveSideEffects() || I->mayReadOrWriteMemory()) + return false; + } + // Keep going + return true; + })) + return false; // Check for memory dependencies which prohibit the unrolling we are doing. // Because of the way we are unrolling Fore/Sub/Aft blocks, we need to check