LLVM API Documentation
00001 //===-- StructRetPromotion.cpp - Promote sret arguments ------------------===// 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 functions that return a struct (using a pointer to the struct 00011 // as the first argument of the function, marked with the 'sret' attribute) and 00012 // replaces them with a new function that simply returns each of the elements of 00013 // that struct (using multiple return values). 00014 // 00015 // This pass works under a number of conditions: 00016 // 1. The returned struct must not contain other structs 00017 // 2. The returned struct must only be used to load values from 00018 // 3. The placeholder struct passed in is the result of an alloca 00019 // 00020 //===----------------------------------------------------------------------===// 00021 00022 #define DEBUG_TYPE "sretpromotion" 00023 #include "llvm/Transforms/IPO.h" 00024 #include "llvm/Constants.h" 00025 #include "llvm/DerivedTypes.h" 00026 #include "llvm/Module.h" 00027 #include "llvm/CallGraphSCCPass.h" 00028 #include "llvm/Instructions.h" 00029 #include "llvm/Analysis/CallGraph.h" 00030 #include "llvm/Support/CallSite.h" 00031 #include "llvm/Support/CFG.h" 00032 #include "llvm/Support/Debug.h" 00033 #include "llvm/ADT/Statistic.h" 00034 #include "llvm/ADT/SmallVector.h" 00035 #include "llvm/ADT/Statistic.h" 00036 #include "llvm/Support/Compiler.h" 00037 using namespace llvm; 00038 00039 STATISTIC(NumRejectedSRETUses , "Number of sret rejected due to unexpected uses"); 00040 STATISTIC(NumSRET , "Number of sret promoted"); 00041 namespace { 00042 /// SRETPromotion - This pass removes sret parameter and updates 00043 /// function to use multiple return value. 00044 /// 00045 struct VISIBILITY_HIDDEN SRETPromotion : public CallGraphSCCPass { 00046 virtual void getAnalysisUsage(AnalysisUsage &AU) const { 00047 CallGraphSCCPass::getAnalysisUsage(AU); 00048 } 00049 00050 virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCC); 00051 static char ID; // Pass identification, replacement for typeid 00052 SRETPromotion() : CallGraphSCCPass(&ID) {} 00053 00054 private: 00055 bool PromoteReturn(CallGraphNode *CGN); 00056 bool isSafeToUpdateAllCallers(Function *F); 00057 Function *cloneFunctionBody(Function *F, const StructType *STy); 00058 void updateCallSites(Function *F, Function *NF); 00059 bool nestedStructType(const StructType *STy); 00060 }; 00061 } 00062 00063 char SRETPromotion::ID = 0; 00064 static RegisterPass<SRETPromotion> 00065 X("sretpromotion", "Promote sret arguments to multiple ret values"); 00066 00067 Pass *llvm::createStructRetPromotionPass() { 00068 return new SRETPromotion(); 00069 } 00070 00071 bool SRETPromotion::runOnSCC(const std::vector<CallGraphNode *> &SCC) { 00072 bool Changed = false; 00073 00074 for (unsigned i = 0, e = SCC.size(); i != e; ++i) 00075 Changed |= PromoteReturn(SCC[i]); 00076 00077 return Changed; 00078 } 00079 00080 /// PromoteReturn - This method promotes function that uses StructRet paramater 00081 /// into a function that uses mulitple return value. 00082 bool SRETPromotion::PromoteReturn(CallGraphNode *CGN) { 00083 Function *F = CGN->getFunction(); 00084 00085 if (!F || F->isDeclaration() || !F->hasLocalLinkage()) 00086 return false; 00087 00088 // Make sure that function returns struct. 00089 if (F->arg_size() == 0 || !F->hasStructRetAttr() || F->doesNotReturn()) 00090 return false; 00091 00092 DOUT << "SretPromotion: Looking at sret function " << F->getNameStart() << "\n"; 00093 00094 assert (F->getReturnType() == Type::VoidTy && "Invalid function return type"); 00095 Function::arg_iterator AI = F->arg_begin(); 00096 const llvm::PointerType *FArgType = dyn_cast<PointerType>(AI->getType()); 00097 assert (FArgType && "Invalid sret parameter type"); 00098 const llvm::StructType *STy = 00099 dyn_cast<StructType>(FArgType->getElementType()); 00100 assert (STy && "Invalid sret parameter element type"); 00101 00102 // Check if it is ok to perform this promotion. 00103 if (isSafeToUpdateAllCallers(F) == false) { 00104 DOUT << "SretPromotion: Not all callers can be updated\n"; 00105 NumRejectedSRETUses++; 00106 return false; 00107 } 00108 00109 DOUT << "SretPromotion: sret argument will be promoted\n"; 00110 NumSRET++; 00111 // [1] Replace use of sret parameter 00112 AllocaInst *TheAlloca = new AllocaInst (STy, NULL, "mrv", 00113 F->getEntryBlock().begin()); 00114 Value *NFirstArg = F->arg_begin(); 00115 NFirstArg->replaceAllUsesWith(TheAlloca); 00116 00117 // [2] Find and replace ret instructions 00118 for (Function::iterator FI = F->begin(), FE = F->end(); FI != FE; ++FI) 00119 for(BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ) { 00120 Instruction *I = BI; 00121 ++BI; 00122 if (isa<ReturnInst>(I)) { 00123 Value *NV = new LoadInst(TheAlloca, "mrv.ld", I); 00124 ReturnInst *NR = ReturnInst::Create(NV, I); 00125 I->replaceAllUsesWith(NR); 00126 I->eraseFromParent(); 00127 } 00128 } 00129 00130 // [3] Create the new function body and insert it into the module. 00131 Function *NF = cloneFunctionBody(F, STy); 00132 00133 // [4] Update all call sites to use new function 00134 updateCallSites(F, NF); 00135 00136 F->eraseFromParent(); 00137 getAnalysis<CallGraph>().changeFunction(F, NF); 00138 return true; 00139 } 00140 00141 // Check if it is ok to perform this promotion. 00142 bool SRETPromotion::isSafeToUpdateAllCallers(Function *F) { 00143 00144 if (F->use_empty()) 00145 // No users. OK to modify signature. 00146 return true; 00147 00148 for (Value::use_iterator FnUseI = F->use_begin(), FnUseE = F->use_end(); 00149 FnUseI != FnUseE; ++FnUseI) { 00150 // The function is passed in as an argument to (possibly) another function, 00151 // we can't change it! 00152 CallSite CS = CallSite::get(*FnUseI); 00153 Instruction *Call = CS.getInstruction(); 00154 // The function is used by something else than a call or invoke instruction, 00155 // we can't change it! 00156 if (!Call || !CS.isCallee(FnUseI)) 00157 return false; 00158 CallSite::arg_iterator AI = CS.arg_begin(); 00159 Value *FirstArg = *AI; 00160 00161 if (!isa<AllocaInst>(FirstArg)) 00162 return false; 00163 00164 // Check FirstArg's users. 00165 for (Value::use_iterator ArgI = FirstArg->use_begin(), 00166 ArgE = FirstArg->use_end(); ArgI != ArgE; ++ArgI) { 00167 00168 // If FirstArg user is a CallInst that does not correspond to current 00169 // call site then this function F is not suitable for sret promotion. 00170 if (CallInst *CI = dyn_cast<CallInst>(ArgI)) { 00171 if (CI != Call) 00172 return false; 00173 } 00174 // If FirstArg user is a GEP whose all users are not LoadInst then 00175 // this function F is not suitable for sret promotion. 00176 else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(ArgI)) { 00177 // TODO : Use dom info and insert PHINodes to collect get results 00178 // from multiple call sites for this GEP. 00179 if (GEP->getParent() != Call->getParent()) 00180 return false; 00181 for (Value::use_iterator GEPI = GEP->use_begin(), GEPE = GEP->use_end(); 00182 GEPI != GEPE; ++GEPI) 00183 if (!isa<LoadInst>(GEPI)) 00184 return false; 00185 } 00186 // Any other FirstArg users make this function unsuitable for sret 00187 // promotion. 00188 else 00189 return false; 00190 } 00191 } 00192 00193 return true; 00194 } 00195 00196 /// cloneFunctionBody - Create a new function based on F and 00197 /// insert it into module. Remove first argument. Use STy as 00198 /// the return type for new function. 00199 Function *SRETPromotion::cloneFunctionBody(Function *F, 00200 const StructType *STy) { 00201 00202 const FunctionType *FTy = F->getFunctionType(); 00203 std::vector<const Type*> Params; 00204 00205 // Attributes - Keep track of the parameter attributes for the arguments. 00206 SmallVector<AttributeWithIndex, 8> AttributesVec; 00207 const AttrListPtr &PAL = F->getAttributes(); 00208 00209 // Add any return attributes. 00210 if (Attributes attrs = PAL.getRetAttributes()) 00211 AttributesVec.push_back(AttributeWithIndex::get(0, attrs)); 00212 00213 // Skip first argument. 00214 Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); 00215 ++I; 00216 // 0th parameter attribute is reserved for return type. 00217 // 1th parameter attribute is for first 1st sret argument. 00218 unsigned ParamIndex = 2; 00219 while (I != E) { 00220 Params.push_back(I->getType()); 00221 if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) 00222 AttributesVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); 00223 ++I; 00224 ++ParamIndex; 00225 } 00226 00227 // Add any fn attributes. 00228 if (Attributes attrs = PAL.getFnAttributes()) 00229 AttributesVec.push_back(AttributeWithIndex::get(~0, attrs)); 00230 00231 00232 FunctionType *NFTy = FunctionType::get(STy, Params, FTy->isVarArg()); 00233 Function *NF = Function::Create(NFTy, F->getLinkage()); 00234 NF->takeName(F); 00235 NF->copyAttributesFrom(F); 00236 NF->setAttributes(AttrListPtr::get(AttributesVec.begin(), AttributesVec.end())); 00237 F->getParent()->getFunctionList().insert(F, NF); 00238 NF->getBasicBlockList().splice(NF->begin(), F->getBasicBlockList()); 00239 00240 // Replace arguments 00241 I = F->arg_begin(); 00242 E = F->arg_end(); 00243 Function::arg_iterator NI = NF->arg_begin(); 00244 ++I; 00245 while (I != E) { 00246 I->replaceAllUsesWith(NI); 00247 NI->takeName(I); 00248 ++I; 00249 ++NI; 00250 } 00251 00252 return NF; 00253 } 00254 00255 /// updateCallSites - Update all sites that call F to use NF. 00256 void SRETPromotion::updateCallSites(Function *F, Function *NF) { 00257 CallGraph &CG = getAnalysis<CallGraph>(); 00258 SmallVector<Value*, 16> Args; 00259 00260 // Attributes - Keep track of the parameter attributes for the arguments. 00261 SmallVector<AttributeWithIndex, 8> ArgAttrsVec; 00262 00263 while (!F->use_empty()) { 00264 CallSite CS = CallSite::get(*F->use_begin()); 00265 Instruction *Call = CS.getInstruction(); 00266 00267 const AttrListPtr &PAL = F->getAttributes(); 00268 // Add any return attributes. 00269 if (Attributes attrs = PAL.getRetAttributes()) 00270 ArgAttrsVec.push_back(AttributeWithIndex::get(0, attrs)); 00271 00272 // Copy arguments, however skip first one. 00273 CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); 00274 Value *FirstCArg = *AI; 00275 ++AI; 00276 // 0th parameter attribute is reserved for return type. 00277 // 1th parameter attribute is for first 1st sret argument. 00278 unsigned ParamIndex = 2; 00279 while (AI != AE) { 00280 Args.push_back(*AI); 00281 if (Attributes Attrs = PAL.getParamAttributes(ParamIndex)) 00282 ArgAttrsVec.push_back(AttributeWithIndex::get(ParamIndex - 1, Attrs)); 00283 ++ParamIndex; 00284 ++AI; 00285 } 00286 00287 // Add any function attributes. 00288 if (Attributes attrs = PAL.getFnAttributes()) 00289 ArgAttrsVec.push_back(AttributeWithIndex::get(~0, attrs)); 00290 00291 AttrListPtr NewPAL = AttrListPtr::get(ArgAttrsVec.begin(), ArgAttrsVec.end()); 00292 00293 // Build new call instruction. 00294 Instruction *New; 00295 if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) { 00296 New = InvokeInst::Create(NF, II->getNormalDest(), II->getUnwindDest(), 00297 Args.begin(), Args.end(), "", Call); 00298 cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv()); 00299 cast<InvokeInst>(New)->setAttributes(NewPAL); 00300 } else { 00301 New = CallInst::Create(NF, Args.begin(), Args.end(), "", Call); 00302 cast<CallInst>(New)->setCallingConv(CS.getCallingConv()); 00303 cast<CallInst>(New)->setAttributes(NewPAL); 00304 if (cast<CallInst>(Call)->isTailCall()) 00305 cast<CallInst>(New)->setTailCall(); 00306 } 00307 Args.clear(); 00308 ArgAttrsVec.clear(); 00309 New->takeName(Call); 00310 00311 // Update the callgraph to know that the callsite has been transformed. 00312 CG[Call->getParent()->getParent()]->replaceCallSite(Call, New); 00313 00314 // Update all users of sret parameter to extract value using extractvalue. 00315 for (Value::use_iterator UI = FirstCArg->use_begin(), 00316 UE = FirstCArg->use_end(); UI != UE; ) { 00317 User *U2 = *UI++; 00318 CallInst *C2 = dyn_cast<CallInst>(U2); 00319 if (C2 && (C2 == Call)) 00320 continue; 00321 else if (GetElementPtrInst *UGEP = dyn_cast<GetElementPtrInst>(U2)) { 00322 ConstantInt *Idx = dyn_cast<ConstantInt>(UGEP->getOperand(2)); 00323 assert (Idx && "Unexpected getelementptr index!"); 00324 Value *GR = ExtractValueInst::Create(New, Idx->getZExtValue(), 00325 "evi", UGEP); 00326 while(!UGEP->use_empty()) { 00327 // isSafeToUpdateAllCallers has checked that all GEP uses are 00328 // LoadInsts 00329 LoadInst *L = cast<LoadInst>(*UGEP->use_begin()); 00330 L->replaceAllUsesWith(GR); 00331 L->eraseFromParent(); 00332 } 00333 UGEP->eraseFromParent(); 00334 } 00335 else assert( 0 && "Unexpected sret parameter use"); 00336 } 00337 Call->eraseFromParent(); 00338 } 00339 } 00340 00341 /// nestedStructType - Return true if STy includes any 00342 /// other aggregate types 00343 bool SRETPromotion::nestedStructType(const StructType *STy) { 00344 unsigned Num = STy->getNumElements(); 00345 for (unsigned i = 0; i < Num; i++) { 00346 const Type *Ty = STy->getElementType(i); 00347 if (!Ty->isSingleValueType() && Ty != Type::VoidTy) 00348 return true; 00349 } 00350 return false; 00351 }