LLVM API Documentation
00001 //===-- GlobalMerge.cpp - Internal globals merging -----------------------===// 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 // This pass merges globals with internal linkage into one. This way all the 00010 // globals which were merged into a biggest one can be addressed using offsets 00011 // from the same base pointer (no need for separate base pointer for each of the 00012 // global). Such a transformation can significantly reduce the register pressure 00013 // when many globals are involved. 00014 // 00015 // For example, consider the code which touches several global variables at 00016 // once: 00017 // 00018 // static int foo[N], bar[N], baz[N]; 00019 // 00020 // for (i = 0; i < N; ++i) { 00021 // foo[i] = bar[i] * baz[i]; 00022 // } 00023 // 00024 // On ARM the addresses of 3 arrays should be kept in the registers, thus 00025 // this code has quite large register pressure (loop body): 00026 // 00027 // ldr r1, [r5], #4 00028 // ldr r2, [r6], #4 00029 // mul r1, r2, r1 00030 // str r1, [r0], #4 00031 // 00032 // Pass converts the code to something like: 00033 // 00034 // static struct { 00035 // int foo[N]; 00036 // int bar[N]; 00037 // int baz[N]; 00038 // } merged; 00039 // 00040 // for (i = 0; i < N; ++i) { 00041 // merged.foo[i] = merged.bar[i] * merged.baz[i]; 00042 // } 00043 // 00044 // and in ARM code this becomes: 00045 // 00046 // ldr r0, [r5, #40] 00047 // ldr r1, [r5, #80] 00048 // mul r0, r1, r0 00049 // str r0, [r5], #4 00050 // 00051 // note that we saved 2 registers here almostly "for free". 00052 // ===---------------------------------------------------------------------===// 00053 00054 #include "llvm/Transforms/Scalar.h" 00055 #include "llvm/ADT/SmallPtrSet.h" 00056 #include "llvm/ADT/Statistic.h" 00057 #include "llvm/IR/Attributes.h" 00058 #include "llvm/IR/Constants.h" 00059 #include "llvm/IR/DataLayout.h" 00060 #include "llvm/IR/DerivedTypes.h" 00061 #include "llvm/IR/Function.h" 00062 #include "llvm/IR/GlobalVariable.h" 00063 #include "llvm/IR/Instructions.h" 00064 #include "llvm/IR/Intrinsics.h" 00065 #include "llvm/IR/Module.h" 00066 #include "llvm/Pass.h" 00067 #include "llvm/CodeGen/Passes.h" 00068 #include "llvm/Support/CommandLine.h" 00069 #include "llvm/Target/TargetLowering.h" 00070 #include "llvm/Target/TargetLoweringObjectFile.h" 00071 #include "llvm/Target/TargetSubtargetInfo.h" 00072 using namespace llvm; 00073 00074 #define DEBUG_TYPE "global-merge" 00075 00076 static cl::opt<bool> 00077 EnableGlobalMerge("enable-global-merge", cl::Hidden, 00078 cl::desc("Enable global merge pass"), 00079 cl::init(true)); 00080 00081 static cl::opt<bool> 00082 EnableGlobalMergeOnConst("global-merge-on-const", cl::Hidden, 00083 cl::desc("Enable global merge pass on constants"), 00084 cl::init(false)); 00085 00086 // FIXME: this could be a transitional option, and we probably need to remove 00087 // it if only we are sure this optimization could always benefit all targets. 00088 static cl::opt<bool> 00089 EnableGlobalMergeOnExternal("global-merge-on-external", cl::Hidden, 00090 cl::desc("Enable global merge pass on external linkage"), 00091 cl::init(false)); 00092 00093 STATISTIC(NumMerged , "Number of globals merged"); 00094 namespace { 00095 class GlobalMerge : public FunctionPass { 00096 const TargetMachine *TM; 00097 00098 bool doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 00099 Module &M, bool isConst, unsigned AddrSpace) const; 00100 00101 /// \brief Check if the given variable has been identified as must keep 00102 /// \pre setMustKeepGlobalVariables must have been called on the Module that 00103 /// contains GV 00104 bool isMustKeepGlobalVariable(const GlobalVariable *GV) const { 00105 return MustKeepGlobalVariables.count(GV); 00106 } 00107 00108 /// Collect every variables marked as "used" or used in a landing pad 00109 /// instruction for this Module. 00110 void setMustKeepGlobalVariables(Module &M); 00111 00112 /// Collect every variables marked as "used" 00113 void collectUsedGlobalVariables(Module &M); 00114 00115 /// Keep track of the GlobalVariable that must not be merged away 00116 SmallPtrSet<const GlobalVariable *, 16> MustKeepGlobalVariables; 00117 00118 public: 00119 static char ID; // Pass identification, replacement for typeid. 00120 explicit GlobalMerge(const TargetMachine *TM = nullptr) 00121 : FunctionPass(ID), TM(TM) { 00122 initializeGlobalMergePass(*PassRegistry::getPassRegistry()); 00123 } 00124 00125 bool doInitialization(Module &M) override; 00126 bool runOnFunction(Function &F) override; 00127 bool doFinalization(Module &M) override; 00128 00129 const char *getPassName() const override { 00130 return "Merge internal globals"; 00131 } 00132 00133 void getAnalysisUsage(AnalysisUsage &AU) const override { 00134 AU.setPreservesCFG(); 00135 FunctionPass::getAnalysisUsage(AU); 00136 } 00137 }; 00138 } // end anonymous namespace 00139 00140 char GlobalMerge::ID = 0; 00141 INITIALIZE_TM_PASS(GlobalMerge, "global-merge", "Merge global variables", 00142 false, false) 00143 00144 bool GlobalMerge::doMerge(SmallVectorImpl<GlobalVariable*> &Globals, 00145 Module &M, bool isConst, unsigned AddrSpace) const { 00146 const TargetLowering *TLI = TM->getSubtargetImpl()->getTargetLowering(); 00147 const DataLayout *DL = TLI->getDataLayout(); 00148 00149 // FIXME: Infer the maximum possible offset depending on the actual users 00150 // (these max offsets are different for the users inside Thumb or ARM 00151 // functions) 00152 unsigned MaxOffset = TLI->getMaximalGlobalOffset(); 00153 00154 // FIXME: Find better heuristics 00155 std::stable_sort(Globals.begin(), Globals.end(), 00156 [DL](const GlobalVariable *GV1, const GlobalVariable *GV2) { 00157 Type *Ty1 = cast<PointerType>(GV1->getType())->getElementType(); 00158 Type *Ty2 = cast<PointerType>(GV2->getType())->getElementType(); 00159 00160 return (DL->getTypeAllocSize(Ty1) < DL->getTypeAllocSize(Ty2)); 00161 }); 00162 00163 Type *Int32Ty = Type::getInt32Ty(M.getContext()); 00164 00165 assert(Globals.size() > 1); 00166 00167 // FIXME: This simple solution merges globals all together as maximum as 00168 // possible. However, with this solution it would be hard to remove dead 00169 // global symbols at link-time. An alternative solution could be checking 00170 // global symbols references function by function, and make the symbols 00171 // being referred in the same function merged and we would probably need 00172 // to introduce heuristic algorithm to solve the merge conflict from 00173 // different functions. 00174 for (size_t i = 0, e = Globals.size(); i != e; ) { 00175 size_t j = 0; 00176 uint64_t MergedSize = 0; 00177 std::vector<Type*> Tys; 00178 std::vector<Constant*> Inits; 00179 00180 bool HasExternal = false; 00181 GlobalVariable *TheFirstExternal = 0; 00182 for (j = i; j != e; ++j) { 00183 Type *Ty = Globals[j]->getType()->getElementType(); 00184 MergedSize += DL->getTypeAllocSize(Ty); 00185 if (MergedSize > MaxOffset) { 00186 break; 00187 } 00188 Tys.push_back(Ty); 00189 Inits.push_back(Globals[j]->getInitializer()); 00190 00191 if (Globals[j]->hasExternalLinkage() && !HasExternal) { 00192 HasExternal = true; 00193 TheFirstExternal = Globals[j]; 00194 } 00195 } 00196 00197 // If merged variables doesn't have external linkage, we needn't to expose 00198 // the symbol after merging. 00199 GlobalValue::LinkageTypes Linkage = HasExternal 00200 ? GlobalValue::ExternalLinkage 00201 : GlobalValue::InternalLinkage; 00202 00203 StructType *MergedTy = StructType::get(M.getContext(), Tys); 00204 Constant *MergedInit = ConstantStruct::get(MergedTy, Inits); 00205 00206 // If merged variables have external linkage, we use symbol name of the 00207 // first variable merged as the suffix of global symbol name. This would 00208 // be able to avoid the link-time naming conflict for globalm symbols. 00209 GlobalVariable *MergedGV = new GlobalVariable( 00210 M, MergedTy, isConst, Linkage, MergedInit, 00211 HasExternal ? "_MergedGlobals_" + TheFirstExternal->getName() 00212 : "_MergedGlobals", 00213 nullptr, GlobalVariable::NotThreadLocal, AddrSpace); 00214 00215 for (size_t k = i; k < j; ++k) { 00216 GlobalValue::LinkageTypes Linkage = Globals[k]->getLinkage(); 00217 std::string Name = Globals[k]->getName(); 00218 00219 Constant *Idx[2] = { 00220 ConstantInt::get(Int32Ty, 0), 00221 ConstantInt::get(Int32Ty, k-i) 00222 }; 00223 Constant *GEP = ConstantExpr::getInBoundsGetElementPtr(MergedGV, Idx); 00224 Globals[k]->replaceAllUsesWith(GEP); 00225 Globals[k]->eraseFromParent(); 00226 00227 if (Linkage != GlobalValue::InternalLinkage) { 00228 // Generate a new alias... 00229 auto *PTy = cast<PointerType>(GEP->getType()); 00230 GlobalAlias::create(PTy->getElementType(), PTy->getAddressSpace(), 00231 Linkage, Name, GEP, &M); 00232 } 00233 00234 NumMerged++; 00235 } 00236 i = j; 00237 } 00238 00239 return true; 00240 } 00241 00242 void GlobalMerge::collectUsedGlobalVariables(Module &M) { 00243 // Extract global variables from llvm.used array 00244 const GlobalVariable *GV = M.getGlobalVariable("llvm.used"); 00245 if (!GV || !GV->hasInitializer()) return; 00246 00247 // Should be an array of 'i8*'. 00248 const ConstantArray *InitList = cast<ConstantArray>(GV->getInitializer()); 00249 00250 for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) 00251 if (const GlobalVariable *G = 00252 dyn_cast<GlobalVariable>(InitList->getOperand(i)->stripPointerCasts())) 00253 MustKeepGlobalVariables.insert(G); 00254 } 00255 00256 void GlobalMerge::setMustKeepGlobalVariables(Module &M) { 00257 collectUsedGlobalVariables(M); 00258 00259 for (Module::iterator IFn = M.begin(), IEndFn = M.end(); IFn != IEndFn; 00260 ++IFn) { 00261 for (Function::iterator IBB = IFn->begin(), IEndBB = IFn->end(); 00262 IBB != IEndBB; ++IBB) { 00263 // Follow the invoke link to find the landing pad instruction 00264 const InvokeInst *II = dyn_cast<InvokeInst>(IBB->getTerminator()); 00265 if (!II) continue; 00266 00267 const LandingPadInst *LPInst = II->getUnwindDest()->getLandingPadInst(); 00268 // Look for globals in the clauses of the landing pad instruction 00269 for (unsigned Idx = 0, NumClauses = LPInst->getNumClauses(); 00270 Idx != NumClauses; ++Idx) 00271 if (const GlobalVariable *GV = 00272 dyn_cast<GlobalVariable>(LPInst->getClause(Idx) 00273 ->stripPointerCasts())) 00274 MustKeepGlobalVariables.insert(GV); 00275 } 00276 } 00277 } 00278 00279 bool GlobalMerge::doInitialization(Module &M) { 00280 if (!EnableGlobalMerge) 00281 return false; 00282 00283 DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, 00284 BSSGlobals; 00285 const TargetLowering *TLI = TM->getSubtargetImpl()->getTargetLowering(); 00286 const DataLayout *DL = TLI->getDataLayout(); 00287 unsigned MaxOffset = TLI->getMaximalGlobalOffset(); 00288 bool Changed = false; 00289 setMustKeepGlobalVariables(M); 00290 00291 // Grab all non-const globals. 00292 for (Module::global_iterator I = M.global_begin(), 00293 E = M.global_end(); I != E; ++I) { 00294 // Merge is safe for "normal" internal or external globals only 00295 if (I->isDeclaration() || I->isThreadLocal() || I->hasSection()) 00296 continue; 00297 00298 if (!(EnableGlobalMergeOnExternal && I->hasExternalLinkage()) && 00299 !I->hasInternalLinkage()) 00300 continue; 00301 00302 PointerType *PT = dyn_cast<PointerType>(I->getType()); 00303 assert(PT && "Global variable is not a pointer!"); 00304 00305 unsigned AddressSpace = PT->getAddressSpace(); 00306 00307 // Ignore fancy-aligned globals for now. 00308 unsigned Alignment = DL->getPreferredAlignment(I); 00309 Type *Ty = I->getType()->getElementType(); 00310 if (Alignment > DL->getABITypeAlignment(Ty)) 00311 continue; 00312 00313 // Ignore all 'special' globals. 00314 if (I->getName().startswith("llvm.") || 00315 I->getName().startswith(".llvm.")) 00316 continue; 00317 00318 // Ignore all "required" globals: 00319 if (isMustKeepGlobalVariable(I)) 00320 continue; 00321 00322 if (DL->getTypeAllocSize(Ty) < MaxOffset) { 00323 if (TargetLoweringObjectFile::getKindForGlobal(I, *TM).isBSSLocal()) 00324 BSSGlobals[AddressSpace].push_back(I); 00325 else if (I->isConstant()) 00326 ConstGlobals[AddressSpace].push_back(I); 00327 else 00328 Globals[AddressSpace].push_back(I); 00329 } 00330 } 00331 00332 for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 00333 I = Globals.begin(), E = Globals.end(); I != E; ++I) 00334 if (I->second.size() > 1) 00335 Changed |= doMerge(I->second, M, false, I->first); 00336 00337 for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 00338 I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) 00339 if (I->second.size() > 1) 00340 Changed |= doMerge(I->second, M, false, I->first); 00341 00342 if (EnableGlobalMergeOnConst) 00343 for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator 00344 I = ConstGlobals.begin(), E = ConstGlobals.end(); I != E; ++I) 00345 if (I->second.size() > 1) 00346 Changed |= doMerge(I->second, M, true, I->first); 00347 00348 return Changed; 00349 } 00350 00351 bool GlobalMerge::runOnFunction(Function &F) { 00352 return false; 00353 } 00354 00355 bool GlobalMerge::doFinalization(Module &M) { 00356 MustKeepGlobalVariables.clear(); 00357 return false; 00358 } 00359 00360 Pass *llvm::createGlobalMergePass(const TargetMachine *TM) { 00361 return new GlobalMerge(TM); 00362 }