* ``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:
* *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<bcunnamedaddr>` attribute of this function
* *prologuedata*: If non-zero, the value index of the prologue data for this function,
plus 1.
* *threadlocal*: If present, an encoding of the
:ref:`thread local property<bcthreadlocal>` 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<bcunnamedaddr>` attribute of this alias
MODULE_CODE_PURGEVALS Record
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
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
Syntax::
@<GlobalVarName> = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal]
- [unnamed_addr] [AddrSpace] [ExternallyInitialized]
+ [(unnamed_addr|local_unnamed_addr)] [AddrSpace]
+ [ExternallyInitialized]
<global | constant> <Type> [<InitializerConstant>]
[, section "name"] [, comdat [($name)]]
[, align <Alignment>] (, !name !N)*
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 <linkage>`, an optional :ref:`visibility
-style <visibility>`, an optional :ref:`DLL storage class <dllstorageclass>`,
-an optional :ref:`calling convention <callingconv>`,
-an optional ``unnamed_addr`` attribute, a return type, an optional
-:ref:`parameter attribute <paramattrs>` for the return type, a function
-name, a possibly empty list of arguments, an optional alignment, an optional
-:ref:`garbage collector name <gc>`, an optional :ref:`prefix <prefixdata>`,
-and an optional :ref:`prologue <prologuedata>`.
+optional :ref:`linkage type <linkage>`, an optional :ref:`visibility style
+<visibility>`, an optional :ref:`DLL storage class <dllstorageclass>`, an
+optional :ref:`calling convention <callingconv>`, an optional ``unnamed_addr``
+or ``local_unnamed_addr`` attribute, a return type, an optional :ref:`parameter
+attribute <paramattrs>` for the return type, a function name, a possibly
+empty list of arguments, an optional alignment, an optional :ref:`garbage
+collector name <gc>`, an optional :ref:`prefix <prefixdata>`, and an optional
+:ref:`prologue <prologuedata>`.
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
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]
<ResultType> @<FunctionName> ([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:
Syntax::
- @<Name> = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] [unnamed_addr] alias <AliaseeTy>, <AliaseeTy>* @<Aliasee>
+ @<Name> = [Linkage] [Visibility] [DLLStorageClass] [ThreadLocal] [(unnamed_addr|local_unnamed_addr)] alias <AliaseeTy>, <AliaseeTy>* @<Aliasee>
The linkage must be one of ``private``, ``internal``, ``linkonce``, ``weak``,
``linkonce_odr``, ``weak_odr``, ``external``. Note that some system linkers
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:
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);
}
// 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
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;
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();
return AI->getParent() && AI->getFunction() && AI->isStaticAlloca();
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
return (GV->hasLocalLinkage() || GV->hasHiddenVisibility() ||
- GV->hasProtectedVisibility() || GV->hasUnnamedAddr()) &&
+ GV->hasProtectedVisibility() || GV->hasGlobalUnnamedAddr()) &&
!GV->isThreadLocal();
if (const Argument *A = dyn_cast<Argument>(V))
return A->hasByValAttr();
KEYWORD(hidden);
KEYWORD(protected);
KEYWORD(unnamed_addr);
+ KEYWORD(local_unnamed_addr);
KEYWORD(externally_initialized);
KEYWORD(extern_weak);
KEYWORD(external);
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
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)
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)
///
/// 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;
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");
std::string Section;
unsigned Alignment;
std::string GC;
- bool UnnamedAddr;
+ GlobalValue::UnnamedAddr UnnamedAddr = GlobalValue::UnnamedAddr::None;
LocTy UnnamedAddrLoc;
Constant *Prefix = nullptr;
Constant *Prologue = nullptr;
Comdat *C;
if (ParseArgumentList(ArgList, isVarArg) ||
- ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
- &UnnamedAddrLoc) ||
+ ParseOptionalUnnamedAddr(UnnamedAddr) ||
ParseFnAttributeValuePairs(FuncAttrs, FwdRefAttrGrps, false,
BuiltinLoc) ||
(EatIfPresent(lltok::kw_section) &&
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);
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();
kw_hidden,
kw_protected,
kw_unnamed_addr,
+ kw_local_unnamed_addr,
kw_externally_initialized,
kw_extern_weak,
kw_external,
}
}
+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;
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)
} else if (hasImplicitComdat(RawLinkage)) {
NewGV->setComdat(reinterpret_cast<Comdat *>(1));
}
+
break;
}
case bitc::MODULE_CODE_GLOBALVAR_ATTACHMENT: {
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));
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;
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<unsigned, 64> Vals;
for (const Comdat *C : VE.getComdats()) {
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);
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));
// 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()));
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();
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
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<GlobalAlias>(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
// 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<GlobalValue>(GV->getOperand(0)))
return false;
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.
V.setLinkage(GlobalValue::ExternalLinkage);
V.setVisibility(GlobalValue::HiddenVisibility);
}
- V.setUnnamedAddr(false);
+ V.setUnnamedAddr(GlobalValue::UnnamedAddr::None);
assert(!R.needsRenaming(V) && "Invalid global name.");
}
}
}
+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();
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 << ") ";
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<GlobalAlias>(GIS))
Out << "alias ";
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()) {
}
LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global) {
- return unwrap<GlobalValue>(Global)->hasUnnamedAddr();
+ return unwrap<GlobalValue>(Global)->hasGlobalUnnamedAddr();
}
void LLVMSetUnnamedAddr(LLVMValueRef Global, LLVMBool HasUnnamedAddr) {
- unwrap<GlobalValue>(Global)->setUnnamedAddr(HasUnnamedAddr);
+ unwrap<GlobalValue>(Global)->setUnnamedAddr(
+ HasUnnamedAddr ? GlobalValue::UnnamedAddr::Global
+ : GlobalValue::UnnamedAddr::None);
}
/*--.. Operations on global variables, load and store instructions .........--*/
/// 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());
}
StrConstant, Name, nullptr,
GlobalVariable::NotThreadLocal,
AddressSpace);
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
return GV;
}
if (Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::JumpTable)) {
const GlobalValue *GV = cast<GlobalValue>(V);
- Assert(GV->hasUnnamedAddr(),
+ Assert(GV->hasGlobalUnnamedAddr(),
"Attribute 'jumptable' requires 'unnamed_addr'", V);
}
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!");
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
nullptr,
GlobalVariable::NotThreadLocal,
AMDGPUAS::LOCAL_ADDRESS);
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
GV->setAlignment(I.getAlignment());
Value *TCntY, *TCntZ;
// 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"
if (A.hasLocalLinkage() && !B.hasLocalLinkage())
return false;
- return A.hasUnnamedAddr();
+ return A.hasGlobalUnnamedAddr();
}
static unsigned getAlignment(GlobalVariable *GV) {
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));
static bool
processGlobal(GlobalValue &GV, TargetLibraryInfo *TLI,
function_ref<DominatorTree &(Function &)> LookupDomTree) {
- // Do more involved optimizations if the global is internal.
- if (!GV.hasLocalLinkage())
+ if (GV.getName().startswith("llvm."))
return false;
GlobalStatus GS;
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<GlobalVariable>(&GV);
if (!GVar)
return Changed;
// 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);
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;
}
auto GV = new GlobalVariable(M, LocStruct->getType(), true,
GlobalValue::PrivateLinkage, LocStruct,
kAsanGenPrefix);
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
return GV;
}
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;
}
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)
ConstantArray::get(EdgeTableTy,
makeArrayRef(&EdgeTable[0],TableSize)),
"__llvm_gcda_edge_table");
- EdgeTableGV->setUnnamedAddr(true);
+ EdgeTableGV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
return EdgeTableGV;
}
ConstantInt::get(Type::getInt32Ty(*Ctx),
0xffffffff),
"__llvm_gcov_global_state_pred");
- GV->setUnnamedAddr(true);
+ GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
}
return GV;
}
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);
void GCOVProfiler::insertIndirectCounterIncrement() {
Function *Fn =
cast<Function>(GCOVProfiler::getIncrementIndirectCounterFunc());
- Fn->setUnnamedAddr(true);
+ Fn->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
Fn->setLinkage(GlobalValue::InternalLinkage);
Fn->addFnAttr(Attribute::NoInline);
if (Options.NoRedZone)
"__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);
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);
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);
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});
// of the module and recorded in the summary index for use when importing
// from that module.
auto *GVar = dyn_cast<GlobalVariable>(SGV);
- if (GVar && GVar->isConstant() && GVar->hasUnnamedAddr())
+ if (GVar && GVar->isConstant() && GVar->hasGlobalUnnamedAddr())
return false;
if (GVar && GVar->hasSection())
}
}
- if (StoredVal == GV->getInitializer()) {
+ if (GV->hasInitializer() && StoredVal == GV->getInitializer()) {
if (GS.StoredType < GlobalStatus::InitializerStored)
GS.StoredType = GlobalStatus::InitializerStored;
} else if (isa<LoadInst>(StoredVal) &&
Array = new GlobalVariable(M, ArrayTy, /*constant=*/true,
GlobalVariable::PrivateLinkage, Initializer,
"switch.table");
- Array->setUnnamedAddr(true);
+ Array->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
Kind = ArrayKind;
}
--- /dev/null
+; 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
+}
;; Global Variables
; Format: [@<GlobalVarName> =] [Linkage] [Visibility] [DLLStorageClass]
-; [ThreadLocal] [unnamed_addr] [AddrSpace] [ExternallyInitialized]
+; [ThreadLocal] [(unnamed_addr|local_unnamed_addr)] [AddrSpace] [ExternallyInitialized]
; <global | constant> <Type> [<InitializerConstant>]
; [, section "name"] [, comdat [($name)]] [, align <Alignment>]
@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
@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 @<Name> = [Linkage] [Visibility] ifunc <IFuncTy>,
; Format: define [linkage] [visibility] [DLLStorageClass]
; [cconv] [ret attrs]
; <ResultType> @<FunctionName> ([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] { ... }
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)
; 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
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
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
; 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
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
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
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) ]
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
; 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
}
; 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)
; 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)
; 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)
; 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)
; 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
; 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
; 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
; 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
; 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
; 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
; 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
; 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
@.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 }
@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:
; 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:
}
@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() {
@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
; 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
; 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
; 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
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()
; 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() {
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
}
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
; CHECK-DAG: define internal void @f4()
; OPT2-NOT: @f4
-define linkonce_odr void @f4() {
+define linkonce_odr void @f4() local_unnamed_addr {
ret void
}
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
; 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
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;
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()) {
return Obj.takeIndex();
}
-static std::unique_ptr<Module> getModuleForFile(
- LLVMContext &Context, claimed_file &F, const void *View, StringRef Name,
- raw_fd_ostream *ApiFile, StringSet<> &Internalize, StringSet<> &Maybe,
- std::vector<GlobalValue *> &Keep, StringMap<unsigned> &Realign) {
+static std::unique_ptr<Module>
+getModuleForFile(LLVMContext &Context, claimed_file &F, const void *View,
+ StringRef Name, raw_fd_ostream *ApiFile,
+ StringSet<> &Internalize, std::vector<GlobalValue *> &Keep,
+ StringMap<unsigned> &Realign) {
MemoryBufferRef BufferRef(StringRef((const char *)View, F.filesize), Name);
ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
object::IRObjectFile::create(BufferRef, Context);
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;
}
}
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<GlobalValue *> Keep;
StringMap<unsigned> Realign;
- std::unique_ptr<Module> M = getModuleForFile(
- Context, F, View, Name, ApiFile, Internalize, Maybe, Keep, Realign);
+ std::unique_ptr<Module> M = getModuleForFile(Context, F, View, Name, ApiFile,
+ Internalize, Keep, Realign);
if (!M.get())
return;
if (!options::triple.empty())
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");
IRMover L(*Combined);
StringSet<> Internalize;
- StringSet<> Maybe;
for (claimed_file &F : Modules) {
// RAII object to manage the file opening and releasing interfaces with
// gold.
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) {
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;