mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	The 'Modified' variable should have been removed from SimplifyLibCalls in r177619, but was missed. This commit removes it. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@177622 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			248 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			248 lines
		
	
	
		
			7.6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| //===- SimplifyLibCalls.cpp - Optimize specific well-known library calls --===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file implements a simple pass that applies a variety of small
 | |
| // optimizations for calls to specific well-known function calls (e.g. runtime
 | |
| // library functions).   Any optimization that takes the very simple form
 | |
| // "replace call to library function with simpler code that provides the same
 | |
| // result" belongs in this file.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #define DEBUG_TYPE "simplify-libcalls"
 | |
| #include "llvm/Transforms/Scalar.h"
 | |
| #include "llvm/ADT/STLExtras.h"
 | |
| #include "llvm/ADT/SmallPtrSet.h"
 | |
| #include "llvm/ADT/StringMap.h"
 | |
| #include "llvm/Analysis/ValueTracking.h"
 | |
| #include "llvm/Config/config.h"            // FIXME: Shouldn't depend on host!
 | |
| #include "llvm/IR/DataLayout.h"
 | |
| #include "llvm/IR/IRBuilder.h"
 | |
| #include "llvm/IR/LLVMContext.h"
 | |
| #include "llvm/IR/Module.h"
 | |
| #include "llvm/Pass.h"
 | |
| #include "llvm/Support/CommandLine.h"
 | |
| #include "llvm/Support/Debug.h"
 | |
| #include "llvm/Support/raw_ostream.h"
 | |
| #include "llvm/Target/TargetLibraryInfo.h"
 | |
| #include "llvm/Transforms/Utils/BuildLibCalls.h"
 | |
| using namespace llvm;
 | |
| 
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // Optimizer Base Class
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| /// This class is the abstract base class for the set of optimizations that
 | |
| /// corresponds to one library call.
 | |
| namespace {
 | |
| class LibCallOptimization {
 | |
| protected:
 | |
|   Function *Caller;
 | |
|   const DataLayout *TD;
 | |
|   const TargetLibraryInfo *TLI;
 | |
|   LLVMContext* Context;
 | |
| public:
 | |
|   LibCallOptimization() { }
 | |
|   virtual ~LibCallOptimization() {}
 | |
| 
 | |
|   /// CallOptimizer - This pure virtual method is implemented by base classes to
 | |
|   /// do various optimizations.  If this returns null then no transformation was
 | |
|   /// performed.  If it returns CI, then it transformed the call and CI is to be
 | |
|   /// deleted.  If it returns something else, replace CI with the new value and
 | |
|   /// delete CI.
 | |
|   virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)
 | |
|     =0;
 | |
| 
 | |
|   Value *OptimizeCall(CallInst *CI, const DataLayout *TD,
 | |
|                       const TargetLibraryInfo *TLI, IRBuilder<> &B) {
 | |
|     Caller = CI->getParent()->getParent();
 | |
|     this->TD = TD;
 | |
|     this->TLI = TLI;
 | |
|     if (CI->getCalledFunction())
 | |
|       Context = &CI->getCalledFunction()->getContext();
 | |
| 
 | |
|     // We never change the calling convention.
 | |
|     if (CI->getCallingConv() != llvm::CallingConv::C)
 | |
|       return NULL;
 | |
| 
 | |
|     return CallOptimizer(CI->getCalledFunction(), CI, B);
 | |
|   }
 | |
| };
 | |
| } // End anonymous namespace.
 | |
| 
 | |
| 
 | |
| //===----------------------------------------------------------------------===//
 | |
| // SimplifyLibCalls Pass Implementation
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| namespace {
 | |
|   /// This pass optimizes well known library functions from libc and libm.
 | |
|   ///
 | |
|   class SimplifyLibCalls : public FunctionPass {
 | |
|     TargetLibraryInfo *TLI;
 | |
| 
 | |
|     StringMap<LibCallOptimization*> Optimizations;
 | |
|   public:
 | |
|     static char ID; // Pass identification
 | |
|     SimplifyLibCalls() : FunctionPass(ID) {
 | |
|       initializeSimplifyLibCallsPass(*PassRegistry::getPassRegistry());
 | |
|     }
 | |
|     void AddOpt(LibFunc::Func F, LibCallOptimization* Opt);
 | |
|     void AddOpt(LibFunc::Func F1, LibFunc::Func F2, LibCallOptimization* Opt);
 | |
| 
 | |
|     void InitOptimizations();
 | |
|     bool runOnFunction(Function &F);
 | |
| 
 | |
|     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
 | |
|       AU.addRequired<TargetLibraryInfo>();
 | |
|     }
 | |
|   };
 | |
| } // end anonymous namespace.
 | |
| 
 | |
| char SimplifyLibCalls::ID = 0;
 | |
| 
 | |
| INITIALIZE_PASS_BEGIN(SimplifyLibCalls, "simplify-libcalls",
 | |
|                       "Simplify well-known library calls", false, false)
 | |
| INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
 | |
| INITIALIZE_PASS_END(SimplifyLibCalls, "simplify-libcalls",
 | |
|                     "Simplify well-known library calls", false, false)
 | |
| 
 | |
| // Public interface to the Simplify LibCalls pass.
 | |
| FunctionPass *llvm::createSimplifyLibCallsPass() {
 | |
|   return new SimplifyLibCalls();
 | |
| }
 | |
| 
 | |
| void SimplifyLibCalls::AddOpt(LibFunc::Func F, LibCallOptimization* Opt) {
 | |
|   if (TLI->has(F))
 | |
|     Optimizations[TLI->getName(F)] = Opt;
 | |
| }
 | |
| 
 | |
| void SimplifyLibCalls::AddOpt(LibFunc::Func F1, LibFunc::Func F2,
 | |
|                               LibCallOptimization* Opt) {
 | |
|   if (TLI->has(F1) && TLI->has(F2))
 | |
|     Optimizations[TLI->getName(F1)] = Opt;
 | |
| }
 | |
| 
 | |
| /// Optimizations - Populate the Optimizations map with all the optimizations
 | |
| /// we know.
 | |
| void SimplifyLibCalls::InitOptimizations() {
 | |
| }
 | |
| 
 | |
| 
 | |
| /// runOnFunction - Top level algorithm.
 | |
| ///
 | |
| bool SimplifyLibCalls::runOnFunction(Function &F) {
 | |
|   TLI = &getAnalysis<TargetLibraryInfo>();
 | |
| 
 | |
|   if (Optimizations.empty())
 | |
|     InitOptimizations();
 | |
| 
 | |
|   const DataLayout *TD = getAnalysisIfAvailable<DataLayout>();
 | |
| 
 | |
|   IRBuilder<> Builder(F.getContext());
 | |
| 
 | |
|   bool Changed = false;
 | |
|   for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
 | |
|     for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
 | |
|       // Ignore non-calls.
 | |
|       CallInst *CI = dyn_cast<CallInst>(I++);
 | |
|       if (!CI || CI->hasFnAttr(Attribute::NoBuiltin)) continue;
 | |
| 
 | |
|       // Ignore indirect calls and calls to non-external functions.
 | |
|       Function *Callee = CI->getCalledFunction();
 | |
|       if (Callee == 0 || !Callee->isDeclaration() ||
 | |
|           !(Callee->hasExternalLinkage() || Callee->hasDLLImportLinkage()))
 | |
|         continue;
 | |
| 
 | |
|       // Ignore unknown calls.
 | |
|       LibCallOptimization *LCO = Optimizations.lookup(Callee->getName());
 | |
|       if (!LCO) continue;
 | |
| 
 | |
|       // Set the builder to the instruction after the call.
 | |
|       Builder.SetInsertPoint(BB, I);
 | |
| 
 | |
|       // Use debug location of CI for all new instructions.
 | |
|       Builder.SetCurrentDebugLocation(CI->getDebugLoc());
 | |
| 
 | |
|       // Try to optimize this call.
 | |
|       Value *Result = LCO->OptimizeCall(CI, TD, TLI, Builder);
 | |
|       if (Result == 0) continue;
 | |
| 
 | |
|       DEBUG(dbgs() << "SimplifyLibCalls simplified: " << *CI;
 | |
|             dbgs() << "  into: " << *Result << "\n");
 | |
| 
 | |
|       // Something changed!
 | |
|       Changed = true;
 | |
| 
 | |
|       // Inspect the instruction after the call (which was potentially just
 | |
|       // added) next.
 | |
|       I = CI; ++I;
 | |
| 
 | |
|       if (CI != Result && !CI->use_empty()) {
 | |
|         CI->replaceAllUsesWith(Result);
 | |
|         if (!Result->hasName())
 | |
|           Result->takeName(CI);
 | |
|       }
 | |
|       CI->eraseFromParent();
 | |
|     }
 | |
|   }
 | |
|   return Changed;
 | |
| }
 | |
| 
 | |
| // TODO:
 | |
| //   Additional cases that we need to add to this file:
 | |
| //
 | |
| // cbrt:
 | |
| //   * cbrt(expN(X))  -> expN(x/3)
 | |
| //   * cbrt(sqrt(x))  -> pow(x,1/6)
 | |
| //   * cbrt(sqrt(x))  -> pow(x,1/9)
 | |
| //
 | |
| // exp, expf, expl:
 | |
| //   * exp(log(x))  -> x
 | |
| //
 | |
| // log, logf, logl:
 | |
| //   * log(exp(x))   -> x
 | |
| //   * log(x**y)     -> y*log(x)
 | |
| //   * log(exp(y))   -> y*log(e)
 | |
| //   * log(exp2(y))  -> y*log(2)
 | |
| //   * log(exp10(y)) -> y*log(10)
 | |
| //   * log(sqrt(x))  -> 0.5*log(x)
 | |
| //   * log(pow(x,y)) -> y*log(x)
 | |
| //
 | |
| // lround, lroundf, lroundl:
 | |
| //   * lround(cnst) -> cnst'
 | |
| //
 | |
| // pow, powf, powl:
 | |
| //   * pow(exp(x),y)  -> exp(x*y)
 | |
| //   * pow(sqrt(x),y) -> pow(x,y*0.5)
 | |
| //   * pow(pow(x,y),z)-> pow(x,y*z)
 | |
| //
 | |
| // round, roundf, roundl:
 | |
| //   * round(cnst) -> cnst'
 | |
| //
 | |
| // signbit:
 | |
| //   * signbit(cnst) -> cnst'
 | |
| //   * signbit(nncst) -> 0 (if pstv is a non-negative constant)
 | |
| //
 | |
| // sqrt, sqrtf, sqrtl:
 | |
| //   * sqrt(expN(x))  -> expN(x*0.5)
 | |
| //   * sqrt(Nroot(x)) -> pow(x,1/(2*N))
 | |
| //   * sqrt(pow(x,y)) -> pow(|x|,y*0.5)
 | |
| //
 | |
| // strchr:
 | |
| //   * strchr(p, 0) -> strlen(p)
 | |
| // tan, tanf, tanl:
 | |
| //   * tan(atan(x)) -> x
 | |
| //
 | |
| // trunc, truncf, truncl:
 | |
| //   * trunc(cnst) -> cnst'
 | |
| //
 | |
| //
 |