llvm.org GIT mirror llvm / e9afeb0
[PM] Port the PostOrderFunctionAttrs pass to the new pass manager and convert one test to use this. This is a particularly significant milestone because it required a working per-function AA framework which can be queried over each function from within a CGSCC transform pass (and additionally a module analysis to be accessible). This is essentially *the* point of the entire pass manager rewrite. A CGSCC transform is able to query for multiple different function's analysis results. It works. The whole thing appears to actually work and accomplish the original goal. While we were able to hack function attrs and basic-aa to "work" in the old pass manager, this port doesn't use any of that, it directly leverages the new fundamental functionality. For this to work, the CGSCC framework also has to support SCC-based behavior analysis, etc. The only part of the CGSCC pass infrastructure not sorted out at this point are the updates in the face of inlining and running function passes that mutate the call graph. The changes are pretty boring and boiler-plate. Most of the work was factored into more focused preperatory patches. But this is what wires it all together. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261203 91177308-0d34-0410-b5e6-96231b3b80d8 Chandler Carruth 3 years ago
11 changed file(s) with 156 addition(s) and 51 deletion(s). Raw diff Collapse all Expand all
230230 void initializePostDomPrinterPass(PassRegistry&);
231231 void initializePostDomViewerPass(PassRegistry&);
232232 void initializePostDominatorTreePass(PassRegistry&);
233 void initializePostOrderFunctionAttrsPass(PassRegistry&);
233 void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&);
234234 void initializePostRASchedulerPass(PassRegistry&);
235235 void initializePostMachineSchedulerPass(PassRegistry&);
236236 void initializePrintFunctionPassWrapperPass(PassRegistry&);
3535 #include "llvm/IR/Function.h"
3636 #include "llvm/IR/IRPrintingPasses.h"
3737 #include "llvm/Transforms/IPO.h"
38 #include "llvm/Transforms/IPO/FunctionAttrs.h"
3839 #include "llvm/Transforms/Instrumentation.h"
3940 #include "llvm/Transforms/ObjCARC.h"
4041 #include "llvm/Transforms/Scalar.h"
158159 (void) llvm::createPostDomTree();
159160 (void) llvm::createInstructionNamerPass();
160161 (void) llvm::createMetaRenamerPass();
161 (void) llvm::createPostOrderFunctionAttrsPass();
162 (void) llvm::createPostOrderFunctionAttrsLegacyPass();
162163 (void) llvm::createReversePostOrderFunctionAttrsPass();
163164 (void) llvm::createMergeFunctionsPass();
164165 std::string buf;
0 //===-- FunctionAttrs.h - Compute function attrs --------------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// Provides passes for computing function attributes based on interprocedural
10 /// analyses.
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
14 #define LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
15
16 #include "llvm/Analysis/LazyCallGraph.h"
17 #include "llvm/Analysis/CGSCCPassManager.h"
18 #include "llvm/IR/PassManager.h"
19
20 namespace llvm {
21
22 /// Computes function attributes in post-order over the call graph.
23 ///
24 /// By operating in post-order, this pass computes precise attributes for
25 /// called functions prior to processsing their callers. This "bottom-up"
26 /// approach allows powerful interprocedural inference of function attributes
27 /// like memory access patterns, etc. It can discover functions that do not
28 /// access memory, or only read memory, and give them the readnone/readonly
29 /// attribute. It also discovers function arguments that are not captured by
30 /// the function and marks them with the nocapture attribute.
31 class PostOrderFunctionAttrsPass {
32 public:
33 static StringRef name() { return "PostOrderFunctionAttrsPass"; }
34
35 PreservedAnalyses run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM);
36 };
37
38 /// Create a legacy pass manager instance of a pass to compute function attrs
39 /// in post-order.
40 Pass *createPostOrderFunctionAttrsLegacyPass();
41
42 }
43
44 #endif // LLVM_TRANSFORMS_IPO_FUNCTIONATTRS_H
187187 ModulePass *createStripDeadPrototypesPass();
188188
189189 //===----------------------------------------------------------------------===//
190 /// createPostOrderFunctionAttrsPass - This pass walks SCCs of the call graph
191 /// in post-order to deduce and propagate function attributes. It can discover
192 /// functions that do not access memory, or only read memory, and give them the
193 /// readnone/readonly attribute. It also discovers function arguments that are
194 /// not captured by the function and marks them with the nocapture attribute.
195 ///
196 Pass *createPostOrderFunctionAttrsPass();
197
198 //===----------------------------------------------------------------------===//
199190 /// createReversePostOrderFunctionAttrsPass - This pass walks SCCs of the call
200191 /// graph in RPO to deduce and propagate function attributes. Currently it
201192 /// only handles synthesizing norecurse attributes.
9292 initializeSROALegacyPassPass(R);
9393 initializeSROA_DTPass(R);
9494 initializeSROA_SSAUpPass(R);
95 initializePostOrderFunctionAttrsPass(R);
95 initializePostOrderFunctionAttrsLegacyPassPass(R);
9696 initializeReversePostOrderFunctionAttrsPass(R);
9797 initializeGlobalsAAWrapperPassPass(R);
9898 initializeLICMPass(R);
3131 #include "llvm/Support/Debug.h"
3232 #include "llvm/Target/TargetMachine.h"
3333 #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
34 #include "llvm/Transforms/IPO/FunctionAttrs.h"
3435 #include "llvm/Transforms/IPO/InferFunctionAttrs.h"
3536 #include "llvm/Transforms/IPO/StripDeadPrototypes.h"
3637 #include "llvm/Transforms/InstCombine/InstCombine.h"
4646 #define CGSCC_PASS(NAME, CREATE_PASS)
4747 #endif
4848 CGSCC_PASS("invalidate", InvalidateAllAnalysesPass())
49 CGSCC_PASS("function-attrs", PostOrderFunctionAttrsPass())
4950 CGSCC_PASS("no-op-cgscc", NoOpCGSCCPass())
5051 #undef CGSCC_PASS
5152
1212 ///
1313 //===----------------------------------------------------------------------===//
1414
15 #include "llvm/Transforms/IPO/FunctionAttrs.h"
1516 #include "llvm/Transforms/IPO.h"
1617 #include "llvm/ADT/SCCIterator.h"
1718 #include "llvm/ADT/SetVector.h"
4950 namespace {
5051 typedef SmallSetVector SCCNodeSet;
5152 }
52
53 namespace {
54 struct PostOrderFunctionAttrs : public CallGraphSCCPass {
55 static char ID; // Pass identification, replacement for typeid
56 PostOrderFunctionAttrs() : CallGraphSCCPass(ID) {
57 initializePostOrderFunctionAttrsPass(*PassRegistry::getPassRegistry());
58 }
59
60 bool runOnSCC(CallGraphSCC &SCC) override;
61
62 void getAnalysisUsage(AnalysisUsage &AU) const override {
63 AU.setPreservesCFG();
64 AU.addRequired();
65 AU.addRequired();
66 addUsedAAAnalyses(AU);
67 CallGraphSCCPass::getAnalysisUsage(AU);
68 }
69
70 private:
71 TargetLibraryInfo *TLI;
72 };
73 }
74
75 char PostOrderFunctionAttrs::ID = 0;
76 INITIALIZE_PASS_BEGIN(PostOrderFunctionAttrs, "functionattrs",
77 "Deduce function attributes", false, false)
78 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
79 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
80 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
81 INITIALIZE_PASS_END(PostOrderFunctionAttrs, "functionattrs",
82 "Deduce function attributes", false, false)
83
84 Pass *llvm::createPostOrderFunctionAttrsPass() { return new PostOrderFunctionAttrs(); }
8553
8654 namespace {
8755 /// The three kinds of memory access relevant to 'readonly' and
1018986 return setDoesNotRecurse(*F);
1019987 }
1020988
1021 bool PostOrderFunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
989 PreservedAnalyses
990 PostOrderFunctionAttrsPass::run(LazyCallGraph::SCC &C, CGSCCAnalysisManager *AM) {
991 Module &M = *C.begin()->getFunction().getParent();
992 const ModuleAnalysisManager &MAM =
993 AM->getResult(C).getManager();
994 FunctionAnalysisManager &FAM =
995 AM->getResult(C).getManager();
996
997 // FIXME: Need some way to make it more reasonable to assume that this is
998 // always cached.
999 TargetLibraryInfo &TLI = *MAM.getCachedResult(M);
1000
1001 // We pass a lambda into functions to wire them up to the analysis manager
1002 // for getting function analyses.
1003 auto AARGetter = [&](Function &F) -> AAResults & {
1004 return FAM.getResult(F);
1005 };
1006
1007 // Fill SCCNodes with the elements of the SCC. Also track whether there are
1008 // any external or opt-none nodes that will prevent us from optimizing any
1009 // part of the SCC.
1010 SCCNodeSet SCCNodes;
1011 bool HasUnknownCall = false;
1012 for (LazyCallGraph::Node &N : C) {
1013 Function &F = N.getFunction();
1014 if (F.hasFnAttribute(Attribute::OptimizeNone)) {
1015 // Treat any function we're trying not to optimize as if it were an
1016 // indirect call and omit it from the node set used below.
1017 HasUnknownCall = true;
1018 continue;
1019 }
1020 // Track whether any functions in this SCC have an unknown call edge.
1021 // Note: if this is ever a performance hit, we can common it with
1022 // subsequent routines which also do scans over the instructions of the
1023 // function.
1024 if (!HasUnknownCall)
1025 for (Instruction &I : instructions(F))
1026 if (auto CS = CallSite(&I))
1027 if (!CS.getCalledFunction()) {
1028 HasUnknownCall = true;
1029 break;
1030 }
1031
1032 SCCNodes.insert(&F);
1033 }
1034
1035 bool Changed = false;
1036 Changed |= addReadAttrs(SCCNodes, AARGetter);
1037 Changed |= addArgumentAttrs(SCCNodes);
1038
1039 // If we have no external nodes participating in the SCC, we can deduce some
1040 // more precise attributes as well.
1041 if (!HasUnknownCall) {
1042 Changed |= addNoAliasAttrs(SCCNodes);
1043 Changed |= addNonNullAttrs(SCCNodes, TLI);
1044 Changed |= removeConvergentAttrs(SCCNodes);
1045 Changed |= addNoRecurseAttrs(SCCNodes);
1046 }
1047
1048 return Changed ? PreservedAnalyses::none() : PreservedAnalyses::all();
1049 }
1050
1051 namespace {
1052 struct PostOrderFunctionAttrsLegacyPass : public CallGraphSCCPass {
1053 static char ID; // Pass identification, replacement for typeid
1054 PostOrderFunctionAttrsLegacyPass() : CallGraphSCCPass(ID) {
1055 initializePostOrderFunctionAttrsLegacyPassPass(*PassRegistry::getPassRegistry());
1056 }
1057
1058 bool runOnSCC(CallGraphSCC &SCC) override;
1059
1060 void getAnalysisUsage(AnalysisUsage &AU) const override {
1061 AU.setPreservesCFG();
1062 AU.addRequired();
1063 AU.addRequired();
1064 addUsedAAAnalyses(AU);
1065 CallGraphSCCPass::getAnalysisUsage(AU);
1066 }
1067
1068 private:
1069 TargetLibraryInfo *TLI;
1070 };
1071 }
1072
1073 char PostOrderFunctionAttrsLegacyPass::ID = 0;
1074 INITIALIZE_PASS_BEGIN(PostOrderFunctionAttrsLegacyPass, "functionattrs",
1075 "Deduce function attributes", false, false)
1076 INITIALIZE_PASS_DEPENDENCY(AssumptionCacheTracker)
1077 INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
1078 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
1079 INITIALIZE_PASS_END(PostOrderFunctionAttrsLegacyPass, "functionattrs",
1080 "Deduce function attributes", false, false)
1081
1082 Pass *llvm::createPostOrderFunctionAttrsLegacyPass() { return new PostOrderFunctionAttrsLegacyPass(); }
1083
1084 bool PostOrderFunctionAttrsLegacyPass::runOnSCC(CallGraphSCC &SCC) {
10221085 TLI = &getAnalysis().getTLI();
10231086 bool Changed = false;
10241087
1717 #include "llvm/InitializePasses.h"
1818 #include "llvm/IR/LegacyPassManager.h"
1919 #include "llvm/Transforms/IPO.h"
20 #include "llvm/Transforms/IPO/FunctionAttrs.h"
2021
2122 using namespace llvm;
2223
4041 initializeLowerBitSetsPass(Registry);
4142 initializeMergeFunctionsPass(Registry);
4243 initializePartialInlinerPass(Registry);
43 initializePostOrderFunctionAttrsPass(Registry);
44 initializePostOrderFunctionAttrsLegacyPassPass(Registry);
4445 initializeReversePostOrderFunctionAttrsPass(Registry);
4546 initializePruneEHPass(Registry);
4647 initializeStripDeadPrototypesLegacyPassPass(Registry);
7273 }
7374
7475 void LLVMAddFunctionAttrsPass(LLVMPassManagerRef PM) {
75 unwrap(PM)->add(createPostOrderFunctionAttrsPass());
76 unwrap(PM)->add(createPostOrderFunctionAttrsLegacyPass());
7677 }
7778
7879 void LLVMAddFunctionInliningPass(LLVMPassManagerRef PM) {
3030 #include "llvm/Target/TargetMachine.h"
3131 #include "llvm/Transforms/IPO.h"
3232 #include "llvm/Transforms/IPO/ForceFunctionAttrs.h"
33 #include "llvm/Transforms/IPO/FunctionAttrs.h"
3334 #include "llvm/Transforms/IPO/InferFunctionAttrs.h"
3435 #include "llvm/Transforms/Scalar.h"
3536 #include "llvm/Transforms/Vectorize.h"
381382 Inliner = nullptr;
382383 }
383384 if (!DisableUnitAtATime)
384 MPM.add(createPostOrderFunctionAttrsPass());
385 MPM.add(createPostOrderFunctionAttrsLegacyPass());
385386 if (OptLevel > 2)
386387 MPM.add(createArgumentPromotionPass()); // Scalarize uninlined fn args
387388
576577 PM.add(createIPSCCPPass());
577578
578579 // Now that we internalized some globals, see if we can hack on them!
579 PM.add(createPostOrderFunctionAttrsPass());
580 PM.add(createPostOrderFunctionAttrsLegacyPass());
580581 PM.add(createReversePostOrderFunctionAttrsPass());
581582 PM.add(createGlobalOptimizerPass());
582583 // Promote any localized global vars.
626627 PM.add(createScalarReplAggregatesPass());
627628
628629 // Run a few AA driven optimizations here and now, to cleanup the code.
629 PM.add(createPostOrderFunctionAttrsPass()); // Add nocapture.
630 PM.add(createPostOrderFunctionAttrsLegacyPass()); // Add nocapture.
630631 PM.add(createGlobalsAAWrapperPass()); // IP alias analysis.
631632
632633 PM.add(createLICMPass()); // Hoist loop invariants.
0 ; RUN: opt < %s -functionattrs -S | FileCheck %s
1 ; RUN: opt < %s -aa-pipeline=basic-aa -passes='require,cgscc(function-attrs)' -S | FileCheck %s
12 @x = global i32 0
23
34 declare void @test1_1(i8* %x1_1, i8* readonly %y1_1, ...)