mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-30 16:17:05 +00:00 
			
		
		
		
	This required converting a bunch of stuff off DOUT and other cleanups. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79819 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			182 lines
		
	
	
		
			6.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			6.0 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/Support/raw_ostream.h"
 | |
| #include "llvm/ADT/SmallPtrSet.h"
 | |
| #include <vector>
 | |
| 
 | |
| using namespace llvm;
 | |
| 
 | |
| static cl::opt<unsigned>     
 | |
| BasicInlineThreshold("basic-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);
 | |
|       }
 | |
|   }
 | |
|   
 | |
|   DEBUG(errs() << ": " << 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 that are never inlinable.
 | |
|         if (Callee->isDeclaration() ||
 | |
|             CS.getInstruction()->getParent()->getParent() == Callee) {
 | |
|           CallSites.erase(CallSites.begin() + index);
 | |
|           --index;
 | |
|           continue;
 | |
|         }
 | |
|         InlineCost IC = CA.getInlineCost(CS, NeverInline);
 | |
|         if (IC.isAlways()) {        
 | |
|           DEBUG(errs() << "  Inlining: cost=always"
 | |
|                        <<", call: " << *CS.getInstruction());
 | |
|         } else if (IC.isNever()) {
 | |
|           DEBUG(errs() << "  NOT Inlining: cost=never"
 | |
|                        <<", call: " << *CS.getInstruction());
 | |
|           continue;
 | |
|         } else {
 | |
|           int Cost = IC.getValue();
 | |
|           
 | |
|           if (Cost >= (int) BasicInlineThreshold) {
 | |
|             DEBUG(errs() << "  NOT Inlining: cost = " << Cost
 | |
|                          << ", call: " <<  *CS.getInstruction());
 | |
|             continue;
 | |
|           } else {
 | |
|             DEBUG(errs() << "  Inlining: cost = " << Cost
 | |
|                          << ", call: " <<  *CS.getInstruction());
 | |
|           }
 | |
|         }
 | |
|         
 | |
|         // Inline
 | |
|         if (InlineFunction(CS, NULL, TD)) {
 | |
|           if (Callee->use_empty() && (Callee->hasLocalLinkage() ||
 | |
|                                       Callee->hasAvailableExternallyLinkage()))
 | |
|             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();
 | |
| }
 | |
| 
 | |
| }
 |