aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp25
-rw-r--r--test/NaCl/Localmods/lit.local.cfg1
-rw-r--r--test/NaCl/Localmods/test-globalopt-main.ll37
-rw-r--r--test/Transforms/GlobalOpt/metadata.ll4
4 files changed, 65 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());
diff --git a/test/NaCl/Localmods/lit.local.cfg b/test/NaCl/Localmods/lit.local.cfg
new file mode 100644
index 0000000000..c6106e4746
--- /dev/null
+++ b/test/NaCl/Localmods/lit.local.cfg
@@ -0,0 +1 @@
+config.suffixes = ['.ll']
diff --git a/test/NaCl/Localmods/test-globalopt-main.ll b/test/NaCl/Localmods/test-globalopt-main.ll
new file mode 100644
index 0000000000..90d0e3193c
--- /dev/null
+++ b/test/NaCl/Localmods/test-globalopt-main.ll
@@ -0,0 +1,37 @@
+; RUN: opt < %s -globalopt -S | FileCheck %s
+
+; Check that our LOCALMOD for the GlobalOpt optimization is working properly.
+; The user code entry point is a function named main that has a single user:
+; a call from _start.
+; @globchar can be folded into an alloca inside @main, and the global can be
+; deleted.
+
+@globchar = internal global i8* null, align 8
+; CHECK-NOT: @globchar = internal global
+
+define internal i32 @main(i32 %argc, i8** %argv) {
+ ; CHECK: @main(i32
+entry:
+ ; CHECK: %globchar = alloca i8*
+ %argc.addr = alloca i32, align 4
+ %argv.addr = alloca i8**, align 8
+ store i32 %argc, i32* %argc.addr, align 4
+ store i8** %argv, i8*** %argv.addr, align 8
+ %0 = load i8*** %argv.addr, align 8
+ %arrayidx = getelementptr inbounds i8** %0, i64 0
+ %1 = load i8** %arrayidx, align 8
+ store i8* %1, i8** @globchar, align 8
+ %2 = load i8** @globchar, align 8
+ %arrayidx1 = getelementptr inbounds i8* %2, i64 1
+ %3 = load i8* %arrayidx1, align 1
+ call void @somefunc(i8 signext %3)
+ ret i32 0
+}
+
+define i32 @_start(i32 %argc, i8** %argv) {
+ %rv = call i32 @main(i32 %argc, i8** %argv)
+ ret i32 %rv
+}
+
+declare void @somefunc(i8 signext)
+
diff --git a/test/Transforms/GlobalOpt/metadata.ll b/test/Transforms/GlobalOpt/metadata.ll
index 730e2b0802..366f61f083 100644
--- a/test/Transforms/GlobalOpt/metadata.ll
+++ b/test/Transforms/GlobalOpt/metadata.ll
@@ -1,4 +1,8 @@
; RUN: opt -S -globalopt < %s | FileCheck %s
+; LOCALMOD: We've changed the heuristic used to detect "main" for the GlobalOpt
+; optimization of replacing globals with allocas. Revert this when fixed
+; properly upstream (http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-July/063580.html)
+; XFAIL: *
; PR6112 - When globalopt does RAUW(@G, %G), the metadata reference should drop
; to null. Function local metadata that references @G from a different function