diff options
author | David Blaikie <dblaikie@gmail.com> | 2017-06-06 20:51:15 +0000 |
---|---|---|
committer | David Blaikie <dblaikie@gmail.com> | 2017-06-06 20:51:15 +0000 |
commit | 3aa7f8086331183bf8c6d4ff840699286f0ffd08 (patch) | |
tree | 0cbecb12eee62d6efb99afbd099315a171d4faaf | |
parent | 698655354d44ec8d1a9f9e205a73f65be2f86fc0 (diff) |
GlobalsModRef+OptNone: Don't prove readnone/other properties from an optnone function
Seems like at least one reasonable interpretation of optnone is that the
optimizer never "looks inside" a function. This fix is consistent with
that interpretation.
Specifically this came up in the situation:
f3 calls f2 calls f1
f2 is always_inline
f1 is optnone
The application of readnone to f1 (& thus to f2) caused the inliner to
kill the call to f2 as being trivially dead (without even checking the
cost function, as it happens - not sure if that's also a bug).
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@304833 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Analysis/GlobalsModRef.cpp | 17 | ||||
-rw-r--r-- | unittests/Analysis/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittests/Analysis/GlobalsModRefTest.cpp | 41 |
3 files changed, 56 insertions, 3 deletions
diff --git a/lib/Analysis/GlobalsModRef.cpp b/lib/Analysis/GlobalsModRef.cpp index 33f00cb19b2..39c38798f3c 100644 --- a/lib/Analysis/GlobalsModRef.cpp +++ b/lib/Analysis/GlobalsModRef.cpp @@ -475,7 +475,10 @@ void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) { const std::vector<CallGraphNode *> &SCC = *I; assert(!SCC.empty() && "SCC with no functions?"); - if (!SCC[0]->getFunction() || !SCC[0]->getFunction()->isDefinitionExact()) { + Function *F = SCC[0]->getFunction(); + + if (!F || !F->isDefinitionExact() || + F->hasFnAttribute(Attribute::OptimizeNone)) { // Calls externally or not exact - can't say anything useful. Remove any // existing function records (may have been created when scanning // globals). @@ -484,13 +487,12 @@ void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) { continue; } - FunctionInfo &FI = FunctionInfos[SCC[0]->getFunction()]; + FunctionInfo &FI = FunctionInfos[F]; bool KnowNothing = false; // Collect the mod/ref properties due to called functions. We only compute // one mod-ref set. for (unsigned i = 0, e = SCC.size(); i != e && !KnowNothing; ++i) { - Function *F = SCC[i]->getFunction(); if (!F) { KnowNothing = true; break; @@ -545,6 +547,15 @@ void GlobalsAAResult::AnalyzeCallGraph(CallGraph &CG, Module &M) { for (auto *Node : SCC) { if (FI.getModRefInfo() == MRI_ModRef) break; // The mod/ref lattice saturates here. + + // Don't prove any properties based on the implementation of an optnone + // function. + if (Node->getFunction()->hasFnAttribute(Attribute::OptimizeNone)) { + FI.addModRefInfo(MRI_Ref); + FI.addModRefInfo(MRI_Mod); + continue; + } + for (Instruction &I : instructions(Node->getFunction())) { if (FI.getModRefInfo() == MRI_ModRef) break; // The mod/ref lattice saturates here. diff --git a/unittests/Analysis/CMakeLists.txt b/unittests/Analysis/CMakeLists.txt index 8082c54b9c6..ac8bca25d93 100644 --- a/unittests/Analysis/CMakeLists.txt +++ b/unittests/Analysis/CMakeLists.txt @@ -12,6 +12,7 @@ add_llvm_unittest(AnalysisTests CallGraphTest.cpp CFGTest.cpp CGSCCPassManagerTest.cpp + GlobalsModRefTest.cpp LazyCallGraphTest.cpp LoopInfoTest.cpp MemoryBuiltinsTest.cpp diff --git a/unittests/Analysis/GlobalsModRefTest.cpp b/unittests/Analysis/GlobalsModRefTest.cpp new file mode 100644 index 00000000000..da8b44d273f --- /dev/null +++ b/unittests/Analysis/GlobalsModRefTest.cpp @@ -0,0 +1,41 @@ +//===--- GlobalsModRefTest.cpp - Mixed TBAA unit tests --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/GlobalsModRef.h" +#include "llvm/AsmParser/Parser.h" +#include "llvm/Support/SourceMgr.h" +#include "gtest/gtest.h" + +using namespace llvm; + +TEST(GlobalsModRef, OptNone) { + StringRef Assembly = R"( + define void @f() optnone { + ret void + } + )"; + + LLVMContext Context; + SMDiagnostic Error; + auto M = parseAssemblyString(Assembly, Error, Context); + ASSERT_TRUE(M) << "Bad assembly?"; + + const auto &funcs = M->functions(); + ASSERT_NE(funcs.begin(), funcs.end()); + EXPECT_EQ(std::next(funcs.begin()), funcs.end()); + const Function &F = *funcs.begin(); + + Triple Trip(M->getTargetTriple()); + TargetLibraryInfoImpl TLII(Trip); + TargetLibraryInfo TLI(TLII); + llvm::CallGraph CG(*M); + + auto AAR = GlobalsAAResult::analyzeModule(*M, TLI, CG); + EXPECT_EQ(FMRB_UnknownModRefBehavior, AAR.getModRefBehavior(&F)); +} |