mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	correctly indicates whether it changed the code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72038 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			359 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			359 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===-- CodePlacementOpt.cpp - Code Placement 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 the pass that optimize code placement and align loop
 | |
| // headers to target specific alignment boundary.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #define DEBUG_TYPE "code-placement"
 | |
| #include "llvm/CodeGen/MachineLoopInfo.h"
 | |
| #include "llvm/CodeGen/MachineFunctionPass.h"
 | |
| #include "llvm/CodeGen/Passes.h"
 | |
| #include "llvm/Target/TargetInstrInfo.h"
 | |
| #include "llvm/Target/TargetLowering.h"
 | |
| #include "llvm/Target/TargetMachine.h"
 | |
| #include "llvm/Support/Compiler.h"
 | |
| #include "llvm/Support/Debug.h"
 | |
| #include "llvm/ADT/Statistic.h"
 | |
| using namespace llvm;
 | |
| 
 | |
| STATISTIC(NumHeaderAligned, "Number of loop header aligned");
 | |
| STATISTIC(NumIntraElim,     "Number of intra loop branches eliminated");
 | |
| STATISTIC(NumIntraMoved,    "Number of intra loop branches moved");
 | |
| 
 | |
| namespace {
 | |
|   class CodePlacementOpt : public MachineFunctionPass {
 | |
|     const MachineLoopInfo *MLI;
 | |
|     const TargetInstrInfo *TII;
 | |
|     const TargetLowering  *TLI;
 | |
| 
 | |
|     /// ChangedMBBs - BBs which are modified by OptimizeIntraLoopEdges.
 | |
|     SmallPtrSet<MachineBasicBlock*, 8> ChangedMBBs;
 | |
| 
 | |
|     /// UncondJmpMBBs - A list of BBs which are in loops and end with
 | |
|     /// unconditional branches.
 | |
|     SmallVector<std::pair<MachineBasicBlock*,MachineBasicBlock*>, 4>
 | |
|     UncondJmpMBBs;
 | |
| 
 | |
|     /// LoopHeaders - A list of BBs which are loop headers.
 | |
|     SmallVector<MachineBasicBlock*, 4> LoopHeaders;
 | |
| 
 | |
|   public:
 | |
|     static char ID;
 | |
|     CodePlacementOpt() : MachineFunctionPass(&ID) {}
 | |
| 
 | |
|     virtual bool runOnMachineFunction(MachineFunction &MF);
 | |
|     virtual const char *getPassName() const {
 | |
|       return "Code Placement Optimizater";
 | |
|     }
 | |
| 
 | |
|     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
 | |
|       AU.addRequired<MachineLoopInfo>();
 | |
|       AU.addPreservedID(MachineDominatorsID);
 | |
|       MachineFunctionPass::getAnalysisUsage(AU);
 | |
|     }
 | |
| 
 | |
|   private:
 | |
|     bool OptimizeIntraLoopEdges();
 | |
|     bool HeaderShouldBeAligned(MachineBasicBlock *MBB, MachineLoop *L,
 | |
|                                SmallPtrSet<MachineBasicBlock*, 4> &DoNotAlign);
 | |
|     bool AlignLoops(MachineFunction &MF);
 | |
|   };
 | |
| 
 | |
|   char CodePlacementOpt::ID = 0;
 | |
| } // end anonymous namespace
 | |
| 
 | |
| FunctionPass *llvm::createCodePlacementOptPass() {
 | |
|   return new CodePlacementOpt();
 | |
| }
 | |
| 
 | |
| /// OptimizeBackEdges - Place loop back edges to move unconditional branches
 | |
| /// out of the loop.
 | |
| ///
 | |
| ///       A:
 | |
| ///       ...
 | |
| ///       <fallthrough to B>
 | |
| ///
 | |
| ///       B:  --> loop header
 | |
| ///       ...
 | |
| ///       jcc <cond> C, [exit]
 | |
| ///
 | |
| ///       C:
 | |
| ///       ...
 | |
| ///       jmp B
 | |
| ///
 | |
| /// ==>
 | |
| ///
 | |
| ///       A:
 | |
| ///       ...
 | |
| ///       jmp B
 | |
| ///
 | |
| ///       C:  --> new loop header
 | |
| ///       ...
 | |
| ///       <fallthough to B>
 | |
| ///       
 | |
| ///       B:
 | |
| ///       ...
 | |
| ///       jcc <cond> C, [exit]
 | |
| ///
 | |
| bool CodePlacementOpt::OptimizeIntraLoopEdges() {
 | |
|   if (!TLI->shouldOptimizeCodePlacement())
 | |
|     return false;
 | |
| 
 | |
|   bool Changed = false;
 | |
|   for (unsigned i = 0, e = UncondJmpMBBs.size(); i != e; ++i) {
 | |
|     MachineBasicBlock *MBB = UncondJmpMBBs[i].first;
 | |
|     MachineBasicBlock *SuccMBB = UncondJmpMBBs[i].second;
 | |
|     MachineLoop *L = MLI->getLoopFor(MBB);
 | |
|     assert(L && "BB is expected to be in a loop!");
 | |
| 
 | |
|     if (ChangedMBBs.count(MBB)) {
 | |
|       // BB has been modified, re-analyze.
 | |
|       MachineBasicBlock *TBB = 0, *FBB = 0;
 | |
|       SmallVector<MachineOperand, 4> Cond;
 | |
|       if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond) || !Cond.empty())
 | |
|         continue;
 | |
|       if (MLI->getLoopFor(TBB) != L || TBB->isLandingPad())
 | |
|         continue;
 | |
|       SuccMBB = TBB;
 | |
|     } else {
 | |
|       assert(MLI->getLoopFor(SuccMBB) == L &&
 | |
|              "Successor is not in the same loop!");
 | |
|     }
 | |
| 
 | |
|     if (MBB->isLayoutSuccessor(SuccMBB)) {
 | |
|       // Successor is right after MBB, just eliminate the unconditional jmp.
 | |
|       // Can this happen?
 | |
|       TII->RemoveBranch(*MBB);
 | |
|       ChangedMBBs.insert(MBB);
 | |
|       ++NumIntraElim;
 | |
|       Changed = true;
 | |
|       continue;
 | |
|     }
 | |
| 
 | |
|     // Now check if the predecessor is fallthrough from any BB. If there is,
 | |
|     // that BB should be from outside the loop since edge will become a jmp.
 | |
|     bool OkToMove = true;
 | |
|     MachineBasicBlock *FtMBB = 0, *FtTBB = 0, *FtFBB = 0;
 | |
|     SmallVector<MachineOperand, 4> FtCond;    
 | |
|     for (MachineBasicBlock::pred_iterator PI = SuccMBB->pred_begin(),
 | |
|            PE = SuccMBB->pred_end(); PI != PE; ++PI) {
 | |
|       MachineBasicBlock *PredMBB = *PI;
 | |
|       if (PredMBB->isLayoutSuccessor(SuccMBB)) {
 | |
|         if (TII->AnalyzeBranch(*PredMBB, FtTBB, FtFBB, FtCond)) {
 | |
|           OkToMove = false;
 | |
|           break;
 | |
|         }
 | |
|         if (!FtTBB)
 | |
|           FtTBB = SuccMBB;
 | |
|         else if (!FtFBB) {
 | |
|           assert(FtFBB != SuccMBB && "Unexpected control flow!");
 | |
|           FtFBB = SuccMBB;
 | |
|         }
 | |
|         
 | |
|         // A fallthrough.
 | |
|         FtMBB = PredMBB;
 | |
|         MachineLoop *PL = MLI->getLoopFor(PredMBB);
 | |
|         if (PL && (PL == L || PL->getLoopDepth() >= L->getLoopDepth()))
 | |
|           OkToMove = false;
 | |
| 
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (!OkToMove)
 | |
|       continue;
 | |
| 
 | |
|     // Is it profitable? If SuccMBB can fallthrough itself, that can be changed
 | |
|     // into a jmp.
 | |
|     MachineBasicBlock *TBB = 0, *FBB = 0;
 | |
|     SmallVector<MachineOperand, 4> Cond;
 | |
|     if (TII->AnalyzeBranch(*SuccMBB, TBB, FBB, Cond))
 | |
|       continue;
 | |
|     if (!TBB && Cond.empty())
 | |
|       TBB = next(MachineFunction::iterator(SuccMBB));
 | |
|     else if (!FBB && !Cond.empty())
 | |
|       FBB = next(MachineFunction::iterator(SuccMBB));
 | |
| 
 | |
|     // This calculate the cost of the transformation. Also, it finds the *only*
 | |
|     // intra-loop edge if there is one.
 | |
|     int Cost = 0;
 | |
|     bool HasOneIntraSucc = true;
 | |
|     MachineBasicBlock *IntraSucc = 0;
 | |
|     for (MachineBasicBlock::succ_iterator SI = SuccMBB->succ_begin(),
 | |
|            SE = SuccMBB->succ_end(); SI != SE; ++SI) {
 | |
|       MachineBasicBlock *SSMBB = *SI;
 | |
|       if (MLI->getLoopFor(SSMBB) == L) {
 | |
|         if (!IntraSucc)
 | |
|           IntraSucc = SSMBB;
 | |
|         else
 | |
|           HasOneIntraSucc = false;
 | |
|       }
 | |
| 
 | |
|       if (SuccMBB->isLayoutSuccessor(SSMBB))
 | |
|         // This will become a jmp.
 | |
|         ++Cost;
 | |
|       else if (MBB->isLayoutSuccessor(SSMBB)) {
 | |
|         // One of the successor will become the new fallthrough.
 | |
|         if (SSMBB == FBB) {
 | |
|           FBB = 0;
 | |
|           --Cost;
 | |
|         } else if (!FBB && SSMBB == TBB && Cond.empty()) {
 | |
|           TBB = 0;
 | |
|           --Cost;
 | |
|         } else if (!Cond.empty() && !TII->ReverseBranchCondition(Cond)) {
 | |
|           assert(SSMBB == TBB);
 | |
|           TBB = FBB;
 | |
|           FBB = 0;
 | |
|           --Cost;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     if (Cost)
 | |
|       continue;
 | |
| 
 | |
|     // Now, let's move the successor to below the BB to eliminate the jmp.
 | |
|     SuccMBB->moveAfter(MBB);
 | |
|     TII->RemoveBranch(*MBB);
 | |
|     TII->RemoveBranch(*SuccMBB);
 | |
|     if (TBB)
 | |
|       TII->InsertBranch(*SuccMBB, TBB, FBB, Cond);
 | |
|     ChangedMBBs.insert(MBB);
 | |
|     ChangedMBBs.insert(SuccMBB);
 | |
|     if (FtMBB) {
 | |
|       TII->RemoveBranch(*FtMBB);
 | |
|       TII->InsertBranch(*FtMBB, FtTBB, FtFBB, FtCond);
 | |
|       ChangedMBBs.insert(FtMBB);
 | |
|     }
 | |
|     Changed = true;
 | |
| 
 | |
|     // If BB is the loop latch, we may have a new loop headr.
 | |
|     if (MBB == L->getLoopLatch()) {
 | |
|       assert(MLI->isLoopHeader(SuccMBB) &&
 | |
|              "Only succ of loop latch is not the header?");
 | |
|       if (HasOneIntraSucc && IntraSucc)
 | |
|         std::replace(LoopHeaders.begin(),LoopHeaders.end(), SuccMBB, IntraSucc);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   ++NumIntraMoved;
 | |
|   return Changed;
 | |
| }
 | |
| 
 | |
| /// HeaderShouldBeAligned - Return true if the specified loop header block
 | |
| /// should be aligned. For now, we will not align it if all the predcessors
 | |
| /// (i.e. loop back edges) are laid out above the header. FIXME: Do not
 | |
| /// align small loops.
 | |
| bool
 | |
| CodePlacementOpt::HeaderShouldBeAligned(MachineBasicBlock *MBB, MachineLoop *L,
 | |
|                                SmallPtrSet<MachineBasicBlock*, 4> &DoNotAlign) {
 | |
|   if (DoNotAlign.count(MBB))
 | |
|     return false;
 | |
| 
 | |
|   bool BackEdgeBelow = false;
 | |
|   for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
 | |
|          PE = MBB->pred_end(); PI != PE; ++PI) {
 | |
|     MachineBasicBlock *PredMBB = *PI;
 | |
|     if (PredMBB == MBB || PredMBB->getNumber() > MBB->getNumber()) {
 | |
|       BackEdgeBelow = true;
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!BackEdgeBelow)
 | |
|     return false;
 | |
| 
 | |
|   // Ok, we are going to align this loop header. If it's an inner loop,
 | |
|   // do not align its outer loop.
 | |
|   MachineBasicBlock *PreHeader = L->getLoopPreheader();
 | |
|   if (PreHeader) {
 | |
|     MachineLoop *L = MLI->getLoopFor(PreHeader);
 | |
|     if (L) {
 | |
|       MachineBasicBlock *HeaderBlock = L->getHeader();
 | |
|       HeaderBlock->setAlignment(0);
 | |
|       DoNotAlign.insert(HeaderBlock);
 | |
|     }
 | |
|   }
 | |
|   return true;
 | |
| }
 | |
| 
 | |
| /// AlignLoops - Align loop headers to target preferred alignments.
 | |
| ///
 | |
| bool CodePlacementOpt::AlignLoops(MachineFunction &MF) {
 | |
|   const Function *F = MF.getFunction();
 | |
|   if (F->hasFnAttr(Attribute::OptimizeForSize))
 | |
|     return false;
 | |
| 
 | |
|   unsigned Align = TLI->getPrefLoopAlignment();
 | |
|   if (!Align)
 | |
|     return false;  // Don't care about loop alignment.
 | |
| 
 | |
|   // Make sure blocks are numbered in order
 | |
|   MF.RenumberBlocks();
 | |
| 
 | |
|   bool Changed = false;
 | |
|   SmallPtrSet<MachineBasicBlock*, 4> DoNotAlign;
 | |
|   for (unsigned i = 0, e = LoopHeaders.size(); i != e; ++i) {
 | |
|     MachineBasicBlock *HeaderMBB = LoopHeaders[i];
 | |
|     MachineBasicBlock *PredMBB = prior(MachineFunction::iterator(HeaderMBB));
 | |
|     MachineLoop *L = MLI->getLoopFor(HeaderMBB);
 | |
|     if (L == MLI->getLoopFor(PredMBB))
 | |
|       // If previously BB is in the same loop, don't align this BB. We want
 | |
|       // to prevent adding noop's inside a loop.
 | |
|       continue;
 | |
|     if (HeaderShouldBeAligned(HeaderMBB, L, DoNotAlign)) {
 | |
|       HeaderMBB->setAlignment(Align);
 | |
|       Changed = true;
 | |
|       ++NumHeaderAligned;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Changed;
 | |
| }
 | |
| 
 | |
| bool CodePlacementOpt::runOnMachineFunction(MachineFunction &MF) {
 | |
|   MLI = &getAnalysis<MachineLoopInfo>();
 | |
|   if (MLI->empty())
 | |
|     return false;  // No loops.
 | |
| 
 | |
|   TLI = MF.getTarget().getTargetLowering();
 | |
|   TII = MF.getTarget().getInstrInfo();
 | |
| 
 | |
|   // Analyze the BBs first and keep track of loop headers and BBs that
 | |
|   // end with an unconditional jmp to another block in the same loop.
 | |
|   for (MachineFunction::iterator I = MF.begin(), E = MF.end(); I != E; ++I) {
 | |
|     MachineBasicBlock *MBB = I;
 | |
|     if (MBB->isLandingPad())
 | |
|       continue;
 | |
|     MachineLoop *L = MLI->getLoopFor(MBB);
 | |
|     if (!L)
 | |
|       continue;
 | |
|     if (MLI->isLoopHeader(MBB))
 | |
|       LoopHeaders.push_back(MBB);
 | |
| 
 | |
|     MachineBasicBlock *TBB = 0, *FBB = 0;
 | |
|     SmallVector<MachineOperand, 4> Cond;
 | |
|     if (TII->AnalyzeBranch(*MBB, TBB, FBB, Cond) || !Cond.empty())
 | |
|       continue;
 | |
|     if (MLI->getLoopFor(TBB) == L && !TBB->isLandingPad())
 | |
|       UncondJmpMBBs.push_back(std::make_pair(MBB, TBB));
 | |
|   }
 | |
| 
 | |
|   bool Changed = OptimizeIntraLoopEdges();
 | |
| 
 | |
|   Changed |= AlignLoops(MF);
 | |
| 
 | |
|   ChangedMBBs.clear();
 | |
|   UncondJmpMBBs.clear();
 | |
|   LoopHeaders.clear();
 | |
| 
 | |
|   return Changed;
 | |
| }
 |