static bool fold(std::vector<Function *> &FnVec, unsigned i, unsigned j) { if (FnVec[i]->mayBeOverridden() && !FnVec[j]->mayBeOverridden()) std::swap(FnVec[i], FnVec[j]); Function *F = FnVec[i]; Function *G = FnVec[j]; if (!F->mayBeOverridden()) { if (G->hasLocalLinkage()) { F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); G->replaceAllUsesWith(F); G->eraseFromParent(); ++NumFunctionsMerged; return true; } if (G->hasExternalLinkage() || G->hasWeakLinkage()) { GlobalAlias *GA = new GlobalAlias(G->getType(), G->getLinkage(), "", F, G->getParent()); F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); GA->takeName(G); GA->setVisibility(G->getVisibility()); G->replaceAllUsesWith(GA); G->eraseFromParent(); ++NumFunctionsMerged; return true; } } if (F->hasWeakLinkage() && G->hasWeakLinkage()) { GlobalAlias *GA_F = new GlobalAlias(F->getType(), F->getLinkage(), "", 0, F->getParent()); GA_F->takeName(F); GA_F->setVisibility(F->getVisibility()); F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); F->replaceAllUsesWith(GA_F); F->setName("folded." + GA_F->getName()); F->setLinkage(GlobalValue::ExternalLinkage); GA_F->setAliasee(F); GlobalAlias *GA_G = new GlobalAlias(G->getType(), G->getLinkage(), "", F, G->getParent()); GA_G->takeName(G); GA_G->setVisibility(G->getVisibility()); G->replaceAllUsesWith(GA_G); G->eraseFromParent(); ++NumFunctionsMerged; return true; } DOUT << "Failed on " << F->getName() << " and " << G->getName() << "\n"; ++NumMergeFails; return false; }
static void AliasGToF(Function *F, Function *G) { if (!G->hasExternalLinkage() && !G->hasLocalLinkage() && !G->hasWeakLinkage()) return ThunkGToF(F, G); GlobalAlias *GA = new GlobalAlias( G->getType(), G->getLinkage(), "", ConstantExpr::getBitCast(F, G->getType()), G->getParent()); F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); GA->takeName(G); GA->setVisibility(G->getVisibility()); G->replaceAllUsesWith(GA); G->eraseFromParent(); }
// Replace G with an alias to F and delete G. void MergeFunctions::writeAlias(Function *F, Function *G) { Constant *BitcastF = ConstantExpr::getBitCast(F, G->getType()); GlobalAlias *GA = new GlobalAlias(G->getType(), G->getLinkage(), "", BitcastF, G->getParent()); F->setAlignment(std::max(F->getAlignment(), G->getAlignment())); GA->takeName(G); GA->setVisibility(G->getVisibility()); removeUsers(G); G->replaceAllUsesWith(GA); G->eraseFromParent(); DEBUG(dbgs() << "writeAlias: " << GA->getName() << '\n'); ++NumAliasesWritten; }
/// Given a disjoint set of bitsets and globals, layout the globals, build the /// bit sets and lower the llvm.bitset.test calls. void LowerBitSets::buildBitSetsFromGlobalVariables( ArrayRef<Metadata *> BitSets, ArrayRef<GlobalVariable *> Globals) { // Build a new global with the combined contents of the referenced globals. // This global is a struct whose even-indexed elements contain the original // contents of the referenced globals and whose odd-indexed elements contain // any padding required to align the next element to the next power of 2. std::vector<Constant *> GlobalInits; const DataLayout &DL = M->getDataLayout(); for (GlobalVariable *G : Globals) { GlobalInits.push_back(G->getInitializer()); uint64_t InitSize = DL.getTypeAllocSize(G->getValueType()); // Compute the amount of padding required. uint64_t Padding = NextPowerOf2(InitSize - 1) - InitSize; // Cap at 128 was found experimentally to have a good data/instruction // overhead tradeoff. if (Padding > 128) Padding = RoundUpToAlignment(InitSize, 128) - InitSize; GlobalInits.push_back( ConstantAggregateZero::get(ArrayType::get(Int8Ty, Padding))); } if (!GlobalInits.empty()) GlobalInits.pop_back(); Constant *NewInit = ConstantStruct::getAnon(M->getContext(), GlobalInits); auto *CombinedGlobal = new GlobalVariable(*M, NewInit->getType(), /*isConstant=*/true, GlobalValue::PrivateLinkage, NewInit); StructType *NewTy = cast<StructType>(NewInit->getType()); const StructLayout *CombinedGlobalLayout = DL.getStructLayout(NewTy); // Compute the offsets of the original globals within the new global. DenseMap<GlobalObject *, uint64_t> GlobalLayout; for (unsigned I = 0; I != Globals.size(); ++I) // Multiply by 2 to account for padding elements. GlobalLayout[Globals[I]] = CombinedGlobalLayout->getElementOffset(I * 2); lowerBitSetCalls(BitSets, CombinedGlobal, GlobalLayout); // Build aliases pointing to offsets into the combined global for each // global from which we built the combined global, and replace references // to the original globals with references to the aliases. for (unsigned I = 0; I != Globals.size(); ++I) { // Multiply by 2 to account for padding elements. Constant *CombinedGlobalIdxs[] = {ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, I * 2)}; Constant *CombinedGlobalElemPtr = ConstantExpr::getGetElementPtr( NewInit->getType(), CombinedGlobal, CombinedGlobalIdxs); if (LinkerSubsectionsViaSymbols) { Globals[I]->replaceAllUsesWith(CombinedGlobalElemPtr); } else { assert(Globals[I]->getType()->getAddressSpace() == 0); GlobalAlias *GAlias = GlobalAlias::create(NewTy->getElementType(I * 2), 0, Globals[I]->getLinkage(), "", CombinedGlobalElemPtr, M); GAlias->setVisibility(Globals[I]->getVisibility()); GAlias->takeName(Globals[I]); Globals[I]->replaceAllUsesWith(GAlias); } Globals[I]->eraseFromParent(); } }
// emit_alias_to_llvm - Given decl and target emit alias to target. void emit_alias_to_llvm(tree decl, tree target, tree target_decl) { if (errorcount || sorrycount) return; timevar_push(TV_LLVM_GLOBALS); // Get or create LLVM global for our alias. GlobalValue *V = cast<GlobalValue>(DECL_LLVM(decl)); GlobalValue *Aliasee = NULL; if (target_decl) Aliasee = cast<GlobalValue>(DECL_LLVM(target_decl)); else { // This is something insane. Probably only LTHUNKs can be here // Try to grab decl from IDENTIFIER_NODE // Query SymTab for aliasee const char* AliaseeName = IDENTIFIER_POINTER(target); Aliasee = dyn_cast_or_null<GlobalValue>(TheModule-> getValueSymbolTable().lookup(AliaseeName)); // Last resort. Query for name set via __asm__ if (!Aliasee) { std::string starred = std::string("\001") + AliaseeName; Aliasee = dyn_cast_or_null<GlobalValue>(TheModule-> getValueSymbolTable().lookup(starred)); } if (!Aliasee) { error ("%J%qD aliased to undefined symbol %qE", decl, decl, target); timevar_pop(TV_LLVM_GLOBALS); return; } } GlobalValue::LinkageTypes Linkage; // Check for external weak linkage if (DECL_EXTERNAL(decl) && DECL_WEAK(decl)) Linkage = GlobalValue::WeakLinkage; else if (!TREE_PUBLIC(decl)) Linkage = GlobalValue::InternalLinkage; else Linkage = GlobalValue::ExternalLinkage; GlobalAlias* GA = new GlobalAlias(Aliasee->getType(), Linkage, "", Aliasee, TheModule); // Handle visibility style if (TREE_PUBLIC(decl)) { if (DECL_VISIBILITY(decl) == VISIBILITY_HIDDEN) GA->setVisibility(GlobalValue::HiddenVisibility); else if (DECL_VISIBILITY(decl) == VISIBILITY_PROTECTED) GA->setVisibility(GlobalValue::ProtectedVisibility); } if (V->getType() == GA->getType()) V->replaceAllUsesWith(GA); else if (!V->use_empty()) { error ("%J Alias %qD used with invalid type!", decl, decl); timevar_pop(TV_LLVM_GLOBALS); return; } changeLLVMValue(V, GA); GA->takeName(V); if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) GV->eraseFromParent(); else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) GA->eraseFromParent(); else if (Function *F = dyn_cast<Function>(V)) F->eraseFromParent(); else assert(0 && "Unsuported global value"); TREE_ASM_WRITTEN(decl) = 1; timevar_pop(TV_LLVM_GLOBALS); return; }