mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	several things that were neither in an anonymous namespace nor static but not intended to be global. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@51017 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			169 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			169 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===- BasicInliner.cpp - Basic function level inliner --------------------===//
 | 
						|
//
 | 
						|
//                     The LLVM Compiler Infrastructure
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file defines a simple function based inliner that does not use
 | 
						|
// call graph information. 
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#define DEBUG_TYPE "basicinliner"
 | 
						|
 | 
						|
#include "llvm/Module.h"
 | 
						|
#include "llvm/Function.h"
 | 
						|
#include "llvm/Transforms/Utils/BasicInliner.h"
 | 
						|
#include "llvm/Transforms/Utils/Cloning.h"
 | 
						|
#include "llvm/Support/CallSite.h"
 | 
						|
#include "llvm/Support/CommandLine.h"
 | 
						|
#include "llvm/Support/Debug.h"
 | 
						|
#include "llvm/ADT/SmallPtrSet.h"
 | 
						|
#include <vector>
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
static cl::opt<unsigned>     
 | 
						|
BasicInlineThreshold("inline-threshold", cl::Hidden, cl::init(200),
 | 
						|
                     cl::desc("Control the amount of basic inlining to perform (default = 200)"));
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
 | 
						|
  /// BasicInlinerImpl - BasicInliner implemantation class. This hides
 | 
						|
  /// container info, used by basic inliner, from public interface.
 | 
						|
  struct VISIBILITY_HIDDEN BasicInlinerImpl {
 | 
						|
    
 | 
						|
    BasicInlinerImpl(const BasicInlinerImpl&); // DO NOT IMPLEMENT
 | 
						|
    void operator=(const BasicInlinerImpl&); // DO NO IMPLEMENT
 | 
						|
  public:
 | 
						|
    BasicInlinerImpl(TargetData *T) : TD(T) {}
 | 
						|
 | 
						|
    /// addFunction - Add function into the list of functions to process.
 | 
						|
    /// All functions must be inserted using this interface before invoking
 | 
						|
    /// inlineFunctions().
 | 
						|
    void addFunction(Function *F) {
 | 
						|
      Functions.push_back(F);
 | 
						|
    }
 | 
						|
 | 
						|
    /// neverInlineFunction - Sometimes a function is never to be inlined 
 | 
						|
    /// because of one or other reason. 
 | 
						|
    void neverInlineFunction(Function *F) {
 | 
						|
      NeverInline.insert(F);
 | 
						|
    }
 | 
						|
 | 
						|
    /// inlineFuctions - Walk all call sites in all functions supplied by
 | 
						|
    /// client. Inline as many call sites as possible. Delete completely
 | 
						|
    /// inlined functions.
 | 
						|
    void inlineFunctions();
 | 
						|
    
 | 
						|
  private:
 | 
						|
    TargetData *TD;
 | 
						|
    std::vector<Function *> Functions;
 | 
						|
    SmallPtrSet<const Function *, 16> NeverInline;
 | 
						|
    SmallPtrSet<Function *, 8> DeadFunctions;
 | 
						|
    InlineCostAnalyzer CA;
 | 
						|
  };
 | 
						|
 | 
						|
/// inlineFuctions - Walk all call sites in all functions supplied by
 | 
						|
/// client. Inline as many call sites as possible. Delete completely
 | 
						|
/// inlined functions.
 | 
						|
void BasicInlinerImpl::inlineFunctions() {
 | 
						|
      
 | 
						|
  // Scan through and identify all call sites ahead of time so that we only
 | 
						|
  // inline call sites in the original functions, not call sites that result
 | 
						|
  // from inlining other functions.
 | 
						|
  std::vector<CallSite> CallSites;
 | 
						|
  
 | 
						|
  for (std::vector<Function *>::iterator FI = Functions.begin(),
 | 
						|
         FE = Functions.end(); FI != FE; ++FI) {
 | 
						|
    Function *F = *FI;
 | 
						|
    for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
 | 
						|
      for (BasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) {
 | 
						|
        CallSite CS = CallSite::get(I);
 | 
						|
        if (CS.getInstruction() && CS.getCalledFunction()
 | 
						|
            && !CS.getCalledFunction()->isDeclaration())
 | 
						|
          CallSites.push_back(CS);
 | 
						|
      }
 | 
						|
  }
 | 
						|
  
 | 
						|
  DOUT << ": " << CallSites.size() << " call sites.\n";
 | 
						|
  
 | 
						|
  // Inline call sites.
 | 
						|
  bool Changed = false;
 | 
						|
  do {
 | 
						|
    Changed = false;
 | 
						|
    for (unsigned index = 0; index != CallSites.size() && !CallSites.empty(); ++index) {
 | 
						|
      CallSite CS = CallSites[index];
 | 
						|
      if (Function *Callee = CS.getCalledFunction()) {
 | 
						|
        
 | 
						|
        // Eliminate calls taht are never inlinable.
 | 
						|
        if (Callee->isDeclaration() ||
 | 
						|
            CS.getInstruction()->getParent()->getParent() == Callee) {
 | 
						|
          CallSites.erase(CallSites.begin() + index);
 | 
						|
              --index;
 | 
						|
              continue;
 | 
						|
        }
 | 
						|
        int InlineCost = CA.getInlineCost(CS, NeverInline);
 | 
						|
        if (InlineCost >= (int) BasicInlineThreshold) {
 | 
						|
              DOUT << "  NOT Inlining: cost = " << InlineCost
 | 
						|
                   << ", call: " <<  *CS.getInstruction();
 | 
						|
              continue;
 | 
						|
        }
 | 
						|
        
 | 
						|
        DOUT << "  Inlining: cost=" << InlineCost
 | 
						|
             <<", call: " << *CS.getInstruction();
 | 
						|
        
 | 
						|
        // Inline
 | 
						|
        if (InlineFunction(CS, NULL, TD)) {
 | 
						|
          if (Callee->use_empty() && Callee->hasInternalLinkage())
 | 
						|
                DeadFunctions.insert(Callee);
 | 
						|
          Changed = true;
 | 
						|
          CallSites.erase(CallSites.begin() + index);
 | 
						|
          --index;
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } while (Changed);
 | 
						|
  
 | 
						|
  // Remove completely inlined functions from module.
 | 
						|
  for(SmallPtrSet<Function *, 8>::iterator I = DeadFunctions.begin(),
 | 
						|
        E = DeadFunctions.end(); I != E; ++I) {
 | 
						|
    Function *D = *I;
 | 
						|
    Module *M = D->getParent();
 | 
						|
    M->getFunctionList().remove(D);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
BasicInliner::BasicInliner(TargetData *TD) {
 | 
						|
  Impl = new BasicInlinerImpl(TD);
 | 
						|
}
 | 
						|
 | 
						|
BasicInliner::~BasicInliner() {
 | 
						|
  delete Impl;
 | 
						|
}
 | 
						|
 | 
						|
/// addFunction - Add function into the list of functions to process.
 | 
						|
/// All functions must be inserted using this interface before invoking
 | 
						|
/// inlineFunctions().
 | 
						|
void BasicInliner::addFunction(Function *F) {
 | 
						|
  Impl->addFunction(F);
 | 
						|
}
 | 
						|
 | 
						|
/// neverInlineFunction - Sometimes a function is never to be inlined because
 | 
						|
/// of one or other reason. 
 | 
						|
void BasicInliner::neverInlineFunction(Function *F) {
 | 
						|
  Impl->neverInlineFunction(F);
 | 
						|
}
 | 
						|
 | 
						|
/// inlineFuctions - Walk all call sites in all functions supplied by
 | 
						|
/// client. Inline as many call sites as possible. Delete completely
 | 
						|
/// inlined functions.
 | 
						|
void BasicInliner::inlineFunctions() {
 | 
						|
  Impl->inlineFunctions();
 | 
						|
}
 | 
						|
 | 
						|
}
 |