]> granicus.if.org Git - llvm/commitdiff
GlobalsModRef+OptNone: Don't prove readnone/other properties from an optnone function
authorDavid Blaikie <dblaikie@gmail.com>
Tue, 6 Jun 2017 20:51:15 +0000 (20:51 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Tue, 6 Jun 2017 20:51:15 +0000 (20:51 +0000)
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

lib/Analysis/GlobalsModRef.cpp
unittests/Analysis/CMakeLists.txt
unittests/Analysis/GlobalsModRefTest.cpp [new file with mode: 0644]

index 33f00cb19b269687b61d84318a69d8d3d7a45440..39c38798f3c4936976dadfc17db52e2c6460c804 100644 (file)
@@ -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.
index 8082c54b9c662f7421931e0602aec207fa486006..ac8bca25d93a899c6166261b2a1e549aa326f766 100644 (file)
@@ -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 (file)
index 0000000..da8b44d
--- /dev/null
@@ -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));
+}