Index: llvm/trunk/docs/BitCodeFormat.rst =================================================================== --- llvm/trunk/docs/BitCodeFormat.rst +++ llvm/trunk/docs/BitCodeFormat.rst @@ -731,8 +731,14 @@ * ``initialexec``: code 3 * ``localexec``: code 4 -* *unnamed_addr*: If present and non-zero, indicates that the variable has - ``unnamed_addr`` +.. _bcunnamedaddr: + +* *unnamed_addr*: If present, an encoding of the ``unnamed_addr`` attribute of this + variable: + + * not ``unnamed_addr``: code 0 + * ``unnamed_addr``: code 1 + * ``local_unnamed_addr``: code 2 .. _bcdllstorageclass: @@ -791,8 +797,8 @@ * *gc*: If present and nonzero, the 1-based garbage collector index in the table of `MODULE_CODE_GCNAME`_ entries. -* *unnamed_addr*: If present and non-zero, indicates that the function has - ``unnamed_addr`` +* *unnamed_addr*: If present, an encoding of the + :ref:`unnamed_addr` attribute of this function * *prologuedata*: If non-zero, the value index of the prologue data for this function, plus 1. @@ -830,8 +836,8 @@ * *threadlocal*: If present, an encoding of the :ref:`thread local property` of the alias -* *unnamed_addr*: If present and non-zero, indicates that the alias has - ``unnamed_addr`` +* *unnamed_addr*: If present, an encoding of the + :ref:`unnamed_addr` attribute of this alias MODULE_CODE_PURGEVALS Record ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -589,6 +589,9 @@ merged with a ``unnamed_addr`` constant, the result being a constant whose address is significant. +If the ``local_unnamed_addr`` attribute is given, the address is known to +not be significant within the module. + A global variable may be declared to reside in a target-specific numbered address space. For targets that support them, address spaces may affect how optimizations are performed and/or what target @@ -628,7 +631,8 @@ Syntax:: @ = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] - [unnamed_addr] [AddrSpace] [ExternallyInitialized] + [(unnamed_addr|local_unnamed_addr)] [AddrSpace] + [ExternallyInitialized] [] [, section "name"] [, comdat [($name)]] [, align ] (, !name !N)* @@ -675,14 +679,14 @@ an opening curly brace, a list of basic blocks, and a closing curly brace. LLVM function declarations consist of the "``declare``" keyword, an -optional :ref:`linkage type `, an optional :ref:`visibility -style `, an optional :ref:`DLL storage class `, -an optional :ref:`calling convention `, -an optional ``unnamed_addr`` attribute, a return type, an optional -:ref:`parameter attribute ` for the return type, a function -name, a possibly empty list of arguments, an optional alignment, an optional -:ref:`garbage collector name `, an optional :ref:`prefix `, -and an optional :ref:`prologue `. +optional :ref:`linkage type `, an optional :ref:`visibility style +`, an optional :ref:`DLL storage class `, an +optional :ref:`calling convention `, an optional ``unnamed_addr`` +or ``local_unnamed_addr`` attribute, a return type, an optional :ref:`parameter +attribute ` for the return type, a function name, a possibly +empty list of arguments, an optional alignment, an optional :ref:`garbage +collector name `, an optional :ref:`prefix `, and an optional +:ref:`prologue `. A function definition contains a list of basic blocks, forming the CFG (Control Flow Graph) for the function. Each basic block may optionally start with a label @@ -713,14 +717,17 @@ If the ``unnamed_addr`` attribute is given, the address is known to not be significant and two identical functions can be merged. +If the ``local_unnamed_addr`` attribute is given, the address is known to +not be significant within the module. + Syntax:: define [linkage] [visibility] [DLLStorageClass] [cconv] [ret attrs] @ ([argument list]) - [unnamed_addr] [fn Attrs] [section "name"] [comdat [($name)]] - [align N] [gc] [prefix Constant] [prologue Constant] - [personality Constant] (!name !N)* { ... } + [(unnamed_addr|local_unnamed_addr)] [fn Attrs] [section "name"] + [comdat [($name)]] [align N] [gc] [prefix Constant] + [prologue Constant] [personality Constant] (!name !N)* { ... } The argument list is a comma separated sequence of arguments where each argument is of the following form: @@ -747,7 +754,7 @@ Syntax:: - @ = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] [unnamed_addr] alias , * @ + @ = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] [(unnamed_addr|local_unnamed_addr)] alias , * @ The linkage must be one of ``private``, ``internal``, ``linkonce``, ``weak``, ``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers @@ -757,6 +764,9 @@ the aliasee expression. ``unnamed_addr`` ones are only guaranteed to point to the same content. +If the ``local_unnamed_addr`` attribute is given, the address is known to +not be significant within the module. + Since aliases are only a second name, some restrictions apply, of which some can only be checked when producing an object file: Index: llvm/trunk/include/llvm/IR/GlobalValue.h =================================================================== --- llvm/trunk/include/llvm/IR/GlobalValue.h +++ llvm/trunk/include/llvm/IR/GlobalValue.h @@ -70,8 +70,9 @@ LinkageTypes Linkage, const Twine &Name, unsigned AddressSpace) : Constant(PointerType::get(Ty, AddressSpace), VTy, Ops, NumOps), ValueType(Ty), Linkage(Linkage), Visibility(DefaultVisibility), - UnnamedAddr(0), DllStorageClass(DefaultStorageClass), - ThreadLocal(NotThreadLocal), IntID((Intrinsic::ID)0U), Parent(nullptr) { + UnnamedAddrVal(unsigned(UnnamedAddr::None)), + DllStorageClass(DefaultStorageClass), ThreadLocal(NotThreadLocal), + IntID((Intrinsic::ID)0U), Parent(nullptr) { setName(Name); } @@ -80,7 +81,7 @@ // them. unsigned Linkage : 4; // The linkage of this global unsigned Visibility : 2; // The visibility style of this global - unsigned UnnamedAddr : 1; // This value's address is not significant + unsigned UnnamedAddrVal : 2; // This value's address is not significant unsigned DllStorageClass : 2; // DLL storage class unsigned ThreadLocal : 3; // Is this symbol "Thread Local", if so, what is @@ -89,7 +90,7 @@ private: // Give subclasses access to what otherwise would be wasted padding. - // (19 + 3 + 2 + 1 + 2 + 5) == 32. + // (19 + 4 + 2 + 2 + 2 + 3) == 32. unsigned SubClassData : GlobalValueSubClassDataBits; friend class Constant; @@ -153,8 +154,37 @@ unsigned getAlignment() const; - bool hasUnnamedAddr() const { return UnnamedAddr; } - void setUnnamedAddr(bool Val) { UnnamedAddr = Val; } + enum class UnnamedAddr { + None, + Local, + Global, + }; + + bool hasGlobalUnnamedAddr() const { + return getUnnamedAddr() == UnnamedAddr::Global; + } + + /// Returns true if this value's address is not significant in this module. + /// This attribute is intended to be used only by the code generator and LTO + /// to allow the linker to decide whether the global needs to be in the symbol + /// table. It should probably not be used in optimizations, as the value may + /// have uses outside the module; use hasGlobalUnnamedAddr() instead. + bool hasAtLeastLocalUnnamedAddr() const { + return getUnnamedAddr() != UnnamedAddr::None; + } + + UnnamedAddr getUnnamedAddr() const { + return UnnamedAddr(UnnamedAddrVal); + } + void setUnnamedAddr(UnnamedAddr Val) { UnnamedAddrVal = unsigned(Val); } + + static UnnamedAddr getMinUnnamedAddr(UnnamedAddr A, UnnamedAddr B) { + if (A == UnnamedAddr::None || B == UnnamedAddr::None) + return UnnamedAddr::None; + if (A == UnnamedAddr::Local || B == UnnamedAddr::Local) + return UnnamedAddr::Local; + return UnnamedAddr::Global; + } bool hasComdat() const { return getComdat() != nullptr; } Comdat *getComdat(); Index: llvm/trunk/lib/Analysis/InstructionSimplify.cpp =================================================================== --- llvm/trunk/lib/Analysis/InstructionSimplify.cpp +++ llvm/trunk/lib/Analysis/InstructionSimplify.cpp @@ -2086,7 +2086,7 @@ return AI->getParent() && AI->getFunction() && AI->isStaticAlloca(); if (const GlobalValue *GV = dyn_cast(V)) return (GV->hasLocalLinkage() || GV->hasHiddenVisibility() || - GV->hasProtectedVisibility() || GV->hasUnnamedAddr()) && + GV->hasProtectedVisibility() || GV->hasGlobalUnnamedAddr()) && !GV->isThreadLocal(); if (const Argument *A = dyn_cast(V)) return A->hasByValAttr(); Index: llvm/trunk/lib/AsmParser/LLLexer.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLLexer.cpp +++ llvm/trunk/lib/AsmParser/LLLexer.cpp @@ -513,6 +513,7 @@ KEYWORD(hidden); KEYWORD(protected); KEYWORD(unnamed_addr); + KEYWORD(local_unnamed_addr); KEYWORD(externally_initialized); KEYWORD(extern_weak); KEYWORD(external); Index: llvm/trunk/lib/AsmParser/LLParser.h =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.h +++ llvm/trunk/lib/AsmParser/LLParser.h @@ -226,9 +226,7 @@ bool ParseTLSModel(GlobalVariable::ThreadLocalMode &TLM); bool ParseOptionalThreadLocal(GlobalVariable::ThreadLocalMode &TLM); - bool parseOptionalUnnamedAddr(bool &UnnamedAddr) { - return ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr); - } + bool ParseOptionalUnnamedAddr(GlobalVariable::UnnamedAddr &UnnamedAddr); bool ParseOptionalAddrSpace(unsigned &AddrSpace); bool ParseOptionalParamAttrs(AttrBuilder &B); bool ParseOptionalReturnAttrs(AttrBuilder &B); @@ -275,12 +273,13 @@ bool ParseGlobal(const std::string &Name, LocTy Loc, unsigned Linkage, bool HasLinkage, unsigned Visibility, unsigned DLLStorageClass, - GlobalVariable::ThreadLocalMode TLM, bool UnnamedAddr); + GlobalVariable::ThreadLocalMode TLM, + GlobalVariable::UnnamedAddr UnnamedAddr); bool parseIndirectSymbol(const std::string &Name, LocTy Loc, unsigned Linkage, unsigned Visibility, unsigned DLLStorageClass, GlobalVariable::ThreadLocalMode TLM, - bool UnnamedAddr); + GlobalVariable::UnnamedAddr UnnamedAddr); bool parseComdat(); bool ParseStandaloneMetadata(); bool ParseNamedMetadata(); Index: llvm/trunk/lib/AsmParser/LLParser.cpp =================================================================== --- llvm/trunk/lib/AsmParser/LLParser.cpp +++ llvm/trunk/lib/AsmParser/LLParser.cpp @@ -429,6 +429,17 @@ return false; } +bool LLParser::ParseOptionalUnnamedAddr( + GlobalVariable::UnnamedAddr &UnnamedAddr) { + if (EatIfPresent(lltok::kw_unnamed_addr)) + UnnamedAddr = GlobalValue::UnnamedAddr::Global; + else if (EatIfPresent(lltok::kw_local_unnamed_addr)) + UnnamedAddr = GlobalValue::UnnamedAddr::Local; + else + UnnamedAddr = GlobalValue::UnnamedAddr::None; + return false; +} + /// ParseUnnamedGlobal: /// OptionalVisibility (ALIAS | IFUNC) ... /// OptionalLinkage OptionalVisibility OptionalDLLStorageClass @@ -455,9 +466,9 @@ bool HasLinkage; unsigned Linkage, Visibility, DLLStorageClass; GlobalVariable::ThreadLocalMode TLM; - bool UnnamedAddr; + GlobalVariable::UnnamedAddr UnnamedAddr; if (ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass) || - ParseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr)) + ParseOptionalThreadLocal(TLM) || ParseOptionalUnnamedAddr(UnnamedAddr)) return true; if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc) @@ -481,10 +492,10 @@ bool HasLinkage; unsigned Linkage, Visibility, DLLStorageClass; GlobalVariable::ThreadLocalMode TLM; - bool UnnamedAddr; + GlobalVariable::UnnamedAddr UnnamedAddr; if (ParseToken(lltok::equal, "expected '=' in global variable") || ParseOptionalLinkage(Linkage, HasLinkage, Visibility, DLLStorageClass) || - ParseOptionalThreadLocal(TLM) || parseOptionalUnnamedAddr(UnnamedAddr)) + ParseOptionalThreadLocal(TLM) || ParseOptionalUnnamedAddr(UnnamedAddr)) return true; if (Lex.getKind() != lltok::kw_alias && Lex.getKind() != lltok::kw_ifunc) @@ -659,11 +670,10 @@ /// /// Everything through OptionalUnnamedAddr has already been parsed. /// -bool LLParser::parseIndirectSymbol(const std::string &Name, LocTy NameLoc, - unsigned L, unsigned Visibility, - unsigned DLLStorageClass, - GlobalVariable::ThreadLocalMode TLM, - bool UnnamedAddr) { +bool LLParser::parseIndirectSymbol( + const std::string &Name, LocTy NameLoc, unsigned L, unsigned Visibility, + unsigned DLLStorageClass, GlobalVariable::ThreadLocalMode TLM, + GlobalVariable::UnnamedAddr UnnamedAddr) { bool IsAlias; if (Lex.getKind() == lltok::kw_alias) IsAlias = true; @@ -799,7 +809,7 @@ unsigned Linkage, bool HasLinkage, unsigned Visibility, unsigned DLLStorageClass, GlobalVariable::ThreadLocalMode TLM, - bool UnnamedAddr) { + GlobalVariable::UnnamedAddr UnnamedAddr) { if (!isValidVisibilityForLinkage(Visibility, Linkage)) return Error(NameLoc, "symbol with local linkage must have default visibility"); @@ -4580,7 +4590,7 @@ std::string Section; unsigned Alignment; std::string GC; - bool UnnamedAddr; + GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None; LocTy UnnamedAddrLoc; Constant *Prefix = nullptr; Constant *Prologue = nullptr; @@ -4588,8 +4598,7 @@ Comdat *C; if (ParseArgumentList(ArgList, isVarArg) || - ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr, - &UnnamedAddrLoc) || + ParseOptionalUnnamedAddr(UnnamedAddr) || ParseFnAttributeValuePairs(FuncAttrs, FwdRefAttrGrps, false, BuiltinLoc) || (EatIfPresent(lltok::kw_section) && Index: llvm/trunk/lib/AsmParser/LLToken.h =================================================================== --- llvm/trunk/lib/AsmParser/LLToken.h +++ llvm/trunk/lib/AsmParser/LLToken.h @@ -60,6 +60,7 @@ kw_hidden, kw_protected, kw_unnamed_addr, + kw_local_unnamed_addr, kw_externally_initialized, kw_extern_weak, kw_external, Index: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp +++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp @@ -773,6 +773,15 @@ } } +static GlobalVariable::UnnamedAddr getDecodedUnnamedAddrType(unsigned Val) { + switch (Val) { + default: // Map unknown to UnnamedAddr::None. + case 0: return GlobalVariable::UnnamedAddr::None; + case 1: return GlobalVariable::UnnamedAddr::Global; + case 2: return GlobalVariable::UnnamedAddr::Local; + } +} + static int getDecodedCastOpcode(unsigned Val) { switch (Val) { default: return -1; @@ -3791,9 +3800,9 @@ if (Record.size() > 7) TLM = getDecodedThreadLocalMode(Record[7]); - bool UnnamedAddr = false; + GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None; if (Record.size() > 8) - UnnamedAddr = Record[8]; + UnnamedAddr = getDecodedUnnamedAddrType(Record[8]); bool ExternallyInitialized = false; if (Record.size() > 9) @@ -3828,6 +3837,7 @@ } else if (hasImplicitComdat(RawLinkage)) { NewGV->setComdat(reinterpret_cast(1)); } + break; } case bitc::MODULE_CODE_GLOBALVAR_ATTACHMENT: { @@ -3885,9 +3895,9 @@ return error("Invalid ID"); Func->setGC(GCTable[Record[8] - 1]); } - bool UnnamedAddr = false; + GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None; if (Record.size() > 9) - UnnamedAddr = Record[9]; + UnnamedAddr = getDecodedUnnamedAddrType(Record[9]); Func->setUnnamedAddr(UnnamedAddr); if (Record.size() > 10 && Record[10] != 0) FunctionPrologues.push_back(std::make_pair(Func, Record[10]-1)); @@ -3974,7 +3984,7 @@ if (OpNum != Record.size()) NewGA->setThreadLocalMode(getDecodedThreadLocalMode(Record[OpNum++])); if (OpNum != Record.size()) - NewGA->setUnnamedAddr(Record[OpNum++]); + NewGA->setUnnamedAddr(getDecodedUnnamedAddrType(Record[OpNum++])); ValueList.push_back(NewGA); IndirectSymbolInits.push_back(std::make_pair(NewGA, Val)); break; Index: llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp +++ llvm/trunk/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -996,6 +996,15 @@ llvm_unreachable("Invalid selection kind"); } +static unsigned getEncodedUnnamedAddr(const GlobalValue &GV) { + switch (GV.getUnnamedAddr()) { + case GlobalValue::UnnamedAddr::None: return 0; + case GlobalValue::UnnamedAddr::Local: return 2; + case GlobalValue::UnnamedAddr::Global: return 1; + } + llvm_unreachable("Invalid unnamed_addr"); +} + void ModuleBitcodeWriter::writeComdats() { SmallVector Vals; for (const Comdat *C : VE.getComdats()) { @@ -1157,12 +1166,13 @@ Vals.push_back(GV.hasSection() ? SectionMap[GV.getSection()] : 0); if (GV.isThreadLocal() || GV.getVisibility() != GlobalValue::DefaultVisibility || - GV.hasUnnamedAddr() || GV.isExternallyInitialized() || + GV.getUnnamedAddr() != GlobalValue::UnnamedAddr::None || + GV.isExternallyInitialized() || GV.getDLLStorageClass() != GlobalValue::DefaultStorageClass || GV.hasComdat()) { Vals.push_back(getEncodedVisibility(GV)); Vals.push_back(getEncodedThreadLocalMode(GV)); - Vals.push_back(GV.hasUnnamedAddr()); + Vals.push_back(getEncodedUnnamedAddr(GV)); Vals.push_back(GV.isExternallyInitialized()); Vals.push_back(getEncodedDLLStorageClass(GV)); Vals.push_back(GV.hasComdat() ? VE.getComdatID(GV.getComdat()) : 0); @@ -1188,7 +1198,7 @@ Vals.push_back(F.hasSection() ? SectionMap[F.getSection()] : 0); Vals.push_back(getEncodedVisibility(F)); Vals.push_back(F.hasGC() ? GCMap[F.getGC()] : 0); - Vals.push_back(F.hasUnnamedAddr()); + Vals.push_back(getEncodedUnnamedAddr(F)); Vals.push_back(F.hasPrologueData() ? (VE.getValueID(F.getPrologueData()) + 1) : 0); Vals.push_back(getEncodedDLLStorageClass(F)); @@ -1205,7 +1215,8 @@ // Emit the alias information. for (const GlobalAlias &A : M.aliases()) { - // ALIAS: [alias type, aliasee val#, linkage, visibility] + // ALIAS: [alias type, aliasee val#, linkage, visibility, dllstorageclass, + // threadlocal, unnamed_addr] Vals.push_back(VE.getTypeID(A.getValueType())); Vals.push_back(A.getType()->getAddressSpace()); Vals.push_back(VE.getValueID(A.getAliasee())); @@ -1213,7 +1224,7 @@ Vals.push_back(getEncodedVisibility(A)); Vals.push_back(getEncodedDLLStorageClass(A)); Vals.push_back(getEncodedThreadLocalMode(A)); - Vals.push_back(A.hasUnnamedAddr()); + Vals.push_back(getEncodedUnnamedAddr(A)); unsigned AbbrevToUse = 0; Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse); Vals.clear(); Index: llvm/trunk/lib/CodeGen/Analysis.cpp =================================================================== --- llvm/trunk/lib/CodeGen/Analysis.cpp +++ llvm/trunk/lib/CodeGen/Analysis.cpp @@ -623,7 +623,9 @@ if (!GV->hasLinkOnceODRLinkage()) return false; - if (GV->hasUnnamedAddr()) + // We assume that anyone who sets global unnamed_addr on a non-constant knows + // what they're doing. + if (GV->hasGlobalUnnamedAddr()) return true; // If it is a non constant variable, it needs to be uniqued across shared @@ -633,21 +635,7 @@ return false; } - // An alias can point to a variable. We could try to resolve the alias to - // decide, but for now just don't hide them. - if (isa(GV)) - return false; - - // If we don't see every use, we have to be conservative and assume the value - // address is significant. - if (GV->getParent()->getMaterializer()) - return false; - - GlobalStatus GS; - if (GlobalStatus::analyzeGlobal(GV, GS)) - return false; - - return !GS.IsCompared; + return GV->hasAtLeastLocalUnnamedAddr(); } // FIXME: make this a proper option Index: llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp =================================================================== --- llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ llvm/trunk/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -1001,7 +1001,7 @@ // Global GOT equivalents are unnamed private globals with a constant // pointer initializer to another global symbol. They must point to a // GlobalVariable or Function, i.e., as GlobalValue. - if (!GV->hasUnnamedAddr() || !GV->hasInitializer() || !GV->isConstant() || + if (!GV->hasGlobalUnnamedAddr() || !GV->hasInitializer() || !GV->isConstant() || !GV->isDiscardableIfUnused() || !dyn_cast(GV->getOperand(0))) return false; Index: llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp =================================================================== --- llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp +++ llvm/trunk/lib/CodeGen/TargetLoweringObjectFileImpl.cpp @@ -429,7 +429,7 @@ const TargetMachine &TM) const { // We may only use a PLT-relative relocation to refer to unnamed_addr // functions. - if (!LHS->hasUnnamedAddr() || !LHS->getValueType()->isFunctionTy()) + if (!LHS->hasGlobalUnnamedAddr() || !LHS->getValueType()->isFunctionTy()) return nullptr; // Basic sanity checks. Index: llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp =================================================================== --- llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ llvm/trunk/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -144,7 +144,7 @@ V.setLinkage(GlobalValue::ExternalLinkage); V.setVisibility(GlobalValue::HiddenVisibility); } - V.setUnnamedAddr(false); + V.setUnnamedAddr(GlobalValue::UnnamedAddr::None); assert(!R.needsRenaming(V) && "Invalid global name."); } Index: llvm/trunk/lib/IR/AsmWriter.cpp =================================================================== --- llvm/trunk/lib/IR/AsmWriter.cpp +++ llvm/trunk/lib/IR/AsmWriter.cpp @@ -2426,6 +2426,17 @@ } } +static StringRef getUnnamedAddrEncoding(GlobalVariable::UnnamedAddr UA) { + switch (UA) { + case GlobalVariable::UnnamedAddr::None: + return ""; + case GlobalVariable::UnnamedAddr::Local: + return "local_unnamed_addr"; + case GlobalVariable::UnnamedAddr::Global: + return "unnamed_addr"; + } +} + static void maybePrintComdat(formatted_raw_ostream &Out, const GlobalObject &GO) { const Comdat *C = GO.getComdat(); @@ -2458,8 +2469,9 @@ PrintVisibility(GV->getVisibility(), Out); PrintDLLStorageClass(GV->getDLLStorageClass(), Out); PrintThreadLocalModel(GV->getThreadLocalMode(), Out); - if (GV->hasUnnamedAddr()) - Out << "unnamed_addr "; + StringRef UA = getUnnamedAddrEncoding(GV->getUnnamedAddr()); + if (!UA.empty()) + Out << UA << ' '; if (unsigned AddressSpace = GV->getType()->getAddressSpace()) Out << "addrspace(" << AddressSpace << ") "; @@ -2499,8 +2511,9 @@ PrintVisibility(GIS->getVisibility(), Out); PrintDLLStorageClass(GIS->getDLLStorageClass(), Out); PrintThreadLocalModel(GIS->getThreadLocalMode(), Out); - if (GIS->hasUnnamedAddr()) - Out << "unnamed_addr "; + StringRef UA = getUnnamedAddrEncoding(GIS->getUnnamedAddr()); + if (!UA.empty()) + Out << UA << ' '; if (isa(GIS)) Out << "alias "; @@ -2656,8 +2669,9 @@ Out << "..."; // Output varargs portion of signature! } Out << ')'; - if (F->hasUnnamedAddr()) - Out << " unnamed_addr"; + StringRef UA = getUnnamedAddrEncoding(F->getUnnamedAddr()); + if (!UA.empty()) + Out << ' ' << UA; if (Attrs.hasAttributes(AttributeSet::FunctionIndex)) Out << " #" << Machine.getAttributeGroupSlot(Attrs.getFnAttributes()); if (F->hasSection()) { Index: llvm/trunk/lib/IR/Core.cpp =================================================================== --- llvm/trunk/lib/IR/Core.cpp +++ llvm/trunk/lib/IR/Core.cpp @@ -1560,11 +1560,13 @@ } LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global) { - return unwrap(Global)->hasUnnamedAddr(); + return unwrap(Global)->hasGlobalUnnamedAddr(); } void LLVMSetUnnamedAddr(LLVMValueRef Global, LLVMBool HasUnnamedAddr) { - unwrap(Global)->setUnnamedAddr(HasUnnamedAddr); + unwrap(Global)->setUnnamedAddr( + HasUnnamedAddr ? GlobalValue::UnnamedAddr::Global + : GlobalValue::UnnamedAddr::None); } /*--.. Operations on global variables, load and store instructions .........--*/ Index: llvm/trunk/lib/IR/Globals.cpp =================================================================== --- llvm/trunk/lib/IR/Globals.cpp +++ llvm/trunk/lib/IR/Globals.cpp @@ -51,7 +51,7 @@ /// create a GlobalValue) from the GlobalValue Src to this one. void GlobalValue::copyAttributesFrom(const GlobalValue *Src) { setVisibility(Src->getVisibility()); - setUnnamedAddr(Src->hasUnnamedAddr()); + setUnnamedAddr(Src->getUnnamedAddr()); setDLLStorageClass(Src->getDLLStorageClass()); } Index: llvm/trunk/lib/IR/IRBuilder.cpp =================================================================== --- llvm/trunk/lib/IR/IRBuilder.cpp +++ llvm/trunk/lib/IR/IRBuilder.cpp @@ -34,7 +34,7 @@ StrConstant, Name, nullptr, GlobalVariable::NotThreadLocal, AddressSpace); - GV->setUnnamedAddr(true); + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); return GV; } Index: llvm/trunk/lib/IR/Verifier.cpp =================================================================== --- llvm/trunk/lib/IR/Verifier.cpp +++ llvm/trunk/lib/IR/Verifier.cpp @@ -1535,7 +1535,7 @@ if (Attrs.hasAttribute(AttributeSet::FunctionIndex, Attribute::JumpTable)) { const GlobalValue *GV = cast(V); - Assert(GV->hasUnnamedAddr(), + Assert(GV->hasGlobalUnnamedAddr(), "Attribute 'jumptable' requires 'unnamed_addr'", V); } Index: llvm/trunk/lib/Linker/IRMover.cpp =================================================================== --- llvm/trunk/lib/Linker/IRMover.cpp +++ llvm/trunk/lib/Linker/IRMover.cpp @@ -791,7 +791,7 @@ return stringErr( "Appending variables with different visibility need to be linked!"); - if (DstGV->hasUnnamedAddr() != SrcGV->hasUnnamedAddr()) + if (DstGV->hasGlobalUnnamedAddr() != SrcGV->hasGlobalUnnamedAddr()) return stringErr( "Appending variables with different unnamed_addr need to be linked!"); Index: llvm/trunk/lib/Linker/LinkModules.cpp =================================================================== --- llvm/trunk/lib/Linker/LinkModules.cpp +++ llvm/trunk/lib/Linker/LinkModules.cpp @@ -377,9 +377,10 @@ DGV->setVisibility(Visibility); GV.setVisibility(Visibility); - bool HasUnnamedAddr = GV.hasUnnamedAddr() && DGV->hasUnnamedAddr(); - DGV->setUnnamedAddr(HasUnnamedAddr); - GV.setUnnamedAddr(HasUnnamedAddr); + GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::getMinUnnamedAddr( + DGV->getUnnamedAddr(), GV.getUnnamedAddr()); + DGV->setUnnamedAddr(UnnamedAddr); + GV.setUnnamedAddr(UnnamedAddr); } // Don't want to append to global_ctors list, for example, when we Index: llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp =================================================================== --- llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp +++ llvm/trunk/lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp @@ -694,7 +694,7 @@ nullptr, GlobalVariable::NotThreadLocal, AMDGPUAS::LOCAL_ADDRESS); - GV->setUnnamedAddr(true); + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); GV->setAlignment(I.getAlignment()); Value *TCntY, *TCntZ; Index: llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp =================================================================== --- llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp +++ llvm/trunk/lib/Target/TargetLoweringObjectFile.cpp @@ -174,7 +174,7 @@ // If the global is required to have a unique address, it can't be put // into a mergable section: just drop it into the general read-only // section instead. - if (!GVar->hasUnnamedAddr()) + if (!GVar->hasGlobalUnnamedAddr()) return SectionKind::getReadOnly(); // If initializer is a null-terminated string, put it in a "cstring" Index: llvm/trunk/lib/Transforms/IPO/ConstantMerge.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/ConstantMerge.cpp +++ llvm/trunk/lib/Transforms/IPO/ConstantMerge.cpp @@ -57,7 +57,7 @@ if (A.hasLocalLinkage() && !B.hasLocalLinkage()) return false; - return A.hasUnnamedAddr(); + return A.hasGlobalUnnamedAddr(); } static unsigned getAlignment(GlobalVariable *GV) { @@ -152,11 +152,11 @@ if (!Slot || Slot == GV) continue; - if (!Slot->hasUnnamedAddr() && !GV->hasUnnamedAddr()) + if (!Slot->hasGlobalUnnamedAddr() && !GV->hasGlobalUnnamedAddr()) continue; - if (!GV->hasUnnamedAddr()) - Slot->setUnnamedAddr(false); + if (!GV->hasGlobalUnnamedAddr()) + Slot->setUnnamedAddr(GlobalValue::UnnamedAddr::None); // Make all uses of the duplicate constant use the canonical version. Replacements.push_back(std::make_pair(GV, Slot)); Index: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp +++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp @@ -1942,8 +1942,7 @@ static bool processGlobal(GlobalValue &GV, TargetLibraryInfo *TLI, function_ref LookupDomTree) { - // Do more involved optimizations if the global is internal. - if (!GV.hasLocalLinkage()) + if (GV.getName().startswith("llvm.")) return false; GlobalStatus GS; @@ -1952,12 +1951,20 @@ return false; bool Changed = false; - if (!GS.IsCompared && !GV.hasUnnamedAddr()) { - GV.setUnnamedAddr(true); - NumUnnamed++; - Changed = true; + if (!GS.IsCompared && !GV.hasGlobalUnnamedAddr()) { + auto NewUnnamedAddr = GV.hasLocalLinkage() ? GlobalValue::UnnamedAddr::Global + : GlobalValue::UnnamedAddr::Local; + if (NewUnnamedAddr != GV.getUnnamedAddr()) { + GV.setUnnamedAddr(NewUnnamedAddr); + NumUnnamed++; + Changed = true; + } } + // Do more involved optimizations if the global is internal. + if (!GV.hasLocalLinkage()) + return Changed; + auto *GVar = dyn_cast(&GV); if (!GVar) return Changed; Index: llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp =================================================================== --- llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp +++ llvm/trunk/lib/Transforms/IPO/MergeFunctions.cpp @@ -1637,7 +1637,7 @@ // Replace G with an alias to F if possible, or else a thunk to F. Deletes G. void MergeFunctions::writeThunkOrAlias(Function *F, Function *G) { - if (HasGlobalAliases && G->hasUnnamedAddr()) { + if (HasGlobalAliases && G->hasGlobalUnnamedAddr()) { if (G->hasExternalLinkage() || G->hasLocalLinkage() || G->hasWeakLinkage()) { writeAlias(F, G); Index: llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp =================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ llvm/trunk/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -832,7 +832,7 @@ GlobalVariable *GV = new GlobalVariable(M, StrConst->getType(), true, GlobalValue::PrivateLinkage, StrConst, kAsanGenPrefix); - if (AllowMerging) GV->setUnnamedAddr(true); + if (AllowMerging) GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); GV->setAlignment(1); // Strings may not be merged w/o setting align 1. return GV; } @@ -849,7 +849,7 @@ auto GV = new GlobalVariable(M, LocStruct->getType(), true, GlobalValue::PrivateLinkage, LocStruct, kAsanGenPrefix); - GV->setUnnamedAddr(true); + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); return GV; } Index: llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp =================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp +++ llvm/trunk/lib/Transforms/Instrumentation/EfficiencySanitizer.cpp @@ -137,7 +137,7 @@ new GlobalVariable(M, StrConst->getType(), true, GlobalValue::PrivateLinkage, StrConst, ""); if (AllowMerging) - GV->setUnnamedAddr(true); + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); GV->setAlignment(1); // Strings may not be merged w/o setting align 1. return GV; } Index: llvm/trunk/lib/Transforms/Instrumentation/GCOVProfiling.cpp =================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ llvm/trunk/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -691,7 +691,7 @@ FunctionType *FTy = FunctionType::get(Type::getVoidTy(*Ctx), false); Function *F = Function::Create(FTy, GlobalValue::InternalLinkage, "__llvm_gcov_init", M); - F->setUnnamedAddr(true); + F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); F->setLinkage(GlobalValue::InternalLinkage); F->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) @@ -766,7 +766,7 @@ ConstantArray::get(EdgeTableTy, makeArrayRef(&EdgeTable[0],TableSize)), "__llvm_gcda_edge_table"); - EdgeTableGV->setUnnamedAddr(true); + EdgeTableGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); return EdgeTableGV; } @@ -840,7 +840,7 @@ ConstantInt::get(Type::getInt32Ty(*Ctx), 0xffffffff), "__llvm_gcov_global_state_pred"); - GV->setUnnamedAddr(true); + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); } return GV; } @@ -852,7 +852,7 @@ if (!WriteoutF) WriteoutF = Function::Create(WriteoutFTy, GlobalValue::InternalLinkage, "__llvm_gcov_writeout", M); - WriteoutF->setUnnamedAddr(true); + WriteoutF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); WriteoutF->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) WriteoutF->addFnAttr(Attribute::NoRedZone); @@ -912,7 +912,7 @@ void GCOVProfiler::insertIndirectCounterIncrement() { Function *Fn = cast(GCOVProfiler::getIncrementIndirectCounterFunc()); - Fn->setUnnamedAddr(true); + Fn->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); Fn->setLinkage(GlobalValue::InternalLinkage); Fn->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) @@ -969,7 +969,7 @@ "__llvm_gcov_flush", M); else FlushF->setLinkage(GlobalValue::InternalLinkage); - FlushF->setUnnamedAddr(true); + FlushF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); FlushF->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) FlushF->addFnAttr(Attribute::NoRedZone); Index: llvm/trunk/lib/Transforms/Instrumentation/InstrProfiling.cpp =================================================================== --- llvm/trunk/lib/Transforms/Instrumentation/InstrProfiling.cpp +++ llvm/trunk/lib/Transforms/Instrumentation/InstrProfiling.cpp @@ -506,7 +506,7 @@ auto *RegisterFTy = FunctionType::get(VoidTy, false); auto *RegisterF = Function::Create(RegisterFTy, GlobalValue::InternalLinkage, getInstrProfRegFuncsName(), M); - RegisterF->setUnnamedAddr(true); + RegisterF->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); if (Options.NoRedZone) RegisterF->addFnAttr(Attribute::NoRedZone); auto *RuntimeRegisterTy = FunctionType::get(VoidTy, VoidPtrTy, false); @@ -606,7 +606,7 @@ auto *F = Function::Create(FunctionType::get(VoidTy, false), GlobalValue::InternalLinkage, getInstrProfInitFuncName(), M); - F->setUnnamedAddr(true); + F->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); F->addFnAttr(Attribute::NoInline); if (Options.NoRedZone) F->addFnAttr(Attribute::NoRedZone); Index: llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp =================================================================== --- llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp +++ llvm/trunk/lib/Transforms/Scalar/LoopIdiomRecognize.cpp @@ -777,7 +777,7 @@ GlobalVariable *GV = new GlobalVariable(*M, PatternValue->getType(), true, GlobalValue::PrivateLinkage, PatternValue, ".memset_pattern"); - GV->setUnnamedAddr(true); // Ok to merge these. + GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); // Ok to merge these. GV->setAlignment(16); Value *PatternPtr = ConstantExpr::getBitCast(GV, Int8PtrTy); NewCall = Builder.CreateCall(MSP, {BasePtr, PatternPtr, NumBytes}); Index: llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp +++ llvm/trunk/lib/Transforms/Utils/FunctionImportUtils.cpp @@ -64,7 +64,7 @@ // of the module and recorded in the summary index for use when importing // from that module. auto *GVar = dyn_cast(SGV); - if (GVar && GVar->isConstant() && GVar->hasUnnamedAddr()) + if (GVar && GVar->isConstant() && GVar->hasGlobalUnnamedAddr()) return false; if (GVar && GVar->hasSection()) Index: llvm/trunk/lib/Transforms/Utils/GlobalStatus.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/GlobalStatus.cpp +++ llvm/trunk/lib/Transforms/Utils/GlobalStatus.cpp @@ -105,7 +105,7 @@ } } - if (StoredVal == GV->getInitializer()) { + if (GV->hasInitializer() && StoredVal == GV->getInitializer()) { if (GS.StoredType < GlobalStatus::InitializerStored) GS.StoredType = GlobalStatus::InitializerStored; } else if (isa(StoredVal) && Index: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp =================================================================== --- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp +++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp @@ -4540,7 +4540,7 @@ Array = new GlobalVariable(M, ArrayTy, /*constant=*/true, GlobalVariable::PrivateLinkage, Initializer, "switch.table"); - Array->setUnnamedAddr(true); + Array->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); Kind = ArrayKind; } Index: llvm/trunk/test/Assembler/local-unnamed-addr.ll =================================================================== --- llvm/trunk/test/Assembler/local-unnamed-addr.ll +++ llvm/trunk/test/Assembler/local-unnamed-addr.ll @@ -0,0 +1,13 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s +; RUN: verify-uselistorder %s + +; CHECK: @c = local_unnamed_addr constant i32 0 +@c = local_unnamed_addr constant i32 0 + +; CHECK: @a = local_unnamed_addr alias i32, i32* @c +@a = local_unnamed_addr alias i32, i32* @c + +; CHECK: define void @f() local_unnamed_addr { +define void @f() local_unnamed_addr { + ret void +} Index: llvm/trunk/test/Bitcode/compatibility.ll =================================================================== --- llvm/trunk/test/Bitcode/compatibility.ll +++ llvm/trunk/test/Bitcode/compatibility.ll @@ -80,7 +80,7 @@ ;; Global Variables ; Format: [@ =] [Linkage] [Visibility] [DLLStorageClass] -; [ThreadLocal] [unnamed_addr] [AddrSpace] [ExternallyInitialized] +; [ThreadLocal] [(unnamed_addr|local_unnamed_addr)] [AddrSpace] [ExternallyInitialized] ; [] ; [, section "name"] [, comdat [($name)]] [, align ] @@ -142,9 +142,11 @@ @g.localexec = thread_local(localexec) global i32 0 ; CHECK: @g.localexec = thread_local(localexec) global i32 0 -; Global Variables -- unnamed_addr +; Global Variables -- unnamed_addr and local_unnamed_addr @g.unnamed_addr = unnamed_addr global i32 0 ; CHECK: @g.unnamed_addr = unnamed_addr global i32 0 +@g.local_unnamed_addr = local_unnamed_addr global i32 0 +; CHECK: @g.local_unnamed_addr = local_unnamed_addr global i32 0 ; Global Variables -- AddrSpace @g.addrspace = addrspace(1) global i32 0 @@ -245,9 +247,11 @@ @a.localexec = thread_local(localexec) alias i32, i32* @g.localexec ; CHECK: @a.localexec = thread_local(localexec) alias i32, i32* @g.localexec -; Aliases -- unnamed_addr +; Aliases -- unnamed_addr and local_unnamed_addr @a.unnamed_addr = unnamed_addr alias i32, i32* @g.unnamed_addr ; CHECK: @a.unnamed_addr = unnamed_addr alias i32, i32* @g.unnamed_addr +@a.local_unnamed_addr = local_unnamed_addr alias i32, i32* @g.local_unnamed_addr +; CHECK: @a.local_unnamed_addr = local_unnamed_addr alias i32, i32* @g.local_unnamed_addr ;; IFunc ; Format @ = [Linkage] [Visibility] ifunc , @@ -278,7 +282,7 @@ ; Format: define [linkage] [visibility] [DLLStorageClass] ; [cconv] [ret attrs] ; @ ([argument list]) -; [unnamed_addr] [fn Attrs] [section "name"] [comdat [($name)]] +; [(unnamed_addr|local_unnamed_addr)] [fn Attrs] [section "name"] [comdat [($name)]] ; [align N] [gc] [prefix Constant] [prologue Constant] ; [personality Constant] { ... } @@ -523,9 +527,11 @@ declare void @f.param.dereferenceable_or_null(i8* dereferenceable_or_null(4)) ; CHECK: declare void @f.param.dereferenceable_or_null(i8* dereferenceable_or_null(4)) -; Functions -- unnamed_addr +; Functions -- unnamed_addr and local_unnamed_addr declare void @f.unnamed_addr() unnamed_addr ; CHECK: declare void @f.unnamed_addr() unnamed_addr +declare void @f.local_unnamed_addr() local_unnamed_addr +; CHECK: declare void @f.local_unnamed_addr() local_unnamed_addr ; Functions -- fn Attrs (Function attributes) declare void @f.alignstack4() alignstack(4) Index: llvm/trunk/test/CodeGen/PowerPC/weak_def_can_be_hidden.ll =================================================================== --- llvm/trunk/test/CodeGen/PowerPC/weak_def_can_be_hidden.ll +++ llvm/trunk/test/CodeGen/PowerPC/weak_def_can_be_hidden.ll @@ -3,7 +3,7 @@ ; RUN: llc -mtriple=powerpc-apple-darwin9 -O0 < %s | FileCheck --check-prefix=CHECK-D89 %s ; RUN: llc -mtriple=powerpc-apple-darwin8 -O0 < %s | FileCheck --check-prefix=CHECK-D89 %s -@v1 = linkonce_odr constant i32 32 +@v1 = linkonce_odr local_unnamed_addr constant i32 32 ; CHECK: .globl _v1 ; CHECK: .weak_def_can_be_hidden _v1 @@ -26,7 +26,7 @@ ret i32* @v2 } -@v3 = linkonce_odr unnamed_addr global i32 32 +@v3 = linkonce_odr unnamed_addr constant i32 32 ; CHECK: .globl _v3 ; CHECK: .weak_def_can_be_hidden _v3 @@ -37,9 +37,9 @@ ret i32* @v3 } -@v4 = linkonce_odr global i32 32 +@v4 = linkonce_odr unnamed_addr global i32 32 ; CHECK: .globl _v4 -; CHECK: .weak_definition _v4 +; CHECK: .weak_def_can_be_hidden _v4 ; CHECK-D89: .globl _v4 ; CHECK-D89: .weak_definition _v4 Index: llvm/trunk/test/CodeGen/X86/weak_def_can_be_hidden.ll =================================================================== --- llvm/trunk/test/CodeGen/X86/weak_def_can_be_hidden.ll +++ llvm/trunk/test/CodeGen/X86/weak_def_can_be_hidden.ll @@ -4,7 +4,7 @@ ; RUN: llc -mtriple=i686-apple-darwin9 -O0 < %s | FileCheck --check-prefix=CHECK-D89 %s ; RUN: llc -mtriple=i686-apple-darwin8 -O0 < %s | FileCheck --check-prefix=CHECK-D89 %s -@v1 = linkonce_odr constant i32 32 +@v1 = linkonce_odr local_unnamed_addr constant i32 32 ; CHECK: .globl _v1 ; CHECK: .weak_def_can_be_hidden _v1 @@ -27,7 +27,7 @@ ret i32* @v2 } -@v3 = linkonce_odr unnamed_addr global i32 32 +@v3 = linkonce_odr unnamed_addr constant i32 32 ; CHECK: .globl _v3 ; CHECK: .weak_def_can_be_hidden _v3 @@ -38,9 +38,9 @@ ret i32* @v3 } -@v4 = linkonce_odr global i32 32 +@v4 = linkonce_odr unnamed_addr global i32 32 ; CHECK: .globl _v4 -; CHECK: .weak_definition _v4 +; CHECK: .weak_def_can_be_hidden _v4 ; CHECK-D89: .globl _v4 ; CHECK-D89: .weak_definition _v4 Index: llvm/trunk/test/Feature/OperandBundles/pr26510.ll =================================================================== --- llvm/trunk/test/Feature/OperandBundles/pr26510.ll +++ llvm/trunk/test/Feature/OperandBundles/pr26510.ll @@ -10,7 +10,7 @@ declare void @foo() readnone -; CHECK-LABEL: define i8* @test(i8* %p) { +; CHECK-LABEL: define i8* @test(i8* %p) ; CHECK: %a = alloca i8*, align 8 ; CHECK: store i8* %p, i8** %a, align 8 ; CHECK: call void @foo() [ "abc"(i8** %a) ] Index: llvm/trunk/test/LTO/X86/cfi_endproc.ll =================================================================== --- llvm/trunk/test/LTO/X86/cfi_endproc.ll +++ llvm/trunk/test/LTO/X86/cfi_endproc.ll @@ -33,8 +33,8 @@ ret i32* @zed1 } -; ZED1_AND_ZED2: d zed2 -@zed2 = linkonce_odr unnamed_addr global i32 42 +; ZED1_AND_ZED2: r zed2 +@zed2 = linkonce_odr unnamed_addr constant i32 42 define i32 @useZed2() { %x = load i32, i32* @zed2 Index: llvm/trunk/test/LTO/X86/linkonce_odr_func.ll =================================================================== --- llvm/trunk/test/LTO/X86/linkonce_odr_func.ll +++ llvm/trunk/test/LTO/X86/linkonce_odr_func.ll @@ -1,61 +1,54 @@ ; RUN: llvm-as < %s >%t1 ; RUN: llvm-lto -o %t2 -dso-symbol=foo1 -dso-symbol=foo2 -dso-symbol=foo3 \ -; RUN: -dso-symbol=foo4 -dso-symbol=v1 -dso-symbol=v2 %t1 -O0 +; RUN: -dso-symbol=v1 -dso-symbol=v2 -dso-symbol=v3 \ +; RUN: -dso-symbol=v4 -dso-symbol=v5 -dso-symbol=v6 %t1 -O0 ; RUN: llvm-nm %t2 | FileCheck %s target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" -; CHECK: t foo1 +; CHECK: W foo1 define linkonce_odr void @foo1() noinline { ret void } -; CHECK: W foo2 -define linkonce_odr void @foo2() noinline { +; CHECK: t foo2 +define linkonce_odr void @foo2() local_unnamed_addr noinline { ret void } ; CHECK: t foo3 -define linkonce_odr void @foo3() noinline { +define linkonce_odr void @foo3() unnamed_addr noinline { ret void } -; CHECK: W foo4 -define linkonce_odr void @foo4() noinline { - ret void -} - -; CHECK: r v1 +; CHECK: V v1 @v1 = linkonce_odr constant i32 32 -define i32 @useV1() { - %x = load i32, i32* @v1 - ret i32 %x -} +; CHECK: r v2 +@v2 = linkonce_odr local_unnamed_addr constant i32 32 -; CHECK: V v2 -@v2 = linkonce_odr global i32 32 +; CHECK: r v3 +@v3 = linkonce_odr unnamed_addr constant i32 32 -define i32 @useV2() { - %x = load i32, i32* @v2 - ret i32 %x -} +; CHECK: V v4 +@v4 = linkonce_odr global i32 32 -declare void @f(void()*) +; CHECK: V v5 +@v5 = linkonce_odr local_unnamed_addr global i32 32 -declare void @p() +; CHECK: d v6 +@v6 = linkonce_odr unnamed_addr global i32 32 -define void @bar() personality void()* @p { -bb0: +define void @use() { call void @foo1() - call void @f(void()* @foo2) - invoke void @foo3() to label %bb1 unwind label %clean -bb1: - invoke void @f(void()* @foo4) to label %bb2 unwind label %clean -bb2: - ret void -clean: - landingpad {i32, i32} cleanup + call void @foo2() + call void @foo3() + %x1 = load i32, i32* @v1 + %x2 = load i32, i32* @v2 + %x3 = load i32, i32* @v3 + %x4 = load i32, i32* @v4 + %x5 = load i32, i32* @v5 + %x6 = load i32, i32* @v6 ret void } Index: llvm/trunk/test/Other/constant-fold-gep.ll =================================================================== --- llvm/trunk/test/Other/constant-fold-gep.ll +++ llvm/trunk/test/Other/constant-fold-gep.ll @@ -24,18 +24,18 @@ ; PLAIN: @F1 = global i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -2) ; PLAIN: @H8 = global i8* getelementptr (i8, i8* null, i32 -1) ; PLAIN: @H1 = global i1* getelementptr (i1, i1* null, i32 -1) -; OPT: @G8 = global i8* null -; OPT: @G1 = global i1* null -; OPT: @F8 = global i8* inttoptr (i64 -1 to i8*) -; OPT: @F1 = global i1* inttoptr (i64 -1 to i1*) -; OPT: @H8 = global i8* inttoptr (i64 -1 to i8*) -; OPT: @H1 = global i1* inttoptr (i64 -1 to i1*) -; TO: @G8 = global i8* null -; TO: @G1 = global i1* null -; TO: @F8 = global i8* inttoptr (i64 -1 to i8*) -; TO: @F1 = global i1* inttoptr (i64 -1 to i1*) -; TO: @H8 = global i8* inttoptr (i64 -1 to i8*) -; TO: @H1 = global i1* inttoptr (i64 -1 to i1*) +; OPT: @G8 = local_unnamed_addr global i8* null +; OPT: @G1 = local_unnamed_addr global i1* null +; OPT: @F8 = local_unnamed_addr global i8* inttoptr (i64 -1 to i8*) +; OPT: @F1 = local_unnamed_addr global i1* inttoptr (i64 -1 to i1*) +; OPT: @H8 = local_unnamed_addr global i8* inttoptr (i64 -1 to i8*) +; OPT: @H1 = local_unnamed_addr global i1* inttoptr (i64 -1 to i1*) +; TO: @G8 = local_unnamed_addr global i8* null +; TO: @G1 = local_unnamed_addr global i1* null +; TO: @F8 = local_unnamed_addr global i8* inttoptr (i64 -1 to i8*) +; TO: @F1 = local_unnamed_addr global i1* inttoptr (i64 -1 to i1*) +; TO: @H8 = local_unnamed_addr global i8* inttoptr (i64 -1 to i8*) +; TO: @H1 = local_unnamed_addr global i1* inttoptr (i64 -1 to i1*) @G8 = global i8* getelementptr (i8, i8* inttoptr (i32 1 to i8*), i32 -1) @G1 = global i1* getelementptr (i1, i1* inttoptr (i32 1 to i1*), i32 -1) @@ -57,24 +57,24 @@ ; PLAIN: @g = constant i64 ptrtoint (double* getelementptr ({ i1, double }, { i1, double }* null, i64 0, i32 1) to i64) ; PLAIN: @h = constant i64 ptrtoint (i1** getelementptr (i1*, i1** null, i32 1) to i64) ; PLAIN: @i = constant i64 ptrtoint (i1** getelementptr ({ i1, i1* }, { i1, i1* }* null, i64 0, i32 1) to i64) -; OPT: @a = constant i64 18480 -; OPT: @b = constant i64 8 -; OPT: @c = constant i64 16 -; OPT: @d = constant i64 88 -; OPT: @e = constant i64 16 -; OPT: @f = constant i64 1 -; OPT: @g = constant i64 8 -; OPT: @h = constant i64 8 -; OPT: @i = constant i64 8 -; TO: @a = constant i64 18480 -; TO: @b = constant i64 8 -; TO: @c = constant i64 16 -; TO: @d = constant i64 88 -; TO: @e = constant i64 16 -; TO: @f = constant i64 1 -; TO: @g = constant i64 8 -; TO: @h = constant i64 8 -; TO: @i = constant i64 8 +; OPT: @a = local_unnamed_addr constant i64 18480 +; OPT: @b = local_unnamed_addr constant i64 8 +; OPT: @c = local_unnamed_addr constant i64 16 +; OPT: @d = local_unnamed_addr constant i64 88 +; OPT: @e = local_unnamed_addr constant i64 16 +; OPT: @f = local_unnamed_addr constant i64 1 +; OPT: @g = local_unnamed_addr constant i64 8 +; OPT: @h = local_unnamed_addr constant i64 8 +; OPT: @i = local_unnamed_addr constant i64 8 +; TO: @a = local_unnamed_addr constant i64 18480 +; TO: @b = local_unnamed_addr constant i64 8 +; TO: @c = local_unnamed_addr constant i64 16 +; TO: @d = local_unnamed_addr constant i64 88 +; TO: @e = local_unnamed_addr constant i64 16 +; TO: @f = local_unnamed_addr constant i64 1 +; TO: @g = local_unnamed_addr constant i64 8 +; TO: @h = local_unnamed_addr constant i64 8 +; TO: @i = local_unnamed_addr constant i64 8 @a = constant i64 mul (i64 3, i64 mul (i64 ptrtoint ({[7 x double], [7 x double]}* getelementptr ({[7 x double], [7 x double]}, {[7 x double], [7 x double]}* null, i64 11) to i64), i64 5)) @b = constant i64 ptrtoint ([13 x double]* getelementptr ({i1, [13 x double]}, {i1, [13 x double]}* null, i64 0, i32 1) to i64) @@ -91,12 +91,12 @@ ; PLAIN: @M = constant i64* getelementptr (i64, i64* null, i32 1) ; PLAIN: @N = constant i64* getelementptr ({ i64, i64 }, { i64, i64 }* null, i32 0, i32 1) ; PLAIN: @O = constant i64* getelementptr ([2 x i64], [2 x i64]* null, i32 0, i32 1) -; OPT: @M = constant i64* inttoptr (i64 8 to i64*) -; OPT: @N = constant i64* inttoptr (i64 8 to i64*) -; OPT: @O = constant i64* inttoptr (i64 8 to i64*) -; TO: @M = constant i64* inttoptr (i64 8 to i64*) -; TO: @N = constant i64* inttoptr (i64 8 to i64*) -; TO: @O = constant i64* inttoptr (i64 8 to i64*) +; OPT: @M = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*) +; OPT: @N = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*) +; OPT: @O = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*) +; TO: @M = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*) +; TO: @N = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*) +; TO: @O = local_unnamed_addr constant i64* inttoptr (i64 8 to i64*) @M = constant i64* getelementptr (i64, i64* null, i32 1) @N = constant i64* getelementptr ({ i64, i64 }, { i64, i64 }* null, i32 0, i32 1) @@ -106,10 +106,10 @@ ; PLAIN: @Y = global [3 x { i32, i32 }]* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 2) ; PLAIN: @Z = global i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1) -; OPT: @Y = global [3 x { i32, i32 }]* getelementptr ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 2) -; OPT: @Z = global i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1) -; TO: @Y = global [3 x { i32, i32 }]* getelementptr ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 2) -; TO: @Z = global i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1) +; OPT: @Y = local_unnamed_addr global [3 x { i32, i32 }]* getelementptr ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 2) +; OPT: @Z = local_unnamed_addr global i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1) +; TO: @Y = local_unnamed_addr global [3 x { i32, i32 }]* getelementptr ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 2) +; TO: @Z = local_unnamed_addr global i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1) @ext = external global [3 x { i32, i32 }] @Y = global [3 x { i32, i32 }]* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 1), i64 1) @@ -142,40 +142,40 @@ ; PLAIN: %t = bitcast i1* getelementptr (i1, i1* null, i32 -1) to i1* ; PLAIN: ret i1* %t ; PLAIN: } -; OPT: define i8* @goo8() #0 { +; OPT: define i8* @goo8() local_unnamed_addr #0 { ; OPT: ret i8* null ; OPT: } -; OPT: define i1* @goo1() #0 { +; OPT: define i1* @goo1() local_unnamed_addr #0 { ; OPT: ret i1* null ; OPT: } -; OPT: define i8* @foo8() #0 { +; OPT: define i8* @foo8() local_unnamed_addr #0 { ; OPT: ret i8* inttoptr (i64 -1 to i8*) ; OPT: } -; OPT: define i1* @foo1() #0 { +; OPT: define i1* @foo1() local_unnamed_addr #0 { ; OPT: ret i1* inttoptr (i64 -1 to i1*) ; OPT: } -; OPT: define i8* @hoo8() #0 { +; OPT: define i8* @hoo8() local_unnamed_addr #0 { ; OPT: ret i8* inttoptr (i64 -1 to i8*) ; OPT: } -; OPT: define i1* @hoo1() #0 { +; OPT: define i1* @hoo1() local_unnamed_addr #0 { ; OPT: ret i1* inttoptr (i64 -1 to i1*) ; OPT: } -; TO: define i8* @goo8() #0 { +; TO: define i8* @goo8() local_unnamed_addr #0 { ; TO: ret i8* null ; TO: } -; TO: define i1* @goo1() #0 { +; TO: define i1* @goo1() local_unnamed_addr #0 { ; TO: ret i1* null ; TO: } -; TO: define i8* @foo8() #0 { +; TO: define i8* @foo8() local_unnamed_addr #0 { ; TO: ret i8* inttoptr (i64 -1 to i8*) ; TO: } -; TO: define i1* @foo1() #0 { +; TO: define i1* @foo1() local_unnamed_addr #0 { ; TO: ret i1* inttoptr (i64 -1 to i1*) ; TO: } -; TO: define i8* @hoo8() #0 { +; TO: define i8* @hoo8() local_unnamed_addr #0 { ; TO: ret i8* inttoptr (i64 -1 to i8*) ; TO: } -; TO: define i1* @hoo1() #0 { +; TO: define i1* @hoo1() local_unnamed_addr #0 { ; TO: ret i1* inttoptr (i64 -1 to i1*) ; TO: } ; SCEV: Classifying expressions for: @goo8 @@ -256,58 +256,58 @@ ; PLAIN: %t = bitcast i64 ptrtoint (i1** getelementptr ({ i1, i1* }, { i1, i1* }* null, i64 0, i32 1) to i64) to i64 ; PLAIN: ret i64 %t ; PLAIN: } -; OPT: define i64 @fa() #0 { +; OPT: define i64 @fa() local_unnamed_addr #0 { ; OPT: ret i64 18480 ; OPT: } -; OPT: define i64 @fb() #0 { +; OPT: define i64 @fb() local_unnamed_addr #0 { ; OPT: ret i64 8 ; OPT: } -; OPT: define i64 @fc() #0 { +; OPT: define i64 @fc() local_unnamed_addr #0 { ; OPT: ret i64 16 ; OPT: } -; OPT: define i64 @fd() #0 { +; OPT: define i64 @fd() local_unnamed_addr #0 { ; OPT: ret i64 88 ; OPT: } -; OPT: define i64 @fe() #0 { +; OPT: define i64 @fe() local_unnamed_addr #0 { ; OPT: ret i64 16 ; OPT: } -; OPT: define i64 @ff() #0 { +; OPT: define i64 @ff() local_unnamed_addr #0 { ; OPT: ret i64 1 ; OPT: } -; OPT: define i64 @fg() #0 { +; OPT: define i64 @fg() local_unnamed_addr #0 { ; OPT: ret i64 8 ; OPT: } -; OPT: define i64 @fh() #0 { +; OPT: define i64 @fh() local_unnamed_addr #0 { ; OPT: ret i64 8 ; OPT: } -; OPT: define i64 @fi() #0 { +; OPT: define i64 @fi() local_unnamed_addr #0 { ; OPT: ret i64 8 ; OPT: } -; TO: define i64 @fa() #0 { +; TO: define i64 @fa() local_unnamed_addr #0 { ; TO: ret i64 18480 ; TO: } -; TO: define i64 @fb() #0 { +; TO: define i64 @fb() local_unnamed_addr #0 { ; TO: ret i64 8 ; TO: } -; TO: define i64 @fc() #0 { +; TO: define i64 @fc() local_unnamed_addr #0 { ; TO: ret i64 16 ; TO: } -; TO: define i64 @fd() #0 { +; TO: define i64 @fd() local_unnamed_addr #0 { ; TO: ret i64 88 ; TO: } -; TO: define i64 @fe() #0 { +; TO: define i64 @fe() local_unnamed_addr #0 { ; TO: ret i64 16 ; TO: } -; TO: define i64 @ff() #0 { +; TO: define i64 @ff() local_unnamed_addr #0 { ; TO: ret i64 1 ; TO: } -; TO: define i64 @fg() #0 { +; TO: define i64 @fg() local_unnamed_addr #0 { ; TO: ret i64 8 ; TO: } -; TO: define i64 @fh() #0 { +; TO: define i64 @fh() local_unnamed_addr #0 { ; TO: ret i64 8 ; TO: } -; TO: define i64 @fi() #0 { +; TO: define i64 @fi() local_unnamed_addr #0 { ; TO: ret i64 8 ; TO: } ; SCEV: Classifying expressions for: @fa @@ -387,22 +387,22 @@ ; PLAIN: %t = bitcast i64* getelementptr ([2 x i64], [2 x i64]* null, i32 0, i32 1) to i64* ; PLAIN: ret i64* %t ; PLAIN: } -; OPT: define i64* @fM() #0 { +; OPT: define i64* @fM() local_unnamed_addr #0 { ; OPT: ret i64* inttoptr (i64 8 to i64*) ; OPT: } -; OPT: define i64* @fN() #0 { +; OPT: define i64* @fN() local_unnamed_addr #0 { ; OPT: ret i64* inttoptr (i64 8 to i64*) ; OPT: } -; OPT: define i64* @fO() #0 { +; OPT: define i64* @fO() local_unnamed_addr #0 { ; OPT: ret i64* inttoptr (i64 8 to i64*) ; OPT: } -; TO: define i64* @fM() #0 { +; TO: define i64* @fM() local_unnamed_addr #0 { ; TO: ret i64* inttoptr (i64 8 to i64*) ; TO: } -; TO: define i64* @fN() #0 { +; TO: define i64* @fN() local_unnamed_addr #0 { ; TO: ret i64* inttoptr (i64 8 to i64*) ; TO: } -; TO: define i64* @fO() #0 { +; TO: define i64* @fO() local_unnamed_addr #0 { ; TO: ret i64* inttoptr (i64 8 to i64*) ; TO: } ; SCEV: Classifying expressions for: @fM @@ -432,10 +432,10 @@ ; PLAIN: %t = bitcast i32* getelementptr inbounds (i32, i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 0), i64 1) to i32* ; PLAIN: ret i32* %t ; PLAIN: } -; OPT: define i32* @fZ() #0 { +; OPT: define i32* @fZ() local_unnamed_addr #0 { ; OPT: ret i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1) ; OPT: } -; TO: define i32* @fZ() #0 { +; TO: define i32* @fZ() local_unnamed_addr #0 { ; TO: ret i32* getelementptr inbounds ([3 x { i32, i32 }], [3 x { i32, i32 }]* @ext, i64 0, i64 1, i32 1) ; TO: } ; SCEV: Classifying expressions for: @fZ Index: llvm/trunk/test/Transforms/GlobalOpt/2010-10-19-WeakOdr.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/2010-10-19-WeakOdr.ll +++ llvm/trunk/test/Transforms/GlobalOpt/2010-10-19-WeakOdr.ll @@ -2,7 +2,7 @@ ; PR8389: Globals with weak_odr linkage type must not be modified -; CHECK: weak_odr global i32 0 +; CHECK: weak_odr local_unnamed_addr global i32 0 @SomeVar = weak_odr global i32 0 Index: llvm/trunk/test/Transforms/GlobalOpt/alias-used-address-space.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/alias-used-address-space.ll +++ llvm/trunk/test/Transforms/GlobalOpt/alias-used-address-space.ll @@ -16,7 +16,7 @@ ; CHECK-DAG: @llvm.compiler.used = appending global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @ia to i8*)], section "llvm.metadata" @sameAsUsed = global [1 x i8*] [i8* addrspacecast(i8 addrspace(1)* @ca to i8*)] -; CHECK-DAG: @sameAsUsed = global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @c to i8*)] +; CHECK-DAG: @sameAsUsed = local_unnamed_addr global [1 x i8*] [i8* addrspacecast (i8 addrspace(1)* @c to i8*)] @ca = internal alias i8, i8 addrspace(1)* @c ; CHECK: @ca = internal alias i8, i8 addrspace(1)* @c Index: llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll +++ llvm/trunk/test/Transforms/GlobalOpt/alias-used.ll @@ -13,10 +13,10 @@ ; CHECK-DAG: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void ()* @fa3 to i8*), i8* @ia], section "llvm.metadata" @sameAsUsed = global [3 x i8*] [i8* bitcast (void ()* @fa to i8*), i8* bitcast (void ()* @f to i8*), i8* @ca] -; CHECK-DAG: @sameAsUsed = global [3 x i8*] [i8* bitcast (void ()* @f to i8*), i8* bitcast (void ()* @f to i8*), i8* @c] +; CHECK-DAG: @sameAsUsed = local_unnamed_addr global [3 x i8*] [i8* bitcast (void ()* @f to i8*), i8* bitcast (void ()* @f to i8*), i8* @c] @other = global i32* bitcast (void ()* @fa to i32*) -; CHECK-DAG: @other = global i32* bitcast (void ()* @f to i32*) +; CHECK-DAG: @other = local_unnamed_addr global i32* bitcast (void ()* @f to i32*) @fa = internal alias void (), void ()* @f ; CHECK: @fa = internal alias void (), void ()* @f Index: llvm/trunk/test/Transforms/GlobalOpt/assume.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/assume.ll +++ llvm/trunk/test/Transforms/GlobalOpt/assume.ll @@ -1,6 +1,6 @@ ; RUN: opt -S -globalopt < %s | FileCheck %s -; CHECK: @tmp = global i32 42 +; CHECK: @tmp = local_unnamed_addr global i32 42 @llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] @tmp = global i32 0 Index: llvm/trunk/test/Transforms/GlobalOpt/constantfold-initializers.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/constantfold-initializers.ll +++ llvm/trunk/test/Transforms/GlobalOpt/constantfold-initializers.ll @@ -4,13 +4,13 @@ @.str91250 = global [3 x i8] zeroinitializer -; CHECK: @A = global i1 false +; CHECK: @A = local_unnamed_addr global i1 false @A = global i1 icmp ne (i64 sub nsw (i64 ptrtoint (i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str91250, i64 0, i64 1) to i64), i64 ptrtoint ([3 x i8]* @.str91250 to i64)), i64 1) ; PR11352 @xs = global [2 x i32] zeroinitializer, align 4 -; CHECK: @xs = global [2 x i32] [i32 1, i32 1] +; CHECK: @xs = local_unnamed_addr global [2 x i32] [i32 1, i32 1] ; PR12642 %PR12642.struct = type { i8 } @@ -32,7 +32,7 @@ @f = internal global %closure zeroinitializer, align 4 @m = global i32 0, align 4 ; CHECK-NOT: @f -; CHECK: @m = global i32 13 +; CHECK: @m = local_unnamed_addr global i32 13 define internal i32 @test2_helper(%closure* %this, i32 %b) { entry: @@ -53,7 +53,7 @@ ; PR19955 @dllimportptr = global i32* null, align 4 -; CHECK: @dllimportptr = global i32* null, align 4 +; CHECK: @dllimportptr = local_unnamed_addr global i32* null, align 4 @dllimportvar = external dllimport global i32 define internal void @test3() { entry: @@ -62,7 +62,7 @@ } @dllexportptr = global i32* null, align 4 -; CHECK: @dllexportptr = global i32* @dllexportvar, align 4 +; CHECK: @dllexportptr = local_unnamed_addr global i32* @dllexportvar, align 4 @dllexportvar = dllexport global i32 0, align 4 ; CHECK: @dllexportvar = dllexport global i32 20, align 4 define internal void @test4() { @@ -83,7 +83,7 @@ @test6_v1 = internal global { i32, i32 } { i32 42, i32 0 }, align 8 @test6_v2 = global i32 0, align 4 -; CHECK: @test6_v2 = global i32 42, align 4 +; CHECK: @test6_v2 = local_unnamed_addr global i32 42, align 4 define internal void @test6() { %load = load { i32, i32 }, { i32, i32 }* @test6_v1, align 8 %xv0 = extractvalue { i32, i32 } %load, 0 Index: llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-inbounds.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-inbounds.ll +++ llvm/trunk/test/Transforms/GlobalOpt/ctor-list-opt-inbounds.ll @@ -3,8 +3,8 @@ ; Don't get fooled by the inbounds keyword; it doesn't change ; the computed address. -; CHECK: @H = global i32 2 -; CHECK: @I = global i32 2 +; CHECK: @H = local_unnamed_addr global i32 2 +; CHECK: @I = local_unnamed_addr global i32 2 @llvm.global_ctors = appending global [1 x { i32, void ()* }] [ { i32, void ()* } { i32 65535, void ()* @CTOR } ] @addr = external global i32 Index: llvm/trunk/test/Transforms/GlobalOpt/invariant.group.barrier.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/invariant.group.barrier.ll +++ llvm/trunk/test/Transforms/GlobalOpt/invariant.group.barrier.ll @@ -2,8 +2,8 @@ ; This test is hint, what could globalOpt optimize and what it can't ; FIXME: @tmp and @tmp2 can be safely set to 42 -; CHECK: @tmp = global i32 0 -; CHECK: @tmp2 = global i32 0 +; CHECK: @tmp = local_unnamed_addr global i32 0 +; CHECK: @tmp2 = local_unnamed_addr global i32 0 ; CHECK: @tmp3 = global i32 0 @tmp = global i32 0 Index: llvm/trunk/test/Transforms/GlobalOpt/invoke.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/invoke.ll +++ llvm/trunk/test/Transforms/GlobalOpt/invoke.ll @@ -2,7 +2,7 @@ ; rdar://11022897 ; Globalopt should be able to evaluate an invoke. -; CHECK: @tmp = global i32 1 +; CHECK: @tmp = local_unnamed_addr global i32 1 @llvm.global_ctors = appending global [1 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] @tmp = global i32 0 Index: llvm/trunk/test/Transforms/GlobalOpt/pr21191.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/pr21191.ll +++ llvm/trunk/test/Transforms/GlobalOpt/pr21191.ll @@ -6,12 +6,12 @@ define linkonce_odr void @foo() comdat($c) { ret void } -; CHECK: define linkonce_odr void @foo() comdat($c) +; CHECK: define linkonce_odr void @foo() local_unnamed_addr comdat($c) define linkonce_odr void @bar() comdat($c) { ret void } -; CHECK: define linkonce_odr void @bar() comdat($c) +; CHECK: define linkonce_odr void @bar() local_unnamed_addr comdat($c) define void @zed() { call void @foo() Index: llvm/trunk/test/Transforms/GlobalOpt/unnamed-addr.ll =================================================================== --- llvm/trunk/test/Transforms/GlobalOpt/unnamed-addr.ll +++ llvm/trunk/test/Transforms/GlobalOpt/unnamed-addr.ll @@ -10,7 +10,7 @@ ; CHECK: @b = internal global i32 0, align 4 ; CHECK: @c = internal unnamed_addr global i32 0, align 4 ; CHECK: @d = internal unnamed_addr constant [4 x i8] c"foo\00", align 1 -; CHECK: @e = linkonce_odr global i32 0 +; CHECK: @e = linkonce_odr local_unnamed_addr global i32 0 ; CHECK: define internal fastcc void @used_internal() unnamed_addr { define internal void @used_internal() { Index: llvm/trunk/test/tools/gold/X86/coff.ll =================================================================== --- llvm/trunk/test/tools/gold/X86/coff.ll +++ llvm/trunk/test/tools/gold/X86/coff.ll @@ -16,7 +16,7 @@ ret void } -; CHECK: define internal void @h() { -define linkonce_odr void @h() { +; CHECK: define internal void @h() local_unnamed_addr { +define linkonce_odr void @h() local_unnamed_addr { ret void } Index: llvm/trunk/test/tools/gold/X86/emit-llvm.ll =================================================================== --- llvm/trunk/test/tools/gold/X86/emit-llvm.ll +++ llvm/trunk/test/tools/gold/X86/emit-llvm.ll @@ -25,6 +25,24 @@ target triple = "x86_64-unknown-linux-gnu" +; CHECK-DAG: @g1 = linkonce_odr constant i32 32 +@g1 = linkonce_odr constant i32 32 + +; CHECK-DAG: @g2 = internal local_unnamed_addr constant i32 32 +@g2 = linkonce_odr local_unnamed_addr constant i32 32 + +; CHECK-DAG: @g3 = internal unnamed_addr constant i32 32 +@g3 = linkonce_odr unnamed_addr constant i32 32 + +; CHECK-DAG: @g4 = linkonce_odr global i32 32 +@g4 = linkonce_odr global i32 32 + +; CHECK-DAG: @g5 = linkonce_odr local_unnamed_addr global i32 32 +@g5 = linkonce_odr local_unnamed_addr global i32 32 + +; CHECK-DAG: @g6 = internal unnamed_addr global i32 32 +@g6 = linkonce_odr unnamed_addr global i32 32 + @g7 = extern_weak global i32 ; CHECK-DAG: @g7 = extern_weak global i32 @@ -53,7 +71,7 @@ ; CHECK-DAG: define internal void @f4() ; OPT2-NOT: @f4 -define linkonce_odr void @f4() { +define linkonce_odr void @f4() local_unnamed_addr { ret void } @@ -62,14 +80,14 @@ define linkonce_odr void @f5() { ret void } -@g5 = global void()* @f5 +@g9 = global void()* @f5 ; CHECK-DAG: define internal void @f6() unnamed_addr ; OPT-DAG: define internal void @f6() unnamed_addr define linkonce_odr void @f6() unnamed_addr { ret void } -@g6 = global void()* @f6 +@g10 = global void()* @f6 define i32* @f7() { ret i32* @g7 @@ -89,5 +107,5 @@ ; API: f8 PREVAILING_DEF_IRONLY_EXP ; API: g7 UNDEF ; API: g8 UNDEF -; API: g5 PREVAILING_DEF_IRONLY_EXP -; API: g6 PREVAILING_DEF_IRONLY_EXP +; API: g9 PREVAILING_DEF_IRONLY_EXP +; API: g10 PREVAILING_DEF_IRONLY_EXP Index: llvm/trunk/tools/gold/gold-plugin.cpp =================================================================== --- llvm/trunk/tools/gold/gold-plugin.cpp +++ llvm/trunk/tools/gold/gold-plugin.cpp @@ -109,7 +109,7 @@ uint64_t CommonSize = 0; unsigned CommonAlign = 0; bool IsLinkonceOdr = true; - bool UnnamedAddr = true; + GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::Global; GlobalValue::VisibilityTypes Visibility = GlobalValue::DefaultVisibility; bool CommonInternal = false; bool UseCommon = false; @@ -551,7 +551,8 @@ sym.visibility = LDPV_DEFAULT; if (GV) { - Res.UnnamedAddr &= GV->hasUnnamedAddr(); + Res.UnnamedAddr = + GlobalValue::getMinUnnamedAddr(Res.UnnamedAddr, GV->getUnnamedAddr()); Res.IsLinkonceOdr &= GV->hasLinkOnceLinkage(); Res.Visibility = getMinVisibility(Res.Visibility, GV->getVisibility()); switch (GV->getVisibility()) { @@ -690,10 +691,11 @@ return Obj.takeIndex(); } -static std::unique_ptr getModuleForFile( - LLVMContext &Context, claimed_file &F, const void *View, StringRef Name, - raw_fd_ostream *ApiFile, StringSet<> &Internalize, StringSet<> &Maybe, - std::vector &Keep, StringMap &Realign) { +static std::unique_ptr +getModuleForFile(LLVMContext &Context, claimed_file &F, const void *View, + StringRef Name, raw_fd_ostream *ApiFile, + StringSet<> &Internalize, std::vector &Keep, + StringMap &Realign) { MemoryBufferRef BufferRef(StringRef((const char *)View, F.filesize), Name); ErrorOr> ObjOrErr = object::IRObjectFile::create(BufferRef, Context); @@ -827,12 +829,9 @@ break; case LDPR_PREVAILING_DEF_IRONLY_EXP: { - // We can only check for address uses after we merge the modules. The - // reason is that this GV might have a copy in another module - // and in that module the address might be significant, but that - // copy will be LDPR_PREEMPTED_IR. - Maybe.insert(GV->getName()); Keep.push_back(GV); + if (canBeOmittedFromSymbolTable(GV)) + Internalize.insert(GV->getName()); break; } } @@ -1149,11 +1148,11 @@ static void linkInModule(LLVMContext &Context, IRMover &L, claimed_file &F, const void *View, StringRef Name, raw_fd_ostream *ApiFile, StringSet<> &Internalize, - StringSet<> &Maybe, bool SetName = false) { + bool SetName = false) { std::vector Keep; StringMap Realign; - std::unique_ptr M = getModuleForFile( - Context, F, View, Name, ApiFile, Internalize, Maybe, Keep, Realign); + std::unique_ptr M = getModuleForFile(Context, F, View, Name, ApiFile, + Internalize, Keep, Realign); if (!M.get()) return; if (!options::triple.empty()) @@ -1204,7 +1203,7 @@ IRMover L(*NewModule.get()); StringSet<> Dummy; - linkInModule(Context, L, F, View, Name, ApiFile, Dummy, Dummy, true); + linkInModule(Context, L, F, View, Name, ApiFile, Dummy, true); if (renameModuleForThinLTO(*NewModule, CombinedIndex)) message(LDPL_FATAL, "Failed to rename module for ThinLTO"); @@ -1474,7 +1473,6 @@ IRMover L(*Combined); StringSet<> Internalize; - StringSet<> Maybe; for (claimed_file &F : Modules) { // RAII object to manage the file opening and releasing interfaces with // gold. @@ -1482,7 +1480,7 @@ const void *View = getSymbolsAndView(F); if (!View) continue; - linkInModule(Context, L, F, View, F.name, ApiFile, Internalize, Maybe); + linkInModule(Context, L, F, View, F.name, ApiFile, Internalize); } for (const auto &Name : Internalize) { @@ -1491,15 +1489,6 @@ internalize(*GV); } - for (const auto &Name : Maybe) { - GlobalValue *GV = Combined->getNamedValue(Name.first()); - if (!GV) - continue; - GV->setLinkage(GlobalValue::LinkOnceODRLinkage); - if (canBeOmittedFromSymbolTable(GV)) - internalize(*GV); - } - if (options::TheOutputType == options::OT_DISABLE) return LDPS_OK;