@@ -2206,6 +2209,24 @@ object file to prevent the assembler and linker from molesting the symbol.
+
+
+
+
The @llvm.compiler.used directive is the same as the
+@llvm.used directive, except that it only prevents the compiler from
+touching the symbol. On targets that support it, this allows an intelligent
+linker to optimize references to the symbol without being impeded as it would be
+by @llvm.used.
+
+
This is a rare construct that should only be used in rare circumstances, and
+should not be exposed to source languages.
+
+
+
The 'llvm.global_ctors' Global Variable
diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h
index 1872bd26d8a..3618898a79d 100644
--- a/include/llvm/CodeGen/MachineModuleInfo.h
+++ b/include/llvm/CodeGen/MachineModuleInfo.h
@@ -112,8 +112,9 @@ private:
// common EH frames.
std::vector
Personalities;
- // UsedFunctions - the functions in the llvm.used list in a more easily
- // searchable format.
+ /// UsedFunctions - The functions in the @llvm.used list in a more easily
+ /// searchable format. This does not include the functions in
+ /// llvm.compiler.used.
SmallPtrSet UsedFunctions;
/// UsedDbgLabels - labels are used by debug info entries.
@@ -240,9 +241,11 @@ public:
return Personalities;
}
- // UsedFunctions - Return set of the functions in the llvm.used list.
- const SmallPtrSet& getUsedFunctions() const {
- return UsedFunctions;
+ /// isUsedFunction - Return true if the functions in the llvm.used list. This
+ /// does not return true for things in llvm.compiler.used unless they are also
+ /// in llvm.used.
+ bool isUsedFunction(const Function *F) {
+ return UsedFunctions.count(F);
}
/// addCatchTypeInfo - Provide the catch typeinfo for a landing pad.
diff --git a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index a2d154f1ee6..80bdf04e8e8 100644
--- a/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -466,13 +466,13 @@ void AsmPrinter::printPICJumpTableEntry(const MachineJumpTableInfo *MJTI,
/// special global used by LLVM. If so, emit it and return true, otherwise
/// do nothing and return false.
bool AsmPrinter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
- if (GV->getName() == "llvm.used") {
+ if (GV->isName("llvm.used")) {
if (TAI->getUsedDirective() != 0) // No need to emit this at all.
EmitLLVMUsedList(GV->getInitializer());
return true;
}
- // Ignore debug and non-emitted data.
+ // Ignore debug and non-emitted data. This handles llvm.compiler.used.
if (GV->getSection() == "llvm.metadata" ||
GV->hasAvailableExternallyLinkage())
return true;
diff --git a/lib/CodeGen/AsmPrinter/DwarfException.cpp b/lib/CodeGen/AsmPrinter/DwarfException.cpp
index 1af3b118465..fdec97ac6ac 100644
--- a/lib/CodeGen/AsmPrinter/DwarfException.cpp
+++ b/lib/CodeGen/AsmPrinter/DwarfException.cpp
@@ -229,7 +229,7 @@ void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) {
// retains the function in this case, and there is code around that depends
// on unused functions (calling undefined externals) being dead-stripped to
// link correctly. Yes, there really is.
- if (MMI->getUsedFunctions().count(EHFrameInfo.function))
+ if (MMI->isUsedFunction(EHFrameInfo.function))
if (const char *UsedDirective = TAI->getUsedDirective())
O << UsedDirective << EHFrameInfo.FnName << "\n\n";
}
diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp
index 66dd8375eb5..20b819e8235 100644
--- a/lib/CodeGen/MachineModuleInfo.cpp
+++ b/lib/CodeGen/MachineModuleInfo.cpp
@@ -88,7 +88,8 @@ void MachineModuleInfo::EndFunction() {
/// AnalyzeModule - Scan the module for global debug information.
///
void MachineModuleInfo::AnalyzeModule(Module &M) {
- // Insert functions in the llvm.used array into UsedFunctions.
+ // Insert functions in the llvm.used array (but not llvm.compiler.used) into
+ // UsedFunctions.
GlobalVariable *GV = M.getGlobalVariable("llvm.used");
if (!GV || !GV->hasInitializer()) return;
diff --git a/lib/Transforms/IPO/Internalize.cpp b/lib/Transforms/IPO/Internalize.cpp
index 9bc91725170..da92634abf7 100644
--- a/lib/Transforms/IPO/Internalize.cpp
+++ b/lib/Transforms/IPO/Internalize.cpp
@@ -138,7 +138,9 @@ bool InternalizePass::runOnModule(Module &M) {
// Never internalize the llvm.used symbol. It is used to implement
// attribute((used)).
+ // FIXME: Shouldn't this just filter on llvm.metadata section??
ExternalNames.insert("llvm.used");
+ ExternalNames.insert("llvm.compiler.used");
// Never internalize anchors used by the machine module info, else the info
// won't find them. (see MachineModuleInfo.)
diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp
index 82a0952aa20..8f3a7f4a649 100644
--- a/lib/Transforms/IPO/StripSymbols.cpp
+++ b/lib/Transforms/IPO/StripSymbols.cpp
@@ -157,32 +157,26 @@ static void StripTypeSymtab(TypeSymbolTable &ST, bool PreserveDbgInfo) {
}
/// Find values that are marked as llvm.used.
-void findUsedValues(Module &M,
- SmallPtrSet& llvmUsedValues) {
- if (GlobalVariable *LLVMUsed = M.getGlobalVariable("llvm.used")) {
- llvmUsedValues.insert(LLVMUsed);
- // Collect values that are preserved as per explicit request.
- // llvm.used is used to list these values.
- if (ConstantArray *Inits =
- dyn_cast(LLVMUsed->getInitializer())) {
- for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) {
- if (GlobalValue *GV = dyn_cast(Inits->getOperand(i)))
- llvmUsedValues.insert(GV);
- else if (ConstantExpr *CE =
- dyn_cast(Inits->getOperand(i)))
- if (CE->getOpcode() == Instruction::BitCast)
- if (GlobalValue *GV = dyn_cast(CE->getOperand(0)))
- llvmUsedValues.insert(GV);
- }
- }
- }
+static void findUsedValues(GlobalVariable *LLVMUsed,
+ SmallPtrSet &UsedValues) {
+ if (LLVMUsed == 0) return;
+ UsedValues.insert(LLVMUsed);
+
+ ConstantArray *Inits = dyn_cast(LLVMUsed->getInitializer());
+ if (Inits == 0) return;
+
+ for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
+ if (GlobalValue *GV =
+ dyn_cast(Inits->getOperand(i)->stripPointerCasts()))
+ UsedValues.insert(GV);
}
/// StripSymbolNames - Strip symbol names.
bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
SmallPtrSet llvmUsedValues;
- findUsedValues(M, llvmUsedValues);
+ findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
+ findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
@@ -210,7 +204,8 @@ bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
bool StripDebugInfo(Module &M) {
SmallPtrSet llvmUsedValues;
- findUsedValues(M, llvmUsedValues);
+ findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
+ findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);
SmallVector CUs;
SmallVector GVs;
diff --git a/test/CodeGen/X86/compiler_used.ll b/test/CodeGen/X86/compiler_used.ll
new file mode 100644
index 00000000000..b67bc36d507
--- /dev/null
+++ b/test/CodeGen/X86/compiler_used.ll
@@ -0,0 +1,9 @@
+; RUN: llvm-as < %s | llc -mtriple=i386-apple-darwin9 | grep no_dead_strip | count 1
+; We should have a .no_dead_strip directive for Z but not for X/Y.
+
+@X = internal global i8 4
+@Y = internal global i32 123
+@Z = internal global i8 4
+
+@llvm.used = appending global [1 x i8*] [ i8* @Z ], section "llvm.metadata"
+@llvm.compiler_used = appending global [2 x i8*] [ i8* @X, i8* bitcast (i32* @Y to i8*)], section "llvm.metadata"