Index: lib/Transforms/Scalar/LoopInterchange.cpp =================================================================== --- lib/Transforms/Scalar/LoopInterchange.cpp +++ lib/Transforms/Scalar/LoopInterchange.cpp @@ -555,12 +555,6 @@ else LoopNestExit = OuterMostLoopLatchBI->getSuccessor(0); - if (isa(LoopNestExit->begin())) { - DEBUG(dbgs() << "PHI Nodes in loop nest exit is not handled for now " - "since on failure all loops branch to loop nest exit.\n"); - return false; - } - unsigned SelecLoopId = selectLoopForInterchange(LoopList); // Move the selected loop outwards to the best possible position. for (unsigned i = SelecLoopId; i > 0; i--) { @@ -771,8 +765,6 @@ BasicBlock *InnerLoopPreHeader = InnerLoop->getLoopPreheader(); BasicBlock *InnerLoopHeader = InnerLoop->getHeader(); BasicBlock *InnerLoopLatch = InnerLoop->getLoopLatch(); - BasicBlock *OuterLoopLatch = OuterLoop->getLoopLatch(); - BasicBlock *OuterLoopHeader = OuterLoop->getHeader(); PHINode *InnerInductionVar; SmallVector Inductions; @@ -863,20 +855,7 @@ // TODO: We only handle LCSSA PHI's corresponding to reduction for now. BasicBlock *LoopExitBlock = - getLoopLatchExitBlock(OuterLoopLatch, OuterLoopHeader); - if (!LoopExitBlock || !containsSafePHI(LoopExitBlock, true)) { - DEBUG(dbgs() << "Can only handle LCSSA PHIs in outer loops currently.\n"); - ORE->emit([&]() { - return OptimizationRemarkMissed(DEBUG_TYPE, "NoLCSSAPHIOuter", - OuterLoop->getStartLoc(), - OuterLoop->getHeader()) - << "Only outer loops with LCSSA PHIs can be interchange " - "currently."; - }); - return true; - } - - LoopExitBlock = getLoopLatchExitBlock(InnerLoopLatch, InnerLoopHeader); + getLoopLatchExitBlock(InnerLoopLatch, InnerLoopHeader); if (!LoopExitBlock || !containsSafePHI(LoopExitBlock, false)) { DEBUG(dbgs() << "Can only handle LCSSA PHIs in inner loops currently.\n"); ORE->emit([&]() { @@ -962,6 +941,33 @@ return false; } +// We currently support PHI nodes in the outer loop exit, if their incoming +// values either +// * come from outside the outer loop +// * come from the inner loop, ignoring LCSSA PHI nodes. +// In the latter case, the value from the inner loop will only be available +// if both outer and inner loop conditions are true, which will still be true +// after interchanging. +static bool areLoopExitPHIsSupported(Loop *OuterLoop, Loop *InnerLoop) { + BasicBlock *LoopNestExit = OuterLoop->getUniqueExitBlock(); + for (PHINode &PHI : LoopNestExit->phis()) { + for (unsigned i = 0; i < PHI.getNumIncomingValues(); i++) { + if (!OuterLoop->contains(PHI.getIncomingBlock(i))) + continue; + + PHINode *LatchPHI = dyn_cast(PHI.getIncomingValue(i)); + if (!LatchPHI || LatchPHI->getParent() != OuterLoop->getLoopLatch() || + LatchPHI->getNumIncomingValues() != 1) + return false; + + Instruction *LV = dyn_cast(LatchPHI->getIncomingValue(0)); + if (!LV || !InnerLoop->contains(LV->getParent())) + return false; + } + } + return true; +} + bool LoopInterchangeLegality::canInterchangeLoops(unsigned InnerLoopId, unsigned OuterLoopId, CharMatrix &DepMatrix) { @@ -1032,6 +1038,17 @@ return false; } + if (!areLoopExitPHIsSupported(OuterLoop, InnerLoop)) { + DEBUG(dbgs() << "Found unsupported PHI nodes in outer loop exit.\n"); + ORE->emit([&]() { + return OptimizationRemarkMissed(DEBUG_TYPE, "UnsupportedExitPHI", + OuterLoop->getStartLoc(), + OuterLoop->getHeader()) + << "Found unsupported PHI node in loop exit."; + }); + return false; + } + return true; } Index: test/Transforms/LoopInterchange/current-limitations-lcssa.ll =================================================================== --- test/Transforms/LoopInterchange/current-limitations-lcssa.ll +++ /dev/null @@ -1,76 +0,0 @@ -; RUN: opt < %s -basicaa -loop-interchange -S | FileCheck %s -;; We test the complete .ll for adjustment in outer loop header/latch and inner loop header/latch. - -target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" -target triple = "x86_64-unknown-linux-gnu" - -@A = common global [100 x [100 x i32]] zeroinitializer -@C = common global [100 x [100 x i32]] zeroinitializer - -;; FIXME: -;; Test for interchange when we have an lcssa phi. This should ideally be interchanged but it is currently not supported. -;; for(gi=1;gi