LLVM API Documentation
00001 //===-- PartialSpecialization.cpp - Specialize for common constants--------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This pass finds function arguments that are often a common constant and 00011 // specializes a version of the called function for that constant. 00012 // 00013 // This pass simply does the cloning for functions it specializes. It depends 00014 // on IPSCCP and DAE to clean up the results. 00015 // 00016 // The initial heuristic favors constant arguments that are used in control 00017 // flow. 00018 // 00019 //===----------------------------------------------------------------------===// 00020 00021 #define DEBUG_TYPE "partialspecialization" 00022 #include "llvm/Transforms/IPO.h" 00023 #include "llvm/Constant.h" 00024 #include "llvm/Instructions.h" 00025 #include "llvm/Module.h" 00026 #include "llvm/Pass.h" 00027 #include "llvm/ADT/Statistic.h" 00028 #include "llvm/Transforms/Utils/Cloning.h" 00029 #include "llvm/Support/CallSite.h" 00030 #include "llvm/Support/Compiler.h" 00031 #include "llvm/ADT/DenseSet.h" 00032 #include <map> 00033 using namespace llvm; 00034 00035 STATISTIC(numSpecialized, "Number of specialized functions created"); 00036 00037 // Call must be used at least occasionally 00038 static const int CallsMin = 5; 00039 00040 // Must have 10% of calls having the same constant to specialize on 00041 static const double ConstValPercent = .1; 00042 00043 namespace { 00044 class VISIBILITY_HIDDEN PartSpec : public ModulePass { 00045 void scanForInterest(Function&, SmallVector<int, 6>&); 00046 int scanDistribution(Function&, int, std::map<Constant*, int>&); 00047 public : 00048 static char ID; // Pass identification, replacement for typeid 00049 PartSpec() : ModulePass(&ID) {} 00050 bool runOnModule(Module &M); 00051 }; 00052 } 00053 00054 char PartSpec::ID = 0; 00055 static RegisterPass<PartSpec> 00056 X("partialspecialization", "Partial Specialization"); 00057 00058 // Specialize F by replacing the arguments (keys) in replacements with the 00059 // constants (values). Replace all calls to F with those constants with 00060 // a call to the specialized function. Returns the specialized function 00061 static Function* 00062 SpecializeFunction(Function* F, 00063 DenseMap<const Value*, Value*>& replacements) { 00064 // arg numbers of deleted arguments 00065 DenseSet<unsigned> deleted; 00066 for (DenseMap<const Value*, Value*>::iterator 00067 repb = replacements.begin(), repe = replacements.end(); 00068 repb != repe; ++ repb) 00069 deleted.insert(cast<Argument>(repb->first)->getArgNo()); 00070 00071 Function* NF = CloneFunction(F, replacements); 00072 NF->setLinkage(GlobalValue::InternalLinkage); 00073 F->getParent()->getFunctionList().push_back(NF); 00074 00075 for (Value::use_iterator ii = F->use_begin(), ee = F->use_end(); 00076 ii != ee; ) { 00077 Value::use_iterator i = ii;; 00078 ++ii; 00079 if (isa<CallInst>(i) || isa<InvokeInst>(i)) { 00080 CallSite CS(cast<Instruction>(i)); 00081 if (CS.getCalledFunction() == F) { 00082 00083 SmallVector<Value*, 6> args; 00084 for (unsigned x = 0; x < CS.arg_size(); ++x) 00085 if (!deleted.count(x)) 00086 args.push_back(CS.getArgument(x)); 00087 Value* NCall; 00088 if (isa<CallInst>(i)) 00089 NCall = CallInst::Create(NF, args.begin(), args.end(), 00090 CS.getInstruction()->getName(), 00091 CS.getInstruction()); 00092 else 00093 NCall = InvokeInst::Create(NF, cast<InvokeInst>(i)->getNormalDest(), 00094 cast<InvokeInst>(i)->getUnwindDest(), 00095 args.begin(), args.end(), 00096 CS.getInstruction()->getName(), 00097 CS.getInstruction()); 00098 CS.getInstruction()->replaceAllUsesWith(NCall); 00099 CS.getInstruction()->eraseFromParent(); 00100 } 00101 } 00102 } 00103 return NF; 00104 } 00105 00106 00107 bool PartSpec::runOnModule(Module &M) { 00108 bool Changed = false; 00109 for (Module::iterator I = M.begin(); I != M.end(); ++I) { 00110 Function &F = *I; 00111 if (F.isDeclaration() || F.mayBeOverridden()) continue; 00112 SmallVector<int, 6> interestingArgs; 00113 scanForInterest(F, interestingArgs); 00114 00115 // Find the first interesting Argument that we can specialize on 00116 // If there are multiple interesting Arguments, then those will be found 00117 // when processing the cloned function. 00118 bool breakOuter = false; 00119 for (unsigned int x = 0; !breakOuter && x < interestingArgs.size(); ++x) { 00120 std::map<Constant*, int> distribution; 00121 int total = scanDistribution(F, interestingArgs[x], distribution); 00122 if (total > CallsMin) 00123 for (std::map<Constant*, int>::iterator ii = distribution.begin(), 00124 ee = distribution.end(); ii != ee; ++ii) 00125 if (total > ii->second && ii->first && 00126 ii->second > total * ConstValPercent) { 00127 DenseMap<const Value*, Value*> m; 00128 Function::arg_iterator arg = F.arg_begin(); 00129 for (int y = 0; y < interestingArgs[x]; ++y) 00130 ++arg; 00131 m[&*arg] = ii->first; 00132 SpecializeFunction(&F, m); 00133 ++numSpecialized; 00134 breakOuter = true; 00135 Changed = true; 00136 } 00137 } 00138 } 00139 return Changed; 00140 } 00141 00142 /// scanForInterest - This function decides which arguments would be worth 00143 /// specializing on. 00144 void PartSpec::scanForInterest(Function& F, SmallVector<int, 6>& args) { 00145 for(Function::arg_iterator ii = F.arg_begin(), ee = F.arg_end(); 00146 ii != ee; ++ii) { 00147 for(Value::use_iterator ui = ii->use_begin(), ue = ii->use_end(); 00148 ui != ue; ++ui) { 00149 00150 bool interesting = false; 00151 00152 if (isa<CmpInst>(ui)) interesting = true; 00153 else if (isa<CallInst>(ui)) 00154 interesting = ui->getOperand(0) == ii; 00155 else if (isa<InvokeInst>(ui)) 00156 interesting = ui->getOperand(0) == ii; 00157 else if (isa<SwitchInst>(ui)) interesting = true; 00158 else if (isa<BranchInst>(ui)) interesting = true; 00159 00160 if (interesting) { 00161 args.push_back(std::distance(F.arg_begin(), ii)); 00162 break; 00163 } 00164 } 00165 } 00166 } 00167 00168 /// scanDistribution - Construct a histogram of constants for arg of F at arg. 00169 int PartSpec::scanDistribution(Function& F, int arg, 00170 std::map<Constant*, int>& dist) { 00171 bool hasIndirect = false; 00172 int total = 0; 00173 for(Value::use_iterator ii = F.use_begin(), ee = F.use_end(); 00174 ii != ee; ++ii) 00175 if ((isa<CallInst>(ii) || isa<InvokeInst>(ii)) 00176 && ii->getOperand(0) == &F) { 00177 ++dist[dyn_cast<Constant>(ii->getOperand(arg + 1))]; 00178 ++total; 00179 } else 00180 hasIndirect = true; 00181 00182 // Preserve the original address taken function even if all other uses 00183 // will be specialized. 00184 if (hasIndirect) ++total; 00185 return total; 00186 } 00187 00188 ModulePass* llvm::createPartialSpecializationPass() { return new PartSpec(); }