bool GlobalMerge::doInitialization(Module &M) { DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, BSSGlobals; const DataLayout *TD = TLI->getDataLayout(); unsigned MaxOffset = TLI->getMaximalGlobalOffset(); bool Changed = false; // Grab all non-const globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { // Merge is safe for "normal" internal globals only if (!I->hasLocalLinkage() || I->isThreadLocal() || I->hasSection()) continue; PointerType *PT = dyn_cast<PointerType>(I->getType()); assert(PT && "Global variable is not a pointer!"); unsigned AddressSpace = PT->getAddressSpace(); // Ignore fancy-aligned globals for now. unsigned Alignment = TD->getPreferredAlignment(I); Type *Ty = I->getType()->getElementType(); if (Alignment > TD->getABITypeAlignment(Ty)) continue; // Ignore all 'special' globals. if (I->getName().startswith("llvm.") || I->getName().startswith(".llvm.")) continue; if (TD->getTypeAllocSize(Ty) < MaxOffset) { if (TargetLoweringObjectFile::getKindForGlobal(I, TLI->getTargetMachine()) .isBSSLocal()) BSSGlobals[AddressSpace].push_back(I); else if (I->isConstant()) ConstGlobals[AddressSpace].push_back(I); else Globals[AddressSpace].push_back(I); } } for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = Globals.begin(), E = Globals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); // FIXME: This currently breaks the EH processing due to way how the // typeinfo detection works. We might want to detect the TIs and ignore // them in the future. // if (ConstGlobals.size() > 1) // Changed |= doMerge(ConstGlobals, M, true); return Changed; }
bool ARMGlobalMerge::doInitialization(Module &M) { SmallVector<GlobalVariable*, 16> Globals, ConstGlobals, BSSGlobals; const TargetData *TD = TLI->getTargetData(); unsigned MaxOffset = TLI->getMaximalGlobalOffset(); bool Changed = false; // Disable this pass on darwin. The debugger is not yet ready to extract // variable's info from a merged global. if (TLI->getTargetMachine().getSubtarget<ARMSubtarget>().isTargetDarwin()) return false; // Grab all non-const globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { // Merge is safe for "normal" internal globals only if (!I->hasLocalLinkage() || I->isThreadLocal() || I->hasSection()) continue; // Ignore fancy-aligned globals for now. if (I->getAlignment() != 0) continue; // Ignore all 'special' globals. if (I->getName().startswith("llvm.") || I->getName().startswith(".llvm.")) continue; if (TD->getTypeAllocSize(I->getType()->getElementType()) < MaxOffset) { const TargetLoweringObjectFile &TLOF = TLI->getObjFileLowering(); if (TLOF.getKindForGlobal(I, TLI->getTargetMachine()).isBSSLocal()) BSSGlobals.push_back(I); else if (I->isConstant()) ConstGlobals.push_back(I); else Globals.push_back(I); } } if (Globals.size() > 1) Changed |= doMerge(Globals, M, false); if (BSSGlobals.size() > 1) Changed |= doMerge(BSSGlobals, M, false); // FIXME: This currently breaks the EH processing due to way how the // typeinfo detection works. We might want to detect the TIs and ignore // them in the future. // if (ConstGlobals.size() > 1) // Changed |= doMerge(ConstGlobals, M, true); return Changed; }
bool ARMGlobalMerge::doInitialization(Module &M) { SmallVector<GlobalVariable*, 16> Globals, ConstGlobals; const TargetData *TD = TLI->getTargetData(); unsigned MaxOffset = TLI->getMaximalGlobalOffset(); bool Changed = false; // Grab all non-const globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { // Merge is safe for "normal" internal globals only if (!I->hasLocalLinkage() || I->isThreadLocal() || I->hasSection()) continue; // Ignore fancy-aligned globals for now. if (I->getAlignment() != 0) continue; // Ignore all 'special' globals. if (I->getName().startswith("llvm.") || I->getName().startswith(".llvm.")) continue; if (TD->getTypeAllocSize(I->getType()) < MaxOffset) { if (I->isConstant()) ConstGlobals.push_back(I); else Globals.push_back(I); } } if (Globals.size() > 1) Changed |= doMerge(Globals, M, false); // FIXME: This currently breaks the EH processing due to way how the // typeinfo detection works. We might want to detect the TIs and ignore // them in the future. // if (ConstGlobals.size() > 1) // Changed |= doMerge(ConstGlobals, M, true); return Changed; }
bool GlobalMerge::doInitialization(Module &M) { if (!EnableGlobalMerge) return false; auto &DL = M.getDataLayout(); DenseMap<unsigned, SmallVector<GlobalVariable*, 16> > Globals, ConstGlobals, BSSGlobals; bool Changed = false; setMustKeepGlobalVariables(M); // Grab all non-const globals. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { // Merge is safe for "normal" internal or external globals only if (I->isDeclaration() || I->isThreadLocal() || I->hasSection()) continue; if (!(EnableGlobalMergeOnExternal && I->hasExternalLinkage()) && !I->hasInternalLinkage()) continue; PointerType *PT = dyn_cast<PointerType>(I->getType()); assert(PT && "Global variable is not a pointer!"); unsigned AddressSpace = PT->getAddressSpace(); // Ignore fancy-aligned globals for now. unsigned Alignment = DL.getPreferredAlignment(I); Type *Ty = I->getType()->getElementType(); if (Alignment > DL.getABITypeAlignment(Ty)) continue; // Ignore all 'special' globals. if (I->getName().startswith("llvm.") || I->getName().startswith(".llvm.")) continue; // Ignore all "required" globals: if (isMustKeepGlobalVariable(I)) continue; if (DL.getTypeAllocSize(Ty) < MaxOffset) { if (TargetLoweringObjectFile::getKindForGlobal(I, *TM).isBSSLocal()) BSSGlobals[AddressSpace].push_back(I); else if (I->isConstant()) ConstGlobals[AddressSpace].push_back(I); else Globals[AddressSpace].push_back(I); } } for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = Globals.begin(), E = Globals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = BSSGlobals.begin(), E = BSSGlobals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, false, I->first); if (EnableGlobalMergeOnConst) for (DenseMap<unsigned, SmallVector<GlobalVariable*, 16> >::iterator I = ConstGlobals.begin(), E = ConstGlobals.end(); I != E; ++I) if (I->second.size() > 1) Changed |= doMerge(I->second, M, true, I->first); return Changed; }
static PointerType *buildTlsTemplate(Module &M, std::vector<VarInfo> *TlsVars) { std::vector<Type*> FieldBssTypes; std::vector<Type*> FieldInitTypes; std::vector<Constant*> FieldInitValues; PassState State(&M); for (Module::global_iterator GV = M.global_begin(); GV != M.global_end(); ++GV) { if (GV->isThreadLocal()) { if (!GV->hasInitializer()) { // Since this is a whole-program transformation, "extern" TLS // variables are not allowed at this point. report_fatal_error(std::string("TLS variable without an initializer: ") + GV->getName()); } if (!GV->getInitializer()->isNullValue()) { addVarToTlsTemplate(&State, &FieldInitTypes, &FieldInitValues, GV); VarInfo Info; Info.TlsVar = GV; Info.IsBss = false; Info.TemplateIndex = FieldInitTypes.size() - 1; TlsVars->push_back(Info); } } } // Handle zero-initialized TLS variables in a second pass, because // these should follow non-zero-initialized TLS variables. for (Module::global_iterator GV = M.global_begin(); GV != M.global_end(); ++GV) { if (GV->isThreadLocal() && GV->getInitializer()->isNullValue()) { addVarToTlsTemplate(&State, &FieldBssTypes, NULL, GV); VarInfo Info; Info.TlsVar = GV; Info.IsBss = true; Info.TemplateIndex = FieldBssTypes.size() - 1; TlsVars->push_back(Info); } } // Add final alignment padding so that // (struct tls_struct *) __nacl_read_tp() - 1 // gives the correct, aligned start of the TLS variables given the // x86-style layout we are using. This requires some more bytes to // be memset() to zero at runtime. This wastage doesn't seem // important gives that we're not trying to optimize packing by // reordering to put similarly-aligned variables together. padToAlignment(&State, &FieldBssTypes, NULL, State.Alignment); // We create the TLS template structs as "packed" because we insert // alignment padding ourselves, and LLVM's implicit insertion of // padding would interfere with ours. tls_bss_template can start at // a non-aligned address immediately following the last field in // tls_init_template. StructType *InitTemplateType = StructType::create(M.getContext(), "tls_init_template"); InitTemplateType->setBody(FieldInitTypes, /*isPacked=*/true); StructType *BssTemplateType = StructType::create(M.getContext(), "tls_bss_template"); BssTemplateType->setBody(FieldBssTypes, /*isPacked=*/true); StructType *TemplateType = StructType::create(M.getContext(), "tls_struct"); SmallVector<Type*, 2> TemplateTopFields; TemplateTopFields.push_back(InitTemplateType); TemplateTopFields.push_back(BssTemplateType); TemplateType->setBody(TemplateTopFields, /*isPacked=*/true); PointerType *TemplatePtrType = PointerType::get(TemplateType, 0); // We define the following symbols, which are the same as those // defined by NaCl's original customized binutils linker scripts: // __tls_template_start // __tls_template_tdata_end // __tls_template_end // We also define __tls_template_alignment, which was not defined by // the original linker scripts. const char *StartSymbol = "__tls_template_start"; Constant *TemplateData = ConstantStruct::get(InitTemplateType, FieldInitValues); GlobalVariable *TemplateDataVar = new GlobalVariable(M, InitTemplateType, /*isConstant=*/true, GlobalValue::InternalLinkage, TemplateData); setGlobalVariableValue(M, StartSymbol, TemplateDataVar); TemplateDataVar->setName(StartSymbol); Constant *TdataEnd = ConstantExpr::getGetElementPtr( TemplateDataVar, ConstantInt::get(M.getContext(), APInt(32, 1))); setGlobalVariableValue(M, "__tls_template_tdata_end", TdataEnd); Constant *TotalEnd = ConstantExpr::getGetElementPtr( ConstantExpr::getBitCast(TemplateDataVar, TemplatePtrType), ConstantInt::get(M.getContext(), APInt(32, 1))); setGlobalVariableValue(M, "__tls_template_end", TotalEnd); const char *AlignmentSymbol = "__tls_template_alignment"; Type *i32 = Type::getInt32Ty(M.getContext()); GlobalVariable *AlignmentVar = new GlobalVariable( M, i32, /*isConstant=*/true, GlobalValue::InternalLinkage, ConstantInt::get(M.getContext(), APInt(32, State.Alignment))); setGlobalVariableValue(M, AlignmentSymbol, AlignmentVar); AlignmentVar->setName(AlignmentSymbol); return TemplatePtrType; }