//===- LoopRotation.cpp - Loop Rotation Pass ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements Loop Rotation Pass.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "loop-rotate"

#include "llvm/Transforms/Scalar.h"
#include "llvm/Function.h"
#include "llvm/Instructions.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/Dominators.h"
#include "llvm/Analysis/ScalarEvolution.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/SmallVector.h"

using namespace llvm;

#define MAX_HEADER_SIZE 16

STATISTIC(NumRotated, "Number of loops rotated");
namespace {

  class VISIBILITY_HIDDEN RenameData {
  public:
    RenameData(Instruction *O, Value *P, Instruction *H) 
      : Original(O), PreHeader(P), Header(H) { }
  public:
    Instruction *Original; // Original instruction
    Value *PreHeader; // Original pre-header replacement
    Instruction *Header; // New header replacement
  };
  
  class VISIBILITY_HIDDEN LoopRotate : public LoopPass {

  public:
    static char ID; // Pass ID, replacement for typeid
    LoopRotate() : LoopPass((intptr_t)&ID) {}

    // Rotate Loop L as many times as possible. Return true if
    // loop is rotated at least once.
    bool runOnLoop(Loop *L, LPPassManager &LPM);

    // LCSSA form makes instruction renaming easier.
    virtual void getAnalysisUsage(AnalysisUsage &AU) const {
      AU.addRequiredID(LCSSAID);
      AU.addPreservedID(LCSSAID);
      AU.addPreserved<ScalarEvolution>();
      AU.addPreserved<LoopInfo>();
      AU.addRequiredID(LoopSimplifyID);
      AU.addPreservedID(LoopSimplifyID);
      AU.addPreserved<DominatorTree>();
      AU.addPreserved<DominanceFrontier>();
    }

    // Helper functions

    /// Do actual work
    bool rotateLoop(Loop *L, LPPassManager &LPM);
    
    /// Initialize local data
    void initialize();

    /// Make sure all Exit block PHINodes have required incoming values.
    /// If incoming value is constant or defined outside the loop then
    /// PHINode may not have an entry for original pre-header. 
    void  updateExitBlock();

    /// Return true if this instruction is used outside original header.
    bool usedOutsideOriginalHeader(Instruction *In);

    /// Find Replacement information for instruction. Return NULL if it is
    /// not available.
    const RenameData *findReplacementData(Instruction *I);

    /// After loop rotation, loop pre-header has multiple sucessors.
    /// Insert one forwarding basic block to ensure that loop pre-header
    /// has only one successor.
    void preserveCanonicalLoopForm(LPPassManager &LPM);

  private:

    Loop *L;
    BasicBlock *OrigHeader;
    BasicBlock *OrigPreHeader;
    BasicBlock *OrigLatch;
    BasicBlock *NewHeader;
    BasicBlock *Exit;
    LPPassManager *LPM_Ptr;
    SmallVector<RenameData, MAX_HEADER_SIZE> LoopHeaderInfo;
  };
  
  char LoopRotate::ID = 0;
  RegisterPass<LoopRotate> X ("loop-rotate", "Rotate Loops");
}

LoopPass *llvm::createLoopRotatePass() { return new LoopRotate(); }

/// Rotate Loop L as many times as possible. Return true if
/// loop is rotated at least once.
bool LoopRotate::runOnLoop(Loop *Lp, LPPassManager &LPM) {

  bool RotatedOneLoop = false;
  initialize();
  LPM_Ptr = &LPM;

  // One loop can be rotated multiple times.
  while (rotateLoop(Lp,LPM)) {
    RotatedOneLoop = true;
    initialize();
  }

  return RotatedOneLoop;
}

/// Rotate loop LP. Return true if the loop is rotated.
bool LoopRotate::rotateLoop(Loop *Lp, LPPassManager &LPM) {

  L = Lp;

  OrigHeader =  L->getHeader();
  OrigPreHeader = L->getLoopPreheader();
  OrigLatch = L->getLoopLatch();

  // If loop has only one block then there is not much to rotate.
  if (L->getBlocks().size() == 1)
    return false;

  assert (OrigHeader && OrigLatch && OrigPreHeader &&
          "Loop is not in canonical form");

  // If loop header is not one of the loop exit block then
  // either this loop is already rotated or it is not 
  // suitable for loop rotation transformations.
  if (!L->isLoopExit(OrigHeader))
    return false;

  BranchInst *BI = dyn_cast<BranchInst>(OrigHeader->getTerminator());
  if (!BI)
    return false;
  assert (BI->isConditional() && "Branch Instruction is not conditional");

  // Updating PHInodes in loops with multiple exits adds complexity. 
  // Keep it simple, and restrict loop rotation to loops with one exit only.
  // In future, lift this restriction and support for multiple exits if
  // required.
  SmallVector<BasicBlock*, 8> ExitBlocks;
  L->getExitBlocks(ExitBlocks);
  if (ExitBlocks.size() > 1)
    return false;

  // Check size of original header and reject
  // loop if it is very big.
  if (OrigHeader->getInstList().size() > MAX_HEADER_SIZE)
    return false;

  // Now, this loop is suitable for rotation.

  // Find new Loop header. NewHeader is a Header's one and only successor
  // that is inside loop.  Header's other successor is out side the
  // loop. Otherwise loop is not suitable for rotation.
  Exit = BI->getSuccessor(0);
  NewHeader = BI->getSuccessor(1);
  if (L->contains(Exit))
    std::swap(Exit, NewHeader);
  assert (NewHeader && "Unable to determine new loop header");
  assert(L->contains(NewHeader) && !L->contains(Exit) && 
         "Unable to determine loop header and exit blocks");

  // Copy PHI nodes and other instructions from original header
  // into original pre-header. Unlike original header, original pre-header is
  // not a member of loop. 
  //
  // New loop header is one and only successor of original header that 
  // is inside the loop. All other original header successors are outside 
  // the loop. Copy PHI Nodes from original header into new loop header. 
  // Add second incoming value, from original loop pre-header into these phi 
  // nodes. If a value defined in original header is used outside original 
  // header then new loop header will need new phi nodes with two incoming 
  // values, one definition from original header and second definition is 
  // from original loop pre-header.

  // Remove terminator from Original pre-header. Original pre-header will
  // receive a clone of original header terminator as a new terminator.
  OrigPreHeader->getInstList().pop_back();
  BasicBlock::iterator I = OrigHeader->begin(), E = OrigHeader->end();
  PHINode *PN = NULL;
  for (; (PN = dyn_cast<PHINode>(I)); ++I) {
    Instruction *In = I;

    // PHI nodes are not copied into original pre-header. Instead their values
    // are directly propagated.
    Value * NPV = PN->getIncomingValueForBlock(OrigPreHeader);

    // Create new PHI node with two incoming values for NewHeader.
    // One incoming value is from OrigLatch (through OrigHeader) and 
    // second incoming value is from original pre-header.
    PHINode *NH = new PHINode(In->getType(), In->getName());
    NH->addIncoming(PN->getIncomingValueForBlock(OrigLatch), OrigHeader);
    NH->addIncoming(NPV, OrigPreHeader);
    NewHeader->getInstList().push_front(NH);
    
    // "In" can be replaced by NH at various places.
    LoopHeaderInfo.push_back(RenameData(In, NPV, NH));
  }

  // Now, handle non-phi instructions.
  for (; I != E; ++I) {
    Instruction *In = I;

    assert (!isa<PHINode>(In) && "PHINode is not expected here");
    // This is not a PHI instruction. Insert its clone into original pre-header.
    // If this instruction is using a value from same basic block then
    // update it to use value from cloned instruction.
    Instruction *C = In->clone();
    C->setName(In->getName());
    OrigPreHeader->getInstList().push_back(C);

    for (unsigned opi = 0, e = In->getNumOperands(); opi != e; ++opi) {
      if (Instruction *OpPhi = dyn_cast<PHINode>(In->getOperand(opi))) {
        if (const RenameData *D = findReplacementData(OpPhi)) {
          // This is using values from original header PHI node.
          // Here, directly used incoming value from original pre-header.
          C->setOperand(opi, D->PreHeader);
        }
      }
      else if (Instruction *OpInsn = 
               dyn_cast<Instruction>(In->getOperand(opi))) {
        if (const RenameData *D = findReplacementData(OpInsn))
          C->setOperand(opi, D->PreHeader);
      }
    }


    // If this instruction is used outside this basic block then
    // create new PHINode for this instruction.
    Instruction *NewHeaderReplacement = NULL;
    if (usedOutsideOriginalHeader(In)) {
      PHINode *PN = new PHINode(In->getType(), In->getName());
      PN->addIncoming(In, OrigHeader);
      PN->addIncoming(C, OrigPreHeader);
      NewHeader->getInstList().push_front(PN);
      NewHeaderReplacement = PN;
    } 
    
    // "In" can be replaced by NPH or NH at various places.
    LoopHeaderInfo.push_back(RenameData(In, C, NewHeaderReplacement));
  }

  // Rename uses of original header instructions to reflect their new
  // definitions (either from original pre-header node or from newly created
  // new header PHINodes.
  //
  // Original header instructions are used in
  // 1) Original header:
  //
  //    If instruction is used in non-phi instructions then it is using
  //    defintion from original heder iteself. Do not replace this use
  //    with definition from new header or original pre-header.
  //
  //    If instruction is used in phi node then it is an incoming 
  //    value. Rename its use to reflect new definition from new-preheader
  //    or new header.
  //
  // 2) Inside loop but not in original header
  //
  //    Replace this use to reflect definition from new header.
  for(unsigned LHI = 0, LHI_E = LoopHeaderInfo.size(); LHI != LHI_E; ++LHI) {
    const RenameData &ILoopHeaderInfo = LoopHeaderInfo[LHI];

    if (!ILoopHeaderInfo.Header)
      continue;

    Instruction *OldPhi = ILoopHeaderInfo.Original;
    Instruction *NewPhi = ILoopHeaderInfo.Header;

    // Before replacing uses, collect them first, so that iterator is
    // not invalidated.
    SmallVector<Instruction *, 16> AllUses;
    for (Value::use_iterator UI = OldPhi->use_begin(), UE = OldPhi->use_end();
         UI != UE; ++UI) {
      Instruction *U = cast<Instruction>(UI);
      AllUses.push_back(U);
    }

    for (SmallVector<Instruction *, 16>::iterator UI = AllUses.begin(), 
           UE = AllUses.end(); UI != UE; ++UI) {
      Instruction *U = *UI;
      BasicBlock *Parent = U->getParent();

      // Used inside original header
      if (Parent == OrigHeader) {
        // Do not rename uses inside original header non-phi instructions.
        PHINode *PU = dyn_cast<PHINode>(U);
        if (!PU)
          continue;

        // Do not rename uses inside original header phi nodes, if the
        // incoming value is for new header.
        if (PU->getBasicBlockIndex(NewHeader) != -1
            && PU->getIncomingValueForBlock(NewHeader) == U)
          continue;
        
       U->replaceUsesOfWith(OldPhi, NewPhi);
       continue;
      }

      // Used inside loop, but not in original header.
      if (L->contains(U->getParent())) {
        if (U != NewPhi)
          U->replaceUsesOfWith(OldPhi, NewPhi);
        continue;
      }
      
      // Used inside Exit Block. Since we are in LCSSA form, U must be PHINode.
      if (U->getParent() == Exit) {
        assert (isa<PHINode>(U) && "Use in Exit Block that is not PHINode");
        
        PHINode *UPhi = cast<PHINode>(U);
        // UPhi already has one incoming argument from original header. 
        // Add second incoming argument from new Pre header.
        UPhi->addIncoming(ILoopHeaderInfo.PreHeader, OrigPreHeader);
      } else {
        // Used outside Exit block. Create a new PHI node from exit block
        // to receive value from ne new header ane pre header.
        PHINode *PN = new PHINode(U->getType(), U->getName());
        PN->addIncoming(ILoopHeaderInfo.PreHeader, OrigPreHeader);
        PN->addIncoming(OldPhi, OrigHeader);
        Exit->getInstList().push_front(PN);
        U->replaceUsesOfWith(OldPhi, PN);
      }
    }
  }
  
  /// Make sure all Exit block PHINodes have required incoming values.
  updateExitBlock();

  // Update CFG

  // Removing incoming branch from loop preheader to original header.
  // Now original header is inside the loop.
  for (BasicBlock::iterator I = OrigHeader->begin(), E = OrigHeader->end();
       I != E; ++I) {
    Instruction *In = I;
    PHINode *PN = dyn_cast<PHINode>(In);
    if (!PN)
      break;

    PN->removeIncomingValue(OrigPreHeader);
  }

  // Make NewHeader as the new header for the loop.
  L->moveToHeader(NewHeader);

  preserveCanonicalLoopForm(LPM);

  NumRotated++;
  return true;
}

/// Make sure all Exit block PHINodes have required incoming values.
/// If incoming value is constant or defined outside the loop then
/// PHINode may not have an entry for original pre-header. 
void LoopRotate::updateExitBlock() {

  for (BasicBlock::iterator I = Exit->begin(), E = Exit->end();
       I != E; ++I) {

    PHINode *PN = dyn_cast<PHINode>(I);
    if (!PN)
      break;

    // There is already one incoming value from original pre-header block.
    if (PN->getBasicBlockIndex(OrigPreHeader) != -1)
      continue;

    const RenameData *ILoopHeaderInfo;
    Value *V = PN->getIncomingValueForBlock(OrigHeader);
    if (isa<Instruction>(V) && 
        (ILoopHeaderInfo = findReplacementData(cast<Instruction>(V)))) {
      assert(ILoopHeaderInfo->PreHeader && "Missing New Preheader Instruction");
      PN->addIncoming(ILoopHeaderInfo->PreHeader, OrigPreHeader);
    } else {
      PN->addIncoming(V, OrigPreHeader);
    }
  }
}

/// Initialize local data
void LoopRotate::initialize() {
  L = NULL;
  OrigHeader = NULL;
  OrigPreHeader = NULL;
  NewHeader = NULL;
  Exit = NULL;

  LoopHeaderInfo.clear();
}

/// Return true if this instruction is used by any instructions in the loop that
/// aren't in original header.
bool LoopRotate::usedOutsideOriginalHeader(Instruction *In) {

  for (Value::use_iterator UI = In->use_begin(), UE = In->use_end();
       UI != UE; ++UI) {
    Instruction *U = cast<Instruction>(UI);
    if (U->getParent() != OrigHeader) {
      if (L->contains(U->getParent()))
        return true;
    }
  }

  return false;
}

/// Find Replacement information for instruction. Return NULL if it is
/// not available.
const RenameData *LoopRotate::findReplacementData(Instruction *In) {

  // Since LoopHeaderInfo is small, linear walk is OK.
  for(unsigned LHI = 0, LHI_E = LoopHeaderInfo.size(); LHI != LHI_E; ++LHI) {
    const RenameData &ILoopHeaderInfo = LoopHeaderInfo[LHI];
    if (ILoopHeaderInfo.Original == In)
      return &ILoopHeaderInfo;
  }
  return NULL;
}

/// After loop rotation, loop pre-header has multiple sucessors.
/// Insert one forwarding basic block to ensure that loop pre-header
/// has only one successor.
void LoopRotate::preserveCanonicalLoopForm(LPPassManager &LPM) {

  // Right now original pre-header has two successors, new header and
  // exit block. Insert new block between original pre-header and
  // new header such that loop's new pre-header has only one successor.
  BasicBlock *NewPreHeader = new BasicBlock("bb.nph", OrigHeader->getParent(), 
                                NewHeader);
  LoopInfo &LI = LPM.getAnalysis<LoopInfo>();
  if (Loop *PL = LI.getLoopFor(OrigPreHeader))
    PL->addBasicBlockToLoop(NewPreHeader, LI.getBase());
  new BranchInst(NewHeader, NewPreHeader);
  
  BranchInst *OrigPH_BI = cast<BranchInst>(OrigPreHeader->getTerminator());
  if (OrigPH_BI->getSuccessor(0) == NewHeader)
    OrigPH_BI->setSuccessor(0, NewPreHeader);
  else {
    assert (OrigPH_BI->getSuccessor(1) == NewHeader &&
            "Unexpected original pre-header terminator");
    OrigPH_BI->setSuccessor(1, NewPreHeader);
  }
  
  for (BasicBlock::iterator I = NewHeader->begin(), E = NewHeader->end();
       I != E; ++I) {
    Instruction *In = I;
    PHINode *PN = dyn_cast<PHINode>(In);
    if (!PN)
      break;

    int index = PN->getBasicBlockIndex(OrigPreHeader);
    assert (index != -1 && "Expected incoming value from Original PreHeader");
    PN->setIncomingBlock(index, NewPreHeader);
    assert (PN->getBasicBlockIndex(OrigPreHeader) == -1 && 
            "Expected only one incoming value from Original PreHeader");
  }

  if (DominatorTree *DT = getAnalysisToUpdate<DominatorTree>()) {
    DT->addNewBlock(NewPreHeader, OrigPreHeader);
    DT->changeImmediateDominator(L->getHeader(), NewPreHeader);
    DT->changeImmediateDominator(Exit, OrigPreHeader);
    for (Loop::block_iterator BI = L->block_begin(), BE = L->block_end();
         BI != BE; ++BI) {
      BasicBlock *B = *BI;
      if (L->getHeader() != B) {
        DomTreeNode *Node = DT->getNode(B);
        if (Node && Node->getBlock() == OrigHeader)
          DT->changeImmediateDominator(*BI, L->getHeader());
      }
    }
    DT->changeImmediateDominator(OrigHeader, OrigLatch);
  }

  if(DominanceFrontier *DF = getAnalysisToUpdate<DominanceFrontier>()) {

    // New Preheader's dominance frontier is Exit block.
    DominanceFrontier::DomSetType NewPHSet;
    NewPHSet.insert(Exit);
    DF->addBasicBlock(NewPreHeader, NewPHSet);

    // New Header's dominance frontier now includes itself and Exit block
    DominanceFrontier::iterator HeadI = DF->find(L->getHeader());
    if (HeadI != DF->end()) {
      DominanceFrontier::DomSetType & HeaderSet = HeadI->second;
      HeaderSet.clear();
      HeaderSet.insert(L->getHeader());
      HeaderSet.insert(Exit);
    } else {
      DominanceFrontier::DomSetType HeaderSet;
      HeaderSet.insert(L->getHeader());
      HeaderSet.insert(Exit);
      DF->addBasicBlock(L->getHeader(), HeaderSet);
    }

    // Original header (new Loop Latch)'s dominance frontier is Exit.
    DominanceFrontier::iterator LatchI = DF->find(L->getLoopLatch());
    if (LatchI != DF->end()) {
      DominanceFrontier::DomSetType &LatchSet = LatchI->second;
      LatchSet = LatchI->second;
      LatchSet.clear();
      LatchSet.insert(Exit);
    } else {
      DominanceFrontier::DomSetType LatchSet;
      LatchSet.insert(Exit);
      DF->addBasicBlock(L->getHeader(), LatchSet);
    }

    // If a loop block dominates new loop latch then its frontier is
    // new header and Exit.
    BasicBlock *NewLatch = L->getLoopLatch();
    DominatorTree *DT = getAnalysisToUpdate<DominatorTree>();
    for (Loop::block_iterator BI = L->block_begin(), BE = L->block_end();
         BI != BE; ++BI) {
      BasicBlock *B = *BI;
      if (DT->dominates(B, NewLatch)) {
        DominanceFrontier::iterator BDFI = DF->find(B);
        if (BDFI != DF->end()) {
          DominanceFrontier::DomSetType &BSet = BDFI->second;
          BSet = BDFI->second;
          BSet.clear();
          BSet.insert(L->getHeader());
          BSet.insert(Exit);
        } else {
          DominanceFrontier::DomSetType BSet;
          BSet.insert(L->getHeader());
          BSet.insert(Exit);
          DF->addBasicBlock(B, BSet);
        }
      }
    }
  }

  // Preserve canonical loop form, which means Exit block should
  // have only one predecessor.
  BasicBlock *NExit = SplitEdge(L->getLoopLatch(), Exit, this);

  // Preserve LCSSA.
  BasicBlock::iterator I = Exit->begin(), E = Exit->end();
  PHINode *PN = NULL;
  for (; (PN = dyn_cast<PHINode>(I)); ++I) {
    PHINode *NewPN = new PHINode(PN->getType(), PN->getName());
    unsigned N = PN->getNumIncomingValues();
    for (unsigned index = 0; index < N; ++index)
      if (PN->getIncomingBlock(index) == NExit) {
        NewPN->addIncoming(PN->getIncomingValue(index), L->getLoopLatch());
        PN->setIncomingValue(index, NewPN);
        PN->setIncomingBlock(index, NExit);
        NExit->getInstList().push_front(NewPN);
      }
  }

  assert (NewHeader && L->getHeader() == NewHeader 
          && "Invalid loop header after loop rotation");
  assert (NewPreHeader && L->getLoopPreheader() == NewPreHeader
          && "Invalid loop preheader after loop rotation");
  assert (L->getLoopLatch() 
          && "Invalid loop latch after loop rotation");

}
