diff options
-rw-r--r-- | llvm/include/llvm/InitializePasses.h | 2 | ||||
-rw-r--r-- | llvm/include/llvm/LinkAllPasses.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/Transforms/IPO.h | 9 | ||||
-rw-r--r-- | llvm/include/llvm/Transforms/IPO/FunctionAttrs.h | 45 | ||||
-rw-r--r-- | llvm/lib/LTO/LTOCodeGenerator.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Passes/PassBuilder.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/Passes/PassRegistry.def | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/FunctionAttrs.cpp | 131 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/IPO.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Transforms/IPO/PassManagerBuilder.cpp | 7 | ||||
-rw-r--r-- | llvm/test/Transforms/FunctionAttrs/readattrs.ll | 1 |
11 files changed, 156 insertions, 51 deletions
diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index d350a73980e..3c449427520 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -231,7 +231,7 @@ void initializePostDomOnlyViewerPass(PassRegistry&); void initializePostDomPrinterPass(PassRegistry&); void initializePostDomViewerPass(PassRegistry&); void initializePostDominatorTreePass(PassRegistry&); -void initializePostOrderFunctionAttrsPass(PassRegistry&); +void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&); void initializePostRASchedulerPass(PassRegistry&); void initializePostMachineSchedulerPass(PassRegistry&); void initializePrintFunctionPassWrapperPass(PassRegistry&); diff --git a/llvm/include/llvm/LinkAllPasses.h b/llvm/include/llvm/LinkAllPasses.h index 887cef64d06..91d70f4814a 100644 --- a/llvm/include/llvm/LinkAllPasses.h +++ b/llvm/include/llvm/LinkAllPasses.h @@ -36,6 +36,7 @@ #include "llvm/IR/Function.h" #include "llvm/IR/IRPrintingPasses.h" #include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/FunctionAttrs.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar.h" @@ -159,7 +160,7 @@ namespace { (void) llvm::createPostDomTree(); (void) llvm::createInstructionNamerPass(); (void) llvm::createMetaRenamerPass(); - (void) llvm::createPostOrderFunctionAttrsPass(); + (void) llvm::createPostOrderFunctionAttrsLegacyPass(); (void) llvm::createReversePostOrderFunctionAttrsPass(); (void) llvm::createMergeFunctionsPass(); std::string buf; diff --git a/llvm/include/llvm/Transforms/IPO.h b/llvm/include/llvm/Transforms/IPO.h index 6d0f9eaefb7..5a12de55d38 100644 --- a/llvm/include/llvm/Transforms/IPO.h +++ b/llvm/include/llvm/Transforms/IPO.h @@ -188,15 +188,6 @@ ModulePass *createBlockExtractorPass(); ModulePass *createStripDeadPrototypesPass(); //===----------------------------------------------------------------------===// -/// createPostOrderFunctionAttrsPass - This pass walks SCCs of the call graph -/// in post-order to deduce and propagate function attributes. It can discover -/// functions that do not access memory, or only read memory, and give them the -/// readnone/readonly attribute. It also discovers function arguments that are -/// not captured by the function and marks them with the nocapture attribute. -/// -Pass *createPostOrderFunctionAttrsPass(); - -//===----------------------------------------------------------------------===// /// createReversePostOrderFunctionAttrsPass - This pass walks SCCs of the call /// graph in RPO to deduce and propagate function attributes. Currently it /// only handles synthesizing norecurse attributes. diff --git a/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h b/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h new file mode 100644 index 00000000000..ad3c603a36d --- /dev/null +++ b/llvm/include/llvm/Transforms/IPO/FunctionAttrs.h @@ -0,0 +1,45 @@ +//===-- FunctionAttrs.h - Compute function attrs --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// Provides passes for computing function attributes based on interprocedural +/// analyses. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H +#define LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H + +#include "llvm/Analysis/LazyCallGraph.h" +#include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// Computes function attributes in post-order over the call graph. +/// +/// By operating in post-order, this pass computes precise attributes for +/// called functions prior to processsing their callers. This "bottom-up" +/// approach allows powerful interprocedural inference of function attributes +/// like memory access patterns, etc. It can discover functions that do not +/// access memory, or only read memory, and give them the readnone/readonly +/// attribute. It also discovers function arguments that are not captured by +/// the function and marks them with the nocapture attribute. +class PostOrderFunctionAttrsPass { +public: + static StringRef name() { return "PostOrderFunctionAttrsPass"; } + + PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM); +}; + +/// Create a legacy pass manager instance of a pass to compute function attrs +/// in post-order. +Pass *createPostOrderFunctionAttrsLegacyPass(); + +} + +#endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H diff --git a/llvm/lib/LTO/LTOCodeGenerator.cpp b/llvm/lib/LTO/LTOCodeGenerator.cpp index 5d173b262dc..f36dc56774b 100644 --- a/llvm/lib/LTO/LTOCodeGenerator.cpp +++ b/llvm/lib/LTO/LTOCodeGenerator.cpp @@ -93,7 +93,7 @@ void LTOCodeGenerator::initializeLTOPasses() { initializeSROALegacyPassPass(R); initializeSROA_DTPass(R); initializeSROA_SSAUpPass(R); - initializePostOrderFunctionAttrsPass(R); + initializePostOrderFunctionAttrsLegacyPassPass(R); initializeReversePostOrderFunctionAttrsPass(R); initializeGlobalsAAWrapperPassPass(R); initializeLICMPass(R); diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 1a762dfd71b..17fb8c77d68 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -32,6 +32,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO/ForceFunctionAttrs.h" +#include "llvm/Transforms/IPO/FunctionAttrs.h" #include "llvm/Transforms/IPO/InferFunctionAttrs.h" #include "llvm/Transforms/IPO/StripDeadPrototypes.h" #include "llvm/Transforms/InstCombine/InstCombine.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 703032e31a9..44029fb378c 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -47,6 +47,7 @@ CGSCC_ANALYSIS("no-op-cgscc", NoOpCGSCCAnalysis()) #define CGSCC_PASS(NAME, CREATE_PASS) #endif CGSCC_PASS("invalidate<all>", InvalidateAllAnalysesPass()) +CGSCC_PASS("function-attrs", PostOrderFunctionAttrsPass()) CGSCC_PASS("no-op-cgscc", NoOpCGSCCPass()) #undef CGSCC_PASS diff --git a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp index 0cd9b88ea92..586d982d527 100644 --- a/llvm/lib/Transforms/IPO/FunctionAttrs.cpp +++ b/llvm/lib/Transforms/IPO/FunctionAttrs.cpp @@ -13,6 +13,7 @@ /// //===----------------------------------------------------------------------===// +#include "llvm/Transforms/IPO/FunctionAttrs.h" #include "llvm/Transforms/IPO.h" #include "llvm/ADT/SCCIterator.h" #include "llvm/ADT/SetVector.h" @@ -52,39 +53,6 @@ typedef SmallSetVector<Function *, 8> SCCNodeSet; } namespace { -struct PostOrderFunctionAttrs : public CallGraphSCCPass { - static char ID; // Pass identification, replacement for typeid - PostOrderFunctionAttrs() : CallGraphSCCPass(ID) { - initializePostOrderFunctionAttrsPass(*PassRegistry::getPassRegistry()); - } - - bool runOnSCC(CallGraphSCC &SCC) override; - - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - AU.addRequired<AssumptionCacheTracker>(); - AU.addRequired<TargetLibraryInfoWrapperPass>(); - addUsedAAAnalyses(AU); - CallGraphSCCPass::getAnalysisUsage(AU); - } - -private: - TargetLibraryInfo *TLI; -}; -} - -char PostOrderFunctionAttrs::ID = 0; -INITIALIZE_PASS_BEGIN(PostOrderFunctionAttrs, "functionattrs", - "Deduce function attributes", false, false) -INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) -INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) -INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) -INITIALIZE_PASS_END(PostOrderFunctionAttrs, "functionattrs", - "Deduce function attributes", false, false) - -Pass *llvm::createPostOrderFunctionAttrsPass() { return new PostOrderFunctionAttrs(); } - -namespace { /// The three kinds of memory access relevant to 'readonly' and /// 'readnone' attributes. enum MemoryAccessKind { @@ -1019,7 +987,102 @@ static bool addNoRecurseAttrs(const SCCNodeSet &SCCNodes) { return setDoesNotRecurse(*F); } -bool PostOrderFunctionAttrs::runOnSCC(CallGraphSCC &SCC) { +PreservedAnalyses +PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) { + Module &M = *C.begin()->getFunction().getParent(); + const ModuleAnalysisManager &MAM = + AM->getResult<ModuleAnalysisManagerCGSCCProxy>(C).getManager(); + FunctionAnalysisManager &FAM = + AM->getResult<FunctionAnalysisManagerCGSCCProxy>(C).getManager(); + + // FIXME: Need some way to make it more reasonable to assume that this is + // always cached. + TargetLibraryInfo &TLI = *MAM.getCachedResult<TargetLibraryAnalysis>(M); + + // We pass a lambda into functions to wire them up to the analysis manager + // for getting function analyses. + auto AARGetter = [&](Function &F) -> AAResults & { + return FAM.getResult<AAManager>(F); + }; + + // Fill SCCNodes with the elements of the SCC. Also track whether there are + // any external or opt-none nodes that will prevent us from optimizing any + // part of the SCC. + SCCNodeSet SCCNodes; + bool HasUnknownCall = false; + for (LazyCallGraph::Node &N : C) { + Function &F = N.getFunction(); + if (F.hasFnAttribute(Attribute::OptimizeNone)) { + // Treat any function we're trying not to optimize as if it were an + // indirect call and omit it from the node set used below. + HasUnknownCall = true; + continue; + } + // Track whether any functions in this SCC have an unknown call edge. + // Note: if this is ever a performance hit, we can common it with + // subsequent routines which also do scans over the instructions of the + // function. + if (!HasUnknownCall) + for (Instruction &I : instructions(F)) + if (auto CS = CallSite(&I)) + if (!CS.getCalledFunction()) { + HasUnknownCall = true; + break; + } + + SCCNodes.insert(&F); + } + + bool Changed = false; + Changed |= addReadAttrs(SCCNodes, AARGetter); + Changed |= addArgumentAttrs(SCCNodes); + + // If we have no external nodes participating in the SCC, we can deduce some + // more precise attributes as well. + if (!HasUnknownCall) { + Changed |= addNoAliasAttrs(SCCNodes); + Changed |= addNonNullAttrs(SCCNodes, TLI); + Changed |= removeConvergentAttrs(SCCNodes); + Changed |= addNoRecurseAttrs(SCCNodes); + } + + return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all(); +} + +namespace { +struct PostOrderFunctionAttrsLegacyPass : public CallGraphSCCPass { + static char ID; // Pass identification, replacement for typeid + PostOrderFunctionAttrsLegacyPass() : CallGraphSCCPass(ID) { + initializePostOrderFunctionAttrsLegacyPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnSCC(CallGraphSCC &SCC) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override { + AU.setPreservesCFG(); + AU.addRequired<AssumptionCacheTracker>(); + AU.addRequired<TargetLibraryInfoWrapperPass>(); + addUsedAAAnalyses(AU); + CallGraphSCCPass::getAnalysisUsage(AU); + } + +private: + TargetLibraryInfo *TLI; +}; +} + +char PostOrderFunctionAttrsLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(PostOrderFunctionAttrsLegacyPass, "functionattrs", + "Deduce function attributes", false, false) +INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker) +INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass) +INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass) +INITIALIZE_PASS_END(PostOrderFunctionAttrsLegacyPass, "functionattrs", + "Deduce function attributes", false, false) + +Pass *llvm::createPostOrderFunctionAttrsLegacyPass() { return new PostOrderFunctionAttrsLegacyPass(); } + +bool PostOrderFunctionAttrsLegacyPass::runOnSCC(CallGraphSCC &SCC) { TLI = &getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(); bool Changed = false; diff --git a/llvm/lib/Transforms/IPO/IPO.cpp b/llvm/lib/Transforms/IPO/IPO.cpp index dbbe602ece5..10f3365aeb7 100644 --- a/llvm/lib/Transforms/IPO/IPO.cpp +++ b/llvm/lib/Transforms/IPO/IPO.cpp @@ -18,6 +18,7 @@ #include "llvm/InitializePasses.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/IPO/FunctionAttrs.h" using namespace llvm; @@ -41,7 +42,7 @@ void llvm::initializeIPO(PassRegistry &Registry) { initializeLowerBitSetsPass(Registry); initializeMergeFunctionsPass(Registry); initializePartialInlinerPass(Registry); - initializePostOrderFunctionAttrsPass(Registry); + initializePostOrderFunctionAttrsLegacyPassPass(Registry); initializeReversePostOrderFunctionAttrsPass(Registry); initializePruneEHPass(Registry); initializeStripDeadPrototypesLegacyPassPass(Registry); @@ -73,7 +74,7 @@ void LLVMAddDeadArgEliminationPass(LLVMPassManagerRef PM) { } void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM) { - unwrap(PM)->add(createPostOrderFunctionAttrsPass()); + unwrap(PM)->add(createPostOrderFunctionAttrsLegacyPass()); } void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM) { diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index 266ba8e81eb..c490e060f20 100644 --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -31,6 +31,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/ForceFunctionAttrs.h" +#include "llvm/Transforms/IPO/FunctionAttrs.h" #include "llvm/Transforms/IPO/InferFunctionAttrs.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Transforms/Vectorize.h" @@ -382,7 +383,7 @@ void PassManagerBuilder::populateModulePassManager( Inliner = nullptr; } if (!DisableUnitAtATime) - MPM.add(createPostOrderFunctionAttrsPass()); + MPM.add(createPostOrderFunctionAttrsLegacyPass()); if (OptLevel > 2) MPM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args @@ -577,7 +578,7 @@ void PassManagerBuilder::addLTOOptimizationPasses(legacy::PassManagerBase &PM) { PM.add(createIPSCCPPass()); // Now that we internalized some globals, see if we can hack on them! - PM.add(createPostOrderFunctionAttrsPass()); + PM.add(createPostOrderFunctionAttrsLegacyPass()); PM.add(createReversePostOrderFunctionAttrsPass()); PM.add(createGlobalOptimizerPass()); // Promote any localized global vars. @@ -627,7 +628,7 @@ void PassManagerBuilder::addLTOOptimizationPasses(legacy::PassManagerBase &PM) { PM.add(createScalarReplAggregatesPass()); // Run a few AA driven optimizations here and now, to cleanup the code. - PM.add(createPostOrderFunctionAttrsPass()); // Add nocapture. + PM.add(createPostOrderFunctionAttrsLegacyPass()); // Add nocapture. PM.add(createGlobalsAAWrapperPass()); // IP alias analysis. PM.add(createLICMPass()); // Hoist loop invariants. diff --git a/llvm/test/Transforms/FunctionAttrs/readattrs.ll b/llvm/test/Transforms/FunctionAttrs/readattrs.ll index aabdfe8d200..4626cb19748 100644 --- a/llvm/test/Transforms/FunctionAttrs/readattrs.ll +++ b/llvm/test/Transforms/FunctionAttrs/readattrs.ll @@ -1,4 +1,5 @@ ; RUN: opt < %s -functionattrs -S | FileCheck %s +; RUN: opt < %s -aa-pipeline=basic-aa -passes='require<targetlibinfo>,cgscc(function-attrs)' -S | FileCheck %s @x = global i32 0 declare void @test1_1(i8* %x1_1, i8* readonly %y1_1, ...) |