summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2017-02-17 18:17:04 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2017-02-17 18:17:04 +0000
commit37317f1207ae72f81120ecd4d2e557acdd45ca61 (patch)
treef707a6e986e43d086ad640e3cedd06fd59142f9a /llvm/lib
parent521d2223309fe29822179ee8f33f90b7138d6c64 (diff)
downloadbcm5719-llvm-37317f1207ae72f81120ecd4d2e557acdd45ca61.tar.gz
bcm5719-llvm-37317f1207ae72f81120ecd4d2e557acdd45ca61.zip
WholeProgramDevirt: Examine the function body when deciding whether functions are readnone.
The goal is to get an analysis result even for de-refineable functions. Differential Revision: https://reviews.llvm.org/D29803 llvm-svn: 295472
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp53
1 files changed, 41 insertions, 12 deletions
diff --git a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
index 54e6fbd22f2..a9baa8d6bb7 100644
--- a/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
+++ b/llvm/lib/Transforms/IPO/WholeProgramDevirt.cpp
@@ -35,6 +35,8 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/Analysis/AliasAnalysis.h"
+#include "llvm/Analysis/BasicAliasAnalysis.h"
#include "llvm/Analysis/TypeMetadataUtils.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
@@ -63,6 +65,7 @@
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/FunctionAttrs.h"
#include "llvm/Transforms/Utils/Evaluator.h"
#include <algorithm>
#include <cstddef>
@@ -326,6 +329,7 @@ void VTableSlotInfo::addCallSite(Value *VTable, CallSite CS,
struct DevirtModule {
Module &M;
+ function_ref<AAResults &(Function &)> AARGetter;
PassSummaryAction Action;
ModuleSummaryIndex *Summary;
@@ -349,8 +353,9 @@ struct DevirtModule {
// true.
std::map<CallInst *, unsigned> NumUnsafeUsesForTypeTest;
- DevirtModule(Module &M, PassSummaryAction Action, ModuleSummaryIndex *Summary)
- : M(M), Action(Action), Summary(Summary),
+ DevirtModule(Module &M, function_ref<AAResults &(Function &)> AARGetter,
+ PassSummaryAction Action, ModuleSummaryIndex *Summary)
+ : M(M), AARGetter(AARGetter), Action(Action), Summary(Summary),
Int8Ty(Type::getInt8Ty(M.getContext())),
Int8PtrTy(Type::getInt8PtrTy(M.getContext())),
Int32Ty(Type::getInt32Ty(M.getContext())),
@@ -401,7 +406,8 @@ struct DevirtModule {
// Lower the module using the action and summary passed as command line
// arguments. For testing purposes only.
- static bool runForTesting(Module &M);
+ static bool runForTesting(Module &M,
+ function_ref<AAResults &(Function &)> AARGetter);
};
struct WholeProgramDevirt : public ModulePass {
@@ -425,15 +431,24 @@ struct WholeProgramDevirt : public ModulePass {
if (skipModule(M))
return false;
if (UseCommandLine)
- return DevirtModule::runForTesting(M);
- return DevirtModule(M, Action, Summary).run();
+ return DevirtModule::runForTesting(M, LegacyAARGetter(*this));
+ return DevirtModule(M, LegacyAARGetter(*this), Action, Summary).run();
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.addRequired<AssumptionCacheTracker>();
+ AU.addRequired<TargetLibraryInfoWrapperPass>();
}
};
} // end anonymous namespace
-INITIALIZE_PASS(WholeProgramDevirt, "wholeprogramdevirt",
- "Whole program devirtualization", false, false)
+INITIALIZE_PASS_BEGIN(WholeProgramDevirt, "wholeprogramdevirt",
+ "Whole program devirtualization", false, false)
+INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
+INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
+INITIALIZE_PASS_END(WholeProgramDevirt, "wholeprogramdevirt",
+ "Whole program devirtualization", false, false)
char WholeProgramDevirt::ID = 0;
ModulePass *llvm::createWholeProgramDevirtPass(PassSummaryAction Action,
@@ -442,13 +457,18 @@ ModulePass *llvm::createWholeProgramDevirtPass(PassSummaryAction Action,
}
PreservedAnalyses WholeProgramDevirtPass::run(Module &M,
- ModuleAnalysisManager &) {
- if (!DevirtModule(M, PassSummaryAction::None, nullptr).run())
+ ModuleAnalysisManager &AM) {
+ auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
+ auto AARGetter = [&](Function &F) -> AAResults & {
+ return FAM.getResult<AAManager>(F);
+ };
+ if (!DevirtModule(M, AARGetter, PassSummaryAction::None, nullptr).run())
return PreservedAnalyses::all();
return PreservedAnalyses::none();
}
-bool DevirtModule::runForTesting(Module &M) {
+bool DevirtModule::runForTesting(
+ Module &M, function_ref<AAResults &(Function &)> AARGetter) {
ModuleSummaryIndex Summary;
// Handle the command-line summary arguments. This code is for testing
@@ -464,7 +484,7 @@ bool DevirtModule::runForTesting(Module &M) {
ExitOnErr(errorCodeToError(In.error()));
}
- bool Changed = DevirtModule(M, ClSummaryAction, &Summary).run();
+ bool Changed = DevirtModule(M, AARGetter, ClSummaryAction, &Summary).run();
if (!ClWriteSummary.empty()) {
ExitOnError ExitOnErr(
@@ -754,8 +774,17 @@ bool DevirtModule::tryVirtualConstProp(
// Make sure that each function is defined, does not access memory, takes at
// least one argument, does not use its first argument (which we assume is
// 'this'), and has the same return type.
+ //
+ // Note that we test whether this copy of the function is readnone, rather
+ // than testing function attributes, which must hold for any copy of the
+ // function, even a less optimized version substituted at link time. This is
+ // sound because the virtual constant propagation optimizations effectively
+ // inline all implementations of the virtual function into each call site,
+ // rather than using function attributes to perform local optimization.
for (VirtualCallTarget &Target : TargetsForSlot) {
- if (Target.Fn->isDeclaration() || !Target.Fn->doesNotAccessMemory() ||
+ if (Target.Fn->isDeclaration() ||
+ computeFunctionBodyMemoryAccess(*Target.Fn, AARGetter(*Target.Fn)) !=
+ MAK_ReadNone ||
Target.Fn->arg_empty() || !Target.Fn->arg_begin()->use_empty() ||
Target.Fn->getReturnType() != RetType)
return false;
OpenPOWER on IntegriCloud