aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorEli Bendersky <eliben@chromium.org>2013-07-09 15:29:37 -0700
committerEli Bendersky <eliben@chromium.org>2013-07-09 15:29:37 -0700
commit299c82a21a9fd010534ea59c46ae0b88c21f25b7 (patch)
treeef0249a8e74e2d1719330fd58bf0df16a3bf5c09 /lib
parentaf49991972c1ca2364cd7377f4781893ffb3ffc5 (diff)
Make GlobalOpt's GV-by-alloca replacement work for PNaCl.
GlobalOpt currently assumes only an external "main" is the "real main". This is no longer the case for PNaCl, where we internalize "main". Make the test more strict and PNaCl specific by checking that "main" is just used once - in a call from "_start", but does not have to be external. Note that this also addresses a possible bug in the optimization for C code, since C does not guarantee that main is not recursive. This CL's purpose is to address a SPEC performance regression - 10% in 183.equake. The regression appeared after our ABI change that made 'main' internal, which disabled this particular optimization. The CL addresses this by re-enabling the optimization and also being more C-standard conforming. BUG=None Review URL: https://codereview.chromium.org/18615015
Diffstat (limited to 'lib')
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp25
1 files changed, 23 insertions, 2 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp
index 2b9d6670ca..700d0dfb5c 100644
--- a/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/lib/Transforms/IPO/GlobalOpt.cpp
@@ -83,6 +83,9 @@ namespace {
const GlobalStatus &GS);
bool OptimizeEmptyGlobalCXXDtors(Function *CXAAtExitFn);
+ // @LOCALMOD: see usage below
+ bool IsUserEntryPointMain(const Function *Func);
+
DataLayout *TD;
TargetLibraryInfo *TLI;
};
@@ -1933,6 +1936,17 @@ bool GlobalOpt::ProcessGlobal(GlobalVariable *GV,
return ProcessInternalGlobal(GV, GVI, PHIUsers, GS);
}
+bool GlobalOpt::IsUserEntryPointMain(const Function *Func) { // @LOCALMOD
+ if (Func->hasOneUse() && Func->getName() == "main") {
+ const User *FuncUser = Func->use_back();
+ if (const CallInst *CallUser = dyn_cast<CallInst>(FuncUser)) {
+ const Function *Caller = CallUser->getParent()->getParent();
+ return Caller->getName() == "_start";
+ }
+ }
+ return false;
+}
+
/// ProcessInternalGlobal - Analyze the specified global variable and optimize
/// it if possible. If we make a change, return true.
bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV,
@@ -1951,9 +1965,16 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV,
if (!GS.HasMultipleAccessingFunctions &&
GS.AccessingFunction && !GS.HasNonInstructionUser &&
GV->getType()->getElementType()->isSingleValueType() &&
- GS.AccessingFunction->getName() == "main" &&
- GS.AccessingFunction->hasExternalLinkage() &&
+ // @LOCALMOD-BEGIN
+ // The upstream LLVM is looking for an external "main" here. Since in
+ // stable PNaCl bitcode, "main" is internal, we're using a different
+ // heuristic. We're looking for a "main" that is only used in a single
+ // place -- a call from "_start".
+ // TODO: figure out a more proper solution upstream and merge that in.
+ IsUserEntryPointMain(GS.AccessingFunction) &&
+ // @LOCALMOD-END
GV->getType()->getAddressSpace() == 0) {
+
DEBUG(dbgs() << "LOCALIZING GLOBAL: " << *GV);
Instruction &FirstI = const_cast<Instruction&>(*GS.AccessingFunction
->getEntryBlock().begin());