diff options
-rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 25 | ||||
-rw-r--r-- | test/NaCl/Localmods/lit.local.cfg | 1 | ||||
-rw-r--r-- | test/NaCl/Localmods/test-globalopt-main.ll | 37 | ||||
-rw-r--r-- | test/Transforms/GlobalOpt/metadata.ll | 4 |
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 |