aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/IPO
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2013-06-12 13:32:42 -0700
committerStephen Hines <srhines@google.com>2013-06-12 13:32:42 -0700
commit1878f9a7874b1ff569d745c0269f49d3daf7203d (patch)
tree19a8dbaaedf6a056c617e87596b32d3f452af137 /lib/Transforms/IPO
parent7a57f27b857ec4b243d83d392a399f02fc196c0a (diff)
parent100fbdd06be7590b23c4707a98cd605bdb519498 (diff)
downloadexternal_llvm-1878f9a7874b1ff569d745c0269f49d3daf7203d.zip
external_llvm-1878f9a7874b1ff569d745c0269f49d3daf7203d.tar.gz
external_llvm-1878f9a7874b1ff569d745c0269f49d3daf7203d.tar.bz2
Merge commit '100fbdd06be7590b23c4707a98cd605bdb519498' into merge_20130612
Diffstat (limited to 'lib/Transforms/IPO')
-rw-r--r--lib/Transforms/IPO/ConstantMerge.cpp10
-rw-r--r--lib/Transforms/IPO/DeadArgumentElimination.cpp22
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp206
-rw-r--r--lib/Transforms/IPO/PassManagerBuilder.cpp8
-rw-r--r--lib/Transforms/IPO/StripSymbols.cpp15
5 files changed, 212 insertions, 49 deletions
diff --git a/lib/Transforms/IPO/ConstantMerge.cpp b/lib/Transforms/IPO/ConstantMerge.cpp
index b63495b..a7bf188 100644
--- a/lib/Transforms/IPO/ConstantMerge.cpp
+++ b/lib/Transforms/IPO/ConstantMerge.cpp
@@ -27,6 +27,7 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
#include "llvm/Pass.h"
using namespace llvm;
@@ -68,10 +69,11 @@ static void FindUsedValues(GlobalVariable *LLVMUsed,
if (LLVMUsed == 0) return;
ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
- for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
- if (GlobalValue *GV =
- dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
- UsedValues.insert(GV);
+ for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) {
+ Value *Operand = Inits->getOperand(i)->stripPointerCastsNoFollowAliases();
+ GlobalValue *GV = cast<GlobalValue>(Operand);
+ UsedValues.insert(GV);
+ }
}
// True if A is better than B.
diff --git a/lib/Transforms/IPO/DeadArgumentElimination.cpp b/lib/Transforms/IPO/DeadArgumentElimination.cpp
index 49ef1e7..3fdb5f0 100644
--- a/lib/Transforms/IPO/DeadArgumentElimination.cpp
+++ b/lib/Transforms/IPO/DeadArgumentElimination.cpp
@@ -343,8 +343,9 @@ bool DAE::RemoveDeadArgumentsFromCallers(Function &Fn)
if (Fn.isDeclaration() || Fn.mayBeOverridden())
return false;
- // Functions with local linkage should already have been handled.
- if (Fn.hasLocalLinkage())
+ // Functions with local linkage should already have been handled, except the
+ // fragile (variadic) ones which we can improve here.
+ if (Fn.hasLocalLinkage() && !Fn.getFunctionType()->isVarArg())
return false;
if (Fn.use_empty())
@@ -604,9 +605,20 @@ void DAE::SurveyFunction(const Function &F) {
UseVector MaybeLiveArgUses;
for (Function::const_arg_iterator AI = F.arg_begin(),
E = F.arg_end(); AI != E; ++AI, ++i) {
- // See what the effect of this use is (recording any uses that cause
- // MaybeLive in MaybeLiveArgUses).
- Liveness Result = SurveyUses(AI, MaybeLiveArgUses);
+ Liveness Result;
+ if (F.getFunctionType()->isVarArg()) {
+ // Variadic functions will already have a va_arg function expanded inside
+ // them, making them potentially very sensitive to ABI changes resulting
+ // from removing arguments entirely, so don't. For example AArch64 handles
+ // register and stack HFAs very differently, and this is reflected in the
+ // IR which has already been generated.
+ Result = Live;
+ } else {
+ // See what the effect of this use is (recording any uses that cause
+ // MaybeLive in MaybeLiveArgUses).
+ Result = SurveyUses(AI, MaybeLiveArgUses);
+ }
+
// Mark the result.
MarkValue(CreateArg(&F, i), Result, MaybeLiveArgUses);
// Clear the vector again for the next iteration.
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp
index b035a82..a4de71b 100644
--- a/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/lib/Transforms/IPO/GlobalOpt.cpp
@@ -3041,8 +3041,168 @@ bool GlobalOpt::OptimizeGlobalCtorsList(GlobalVariable *&GCL) {
return true;
}
+/// \brief Given "llvm.used" or "llvm.compiler_used" as a global name, collect
+/// the initializer elements of that global in Set and return the global itself.
+static GlobalVariable *
+collectUsedGlobalVariables(const Module &M, const char *Name,
+ SmallPtrSet<GlobalValue *, 8> &Set) {
+ GlobalVariable *GV = M.getGlobalVariable(Name);
+ if (!GV || !GV->hasInitializer())
+ return GV;
+
+ const ConstantArray *Init = cast<ConstantArray>(GV->getInitializer());
+ for (unsigned I = 0, E = Init->getNumOperands(); I != E; ++I) {
+ Value *Op = Init->getOperand(I);
+ GlobalValue *G = cast<GlobalValue>(Op->stripPointerCastsNoFollowAliases());
+ Set.insert(G);
+ }
+ return GV;
+}
+
+static int compareNames(const void *A, const void *B) {
+ const GlobalValue *VA = *reinterpret_cast<GlobalValue* const*>(A);
+ const GlobalValue *VB = *reinterpret_cast<GlobalValue* const*>(B);
+ if (VA->getName() < VB->getName())
+ return -1;
+ if (VB->getName() < VA->getName())
+ return 1;
+ return 0;
+}
+
+static void setUsedInitializer(GlobalVariable &V,
+ SmallPtrSet<GlobalValue *, 8> Init) {
+ SmallVector<llvm::Constant *, 8> UsedArray;
+ PointerType *Int8PtrTy = Type::getInt8PtrTy(V.getContext());
+
+ for (SmallPtrSet<GlobalValue *, 8>::iterator I = Init.begin(), E = Init.end();
+ I != E; ++I) {
+ Constant *Cast = llvm::ConstantExpr::getBitCast(*I, Int8PtrTy);
+ UsedArray.push_back(Cast);
+ }
+ // Sort to get deterministic order.
+ array_pod_sort(UsedArray.begin(), UsedArray.end(), compareNames);
+ ArrayType *ATy = ArrayType::get(Int8PtrTy, UsedArray.size());
+
+ Module *M = V.getParent();
+ V.removeFromParent();
+ GlobalVariable *NV =
+ new GlobalVariable(*M, ATy, false, llvm::GlobalValue::AppendingLinkage,
+ llvm::ConstantArray::get(ATy, UsedArray), "");
+ NV->takeName(&V);
+ NV->setSection("llvm.metadata");
+ delete &V;
+}
+
+namespace {
+/// \brief An easy to access representation of llvm.used and llvm.compiler_used.
+class LLVMUsed {
+ SmallPtrSet<GlobalValue *, 8> Used;
+ SmallPtrSet<GlobalValue *, 8> CompilerUsed;
+ GlobalVariable *UsedV;
+ GlobalVariable *CompilerUsedV;
+
+public:
+ LLVMUsed(const Module &M) {
+ UsedV = collectUsedGlobalVariables(M, "llvm.used", Used);
+ CompilerUsedV =
+ collectUsedGlobalVariables(M, "llvm.compiler_used", CompilerUsed);
+ }
+ typedef SmallPtrSet<GlobalValue *, 8>::iterator iterator;
+ iterator usedBegin() { return Used.begin(); }
+ iterator usedEnd() { return Used.end(); }
+ iterator compilerUsedBegin() { return CompilerUsed.begin(); }
+ iterator compilerUsedEnd() { return CompilerUsed.end(); }
+ bool usedCount(GlobalValue *GV) const { return Used.count(GV); }
+ bool compilerUsedCount(GlobalValue *GV) const {
+ return CompilerUsed.count(GV);
+ }
+ bool usedErase(GlobalValue *GV) { return Used.erase(GV); }
+ bool compilerUsedErase(GlobalValue *GV) { return CompilerUsed.erase(GV); }
+ bool usedInsert(GlobalValue *GV) { return Used.insert(GV); }
+ bool compilerUsedInsert(GlobalValue *GV) { return CompilerUsed.insert(GV); }
+
+ void syncVariablesAndSets() {
+ if (UsedV)
+ setUsedInitializer(*UsedV, Used);
+ if (CompilerUsedV)
+ setUsedInitializer(*CompilerUsedV, CompilerUsed);
+ }
+};
+}
+
+static bool hasUseOtherThanLLVMUsed(GlobalAlias &GA, const LLVMUsed &U) {
+ if (GA.use_empty()) // No use at all.
+ return false;
+
+ assert((!U.usedCount(&GA) || !U.compilerUsedCount(&GA)) &&
+ "We should have removed the duplicated "
+ "element from llvm.compiler_used");
+ if (!GA.hasOneUse())
+ // Strictly more than one use. So at least one is not in llvm.used and
+ // llvm.compiler_used.
+ return true;
+
+ // Exactly one use. Check if it is in llvm.used or llvm.compiler_used.
+ return !U.usedCount(&GA) && !U.compilerUsedCount(&GA);
+}
+
+static bool hasMoreThanOneUseOtherThanLLVMUsed(GlobalValue &V,
+ const LLVMUsed &U) {
+ unsigned N = 2;
+ assert((!U.usedCount(&V) || !U.compilerUsedCount(&V)) &&
+ "We should have removed the duplicated "
+ "element from llvm.compiler_used");
+ if (U.usedCount(&V) || U.compilerUsedCount(&V))
+ ++N;
+ return V.hasNUsesOrMore(N);
+}
+
+static bool mayHaveOtherReferences(GlobalAlias &GA, const LLVMUsed &U) {
+ if (!GA.hasLocalLinkage())
+ return true;
+
+ return U.usedCount(&GA) || U.compilerUsedCount(&GA);
+}
+
+static bool hasUsesToReplace(GlobalAlias &GA, LLVMUsed &U, bool &RenameTarget) {
+ RenameTarget = false;
+ bool Ret = false;
+ if (hasUseOtherThanLLVMUsed(GA, U))
+ Ret = true;
+
+ // If the alias is externally visible, we may still be able to simplify it.
+ if (!mayHaveOtherReferences(GA, U))
+ return Ret;
+
+ // If the aliasee has internal linkage, give it the name and linkage
+ // of the alias, and delete the alias. This turns:
+ // define internal ... @f(...)
+ // @a = alias ... @f
+ // into:
+ // define ... @a(...)
+ Constant *Aliasee = GA.getAliasee();
+ GlobalValue *Target = cast<GlobalValue>(Aliasee->stripPointerCasts());
+ if (!Target->hasLocalLinkage())
+ return Ret;
+
+ // Do not perform the transform if multiple aliases potentially target the
+ // aliasee. This check also ensures that it is safe to replace the section
+ // and other attributes of the aliasee with those of the alias.
+ if (hasMoreThanOneUseOtherThanLLVMUsed(*Target, U))
+ return Ret;
+
+ RenameTarget = true;
+ return true;
+}
+
bool GlobalOpt::OptimizeGlobalAliases(Module &M) {
bool Changed = false;
+ LLVMUsed Used(M);
+
+ for (SmallPtrSet<GlobalValue *, 8>::iterator I = Used.usedBegin(),
+ E = Used.usedEnd();
+ I != E; ++I)
+ Used.compilerUsedErase(*I);
for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
I != E;) {
@@ -3057,37 +3217,29 @@ bool GlobalOpt::OptimizeGlobalAliases(Module &M) {
Constant *Aliasee = J->getAliasee();
GlobalValue *Target = cast<GlobalValue>(Aliasee->stripPointerCasts());
Target->removeDeadConstantUsers();
- bool hasOneUse = Target->hasOneUse() && Aliasee->hasOneUse();
// Make all users of the alias use the aliasee instead.
- if (!J->use_empty()) {
- J->replaceAllUsesWith(Aliasee);
- ++NumAliasesResolved;
- Changed = true;
- }
-
- // If the alias is externally visible, we may still be able to simplify it.
- if (!J->hasLocalLinkage()) {
- // If the aliasee has internal linkage, give it the name and linkage
- // of the alias, and delete the alias. This turns:
- // define internal ... @f(...)
- // @a = alias ... @f
- // into:
- // define ... @a(...)
- if (!Target->hasLocalLinkage())
- continue;
+ bool RenameTarget;
+ if (!hasUsesToReplace(*J, Used, RenameTarget))
+ continue;
- // Do not perform the transform if multiple aliases potentially target the
- // aliasee. This check also ensures that it is safe to replace the section
- // and other attributes of the aliasee with those of the alias.
- if (!hasOneUse)
- continue;
+ J->replaceAllUsesWith(Aliasee);
+ ++NumAliasesResolved;
+ Changed = true;
+ if (RenameTarget) {
// Give the aliasee the name, linkage and other attributes of the alias.
Target->takeName(J);
Target->setLinkage(J->getLinkage());
Target->GlobalValue::copyAttributesFrom(J);
- }
+
+ if (Used.usedErase(J))
+ Used.usedInsert(Target);
+
+ if (Used.compilerUsedErase(J))
+ Used.compilerUsedInsert(Target);
+ } else if (mayHaveOtherReferences(*J, Used))
+ continue;
// Delete the alias.
M.getAliasList().erase(J);
@@ -3095,6 +3247,8 @@ bool GlobalOpt::OptimizeGlobalAliases(Module &M) {
Changed = true;
}
+ Used.syncVariablesAndSets();
+
return Changed;
}
@@ -3223,8 +3377,6 @@ bool GlobalOpt::runOnModule(Module &M) {
// Try to find the llvm.globalctors list.
GlobalVariable *GlobalCtors = FindGlobalCtors(M);
- Function *CXAAtExitFn = FindCXAAtExit(M, TLI);
-
bool LocalChange = true;
while (LocalChange) {
LocalChange = false;
@@ -3242,7 +3394,9 @@ bool GlobalOpt::runOnModule(Module &M) {
// Resolve aliases, when possible.
LocalChange |= OptimizeGlobalAliases(M);
- // Try to remove trivial global destructors.
+ // Try to remove trivial global destructors if they are not removed
+ // already.
+ Function *CXAAtExitFn = FindCXAAtExit(M, TLI);
if (CXAAtExitFn)
LocalChange |= OptimizeEmptyGlobalCXXDtors(CXAAtExitFn);
diff --git a/lib/Transforms/IPO/PassManagerBuilder.cpp b/lib/Transforms/IPO/PassManagerBuilder.cpp
index 986c0b8..8ed7704 100644
--- a/lib/Transforms/IPO/PassManagerBuilder.cpp
+++ b/lib/Transforms/IPO/PassManagerBuilder.cpp
@@ -32,6 +32,12 @@ static cl::opt<bool>
RunLoopVectorization("vectorize-loops",
cl::desc("Run the Loop vectorization passes"));
+// This is a helper flag that we use for testing the profitability of
+// vectorization on -O2 and -Os. It should go away once we make a decision.
+static cl::opt<bool>
+VectorizeO2("vectorize-o2",
+ cl::desc("Enable vectorization on all O levels"));
+
static cl::opt<bool>
RunSLPVectorization("vectorize-slp",
cl::desc("Run the SLP vectorization passes"));
@@ -192,7 +198,7 @@ void PassManagerBuilder::populateModulePassManager(PassManagerBase &MPM) {
MPM.add(createLoopIdiomPass()); // Recognize idioms like memset.
MPM.add(createLoopDeletionPass()); // Delete dead loops
- if (LoopVectorize && OptLevel > 2)
+ if (LoopVectorize && (OptLevel > 2 || VectorizeO2))
MPM.add(createLoopVectorizePass());
if (!DisableUnrollLoops)
diff --git a/lib/Transforms/IPO/StripSymbols.cpp b/lib/Transforms/IPO/StripSymbols.cpp
index 3396f79..754eff6 100644
--- a/lib/Transforms/IPO/StripSymbols.cpp
+++ b/lib/Transforms/IPO/StripSymbols.cpp
@@ -332,16 +332,6 @@ bool StripDebugDeclare::runOnModule(Module &M) {
return true;
}
-/// getRealLinkageName - If special LLVM prefix that is used to inform the asm
-/// printer to not emit usual symbol prefix before the symbol name is used then
-/// return linkage name after skipping this special LLVM prefix.
-static StringRef getRealLinkageName(StringRef LinkageName) {
- char One = '\1';
- if (LinkageName.startswith(StringRef(&One, 1)))
- return LinkageName.substr(1);
- return LinkageName;
-}
-
bool StripDeadDebugInfo::runOnModule(Module &M) {
bool Changed = false;
@@ -401,9 +391,8 @@ bool StripDeadDebugInfo::runOnModule(Module &M) {
StringRef FName = DISubprogram(*I).getLinkageName();
if (FName.empty())
FName = DISubprogram(*I).getName();
- if (NamedMDNode *LVNMD =
- M.getNamedMetadata(Twine("llvm.dbg.lv.",
- getRealLinkageName(FName))))
+ if (NamedMDNode *LVNMD = M.getNamedMetadata(
+ "llvm.dbg.lv." + Function::getRealLinkageName(FName)))
LVNMD->eraseFromParent();
}
}