llvm.org GIT mirror llvm / 3b5b98a
[CFLAA] Split into Anders+Steens analysis. StratifiedSets (as implemented) is very fast, but its accuracy is also limited. If we take a more aggressive andersens-like approach, we can be way more accurate, but we'll also end up being slower. So, we've decided to split CFLAA into CFLSteensAA and CFLAndersAA. Long-term, we want to end up in a place where CFLSteens is queried first; if it can provide an answer, great (since queries are basically map lookups). Otherwise, we'll fall back to CFLAnders, BasicAA, etc. This patch splits everything out so we can try to do something like that when we get a reasonable CFLAnders implementation. Patch by Jia Chen. Differential Revision: http://reviews.llvm.org/D21910 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@274589 91177308-0d34-0410-b5e6-96231b3b80d8 George Burgess IV 4 years ago
83 changed file(s) with 2705 addition(s) and 2503 deletion(s). Raw diff Collapse all Expand all
+0
-159
include/llvm/Analysis/CFLAliasAnalysis.h less more
None //===- CFLAliasAnalysis.h - CFL-Based Alias Analysis Interface ---*- C++ -*-==//
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 /// This is the interface for LLVM's primary stateless and local alias analysis.
10 ///
11 //===----------------------------------------------------------------------===//
12
13 #ifndef LLVM_ANALYSIS_CFLALIASANALYSIS_H
14 #define LLVM_ANALYSIS_CFLALIASANALYSIS_H
15
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/None.h"
18 #include "llvm/ADT/Optional.h"
19 #include "llvm/Analysis/AliasAnalysis.h"
20 #include "llvm/IR/Function.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/IR/ValueHandle.h"
23 #include "llvm/Pass.h"
24 #include
25
26 namespace llvm {
27
28 class TargetLibraryInfo;
29
30 class CFLAAResult : public AAResultBase {
31 friend AAResultBase;
32 class FunctionInfo;
33
34 public:
35 explicit CFLAAResult(const TargetLibraryInfo &);
36 CFLAAResult(CFLAAResult &&Arg);
37 ~CFLAAResult();
38
39 /// Handle invalidation events from the new pass manager.
40 ///
41 /// By definition, this result is stateless and so remains valid.
42 bool invalidate(Function &, const PreservedAnalyses &) { return false; }
43
44 /// \brief Inserts the given Function into the cache.
45 void scan(Function *Fn);
46
47 void evict(Function *Fn);
48
49 /// \brief Ensures that the given function is available in the cache.
50 /// Returns the appropriate entry from the cache.
51 const Optional &ensureCached(Function *Fn);
52
53 AliasResult query(const MemoryLocation &LocA, const MemoryLocation &LocB);
54
55 AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
56 if (LocA.Ptr == LocB.Ptr)
57 return LocA.Size == LocB.Size ? MustAlias : PartialAlias;
58
59 // Comparisons between global variables and other constants should be
60 // handled by BasicAA.
61 // TODO: ConstantExpr handling -- CFLAA may report NoAlias when comparing
62 // a GlobalValue and ConstantExpr, but every query needs to have at least
63 // one Value tied to a Function, and neither GlobalValues nor ConstantExprs
64 // are.
65 if (isa(LocA.Ptr) && isa(LocB.Ptr))
66 return AAResultBase::alias(LocA, LocB);
67
68 AliasResult QueryResult = query(LocA, LocB);
69 if (QueryResult == MayAlias)
70 return AAResultBase::alias(LocA, LocB);
71
72 return QueryResult;
73 }
74
75 /// Get the location associated with a pointer argument of a callsite.
76 ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
77
78 /// Returns the behavior when calling the given call site.
79 FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
80
81 /// Returns the behavior when calling the given function. For use when the
82 /// call site is not known.
83 FunctionModRefBehavior getModRefBehavior(const Function *F);
84
85 private:
86 struct FunctionHandle final : public CallbackVH {
87 FunctionHandle(Function *Fn, CFLAAResult *Result)
88 : CallbackVH(Fn), Result(Result) {
89 assert(Fn != nullptr);
90 assert(Result != nullptr);
91 }
92
93 void deleted() override { removeSelfFromCache(); }
94 void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
95
96 private:
97 CFLAAResult *Result;
98
99 void removeSelfFromCache() {
100 assert(Result != nullptr);
101 auto *Val = getValPtr();
102 Result->evict(cast(Val));
103 setValPtr(nullptr);
104 }
105 };
106
107 const TargetLibraryInfo &TLI;
108
109 /// \brief Cached mapping of Functions to their StratifiedSets.
110 /// If a function's sets are currently being built, it is marked
111 /// in the cache as an Optional without a value. This way, if we
112 /// have any kind of recursion, it is discernable from a function
113 /// that simply has empty sets.
114 DenseMap> Cache;
115 std::forward_list Handles;
116
117 FunctionInfo buildSetsFrom(Function *F);
118 };
119
120 /// Analysis pass providing a never-invalidated alias analysis result.
121 ///
122 /// FIXME: We really should refactor CFL to use the analysis more heavily, and
123 /// in particular to leverage invalidation to trigger re-computation of sets.
124 class CFLAA : public AnalysisInfoMixin {
125 friend AnalysisInfoMixin;
126 static char PassID;
127
128 public:
129 typedef CFLAAResult Result;
130
131 CFLAAResult run(Function &F, AnalysisManager &AM);
132 };
133
134 /// Legacy wrapper pass to provide the CFLAAResult object.
135 class CFLAAWrapperPass : public ImmutablePass {
136 std::unique_ptr Result;
137
138 public:
139 static char ID;
140
141 CFLAAWrapperPass();
142
143 CFLAAResult &getResult() { return *Result; }
144 const CFLAAResult &getResult() const { return *Result; }
145
146 void initializePass() override;
147 void getAnalysisUsage(AnalysisUsage &AU) const override;
148 };
149
150 //===--------------------------------------------------------------------===//
151 //
152 // createCFLAAWrapperPass - This pass implements a set-based approach to
153 // alias analysis.
154 //
155 ImmutablePass *createCFLAAWrapperPass();
156 }
157
158 #endif
0 //=- CFLAndersAliasAnalysis.h - Unification-based Alias Analysis ---*- C++-*-=//
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 /// This is the interface for LLVM's inclusion-based alias analysis
10 /// implemented with CFL graph reachability.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H
15 #define LLVM_ANALYSIS_CFLANDERSALIASANALYSIS_H
16
17 #include "llvm/Analysis/AliasAnalysis.h"
18 #include "llvm/IR/Function.h"
19 #include "llvm/Pass.h"
20
21 namespace llvm {
22
23 class CFLAndersAAResult : public AAResultBase {
24 friend AAResultBase;
25
26 public:
27 explicit CFLAndersAAResult();
28
29 AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
30 // Dummy implementation
31 return AAResultBase::alias(LocA, LocB);
32 }
33 };
34
35 /// Analysis pass providing a never-invalidated alias analysis result.
36 ///
37 /// FIXME: We really should refactor CFL to use the analysis more heavily, and
38 /// in particular to leverage invalidation to trigger re-computation.
39 class CFLAndersAA : public AnalysisInfoMixin {
40 friend AnalysisInfoMixin;
41 static char PassID;
42
43 public:
44 typedef CFLAndersAAResult Result;
45
46 CFLAndersAAResult run(Function &F, AnalysisManager &AM);
47 };
48
49 /// Legacy wrapper pass to provide the CFLAndersAAResult object.
50 class CFLAndersAAWrapperPass : public ImmutablePass {
51 std::unique_ptr Result;
52
53 public:
54 static char ID;
55
56 CFLAndersAAWrapperPass();
57
58 CFLAndersAAResult &getResult() { return *Result; }
59 const CFLAndersAAResult &getResult() const { return *Result; }
60
61 void initializePass() override;
62 void getAnalysisUsage(AnalysisUsage &AU) const override;
63 };
64
65 //===--------------------------------------------------------------------===//
66 //
67 // createCFLAndersAAWrapperPass - This pass implements a set-based approach to
68 // alias analysis.
69 //
70 ImmutablePass *createCFLAndersAAWrapperPass();
71 }
72
73 #endif
0 //=- CFLSteensAliasAnalysis.h - Unification-based Alias Analysis ---*- C++-*-=//
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 /// This is the interface for LLVM's unification-based alias analysis
10 /// implemented with CFL graph reachability.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H
15 #define LLVM_ANALYSIS_CFLSTEENSALIASANALYSIS_H
16
17 #include "llvm/ADT/DenseMap.h"
18 #include "llvm/ADT/None.h"
19 #include "llvm/ADT/Optional.h"
20 #include "llvm/Analysis/AliasAnalysis.h"
21 #include "llvm/IR/Function.h"
22 #include "llvm/IR/Module.h"
23 #include "llvm/IR/ValueHandle.h"
24 #include "llvm/Pass.h"
25 #include
26
27 namespace llvm {
28
29 class TargetLibraryInfo;
30
31 class CFLSteensAAResult : public AAResultBase {
32 friend AAResultBase;
33 class FunctionInfo;
34
35 public:
36 explicit CFLSteensAAResult(const TargetLibraryInfo &);
37 CFLSteensAAResult(CFLSteensAAResult &&Arg);
38 ~CFLSteensAAResult();
39
40 /// Handle invalidation events from the new pass manager.
41 ///
42 /// By definition, this result is stateless and so remains valid.
43 bool invalidate(Function &, const PreservedAnalyses &) { return false; }
44
45 /// \brief Inserts the given Function into the cache.
46 void scan(Function *Fn);
47
48 void evict(Function *Fn);
49
50 /// \brief Ensures that the given function is available in the cache.
51 /// Returns the appropriate entry from the cache.
52 const Optional &ensureCached(Function *Fn);
53
54 AliasResult query(const MemoryLocation &LocA, const MemoryLocation &LocB);
55
56 AliasResult alias(const MemoryLocation &LocA, const MemoryLocation &LocB) {
57 if (LocA.Ptr == LocB.Ptr)
58 return LocA.Size == LocB.Size ? MustAlias : PartialAlias;
59
60 // Comparisons between global variables and other constants should be
61 // handled by BasicAA.
62 // CFLSteensAA may report NoAlias when comparing a GlobalValue and
63 // ConstantExpr, but every query needs to have at least one Value tied to a
64 // Function, and neither GlobalValues nor ConstantExprs are.
65 if (isa(LocA.Ptr) && isa(LocB.Ptr))
66 return AAResultBase::alias(LocA, LocB);
67
68 AliasResult QueryResult = query(LocA, LocB);
69 if (QueryResult == MayAlias)
70 return AAResultBase::alias(LocA, LocB);
71
72 return QueryResult;
73 }
74
75 /// Get the location associated with a pointer argument of a callsite.
76 ModRefInfo getArgModRefInfo(ImmutableCallSite CS, unsigned ArgIdx);
77
78 /// Returns the behavior when calling the given call site.
79 FunctionModRefBehavior getModRefBehavior(ImmutableCallSite CS);
80
81 /// Returns the behavior when calling the given function. For use when the
82 /// call site is not known.
83 FunctionModRefBehavior getModRefBehavior(const Function *F);
84
85 private:
86 struct FunctionHandle final : public CallbackVH {
87 FunctionHandle(Function *Fn, CFLSteensAAResult *Result)
88 : CallbackVH(Fn), Result(Result) {
89 assert(Fn != nullptr);
90 assert(Result != nullptr);
91 }
92
93 void deleted() override { removeSelfFromCache(); }
94 void allUsesReplacedWith(Value *) override { removeSelfFromCache(); }
95
96 private:
97 CFLSteensAAResult *Result;
98
99 void removeSelfFromCache() {
100 assert(Result != nullptr);
101 auto *Val = getValPtr();
102 Result->evict(cast(Val));
103 setValPtr(nullptr);
104 }
105 };
106
107 const TargetLibraryInfo &TLI;
108
109 /// \brief Cached mapping of Functions to their StratifiedSets.
110 /// If a function's sets are currently being built, it is marked
111 /// in the cache as an Optional without a value. This way, if we
112 /// have any kind of recursion, it is discernable from a function
113 /// that simply has empty sets.
114 DenseMap> Cache;
115 std::forward_list Handles;
116
117 FunctionInfo buildSetsFrom(Function *F);
118 };
119
120 /// Analysis pass providing a never-invalidated alias analysis result.
121 ///
122 /// FIXME: We really should refactor CFL to use the analysis more heavily, and
123 /// in particular to leverage invalidation to trigger re-computation of sets.
124 class CFLSteensAA : public AnalysisInfoMixin {
125 friend AnalysisInfoMixin;
126 static char PassID;
127
128 public:
129 typedef CFLSteensAAResult Result;
130
131 CFLSteensAAResult run(Function &F, AnalysisManager &AM);
132 };
133
134 /// Legacy wrapper pass to provide the CFLSteensAAResult object.
135 class CFLSteensAAWrapperPass : public ImmutablePass {
136 std::unique_ptr Result;
137
138 public:
139 static char ID;
140
141 CFLSteensAAWrapperPass();
142
143 CFLSteensAAResult &getResult() { return *Result; }
144 const CFLSteensAAResult &getResult() const { return *Result; }
145
146 void initializePass() override;
147 void getAnalysisUsage(AnalysisUsage &AU) const override;
148 };
149
150 //===--------------------------------------------------------------------===//
151 //
152 // createCFLSteensAAWrapperPass - This pass implements a set-based approach to
153 // alias analysis.
154 //
155 ImmutablePass *createCFLSteensAAWrapperPass();
156 }
157
158 #endif
8181 void initializeCFGPrinterPass(PassRegistry&);
8282 void initializeCFGSimplifyPassPass(PassRegistry&);
8383 void initializeCFGViewerPass(PassRegistry&);
84 void initializeCFLAAWrapperPassPass(PassRegistry&);
84 void initializeCFLAndersAAWrapperPassPass(PassRegistry&);
85 void initializeCFLSteensAAWrapperPassPass(PassRegistry&);
8586 void initializeCallGraphDOTPrinterPass(PassRegistry&);
8687 void initializeCallGraphPrinterLegacyPassPass(PassRegistry&);
8788 void initializeCallGraphViewerPass(PassRegistry&);
1818 #include "llvm/Analysis/AliasSetTracker.h"
1919 #include "llvm/Analysis/AliasAnalysisEvaluator.h"
2020 #include "llvm/Analysis/BasicAliasAnalysis.h"
21 #include "llvm/Analysis/CFLAliasAnalysis.h"
21 #include "llvm/Analysis/CFLAndersAliasAnalysis.h"
22 #include "llvm/Analysis/CFLSteensAliasAnalysis.h"
2223 #include "llvm/Analysis/CallPrinter.h"
2324 #include "llvm/Analysis/DomPrinter.h"
2425 #include "llvm/Analysis/GlobalsModRef.h"
7273 (void) llvm::createCallGraphDOTPrinterPass();
7374 (void) llvm::createCallGraphViewerPass();
7475 (void) llvm::createCFGSimplificationPass();
75 (void) llvm::createCFLAAWrapperPass();
76 (void) llvm::createCFLAndersAAWrapperPass();
77 (void) llvm::createCFLSteensAAWrapperPass();
7678 (void) llvm::createStructurizeCFGPass();
7779 (void) llvm::createConstantMergePass();
7880 (void) llvm::createConstantPropagationPass();
2626 #include "llvm/Analysis/AliasAnalysis.h"
2727 #include "llvm/Analysis/BasicAliasAnalysis.h"
2828 #include "llvm/Analysis/CFG.h"
29 #include "llvm/Analysis/CFLAliasAnalysis.h"
29 #include "llvm/Analysis/CFLAndersAliasAnalysis.h"
30 #include "llvm/Analysis/CFLSteensAliasAnalysis.h"
3031 #include "llvm/Analysis/CaptureTracking.h"
3132 #include "llvm/Analysis/GlobalsModRef.h"
3233 #include "llvm/Analysis/ObjCARCAliasAnalysis.h"
551552 INITIALIZE_PASS_BEGIN(AAResultsWrapperPass, "aa",
552553 "Function Alias Analysis Results", false, true)
553554 INITIALIZE_PASS_DEPENDENCY(BasicAAWrapperPass)
554 INITIALIZE_PASS_DEPENDENCY(CFLAAWrapperPass)
555 INITIALIZE_PASS_DEPENDENCY(CFLAndersAAWrapperPass)
556 INITIALIZE_PASS_DEPENDENCY(CFLSteensAAWrapperPass)
555557 INITIALIZE_PASS_DEPENDENCY(ExternalAAWrapperPass)
556558 INITIALIZE_PASS_DEPENDENCY(GlobalsAAWrapperPass)
557559 INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass)
602604 AAR->addAAResult(WrapperPass->getResult());
603605 if (auto *WrapperPass = getAnalysisIfAvailable())
604606 AAR->addAAResult(WrapperPass->getResult());
605 if (auto *WrapperPass = getAnalysisIfAvailableAWrapperPass>())
607 if (auto *WrapperPass = getAnalysisIfAvailablendersAAWrapperPass>())
608 AAR->addAAResult(WrapperPass->getResult());
609 if (auto *WrapperPass = getAnalysisIfAvailable())
606610 AAR->addAAResult(WrapperPass->getResult());
607611
608612 // If available, run an external AA providing callback over the results as
629633 AU.addUsedIfAvailable();
630634 AU.addUsedIfAvailable();
631635 AU.addUsedIfAvailable();
632 AU.addUsedIfAvailableAWrapperPass>();
636 AU.addUsedIfAvailablendersAAWrapperPass>();
637 AU.addUsedIfAvailable();
633638 }
634639
635640 AAResults llvm::createLegacyPMAAResults(Pass &P, Function &F,
651656 AAR.addAAResult(WrapperPass->getResult());
652657 if (auto *WrapperPass = P.getAnalysisIfAvailable())
653658 AAR.addAAResult(WrapperPass->getResult());
654 if (auto *WrapperPass = P.getAnalysisIfAvailableAWrapperPass>())
659 if (auto *WrapperPass = P.getAnalysisIfAvailablendersAAWrapperPass>())
660 AAR.addAAResult(WrapperPass->getResult());
661 if (auto *WrapperPass = P.getAnalysisIfAvailable())
655662 AAR.addAAResult(WrapperPass->getResult());
656663
657664 return AAR;
694701 AU.addUsedIfAvailable();
695702 AU.addUsedIfAvailable();
696703 AU.addUsedIfAvailable();
697 AU.addUsedIfAvailable();
698 }
704 AU.addUsedIfAvailable();
705 AU.addUsedIfAvailable();
706 }
3333 initializeCFGPrinterPass(Registry);
3434 initializeCFGOnlyViewerPass(Registry);
3535 initializeCFGOnlyPrinterPass(Registry);
36 initializeCFLAAWrapperPassPass(Registry);
36 initializeCFLAndersAAWrapperPassPass(Registry);
37 initializeCFLSteensAAWrapperPassPass(Registry);
3738 initializeDependenceAnalysisWrapperPassPass(Registry);
3839 initializeDelinearizationPass(Registry);
3940 initializeDemandedBitsWrapperPassPass(Registry);
+0
-1145
lib/Analysis/CFLAliasAnalysis.cpp less more
None //===- CFLAliasAnalysis.cpp - CFL-Based Alias Analysis Implementation ------==//
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 //
9 // This file implements a CFL-based context-insensitive alias analysis
10 // algorithm. It does not depend on types. The algorithm is a mixture of the one
11 // described in "Demand-driven alias analysis for C" by Xin Zheng and Radu
12 // Rugina, and "Fast algorithms for Dyck-CFL-reachability with applications to
13 // Alias Analysis" by Zhang Q, Lyu M R, Yuan H, and Su Z. -- to summarize the
14 // papers, we build a graph of the uses of a variable, where each node is a
15 // memory location, and each edge is an action that happened on that memory
16 // location. The "actions" can be one of Dereference, Reference, or Assign.
17 //
18 // Two variables are considered as aliasing iff you can reach one value's node
19 // from the other value's node and the language formed by concatenating all of
20 // the edge labels (actions) conforms to a context-free grammar.
21 //
22 // Because this algorithm requires a graph search on each query, we execute the
23 // algorithm outlined in "Fast algorithms..." (mentioned above)
24 // in order to transform the graph into sets of variables that may alias in
25 // ~nlogn time (n = number of variables), which makes queries take constant
26 // time.
27 //===----------------------------------------------------------------------===//
28
29 // N.B. AliasAnalysis as a whole is phrased as a FunctionPass at the moment, and
30 // CFLAA is interprocedural. This is *technically* A Bad Thing, because
31 // FunctionPasses are only allowed to inspect the Function that they're being
32 // run on. Realistically, this likely isn't a problem until we allow
33 // FunctionPasses to run concurrently.
34
35 #include "llvm/Analysis/CFLAliasAnalysis.h"
36 #include "StratifiedSets.h"
37 #include "llvm/ADT/DenseMap.h"
38 #include "llvm/ADT/None.h"
39 #include "llvm/ADT/Optional.h"
40 #include "llvm/Analysis/MemoryBuiltins.h"
41 #include "llvm/Analysis/TargetLibraryInfo.h"
42 #include "llvm/IR/Constants.h"
43 #include "llvm/IR/Function.h"
44 #include "llvm/IR/InstVisitor.h"
45 #include "llvm/IR/Instructions.h"
46 #include "llvm/Pass.h"
47 #include "llvm/Support/Compiler.h"
48 #include "llvm/Support/Debug.h"
49 #include "llvm/Support/ErrorHandling.h"
50 #include "llvm/Support/raw_ostream.h"
51 #include
52 #include
53 #include
54 #include
55
56 using namespace llvm;
57
58 #define DEBUG_TYPE "cfl-aa"
59
60 CFLAAResult::CFLAAResult(const TargetLibraryInfo &TLI)
61 : AAResultBase(), TLI(TLI) {}
62 CFLAAResult::CFLAAResult(CFLAAResult &&Arg)
63 : AAResultBase(std::move(Arg)), TLI(Arg.TLI) {}
64 CFLAAResult::~CFLAAResult() {}
65
66 /// We use InterfaceValue to describe parameters/return value, as well as
67 /// potential memory locations that are pointed to by parameters/return value,
68 /// of a function.
69 /// Index is an integer which represents a single parameter or a return value.
70 /// When the index is 0, it refers to the return value. Non-zero index i refers
71 /// to the i-th parameter.
72 /// DerefLevel indicates the number of dereferences one must perform on the
73 /// parameter/return value to get this InterfaceValue.
74 struct InterfaceValue {
75 unsigned Index;
76 unsigned DerefLevel;
77 };
78
79 bool operator==(InterfaceValue lhs, InterfaceValue rhs) {
80 return lhs.Index == rhs.Index && lhs.DerefLevel == rhs.DerefLevel;
81 }
82 bool operator!=(InterfaceValue lhs, InterfaceValue rhs) {
83 return !(lhs == rhs);
84 }
85
86 /// We use ExternalRelation to describe an externally visible aliasing relations
87 /// between parameters/return value of a function.
88 struct ExternalRelation {
89 InterfaceValue From, To;
90 };
91
92 /// We use ExternalAttribute to describe an externally visible StratifiedAttrs
93 /// for parameters/return value.
94 struct ExternalAttribute {
95 InterfaceValue IValue;
96 StratifiedAttrs Attr;
97 };
98
99 /// Information we have about a function and would like to keep around.
100 class CFLAAResult::FunctionInfo {
101 StratifiedSets Sets;
102
103 // RetParamRelations is a collection of ExternalRelations.
104 SmallVector RetParamRelations;
105
106 // RetParamAttributes is a collection of ExternalAttributes.
107 SmallVector RetParamAttributes;
108
109 public:
110 FunctionInfo(Function &Fn, const SmallVectorImpl &RetVals,
111 StratifiedSets S);
112
113 const StratifiedSets &getStratifiedSets() const { return Sets; }
114 const SmallVectorImpl &getRetParamRelations() const {
115 return RetParamRelations;
116 }
117 const SmallVectorImpl &getRetParamAttributes() const {
118 return RetParamAttributes;
119 }
120 };
121
122 /// Try to go from a Value* to a Function*. Never returns nullptr.
123 static Optional parentFunctionOfValue(Value *);
124
125 /// Returns possible functions called by the Inst* into the given
126 /// SmallVectorImpl. Returns true if targets found, false otherwise. This is
127 /// templated so we can use it with CallInsts and InvokeInsts.
128 static bool getPossibleTargets(CallSite, SmallVectorImpl &);
129
130 const StratifiedIndex StratifiedLink::SetSentinel =
131 std::numeric_limits::max();
132
133 namespace {
134 /// StratifiedInfo Attribute things.
135 LLVM_CONSTEXPR unsigned MaxStratifiedAttrIndex = NumStratifiedAttrs;
136 LLVM_CONSTEXPR unsigned AttrEscapedIndex = 0;
137 LLVM_CONSTEXPR unsigned AttrUnknownIndex = 1;
138 LLVM_CONSTEXPR unsigned AttrGlobalIndex = 2;
139 LLVM_CONSTEXPR unsigned AttrCallerIndex = 3;
140 LLVM_CONSTEXPR unsigned AttrFirstArgIndex = 4;
141 LLVM_CONSTEXPR unsigned AttrLastArgIndex = MaxStratifiedAttrIndex;
142 LLVM_CONSTEXPR unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex;
143
144 // NOTE: These aren't StratifiedAttrs because bitsets don't have a constexpr
145 // ctor for some versions of MSVC that we support. We could maybe refactor,
146 // but...
147 using StratifiedAttr = unsigned;
148 LLVM_CONSTEXPR StratifiedAttr AttrNone = 0;
149 LLVM_CONSTEXPR StratifiedAttr AttrEscaped = 1 << AttrEscapedIndex;
150 LLVM_CONSTEXPR StratifiedAttr AttrUnknown = 1 << AttrUnknownIndex;
151 LLVM_CONSTEXPR StratifiedAttr AttrGlobal = 1 << AttrGlobalIndex;
152 LLVM_CONSTEXPR StratifiedAttr AttrCaller = 1 << AttrCallerIndex;
153 LLVM_CONSTEXPR StratifiedAttr ExternalAttrMask =
154 AttrEscaped | AttrUnknown | AttrGlobal;
155
156 /// The maximum number of arguments we can put into a summary.
157 LLVM_CONSTEXPR unsigned MaxSupportedArgsInSummary = 50;
158
159 /// StratifiedSets call for knowledge of "direction", so this is how we
160 /// represent that locally.
161 enum class Level { Same, Above, Below };
162
163 /// Edges can be one of four "weights" -- each weight must have an inverse
164 /// weight (Assign has Assign; Reference has Dereference).
165 enum class EdgeType {
166 /// The weight assigned when assigning from or to a value. For example, in:
167 /// %b = getelementptr %a, 0
168 /// ...The relationships are %b assign %a, and %a assign %b. This used to be
169 /// two edges, but having a distinction bought us nothing.
170 Assign,
171
172 /// The edge used when we have an edge going from some handle to a Value.
173 /// Examples of this include:
174 /// %b = load %a (%b Dereference %a)
175 /// %b = extractelement %a, 0 (%a Dereference %b)
176 Dereference,
177
178 /// The edge used when our edge goes from a value to a handle that may have
179 /// contained it at some point. Examples:
180 /// %b = load %a (%a Reference %b)
181 /// %b = extractelement %a, 0 (%b Reference %a)
182 Reference
183 };
184
185 /// The Program Expression Graph (PEG) of CFL analysis
186 class CFLGraph {
187 typedef Value *Node;
188
189 struct Edge {
190 EdgeType Type;
191 Node Other;
192 };
193
194 typedef std::vector EdgeList;
195
196 struct NodeInfo {
197 EdgeList Edges;
198 StratifiedAttrs Attr;
199 };
200
201 typedef DenseMap NodeMap;
202 NodeMap NodeImpls;
203
204 // Gets the inverse of a given EdgeType.
205 static EdgeType flipWeight(EdgeType Initial) {
206 switch (Initial) {
207 case EdgeType::Assign:
208 return EdgeType::Assign;
209 case EdgeType::Dereference:
210 return EdgeType::Reference;
211 case EdgeType::Reference:
212 return EdgeType::Dereference;
213 }
214 llvm_unreachable("Incomplete coverage of EdgeType enum");
215 }
216
217 const NodeInfo *getNode(Node N) const {
218 auto Itr = NodeImpls.find(N);
219 if (Itr == NodeImpls.end())
220 return nullptr;
221 return &Itr->second;
222 }
223 NodeInfo *getNode(Node N) {
224 auto Itr = NodeImpls.find(N);
225 if (Itr == NodeImpls.end())
226 return nullptr;
227 return &Itr->second;
228 }
229
230 static Node nodeDeref(const NodeMap::value_type &P) { return P.first; }
231 typedef std::pointer_to_unary_function
232 NodeDerefFun;
233
234 public:
235 typedef EdgeList::const_iterator const_edge_iterator;
236 typedef mapped_iterator
237 const_node_iterator;
238
239 bool addNode(Node N) {
240 return NodeImpls.insert(std::make_pair(N, NodeInfo{EdgeList(), AttrNone}))
241 .second;
242 }
243
244 void addAttr(Node N, StratifiedAttrs Attr) {
245 auto *Info = getNode(N);
246 assert(Info != nullptr);
247 Info->Attr |= Attr;
248 }
249
250 void addEdge(Node From, Node To, EdgeType Type) {
251 auto *FromInfo = getNode(From);
252 assert(FromInfo != nullptr);
253 auto *ToInfo = getNode(To);
254 assert(ToInfo != nullptr);
255
256 FromInfo->Edges.push_back(Edge{Type, To});
257 ToInfo->Edges.push_back(Edge{flipWeight(Type), From});
258 }
259
260 StratifiedAttrs attrFor(Node N) const {
261 auto *Info = getNode(N);
262 assert(Info != nullptr);
263 return Info->Attr;
264 }
265
266 iterator_range edgesFor(Node N) const {
267 auto *Info = getNode(N);
268 assert(Info != nullptr);
269 auto &Edges = Info->Edges;
270 return make_range(Edges.begin(), Edges.end());
271 }
272
273 iterator_range nodes() const {
274 return make_range(
275 map_iterator(NodeImpls.begin(), NodeDerefFun(nodeDeref)),
276 map_iterator(NodeImpls.end(), NodeDerefFun(nodeDeref)));
277 }
278
279 bool empty() const { return NodeImpls.empty(); }
280 std::size_t size() const { return NodeImpls.size(); }
281 };
282
283 // This is the result of instantiating InterfaceValue at a particular callsite
284 struct InterprocNode {
285 Value *Val;
286 unsigned DerefLevel;
287 };
288
289 // Interprocedural assignment edges that CFLGraph may not easily model
290 struct InterprocEdge {
291 InterprocNode From, To;
292 };
293
294 // Interprocedural attribute tagging that CFLGraph may not easily model
295 struct InterprocAttr {
296 InterprocNode Node;
297 StratifiedAttrs Attr;
298 };
299
300 /// Gets the edges our graph should have, based on an Instruction*
301 class GetEdgesVisitor : public InstVisitor {
302 CFLAAResult &AA;
303 const TargetLibraryInfo &TLI;
304
305 CFLGraph &Graph;
306 SmallVectorImpl &ReturnValues;
307 SmallPtrSetImpl &Externals;
308 SmallPtrSetImpl &Escapes;
309 SmallVectorImpl &InterprocEdges;
310 SmallVectorImpl &InterprocAttrs;
311
312 static bool hasUsefulEdges(ConstantExpr *CE) {
313 // ConstantExpr doesn't have terminators, invokes, or fences, so only needs
314 // to check for compares.
315 return CE->getOpcode() != Instruction::ICmp &&
316 CE->getOpcode() != Instruction::FCmp;
317 }
318
319 void addNode(Value *Val) {
320 if (!Graph.addNode(Val))
321 return;
322
323 if (isa(Val))
324 Externals.insert(Val);
325 else if (auto CExpr = dyn_cast(Val))
326 if (hasUsefulEdges(CExpr))
327 visitConstantExpr(CExpr);
328 }
329
330 void addNodeWithAttr(Value *Val, StratifiedAttrs Attr) {
331 addNode(Val);
332 Graph.addAttr(Val, Attr);
333 }
334
335 void addEdge(Value *From, Value *To, EdgeType Type) {
336 if (!From->getType()->isPointerTy() || !To->getType()->isPointerTy())
337 return;
338 addNode(From);
339 if (To != From)
340 addNode(To);
341 Graph.addEdge(From, To, Type);
342 }
343
344 public:
345 GetEdgesVisitor(CFLAAResult &AA, const TargetLibraryInfo &TLI,
346 CFLGraph &Graph, SmallVectorImpl &ReturnValues,
347 SmallPtrSetImpl &Externals,
348 SmallPtrSetImpl &Escapes,
349 SmallVectorImpl &InterprocEdges,
350 SmallVectorImpl &InterprocAttrs)
351 : AA(AA), TLI(TLI), Graph(Graph), ReturnValues(ReturnValues),
352 Externals(Externals), Escapes(Escapes), InterprocEdges(InterprocEdges),
353 InterprocAttrs(InterprocAttrs) {}
354
355 void visitInstruction(Instruction &) {
356 llvm_unreachable("Unsupported instruction encountered");
357 }
358
359 void visitReturnInst(ReturnInst &Inst) {
360 if (auto RetVal = Inst.getReturnValue()) {
361 if (RetVal->getType()->isPointerTy()) {
362 addNode(RetVal);
363 ReturnValues.push_back(RetVal);
364 }
365 }
366 }
367
368 void visitPtrToIntInst(PtrToIntInst &Inst) {
369 auto *Ptr = Inst.getOperand(0);
370 addNodeWithAttr(Ptr, AttrEscaped);
371 }
372
373 void visitIntToPtrInst(IntToPtrInst &Inst) {
374 auto *Ptr = &Inst;
375 addNodeWithAttr(Ptr, AttrUnknown);
376 }
377
378 void visitCastInst(CastInst &Inst) {
379 auto *Src = Inst.getOperand(0);
380 addEdge(Src, &Inst, EdgeType::Assign);
381 }
382
383 void visitBinaryOperator(BinaryOperator &Inst) {
384 auto *Op1 = Inst.getOperand(0);
385 auto *Op2 = Inst.getOperand(1);
386 addEdge(Op1, &Inst, EdgeType::Assign);
387 addEdge(Op2, &Inst, EdgeType::Assign);
388 }
389
390 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &Inst) {
391 auto *Ptr = Inst.getPointerOperand();
392 auto *Val = Inst.getNewValOperand();
393 addEdge(Ptr, Val, EdgeType::Dereference);
394 }
395
396 void visitAtomicRMWInst(AtomicRMWInst &Inst) {
397 auto *Ptr = Inst.getPointerOperand();
398 auto *Val = Inst.getValOperand();
399 addEdge(Ptr, Val, EdgeType::Dereference);
400 }
401
402 void visitPHINode(PHINode &Inst) {
403 for (Value *Val : Inst.incoming_values())
404 addEdge(Val, &Inst, EdgeType::Assign);
405 }
406
407 void visitGetElementPtrInst(GetElementPtrInst &Inst) {
408 auto *Op = Inst.getPointerOperand();
409 addEdge(Op, &Inst, EdgeType::Assign);
410 }
411
412 void visitSelectInst(SelectInst &Inst) {
413 // Condition is not processed here (The actual statement producing
414 // the condition result is processed elsewhere). For select, the
415 // condition is evaluated, but not loaded, stored, or assigned
416 // simply as a result of being the condition of a select.
417
418 auto *TrueVal = Inst.getTrueValue();
419 auto *FalseVal = Inst.getFalseValue();
420 addEdge(TrueVal, &Inst, EdgeType::Assign);
421 addEdge(FalseVal, &Inst, EdgeType::Assign);
422 }
423
424 void visitAllocaInst(AllocaInst &Inst) { Graph.addNode(&Inst); }
425
426 void visitLoadInst(LoadInst &Inst) {
427 auto *Ptr = Inst.getPointerOperand();
428 auto *Val = &Inst;
429 addEdge(Val, Ptr, EdgeType::Reference);
430 }
431
432 void visitStoreInst(StoreInst &Inst) {
433 auto *Ptr = Inst.getPointerOperand();
434 auto *Val = Inst.getValueOperand();
435 addEdge(Ptr, Val, EdgeType::Dereference);
436 }
437
438 void visitVAArgInst(VAArgInst &Inst) {
439 // We can't fully model va_arg here. For *Ptr = Inst.getOperand(0), it does
440 // two things:
441 // 1. Loads a value from *((T*)*Ptr).
442 // 2. Increments (stores to) *Ptr by some target-specific amount.
443 // For now, we'll handle this like a landingpad instruction (by placing the
444 // result in its own group, and having that group alias externals).
445 addNodeWithAttr(&Inst, AttrUnknown);
446 }
447
448 static bool isFunctionExternal(Function *Fn) {
449 return !Fn->hasExactDefinition();
450 }
451
452 bool tryInterproceduralAnalysis(CallSite CS,
453 const SmallVectorImpl &Fns) {
454 assert(Fns.size() > 0);
455
456 if (CS.arg_size() > MaxSupportedArgsInSummary)
457 return false;
458
459 // Exit early if we'll fail anyway
460 for (auto *Fn : Fns) {
461 if (isFunctionExternal(Fn) || Fn->isVarArg())
462 return false;
463 // Fail if the caller does not provide enough arguments
464 assert(Fn->arg_size() <= CS.arg_size());
465 auto &MaybeInfo = AA.ensureCached(Fn);
466 if (!MaybeInfo.hasValue())
467 return false;
468 }
469
470 auto InstantiateInterfaceIndex = [&CS](unsigned Index) {
471 auto Value =
472 (Index == 0) ? CS.getInstruction() : CS.getArgument(Index - 1);
473 return Value->getType()->isPointerTy() ? Value : nullptr;
474 };
475
476 for (auto *Fn : Fns) {
477 auto &FnInfo = AA.ensureCached(Fn);
478 assert(FnInfo.hasValue());
479
480 auto &RetParamRelations = FnInfo->getRetParamRelations();
481 for (auto &Relation : RetParamRelations) {
482 auto FromVal = InstantiateInterfaceIndex(Relation.From.Index);
483 auto ToVal = InstantiateInterfaceIndex(Relation.To.Index);
484 if (FromVal && ToVal) {
485 auto FromLevel = Relation.From.DerefLevel;
486 auto ToLevel = Relation.To.DerefLevel;
487 InterprocEdges.push_back(
488 InterprocEdge{InterprocNode{FromVal, FromLevel},
489 InterprocNode{ToVal, ToLevel}});
490 }
491 }
492
493 auto &RetParamAttributes = FnInfo->getRetParamAttributes();
494 for (auto &Attribute : RetParamAttributes) {
495 if (auto Val = InstantiateInterfaceIndex(Attribute.IValue.Index)) {
496 InterprocAttrs.push_back(InterprocAttr{
497 InterprocNode{Val, Attribute.IValue.DerefLevel}, Attribute.Attr});
498 }
499 }
500 }
501
502 return true;
503 }
504
505 void visitCallSite(CallSite CS) {
506 auto Inst = CS.getInstruction();
507
508 // Make sure all arguments and return value are added to the graph first
509 for (Value *V : CS.args())
510 addNode(V);
511 if (Inst->getType()->isPointerTy())
512 addNode(Inst);
513
514 // Check if Inst is a call to a library function that allocates/deallocates
515 // on the heap. Those kinds of functions do not introduce any aliases.
516 // TODO: address other common library functions such as realloc(), strdup(),
517 // etc.
518 if (isMallocLikeFn(Inst, &TLI) || isCallocLikeFn(Inst, &TLI) ||
519 isFreeCall(Inst, &TLI))
520 return;
521
522 // TODO: Add support for noalias args/all the other fun function attributes
523 // that we can tack on.
524 SmallVector Targets;
525 if (getPossibleTargets(CS, Targets))
526 if (tryInterproceduralAnalysis(CS, Targets))
527 return;
528
529 // Because the function is opaque, we need to note that anything
530 // could have happened to the arguments (unless the function is marked
531 // readonly or readnone), and that the result could alias just about
532 // anything, too (unless the result is marked noalias).
533 if (!CS.onlyReadsMemory())
534 for (Value *V : CS.args()) {
535 if (V->getType()->isPointerTy())
536 Escapes.insert(V);
537 }
538
539 if (Inst->getType()->isPointerTy()) {
540 auto *Fn = CS.getCalledFunction();
541 if (Fn == nullptr || !Fn->doesNotAlias(0))
542 Graph.addAttr(Inst, AttrUnknown);
543 }
544 }
545
546 /// Because vectors/aggregates are immutable and unaddressable, there's
547 /// nothing we can do to coax a value out of them, other than calling
548 /// Extract{Element,Value}. We can effectively treat them as pointers to
549 /// arbitrary memory locations we can store in and load from.
550 void visitExtractElementInst(ExtractElementInst &Inst) {
551 auto *Ptr = Inst.getVectorOperand();
552 auto *Val = &Inst;
553 addEdge(Val, Ptr, EdgeType::Reference);
554 }
555
556 void visitInsertElementInst(InsertElementInst &Inst) {
557 auto *Vec = Inst.getOperand(0);
558 auto *Val = Inst.getOperand(1);
559 addEdge(Vec, &Inst, EdgeType::Assign);
560 addEdge(&Inst, Val, EdgeType::Dereference);
561 }
562
563 void visitLandingPadInst(LandingPadInst &Inst) {
564 // Exceptions come from "nowhere", from our analysis' perspective.
565 // So we place the instruction its own group, noting that said group may
566 // alias externals
567 addNodeWithAttr(&Inst, AttrUnknown);
568 }
569
570 void visitInsertValueInst(InsertValueInst &Inst) {
571 auto *Agg = Inst.getOperand(0);
572 auto *Val = Inst.getOperand(1);
573 addEdge(Agg, &Inst, EdgeType::Assign);
574 addEdge(&Inst, Val, EdgeType::Dereference);
575 }
576
577 void visitExtractValueInst(ExtractValueInst &Inst) {
578 auto *Ptr = Inst.getAggregateOperand();
579 addEdge(&Inst, Ptr, EdgeType::Reference);
580 }
581
582 void visitShuffleVectorInst(ShuffleVectorInst &Inst) {
583 auto *From1 = Inst.getOperand(0);
584 auto *From2 = Inst.getOperand(1);
585 addEdge(From1, &Inst, EdgeType::Assign);
586 addEdge(From2, &Inst, EdgeType::Assign);
587 }
588
589 void visitConstantExpr(ConstantExpr *CE) {
590 switch (CE->getOpcode()) {
591 default:
592 llvm_unreachable("Unknown instruction type encountered!");
593 // Build the switch statement using the Instruction.def file.
594 #define HANDLE_INST(NUM, OPCODE, CLASS) \
595 case Instruction::OPCODE: \
596 visit##OPCODE(*(CLASS *)CE); \
597 break;
598 #include "llvm/IR/Instruction.def"
599 }
600 }
601 };
602
603 class CFLGraphBuilder {
604 // Input of the builder
605 CFLAAResult &Analysis;
606 const TargetLibraryInfo &TLI;
607
608 // Output of the builder
609 CFLGraph Graph;
610 SmallVector ReturnedValues;
611
612 // Auxiliary structures used by the builder
613 SmallPtrSet ExternalValues;
614 SmallPtrSet EscapedValues;
615 SmallVector InterprocEdges;
616 SmallVector InterprocAttrs;
617
618 // Helper functions
619
620 // Determines whether or not we an instruction is useless to us (e.g.
621 // FenceInst)
622 static bool hasUsefulEdges(Instruction *Inst) {
623 bool IsNonInvokeRetTerminator = isa(Inst) &&
624 !isa(Inst) &&
625 !isa(Inst);
626 return !isa(Inst) && !isa(Inst) &&
627 !IsNonInvokeRetTerminator;
628 }
629
630 void addArgumentToGraph(Argument &Arg) {
631 if (Arg.getType()->isPointerTy()) {
632 Graph.addNode(&Arg);
633 ExternalValues.insert(&Arg);
634 }
635 }
636
637 // Given an Instruction, this will add it to the graph, along with any
638 // Instructions that are potentially only available from said Instruction
639 // For example, given the following line:
640 // %0 = load i16* getelementptr ([1 x i16]* @a, 0, 0), align 2
641 // addInstructionToGraph would add both the `load` and `getelementptr`
642 // instructions to the graph appropriately.
643 void addInstructionToGraph(Instruction &Inst) {
644 if (!hasUsefulEdges(&Inst))
645 return;
646
647 GetEdgesVisitor(Analysis, TLI, Graph, ReturnedValues, ExternalValues,
648 EscapedValues, InterprocEdges, InterprocAttrs)
649 .visit(Inst);
650 }
651
652 // Builds the graph needed for constructing the StratifiedSets for the given
653 // function
654 void buildGraphFrom(Function &Fn) {
655 for (auto &Bb : Fn.getBasicBlockList())
656 for (auto &Inst : Bb.getInstList())
657 addInstructionToGraph(Inst);
658
659 for (auto &Arg : Fn.args())
660 addArgumentToGraph(Arg);
661 }
662
663 public:
664 CFLGraphBuilder(CFLAAResult &Analysis, const TargetLibraryInfo &TLI,
665 Function &Fn)
666 : Analysis(Analysis), TLI(TLI) {
667 buildGraphFrom(Fn);
668 }
669
670 const CFLGraph &getCFLGraph() const { return Graph; }
671 const SmallVector &getReturnValues() const {
672 return ReturnedValues;
673 }
674 const SmallPtrSet &getExternalValues() const {
675 return ExternalValues;
676 }
677 const SmallPtrSet &getEscapedValues() const {
678 return EscapedValues;
679 }
680 const SmallVector &getInterprocEdges() const {
681 return InterprocEdges;
682 }
683 const SmallVector &getInterprocAttrs() const {
684 return InterprocAttrs;
685 }
686 };
687 }
688
689 //===----------------------------------------------------------------------===//
690 // Function declarations that require types defined in the namespace above
691 //===----------------------------------------------------------------------===//
692
693 /// Given a StratifiedAttrs, returns true if it marks the corresponding values
694 /// as globals or arguments
695 static bool isGlobalOrArgAttr(StratifiedAttrs Attr);
696
697 /// Given a StratifiedAttrs, returns true if the corresponding values come from
698 /// an unknown source (such as opaque memory or an integer cast)
699 static bool isUnknownAttr(StratifiedAttrs Attr);
700
701 /// Given an argument number, returns the appropriate StratifiedAttr to set.
702 static StratifiedAttrs argNumberToAttr(unsigned ArgNum);
703
704 /// Given a Value, potentially return which StratifiedAttr it maps to.
705 static Optional valueToAttr(Value *Val);
706
707 /// Gets the "Level" that one should travel in StratifiedSets
708 /// given an EdgeType.
709 static Level directionOfEdgeType(EdgeType);
710
711 /// Determines whether it would be pointless to add the given Value to our sets.
712 static bool canSkipAddingToSets(Value *Val);
713
714 static Optional parentFunctionOfValue(Value *Val) {
715 if (auto *Inst = dyn_cast(Val)) {
716 auto *Bb = Inst->getParent();
717 return Bb->getParent();
718 }
719
720 if (auto *Arg = dyn_cast(Val))
721 return Arg->getParent();
722 return None;
723 }
724
725 static bool getPossibleTargets(CallSite CS,
726 SmallVectorImpl &Output) {
727 if (auto *Fn = CS.getCalledFunction()) {
728 Output.push_back(Fn);
729 return true;
730 }
731
732 // TODO: If the call is indirect, we might be able to enumerate all potential
733 // targets of the call and return them, rather than just failing.
734 return false;
735 }
736
737 static bool isGlobalOrArgAttr(StratifiedAttrs Attr) {
738 return Attr.reset(AttrEscapedIndex)
739 .reset(AttrUnknownIndex)
740 .reset(AttrCallerIndex)
741 .any();
742 }
743
744 static bool isUnknownAttr(StratifiedAttrs Attr) {
745 return Attr.test(AttrUnknownIndex) || Attr.test(AttrCallerIndex);
746 }
747
748 static Optional valueToAttr(Value *Val) {
749 if (isa(Val))
750 return StratifiedAttrs(AttrGlobal);
751
752 if (auto *Arg = dyn_cast(Val))
753 // Only pointer arguments should have the argument attribute,
754 // because things can't escape through scalars without us seeing a
755 // cast, and thus, interaction with them doesn't matter.
756 if (!Arg->hasNoAliasAttr() && Arg->getType()->isPointerTy())
757 return argNumberToAttr(Arg->getArgNo());
758 return None;
759 }
760
761 static StratifiedAttrs argNumberToAttr(unsigned ArgNum) {
762 if (ArgNum >= AttrMaxNumArgs)
763 return AttrUnknown;
764 // N.B. MSVC complains if we use `1U` here, since StratifiedAttrs' ctor takes
765 // an unsigned long long.
766 return StratifiedAttrs(1ULL << (ArgNum + AttrFirstArgIndex));
767 }
768
769 static Level directionOfEdgeType(EdgeType Weight) {
770 switch (Weight) {
771 case EdgeType::Reference:
772 return Level::Above;
773 case EdgeType::Dereference:
774 return Level::Below;
775 case EdgeType::Assign:
776 return Level::Same;
777 }
778 llvm_unreachable("Incomplete switch coverage");
779 }
780
781 static bool canSkipAddingToSets(Value *Val) {
782 // Constants can share instances, which may falsely unify multiple
783 // sets, e.g. in
784 // store i32* null, i32** %ptr1
785 // store i32* null, i32** %ptr2
786 // clearly ptr1 and ptr2 should not be unified into the same set, so
787 // we should filter out the (potentially shared) instance to
788 // i32* null.
789 if (isa(Val)) {
790 // TODO: Because all of these things are constant, we can determine whether
791 // the data is *actually* mutable at graph building time. This will probably
792 // come for free/cheap with offset awareness.
793 bool CanStoreMutableData = isa(Val) ||
794 isa(Val) ||
795 isa(Val);
796 return !CanStoreMutableData;
797 }
798
799 return false;
800 }
801
802 CFLAAResult::FunctionInfo::FunctionInfo(Function &Fn,
803 const SmallVectorImpl &RetVals,
804 StratifiedSets S)
805 : Sets(std::move(S)) {
806 // Historically, an arbitrary upper-bound of 50 args was selected. We may want
807 // to remove this if it doesn't really matter in practice.
808 if (Fn.arg_size() > MaxSupportedArgsInSummary)
809 return;
810
811 DenseMap InterfaceMap;
812
813 // Our intention here is to record all InterfaceValues that share the same
814 // StratifiedIndex in RetParamRelations. For each valid InterfaceValue, we
815 // have its StratifiedIndex scanned here and check if the index is presented
816 // in InterfaceMap: if it is not, we add the correspondence to the map;
817 // otherwise, an aliasing relation is found and we add it to
818 // RetParamRelations.
819
820 auto AddToRetParamRelations = [&](unsigned InterfaceIndex,
821 StratifiedIndex SetIndex) {
822 unsigned Level = 0;
823 while (true) {
824 InterfaceValue CurrValue{InterfaceIndex, Level};
825
826 auto Itr = InterfaceMap.find(SetIndex);
827 if (Itr != InterfaceMap.end()) {
828 if (CurrValue != Itr->second)
829 RetParamRelations.push_back(ExternalRelation{CurrValue, Itr->second});
830 break;
831 }
832
833 auto &Link = Sets.getLink(SetIndex);
834 InterfaceMap.insert(std::make_pair(SetIndex, CurrValue));
835 auto ExternalAttrs = Link.Attrs & StratifiedAttrs(ExternalAttrMask);
836 if (ExternalAttrs.any())
837 RetParamAttributes.push_back(
838 ExternalAttribute{CurrValue, ExternalAttrs});
839
840 if (!Link.hasBelow())
841 break;
842
843 ++Level;
844 SetIndex = Link.Below;
845 }
846 };
847
848 // Populate RetParamRelations for return values
849 for (auto *RetVal : RetVals) {
850 assert(RetVal != nullptr);
851 assert(RetVal->getType()->isPointerTy());
852 auto RetInfo = Sets.find(RetVal);
853 if (RetInfo.hasValue())
854 AddToRetParamRelations(0, RetInfo->Index);
855 }
856
857 // Populate RetParamRelations for parameters
858 unsigned I = 0;
859 for (auto &Param : Fn.args()) {
860 if (Param.getType()->isPointerTy()) {
861 auto ParamInfo = Sets.find(&Param);
862 if (ParamInfo.hasValue())
863 AddToRetParamRelations(I + 1, ParamInfo->Index);
864 }
865 ++I;
866 }
867 }
868
869 // Builds the graph + StratifiedSets for a function.
870 CFLAAResult::FunctionInfo CFLAAResult::buildSetsFrom(Function *Fn) {
871 CFLGraphBuilder GraphBuilder(*this, TLI, *Fn);
872 StratifiedSetsBuilder SetBuilder;
873
874 auto &Graph = GraphBuilder.getCFLGraph();
875 SmallVector Worklist;
876 for (auto Node : Graph.nodes())
877 Worklist.push_back(Node);
878
879 while (!Worklist.empty()) {
880 auto *CurValue = Worklist.pop_back_val();
881 SetBuilder.add(CurValue);
882 if (canSkipAddingToSets(CurValue))
883 continue;
884
885 auto Attr = Graph.attrFor(CurValue);
886 SetBuilder.noteAttributes(CurValue, Attr);
887
888 for (const auto &Edge : Graph.edgesFor(CurValue)) {
889 auto Label = Edge.Type;
890 auto *OtherValue = Edge.Other;
891
892 if (canSkipAddingToSets(OtherValue))
893 continue;
894
895 bool Added;
896 switch (directionOfEdgeType(Label)) {
897 case Level::Above:
898 Added = SetBuilder.addAbove(CurValue, OtherValue);
899 break;
900 case Level::Below:
901 Added = SetBuilder.addBelow(CurValue, OtherValue);
902 break;
903 case Level::Same:
904 Added = SetBuilder.addWith(CurValue, OtherValue);
905 break;
906 }
907
908 if (Added)
909 Worklist.push_back(OtherValue);
910 }
911 }
912
913 // Special handling for globals and arguments
914 for (auto *External : GraphBuilder.getExternalValues()) {
915 SetBuilder.add(External);
916 auto Attr = valueToAttr(External);
917 if (Attr.hasValue()) {
918 SetBuilder.noteAttributes(External, *Attr);
919 if (*Attr == AttrGlobal)
920 SetBuilder.addAttributesBelow(External, 1, AttrUnknown);
921 else
922 SetBuilder.addAttributesBelow(External, 1, AttrCaller);
923 }
924 }
925
926 // Special handling for interprocedural aliases
927 for (auto &Edge : GraphBuilder.getInterprocEdges()) {
928 auto FromVal = Edge.From.Val;
929 auto ToVal = Edge.To.Val;
930 SetBuilder.add(FromVal);
931 SetBuilder.add(ToVal);
932 SetBuilder.addBelowWith(FromVal, Edge.From.DerefLevel, ToVal,
933 Edge.To.DerefLevel);
934 }
935
936 // Special handling for interprocedural attributes
937 for (auto &IPAttr : GraphBuilder.getInterprocAttrs()) {
938 auto Val = IPAttr.Node.Val;
939 SetBuilder.add(Val);
940 SetBuilder.addAttributesBelow(Val, IPAttr.Node.DerefLevel, IPAttr.Attr);
941 }
942
943 // Special handling for opaque external functions
944 for (auto *Escape : GraphBuilder.getEscapedValues()) {
945 SetBuilder.add(Escape);
946 SetBuilder.noteAttributes(Escape, AttrEscaped);
947 SetBuilder.addAttributesBelow(Escape, 1, AttrUnknown);
948 }
949
950 return FunctionInfo(*Fn, GraphBuilder.getReturnValues(), SetBuilder.build());
951 }
952
953 void CFLAAResult::scan(Function *Fn) {
954 auto InsertPair = Cache.insert(std::make_pair(Fn, Optional()));
955 (void)InsertPair;
956 assert(InsertPair.second &&
957 "Trying to scan a function that has already been cached");
958
959 // Note that we can't do Cache[Fn] = buildSetsFrom(Fn) here: the function call
960 // may get evaluated after operator[], potentially triggering a DenseMap
961 // resize and invalidating the reference returned by operator[]
962 auto FunInfo = buildSetsFrom(Fn);
963 Cache[Fn] = std::move(FunInfo);
964
965 Handles.push_front(FunctionHandle(Fn, this));
966 }
967
968 void CFLAAResult::evict(Function *Fn) { Cache.erase(Fn); }
969
970 /// Ensures that the given function is available in the cache, and returns the
971 /// entry.
972 const Optional &
973 CFLAAResult::ensureCached(Function *Fn) {
974 auto Iter = Cache.find(Fn);
975 if (Iter == Cache.end()) {
976 scan(Fn);
977 Iter = Cache.find(Fn);
978 assert(Iter != Cache.end());
979 assert(Iter->second.hasValue());
980 }
981 return Iter->second;
982 }
983
984 AliasResult CFLAAResult::query(const MemoryLocation &LocA,
985 const MemoryLocation &LocB) {
986 auto *ValA = const_cast(LocA.Ptr);
987 auto *ValB = const_cast(LocB.Ptr);
988
989 if (!ValA->getType()->isPointerTy() || !ValB->getType()->isPointerTy())
990 return NoAlias;
991
992 Function *Fn = nullptr;
993 auto MaybeFnA = parentFunctionOfValue(ValA);
994 auto MaybeFnB = parentFunctionOfValue(ValB);
995 if (!MaybeFnA.hasValue() && !MaybeFnB.hasValue()) {
996 // The only times this is known to happen are when globals + InlineAsm are
997 // involved
998 DEBUG(dbgs() << "CFLAA: could not extract parent function information.\n");
999 return MayAlias;
1000 }
1001
1002 if (MaybeFnA.hasValue()) {
1003 Fn = *MaybeFnA;
1004 assert((!MaybeFnB.hasValue() || *MaybeFnB == *MaybeFnA) &&
1005 "Interprocedural queries not supported");
1006 } else {
1007 Fn = *MaybeFnB;
1008 }
1009
1010 assert(Fn != nullptr);
1011 auto &MaybeInfo = ensureCached(Fn);
1012 assert(MaybeInfo.hasValue());
1013
1014 auto &Sets = MaybeInfo->getStratifiedSets();
1015 auto MaybeA = Sets.find(ValA);
1016 if (!MaybeA.hasValue())
1017 return MayAlias;
1018
1019 auto MaybeB = Sets.find(ValB);
1020 if (!MaybeB.hasValue())
1021 return MayAlias;
1022
1023 auto SetA = *MaybeA;
1024 auto SetB = *MaybeB;
1025 auto AttrsA = Sets.getLink(SetA.Index).Attrs;
1026 auto AttrsB = Sets.getLink(SetB.Index).Attrs;
1027
1028 // If both values are local (meaning the corresponding set has attribute
1029 // AttrNone or AttrEscaped), then we know that CFLAA fully models them: they
1030 // may-alias each other if and only if they are in the same set
1031 // If at least one value is non-local (meaning it either is global/argument or
1032 // it comes from unknown sources like integer cast), the situation becomes a
1033 // bit more interesting. We follow three general rules described below:
1034 // - Non-local values may alias each other
1035 // - AttrNone values do not alias any non-local values
1036 // - AttrEscaped do not alias globals/arguments, but they may alias
1037 // AttrUnknown values
1038 if (SetA.Index == SetB.Index)
1039 return MayAlias;
1040 if (AttrsA.none() || AttrsB.none())
1041 return NoAlias;
1042 if (isUnknownAttr(AttrsA) || isUnknownAttr(AttrsB))
1043 return MayAlias;
1044 if (isGlobalOrArgAttr(AttrsA) && isGlobalOrArgAttr(AttrsB))
1045 return MayAlias;
1046 return NoAlias;
1047 }
1048
1049 ModRefInfo CFLAAResult::getArgModRefInfo(ImmutableCallSite CS,
1050 unsigned ArgIdx) {
1051 if (auto CalledFunc = CS.getCalledFunction()) {
1052 auto &MaybeInfo = ensureCached(const_cast(CalledFunc));
1053 if (!MaybeInfo.hasValue())
1054 return MRI_ModRef;
1055 auto &RetParamAttributes = MaybeInfo->getRetParamAttributes();
1056 auto &RetParamRelations = MaybeInfo->getRetParamRelations();
1057
1058 bool ArgAttributeIsWritten =
1059 std::any_of(RetParamAttributes.begin(), RetParamAttributes.end(),
1060 [ArgIdx](const ExternalAttribute &ExtAttr) {
1061 return ExtAttr.IValue.Index == ArgIdx + 1;
1062 });
1063 bool ArgIsAccessed =
1064 std::any_of(RetParamRelations.begin(), RetParamRelations.end(),
1065 [ArgIdx](const ExternalRelation &ExtRelation) {
1066 return ExtRelation.To.Index == ArgIdx + 1 ||
1067 ExtRelation.From.Index == ArgIdx + 1;
1068 });
1069
1070 return (!ArgIsAccessed && !ArgAttributeIsWritten) ? MRI_NoModRef
1071 : MRI_ModRef;
1072 }
1073
1074 return MRI_ModRef;
1075 }
1076
1077 FunctionModRefBehavior CFLAAResult::getModRefBehavior(ImmutableCallSite CS) {
1078 // If we know the callee, try analyzing it
1079 if (auto CalledFunc = CS.getCalledFunction())
1080 return getModRefBehavior(CalledFunc);
1081
1082 // Otherwise, be conservative
1083 return FMRB_UnknownModRefBehavior;
1084 }
1085
1086 FunctionModRefBehavior CFLAAResult::getModRefBehavior(const Function *F) {
1087 assert(F != nullptr);
1088
1089 // TODO: Remove the const_cast
1090 auto &MaybeInfo = ensureCached(const_cast(F));
1091 if (!MaybeInfo.hasValue())
1092 return FMRB_UnknownModRefBehavior;
1093 auto &RetParamAttributes = MaybeInfo->getRetParamAttributes();
1094 auto &RetParamRelations = MaybeInfo->getRetParamRelations();
1095
1096 // First, if any argument is marked Escpaed, Unknown or Global, anything may
1097 // happen to them and thus we can't draw any conclusion.
1098 if (!RetParamAttributes.empty())
1099 return FMRB_UnknownModRefBehavior;
1100
1101 // Currently we don't (and can't) distinguish reads from writes in
1102 // RetParamRelations. All we can say is whether there may be memory access or
1103 // not.
1104 if (RetParamRelations.empty())
1105 return FMRB_DoesNotAccessMemory;
1106
1107 // Check if something beyond argmem gets touched.
1108 bool AccessArgMemoryOnly =
1109 std::all_of(RetParamRelations.begin(), RetParamRelations.end(),
1110 [](const ExternalRelation &ExtRelation) {
1111 // Both DerefLevels has to be 0, since we don't know which
1112 // one is a read and which is a write.
1113 return ExtRelation.From.DerefLevel == 0 &&
1114 ExtRelation.To.DerefLevel == 0;
1115 });
1116 return AccessArgMemoryOnly ? FMRB_OnlyAccessesArgumentPointees
1117 : FMRB_UnknownModRefBehavior;
1118 }
1119
1120 char CFLAA::PassID;
1121
1122 CFLAAResult CFLAA::run(Function &F, AnalysisManager &AM) {
1123 return CFLAAResult(AM.getResult(F));
1124 }
1125
1126 char CFLAAWrapperPass::ID = 0;
1127 INITIALIZE_PASS(CFLAAWrapperPass, "cfl-aa", "CFL-Based Alias Analysis", false,
1128 true)
1129
1130 ImmutablePass *llvm::createCFLAAWrapperPass() { return new CFLAAWrapperPass(); }
1131
1132 CFLAAWrapperPass::CFLAAWrapperPass() : ImmutablePass(ID) {
1133 initializeCFLAAWrapperPassPass(*PassRegistry::getPassRegistry());
1134 }
1135
1136 void CFLAAWrapperPass::initializePass() {
1137 auto &TLIWP = getAnalysis();
1138 Result.reset(new CFLAAResult(TLIWP.getTLI()));
1139 }
1140
1141 void CFLAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
1142 AU.setPreservesAll();
1143 AU.addRequired();
1144 }
0 //- CFLAndersAliasAnalysis.cpp - Unification-based Alias Analysis ---*- C++-*-//
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 //
9 // This file implements a CFL-based, summary-based alias analysis algorithm. It
10 // differs from CFLSteensAliasAnalysis in its inclusion-based nature while
11 // CFLSteensAliasAnalysis is unification-based. This pass has worse performance
12 // than CFLSteensAliasAnalysis (the worst case complexity of
13 // CFLAndersAliasAnalysis is cubic, while the worst case complexity of
14 // CFLSteensAliasAnalysis is almost linear), but it is able to yield more
15 // precise analysis result. The precision of this analysis is roughly the same
16 // as that of an one level context-sensitive Andersen's algorithm.
17 //
18 //===----------------------------------------------------------------------===//
19
20 // N.B. AliasAnalysis as a whole is phrased as a FunctionPass at the moment, and
21 // CFLAndersAA is interprocedural. This is *technically* A Bad Thing, because
22 // FunctionPasses are only allowed to inspect the Function that they're being
23 // run on. Realistically, this likely isn't a problem until we allow
24 // FunctionPasses to run concurrently.
25
26 #include "llvm/Analysis/CFLAndersAliasAnalysis.h"
27 #include "llvm/Pass.h"
28
29 using namespace llvm;
30
31 #define DEBUG_TYPE "cfl-anders-aa"
32
33 CFLAndersAAResult::CFLAndersAAResult() = default;
34
35 char CFLAndersAA::PassID;
36
37 CFLAndersAAResult CFLAndersAA::run(Function &F, AnalysisManager &AM) {
38 return CFLAndersAAResult();
39 }
40
41 char CFLAndersAAWrapperPass::ID = 0;
42 INITIALIZE_PASS(CFLAndersAAWrapperPass, "cfl-anders-aa",
43 "Inclusion-Based CFL Alias Analysis", false, true)
44
45 ImmutablePass *llvm::createCFLAndersAAWrapperPass() {
46 return new CFLAndersAAWrapperPass();
47 }
48
49 CFLAndersAAWrapperPass::CFLAndersAAWrapperPass() : ImmutablePass(ID) {
50 initializeCFLAndersAAWrapperPassPass(*PassRegistry::getPassRegistry());
51 }
52
53 void CFLAndersAAWrapperPass::initializePass() {}
54
55 void CFLAndersAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
56 AU.setPreservesAll();
57 }
0 //- CFLSteensAliasAnalysis.cpp - Unification-based Alias Analysis ---*- C++-*-//
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 //
9 // This file implements a CFL-base, summary-based alias analysis algorithm. It
10 // does not depend on types. The algorithm is a mixture of the one described in
11 // "Demand-driven alias analysis for C" by Xin Zheng and Radu Rugina, and "Fast
12 // algorithms for Dyck-CFL-reachability with applications to Alias Analysis" by
13 // Zhang Q, Lyu M R, Yuan H, and Su Z. -- to summarize the papers, we build a
14 // graph of the uses of a variable, where each node is a memory location, and
15 // each edge is an action that happened on that memory location. The "actions"
16 // can be one of Dereference, Reference, or Assign. The precision of this
17 // analysis is roughly the same as that of an one level context-sensitive
18 // Steensgaard's algorithm.
19 //
20 // Two variables are considered as aliasing iff you can reach one value's node
21 // from the other value's node and the language formed by concatenating all of
22 // the edge labels (actions) conforms to a context-free grammar.
23 //
24 // Because this algorithm requires a graph search on each query, we execute the
25 // algorithm outlined in "Fast algorithms..." (mentioned above)
26 // in order to transform the graph into sets of variables that may alias in
27 // ~nlogn time (n = number of variables), which makes queries take constant
28 // time.
29 //===----------------------------------------------------------------------===//
30
31 // N.B. AliasAnalysis as a whole is phrased as a FunctionPass at the moment, and
32 // CFLSteensAA is interprocedural. This is *technically* A Bad Thing, because
33 // FunctionPasses are only allowed to inspect the Function that they're being
34 // run on. Realistically, this likely isn't a problem until we allow
35 // FunctionPasses to run concurrently.
36
37 #include "llvm/Analysis/CFLSteensAliasAnalysis.h"
38 #include "StratifiedSets.h"
39 #include "llvm/ADT/DenseMap.h"
40 #include "llvm/ADT/None.h"
41 #include "llvm/ADT/Optional.h"
42 #include "llvm/Analysis/MemoryBuiltins.h"
43 #include "llvm/Analysis/TargetLibraryInfo.h"
44 #include "llvm/IR/Constants.h"
45 #include "llvm/IR/Function.h"
46 #include "llvm/IR/InstVisitor.h"
47 #include "llvm/IR/Instructions.h"
48 #include "llvm/Pass.h"
49 #include "llvm/Support/Compiler.h"
50 #include "llvm/Support/Debug.h"
51 #include "llvm/Support/ErrorHandling.h"
52 #include "llvm/Support/raw_ostream.h"
53 #include
54 #include
55 #include
56 #include
57
58 using namespace llvm;
59
60 #define DEBUG_TYPE "cfl-steens-aa"
61
62 CFLSteensAAResult::CFLSteensAAResult(const TargetLibraryInfo &TLI)
63 : AAResultBase(), TLI(TLI) {}
64 CFLSteensAAResult::CFLSteensAAResult(CFLSteensAAResult &&Arg)
65 : AAResultBase(std::move(Arg)), TLI(Arg.TLI) {}
66 CFLSteensAAResult::~CFLSteensAAResult() {}
67
68 /// We use InterfaceValue to describe parameters/return value, as well as
69 /// potential memory locations that are pointed to by parameters/return value,
70 /// of a function.
71 /// Index is an integer which represents a single parameter or a return value.
72 /// When the index is 0, it refers to the return value. Non-zero index i refers
73 /// to the i-th parameter.
74 /// DerefLevel indicates the number of dereferences one must perform on the
75 /// parameter/return value to get this InterfaceValue.
76 struct InterfaceValue {
77 unsigned Index;
78 unsigned DerefLevel;
79 };
80
81 bool operator==(InterfaceValue lhs, InterfaceValue rhs) {
82 return lhs.Index == rhs.Index && lhs.DerefLevel == rhs.DerefLevel;
83 }
84 bool operator!=(InterfaceValue lhs, InterfaceValue rhs) {
85 return !(lhs == rhs);
86 }
87
88 /// We use ExternalRelation to describe an externally visible aliasing relations
89 /// between parameters/return value of a function.
90 struct ExternalRelation {
91 InterfaceValue From, To;
92 };
93
94 /// We use ExternalAttribute to describe an externally visible StratifiedAttrs
95 /// for parameters/return value.
96 struct ExternalAttribute {
97 InterfaceValue IValue;
98 StratifiedAttrs Attr;
99 };
100
101 /// Information we have about a function and would like to keep around.
102 class CFLSteensAAResult::FunctionInfo {
103 StratifiedSets Sets;
104
105 // RetParamRelations is a collection of ExternalRelations.
106 SmallVector RetParamRelations;
107
108 // RetParamAttributes is a collection of ExternalAttributes.
109 SmallVector RetParamAttributes;
110
111 public:
112 FunctionInfo(Function &Fn, const SmallVectorImpl &RetVals,
113 StratifiedSets S);
114
115 const StratifiedSets &getStratifiedSets() const { return Sets; }
116 const SmallVectorImpl &getRetParamRelations() const {
117 return RetParamRelations;
118 }
119 const SmallVectorImpl &getRetParamAttributes() const {
120 return RetParamAttributes;
121 }
122 };
123
124 /// Try to go from a Value* to a Function*. Never returns nullptr.
125 static Optional parentFunctionOfValue(Value *);
126
127 /// Returns possible functions called by the Inst* into the given
128 /// SmallVectorImpl. Returns true if targets found, false otherwise. This is
129 /// templated so we can use it with CallInsts and InvokeInsts.
130 static bool getPossibleTargets(CallSite, SmallVectorImpl &);
131
132 const StratifiedIndex StratifiedLink::SetSentinel =
133 std::numeric_limits::max();
134
135 namespace {
136 /// StratifiedInfo Attribute things.
137 LLVM_CONSTEXPR unsigned MaxStratifiedAttrIndex = NumStratifiedAttrs;
138 LLVM_CONSTEXPR unsigned AttrEscapedIndex = 0;
139 LLVM_CONSTEXPR unsigned AttrUnknownIndex = 1;
140 LLVM_CONSTEXPR unsigned AttrGlobalIndex = 2;
141 LLVM_CONSTEXPR unsigned AttrCallerIndex = 3;
142 LLVM_CONSTEXPR unsigned AttrFirstArgIndex = 4;
143 LLVM_CONSTEXPR unsigned AttrLastArgIndex = MaxStratifiedAttrIndex;
144 LLVM_CONSTEXPR unsigned AttrMaxNumArgs = AttrLastArgIndex - AttrFirstArgIndex;
145
146 // NOTE: These aren't StratifiedAttrs because bitsets don't have a constexpr
147 // ctor for some versions of MSVC that we support. We could maybe refactor,
148 // but...
149 using StratifiedAttr = unsigned;
150 LLVM_CONSTEXPR StratifiedAttr AttrNone = 0;
151 LLVM_CONSTEXPR StratifiedAttr AttrEscaped = 1 << AttrEscapedIndex;
152 LLVM_CONSTEXPR StratifiedAttr AttrUnknown = 1 << AttrUnknownIndex;
153 LLVM_CONSTEXPR StratifiedAttr AttrGlobal = 1 << AttrGlobalIndex;
154 LLVM_CONSTEXPR StratifiedAttr AttrCaller = 1 << AttrCallerIndex;
155 LLVM_CONSTEXPR StratifiedAttr ExternalAttrMask =
156 AttrEscaped | AttrUnknown | AttrGlobal;
157
158 /// The maximum number of arguments we can put into a summary.
159 LLVM_CONSTEXPR unsigned MaxSupportedArgsInSummary = 50;
160
161 /// StratifiedSets call for knowledge of "direction", so this is how we
162 /// represent that locally.
163 enum class Level { Same, Above, Below };
164
165 /// Edges can be one of four "weights" -- each weight must have an inverse
166 /// weight (Assign has Assign; Reference has Dereference).
167 enum class EdgeType {
168 /// The weight assigned when assigning from or to a value. For example, in:
169 /// %b = getelementptr %a, 0
170 /// ...The relationships are %b assign %a, and %a assign %b. This used to be
171 /// two edges, but having a distinction bought us nothing.
172 Assign,
173
174 /// The edge used when we have an edge going from some handle to a Value.
175 /// Examples of this include:
176 /// %b = load %a (%b Dereference %a)
177 /// %b = extractelement %a, 0 (%a Dereference %b)
178 Dereference,
179
180 /// The edge used when our edge goes from a value to a handle that may have
181 /// contained it at some point. Examples:
182 /// %b = load %a (%a Reference %b)
183 /// %b = extractelement %a, 0 (%b Reference %a)
184 Reference
185 };
186
187 /// The Program Expression Graph (PEG) of CFL analysis
188 class CFLGraph {
189 typedef Value *Node;
190
191 struct Edge {
192 EdgeType Type;
193 Node Other;
194 };
195
196 typedef std::vector EdgeList;
197
198 struct NodeInfo {
199 EdgeList Edges;
200 StratifiedAttrs Attr;
201 };
202
203 typedef DenseMap NodeMap;
204 NodeMap NodeImpls;
205
206 // Gets the inverse of a given EdgeType.
207 static EdgeType flipWeight(EdgeType Initial) {
208 switch (Initial) {
209 case EdgeType::Assign:
210 return EdgeType::Assign;
211 case EdgeType::Dereference:
212 return EdgeType::Reference;
213 case EdgeType::Reference:
214 return EdgeType::Dereference;
215 }
216 llvm_unreachable("Incomplete coverage of EdgeType enum");
217 }
218
219 const NodeInfo *getNode(Node N) const {
220 auto Itr = NodeImpls.find(N);
221 if (Itr == NodeImpls.end())
222 return nullptr;
223 return &Itr->second;
224 }
225 NodeInfo *getNode(Node N) {
226 auto Itr = NodeImpls.find(N);
227 if (Itr == NodeImpls.end())
228 return nullptr;
229 return &Itr->second;
230 }
231
232 static Node nodeDeref(const NodeMap::value_type &P) { return P.first; }
233 typedef std::pointer_to_unary_function
234 NodeDerefFun;
235
236 public:
237 typedef EdgeList::const_iterator const_edge_iterator;
238 typedef mapped_iterator
239 const_node_iterator;
240
241 bool addNode(Node N) {
242 return NodeImpls.insert(std::make_pair(N, NodeInfo{EdgeList(), AttrNone}))
243 .second;
244 }
245
246 void addAttr(Node N, StratifiedAttrs Attr) {
247 auto *Info = getNode(N);
248 assert(Info != nullptr);
249 Info->Attr |= Attr;
250 }
251
252 void addEdge(Node From, Node To, EdgeType Type) {
253 auto *FromInfo = getNode(From);
254 assert(FromInfo != nullptr);
255 auto *ToInfo = getNode(To);
256 assert(ToInfo != nullptr);
257
258 FromInfo->Edges.push_back(Edge{Type, To});
259 ToInfo->Edges.push_back(Edge{flipWeight(Type), From});
260 }
261
262 StratifiedAttrs attrFor(Node N) const {
263 auto *Info = getNode(N);
264 assert(Info != nullptr);
265 return Info->Attr;
266 }
267
268 iterator_range edgesFor(Node N) const {
269 auto *Info = getNode(N);
270 assert(Info != nullptr);
271 auto &Edges = Info->Edges;
272 return make_range(Edges.begin(), Edges.end());
273 }
274
275 iterator_range nodes() const {
276 return make_range(
277 map_iterator(NodeImpls.begin(), NodeDerefFun(nodeDeref)),
278 map_iterator(NodeImpls.end(), NodeDerefFun(nodeDeref)));
279 }
280
281 bool empty() const { return NodeImpls.empty(); }
282 std::size_t size() const { return NodeImpls.size(); }
283 };
284
285 // This is the result of instantiating InterfaceValue at a particular callsite
286 struct InterprocNode {
287 Value *Val;
288 unsigned DerefLevel;
289 };
290
291 // Interprocedural assignment edges that CFLGraph may not easily model
292 struct InterprocEdge {
293 InterprocNode From, To;
294 };
295
296 // Interprocedural attribute tagging that CFLGraph may not easily model
297 struct InterprocAttr {
298 InterprocNode Node;
299 StratifiedAttrs Attr;
300 };
301
302 /// Gets the edges our graph should have, based on an Instruction*
303 class GetEdgesVisitor : public InstVisitor {
304 CFLSteensAAResult &AA;
305 const TargetLibraryInfo &TLI;
306
307 CFLGraph &Graph;
308 SmallVectorImpl &ReturnValues;
309 SmallPtrSetImpl &Externals;
310 SmallPtrSetImpl &Escapes;
311 SmallVectorImpl &InterprocEdges;
312 SmallVectorImpl &InterprocAttrs;
313
314 static bool hasUsefulEdges(ConstantExpr *CE) {
315 // ConstantExpr doesn't have terminators, invokes, or fences, so only needs
316 // to check for compares.
317 return CE->getOpcode() != Instruction::ICmp &&
318 CE->getOpcode() != Instruction::FCmp;
319 }
320
321 void addNode(Value *Val) {
322 if (!Graph.addNode(Val))
323 return;
324
325 if (isa(Val))
326 Externals.insert(Val);
327 else if (auto CExpr = dyn_cast(Val))
328 if (hasUsefulEdges(CExpr))
329 visitConstantExpr(CExpr);
330 }
331
332 void addNodeWithAttr(Value *Val, StratifiedAttrs Attr) {
333 addNode(Val);
334 Graph.addAttr(Val, Attr);
335 }
336
337 void addEdge(Value *From, Value *To, EdgeType Type) {
338 if (!From->getType()->isPointerTy() || !To->getType()->isPointerTy())
339 return;
340 addNode(From);
341 if (To != From)
342 addNode(To);
343 Graph.addEdge(From, To, Type);
344 }
345
346 public:
347 GetEdgesVisitor(CFLSteensAAResult &AA, const TargetLibraryInfo &TLI,
348 CFLGraph &Graph, SmallVectorImpl &ReturnValues,
349 SmallPtrSetImpl &Externals,
350 SmallPtrSetImpl &Escapes,
351 SmallVectorImpl &InterprocEdges,
352 SmallVectorImpl &InterprocAttrs)
353 : AA(AA), TLI(TLI), Graph(Graph), ReturnValues(ReturnValues),
354 Externals(Externals), Escapes(Escapes), InterprocEdges(InterprocEdges),
355 InterprocAttrs(InterprocAttrs) {}
356
357 void visitInstruction(Instruction &) {
358 llvm_unreachable("Unsupported instruction encountered");
359 }
360
361 void visitReturnInst(ReturnInst &Inst) {
362 if (auto RetVal = Inst.getReturnValue()) {
363 if (RetVal->getType()->isPointerTy()) {
364 addNode(RetVal);
365 ReturnValues.push_back(RetVal);
366 }
367 }
368 }
369
370 void visitPtrToIntInst(PtrToIntInst &Inst) {
371 auto *Ptr = Inst.getOperand(0);
372 addNodeWithAttr(Ptr, AttrEscaped);
373 }
374
375 void visitIntToPtrInst(IntToPtrInst &Inst) {
376 auto *Ptr = &Inst;
377 addNodeWithAttr(Ptr, AttrUnknown);
378 }
379
380 void visitCastInst(CastInst &Inst) {
381 auto *Src = Inst.getOperand(0);
382 addEdge(Src, &Inst, EdgeType::Assign);
383 }
384
385 void visitBinaryOperator(BinaryOperator &Inst) {
386 auto *Op1 = Inst.getOperand(0);
387 auto *Op2 = Inst.getOperand(1);
388 addEdge(Op1, &Inst, EdgeType::Assign);
389 addEdge(Op2, &Inst, EdgeType::Assign);
390 }
391
392 void visitAtomicCmpXchgInst(AtomicCmpXchgInst &Inst) {
393 auto *Ptr = Inst.getPointerOperand();
394 auto *Val = Inst.getNewValOperand();
395 addEdge(Ptr, Val, EdgeType::Dereference);
396 }
397
398 void visitAtomicRMWInst(AtomicRMWInst &Inst) {
399 auto *Ptr = Inst.getPointerOperand();
400 auto *Val = Inst.getValOperand();
401 addEdge(Ptr, Val, EdgeType::Dereference);
402 }
403
404 void visitPHINode(PHINode &Inst) {
405 for (Value *Val : Inst.incoming_values())
406 addEdge(Val, &Inst, EdgeType::Assign);
407 }
408
409 void visitGetElementPtrInst(GetElementPtrInst &Inst) {
410 auto *Op = Inst.getPointerOperand();
411 addEdge(Op, &Inst, EdgeType::Assign);
412 }
413
414 void visitSelectInst(SelectInst &Inst) {
415 // Condition is not processed here (The actual statement producing
416 // the condition result is processed elsewhere). For select, the
417 // condition is evaluated, but not loaded, stored, or assigned
418 // simply as a result of being the condition of a select.
419
420 auto *TrueVal = Inst.getTrueValue();
421 auto *FalseVal = Inst.getFalseValue();
422 addEdge(TrueVal, &Inst, EdgeType::Assign);
423 addEdge(FalseVal, &Inst, EdgeType::Assign);
424 }
425
426 void visitAllocaInst(AllocaInst &Inst) { Graph.addNode(&Inst); }
427
428 void visitLoadInst(LoadInst &Inst) {
429 auto *Ptr = Inst.getPointerOperand();
430 auto *Val = &Inst;
431 addEdge(Val, Ptr, EdgeType::Reference);
432 }
433
434 void visitStoreInst(StoreInst &Inst) {
435 auto *Ptr = Inst.getPointerOperand();
436 auto *Val = Inst.getValueOperand();
437 addEdge(Ptr, Val, EdgeType::Dereference);
438 }
439
440 void visitVAArgInst(VAArgInst &Inst) {
441 // We can't fully model va_arg here. For *Ptr = Inst.getOperand(0), it does
442 // two things:
443 // 1. Loads a value from *((T*)*Ptr).
444 // 2. Increments (stores to) *Ptr by some target-specific amount.
445 // For now, we'll handle this like a landingpad instruction (by placing the
446 // result in its own group, and having that group alias externals).
447 addNodeWithAttr(&Inst, AttrUnknown);
448 }
449
450 static bool isFunctionExternal(Function *Fn) {
451 return !Fn->hasExactDefinition();
452 }
453
454 bool tryInterproceduralAnalysis(CallSite CS,
455 const SmallVectorImpl &Fns) {
456 assert(Fns.size() > 0);
457
458 if (CS.arg_size() > MaxSupportedArgsInSummary)
459 return false;
460
461 // Exit early if we'll fail anyway
462 for (auto *Fn : Fns) {
463 if (isFunctionExternal(Fn) || Fn->isVarArg())
464 return false;
465 // Fail if the caller does not provide enough arguments
466 assert(Fn->arg_size() <= CS.arg_size());
467 auto &MaybeInfo = AA.ensureCached(Fn);
468 if (!MaybeInfo.hasValue())
469 return false;
470 }
471
472 auto InstantiateInterfaceIndex = [&CS](unsigned Index) {
473 auto Value =
474 (Index == 0) ? CS.getInstruction() : CS.getArgument(Index - 1);
475 return Value->getType()->isPointerTy() ? Value : nullptr;
476 };
477
478 for (auto *Fn : Fns) {
479 auto &FnInfo = AA.ensureCached(Fn);
480 assert(FnInfo.hasValue());
481
482 auto &RetParamRelations = FnInfo->getRetParamRelations();
483 for (auto &Relation : RetParamRelations) {
484 auto FromVal = InstantiateInterfaceIndex(Relation.From.Index);
485 auto ToVal = InstantiateInterfaceIndex(Relation.To.Index);
486 if (FromVal && ToVal) {
487 auto FromLevel = Relation.From.DerefLevel;
488 auto ToLevel = Relation.To.DerefLevel;
489 InterprocEdges.push_back(
490 InterprocEdge{InterprocNode{FromVal, FromLevel},
491 InterprocNode{ToVal, ToLevel}});
492 }
493 }
494
495 auto &RetParamAttributes = FnInfo->getRetParamAttributes();
496 for (auto &Attribute : RetParamAttributes) {
497 if (auto Val = InstantiateInterfaceIndex(Attribute.IValue.Index)) {
498 InterprocAttrs.push_back(InterprocAttr{
499 InterprocNode{Val, Attribute.IValue.DerefLevel}, Attribute.Attr});
500 }
501 }
502 }
503
504 return true;
505 }
506
507 void visitCallSite(CallSite CS) {
508 auto Inst = CS.getInstruction();
509
510 // Make sure all arguments and return value are added to the graph first
511 for (Value *V : CS.args())
512 addNode(V);
513 if (Inst->getType()->isPointerTy())
514 addNode(Inst);
515
516 // Check if Inst is a call to a library function that allocates/deallocates
517 // on the heap. Those kinds of functions do not introduce any aliases.
518 // TODO: address other common library functions such as realloc(), strdup(),
519 // etc.
520 if (isMallocLikeFn(Inst, &TLI) || isCallocLikeFn(Inst, &TLI) ||
521 isFreeCall(Inst, &TLI))
522 return;
523
524 // TODO: Add support for noalias args/all the other fun function attributes
525 // that we can tack on.
526 SmallVector Targets;
527 if (getPossibleTargets(CS, Targets))
528 if (tryInterproceduralAnalysis(CS, Targets))
529 return;
530
531 // Because the function is opaque, we need to note that anything
532 // could have happened to the arguments (unless the function is marked
533 // readonly or readnone), and that the result could alias just about
534 // anything, too (unless the result is marked noalias).
535 if (!CS.onlyReadsMemory())
536 for (Value *V : CS.args()) {
537 if (V->getType()->isPointerTy())
538 Escapes.insert(V);
539 }
540
541 if (Inst->getType()->isPointerTy()) {
542 auto *Fn = CS.getCalledFunction();
543 if (Fn == nullptr || !Fn->doesNotAlias(0))
544 Graph.addAttr(Inst, AttrUnknown);
545 }
546 }
547
548 /// Because vectors/aggregates are immutable and unaddressable, there's
549 /// nothing we can do to coax a value out of them, other than calling
550 /// Extract{Element,Value}. We can effectively treat them as pointers to
551 /// arbitrary memory locations we can store in and load from.
552 void visitExtractElementInst(ExtractElementInst &Inst) {
553 auto *Ptr = Inst.getVectorOperand();
554 auto *Val = &Inst;
555 addEdge(Val, Ptr, EdgeType::Reference);
556 }
557
558 void visitInsertElementInst(InsertElementInst &Inst) {
559 auto *Vec = Inst.getOperand(0);
560 auto *Val = Inst.getOperand(1);
561 addEdge(Vec, &Inst, EdgeType::Assign);
562 addEdge(&Inst, Val, EdgeType::Dereference);
563 }
564
565 void visitLandingPadInst(LandingPadInst &Inst) {
566 // Exceptions come from "nowhere", from our analysis' perspective.
567 // So we place the instruction its own group, noting that said group may
568 // alias externals
569 addNodeWithAttr(&Inst, AttrUnknown);
570 }
571
572 void visitInsertValueInst(InsertValueInst &Inst) {
573 auto *Agg = Inst.getOperand(0);
574 auto *Val = Inst.getOperand(1);
575 addEdge(Agg, &Inst, EdgeType::Assign);
576 addEdge(&Inst, Val, EdgeType::Dereference);
577 }
578
579 void visitExtractValueInst(ExtractValueInst &Inst) {
580 auto *Ptr = Inst.getAggregateOperand();
581 addEdge(&Inst, Ptr, EdgeType::Reference);
582 }
583
584 void visitShuffleVectorInst(ShuffleVectorInst &Inst) {
585 auto *From1 = Inst.getOperand(0);
586 auto *From2 = Inst.getOperand(1);
587 addEdge(From1, &Inst, EdgeType::Assign);
588 addEdge(From2, &Inst, EdgeType::Assign);
589 }
590
591 void visitConstantExpr(ConstantExpr *CE) {
592 switch (CE->getOpcode()) {
593 default:
594 llvm_unreachable("Unknown instruction type encountered!");
595 // Build the switch statement using the Instruction.def file.
596 #define HANDLE_INST(NUM, OPCODE, CLASS) \
597 case Instruction::OPCODE: \
598 visit##OPCODE(*(CLASS *)CE); \
599 break;
600 #include "llvm/IR/Instruction.def"
601 }
602 }
603 };
604
605 class CFLGraphBuilder {
606 // Input of the builder
607 CFLSteensAAResult &Analysis;
608 const TargetLibraryInfo &TLI;
609
610 // Output of the builder
611 CFLGraph Graph;
612 SmallVector ReturnedValues;
613
614 // Auxiliary structures used by the builder
615 SmallPtrSet ExternalValues;
616 SmallPtrSet EscapedValues;
617 SmallVector InterprocEdges;
618 SmallVector InterprocAttrs;
619
620 // Helper functions
621
622 // Determines whether or not we an instruction is useless to us (e.g.
623 // FenceInst)
624 static bool hasUsefulEdges(Instruction *Inst) {
625 bool IsNonInvokeRetTerminator = isa(Inst) &&
626 !isa(Inst) &&
627 !isa(Inst);
628 return !isa(Inst) && !isa(Inst) &&
629 !IsNonInvokeRetTerminator;
630 }
631
632 void addArgumentToGraph(Argument &Arg) {
633 if (Arg.getType()->isPointerTy()) {
634 Graph.addNode(&Arg);
635 ExternalValues.insert(&Arg);
636 }
637 }
638
639 // Given an Instruction, this will add it to the graph, along with any
640 // Instructions that are potentially only available from said Instruction
641 // For example, given the following line:
642 // %0 = load i16* getelementptr ([1 x i16]* @a, 0, 0), align 2
643 // addInstructionToGraph would add both the `load` and `getelementptr`
644 // instructions to the graph appropriately.
645 void addInstructionToGraph(Instruction &Inst) {
646 if (!hasUsefulEdges(&Inst))
647 return;
648
649 GetEdgesVisitor(Analysis, TLI, Graph, ReturnedValues, ExternalValues,
650 EscapedValues, InterprocEdges, InterprocAttrs)
651 .visit(Inst);
652 }
653
654 // Builds the graph needed for constructing the StratifiedSets for the given
655 // function
656 void buildGraphFrom(Function &Fn) {
657 for (auto &Bb : Fn.getBasicBlockList())
658 for (auto &Inst : Bb.getInstList())
659 addInstructionToGraph(Inst);
660
661 for (auto &Arg : Fn.args())
662 addArgumentToGraph(Arg);
663 }
664
665 public:
666 CFLGraphBuilder(CFLSteensAAResult &Analysis, const TargetLibraryInfo &TLI,
667 Function &Fn)
668 : Analysis(Analysis), TLI(TLI) {
669 buildGraphFrom(Fn);
670 }
671
672 const CFLGraph &getCFLGraph() const { return Graph; }
673 const SmallVector &getReturnValues() const {
674 return ReturnedValues;
675 }
676 const SmallPtrSet &getExternalValues() const {
677 return ExternalValues;
678 }
679 const SmallPtrSet &getEscapedValues() const {
680 return EscapedValues;
681 }
682 const SmallVector &getInterprocEdges() const {
683 return InterprocEdges;
684 }
685 const SmallVector &getInterprocAttrs() const {
686 return InterprocAttrs;
687 }
688 };
689 }
690
691 //===----------------------------------------------------------------------===//
692 // Function declarations that require types defined in the namespace above
693 //===----------------------------------------------------------------------===//
694
695 /// Given a StratifiedAttrs, returns true if it marks the corresponding values
696 /// as globals or arguments
697 static bool isGlobalOrArgAttr(StratifiedAttrs Attr);
698
699 /// Given a StratifiedAttrs, returns true if the corresponding values come from
700 /// an unknown source (such as opaque memory or an integer cast)
701 static bool isUnknownAttr(StratifiedAttrs Attr);
702
703 /// Given an argument number, returns the appropriate StratifiedAttr to set.
704 static StratifiedAttrs argNumberToAttr(unsigned ArgNum);
705
706 /// Given a Value, potentially return which StratifiedAttr it maps to.
707 static Optional valueToAttr(Value *Val);
708
709 /// Gets the "Level" that one should travel in StratifiedSets
710 /// given an EdgeType.
711 static Level directionOfEdgeType(EdgeType);
712
713 /// Determines whether it would be pointless to add the given Value to our sets.
714 static bool canSkipAddingToSets(Value *Val);
715
716 static Optional parentFunctionOfValue(Value *Val) {
717 if (auto *Inst = dyn_cast(Val)) {
718 auto *Bb = Inst->getParent();
719 return Bb->getParent();
720 }
721
722 if (auto *Arg = dyn_cast(Val))
723 return Arg->getParent();
724 return None;
725 }
726
727 static bool getPossibleTargets(CallSite CS,
728 SmallVectorImpl &Output) {
729 if (auto *Fn = CS.getCalledFunction()) {
730 Output.push_back(Fn);
731 return true;
732 }
733
734 // TODO: If the call is indirect, we might be able to enumerate all potential
735 // targets of the call and return them, rather than just failing.
736 return false;
737 }
738
739 static bool isGlobalOrArgAttr(StratifiedAttrs Attr) {
740 return Attr.reset(AttrEscapedIndex)
741 .reset(AttrUnknownIndex)
742 .reset(AttrCallerIndex)
743 .any();
744 }
745
746 static bool isUnknownAttr(StratifiedAttrs Attr) {
747 return Attr.test(AttrUnknownIndex) || Attr.test(AttrCallerIndex);
748 }
749
750 static Optional valueToAttr(Value *Val) {
751 if (isa(Val))
752 return StratifiedAttrs(AttrGlobal);
753
754 if (auto *Arg = dyn_cast(Val))
755 // Only pointer arguments should have the argument attribute,
756 // because things can't escape through scalars without us seeing a
757 // cast, and thus, interaction with them doesn't matter.
758 if (!Arg->hasNoAliasAttr() && Arg->getType()->isPointerTy())
759 return argNumberToAttr(Arg->getArgNo());
760 return None;
761 }
762
763 static StratifiedAttrs argNumberToAttr(unsigned ArgNum) {
764 if (ArgNum >= AttrMaxNumArgs)
765 return AttrUnknown;
766 // N.B. MSVC complains if we use `1U` here, since StratifiedAttrs' ctor takes
767 // an unsigned long long.
768 return StratifiedAttrs(1ULL << (ArgNum + AttrFirstArgIndex));
769 }
770
771 static Level directionOfEdgeType(EdgeType Weight) {
772 switch (Weight) {
773 case EdgeType::Reference:
774 return Level::Above;
775 case EdgeType::Dereference:
776 return Level::Below;
777 case EdgeType::Assign:
778 return Level::Same;
779 }
780 llvm_unreachable("Incomplete switch coverage");
781 }
782
783 static bool canSkipAddingToSets(Value *Val) {
784 // Constants can share instances, which may falsely unify multiple
785 // sets, e.g. in
786 // store i32* null, i32** %ptr1
787 // store i32* null, i32** %ptr2
788 // clearly ptr1 and ptr2 should not be unified into the same set, so
789 // we should filter out the (potentially shared) instance to
790 // i32* null.
791 if (isa(Val)) {
792 // TODO: Because all of these things are constant, we can determine whether
793 // the data is *actually* mutable at graph building time. This will probably
794 // come for free/cheap with offset awareness.
795 bool CanStoreMutableData = isa(Val) ||
796 isa(Val) ||
797 isa(Val);
798 return !CanStoreMutableData;
799 }
800
801 return false;
802 }
803
804 CFLSteensAAResult::FunctionInfo::FunctionInfo(
805 Function &Fn, const SmallVectorImpl &RetVals,
806 StratifiedSets S)
807 : Sets(std::move(S)) {
808 // Historically, an arbitrary upper-bound of 50 args was selected. We may want
809 // to remove this if it doesn't really matter in practice.
810 if (Fn.arg_size() > MaxSupportedArgsInSummary)
811 return;
812
813 DenseMap InterfaceMap;
814
815 // Our intention here is to record all InterfaceValues that share the same
816 // StratifiedIndex in RetParamRelations. For each valid InterfaceValue, we
817 // have its StratifiedIndex scanned here and check if the index is presented
818 // in InterfaceMap: if it is not, we add the correspondence to the map;
819 // otherwise, an aliasing relation is found and we add it to
820 // RetParamRelations.
821
822 auto AddToRetParamRelations = [&](unsigned InterfaceIndex,
823 StratifiedIndex SetIndex) {
824 unsigned Level = 0;
825 while (true) {
826 InterfaceValue CurrValue{InterfaceIndex, Level};
827
828 auto Itr = InterfaceMap.find(SetIndex);
829 if (Itr != InterfaceMap.end()) {
830 if (CurrValue != Itr->second)
831 RetParamRelations.push_back(ExternalRelation{CurrValue, Itr->second});
832 break;
833 }
834
835 auto &Link = Sets.getLink(SetIndex);
836 InterfaceMap.insert(std::make_pair(SetIndex, CurrValue));
837 auto ExternalAttrs = Link.Attrs & StratifiedAttrs(ExternalAttrMask);
838 if (ExternalAttrs.any())
839 RetParamAttributes.push_back(
840 ExternalAttribute{CurrValue, ExternalAttrs});
841
842 if (!Link.hasBelow())
843 break;
844
845 ++Level;
846 SetIndex = Link.Below;
847 }
848 };
849
850 // Populate RetParamRelations for return values
851 for (auto *RetVal : RetVals) {
852 assert(RetVal != nullptr);
853 assert(RetVal->getType()->isPointerTy());
854 auto RetInfo = Sets.find(RetVal);
855 if (RetInfo.hasValue())
856 AddToRetParamRelations(0, RetInfo->Index);
857 }
858
859 // Populate RetParamRelations for parameters
860 unsigned I = 0;
861 for (auto &Param : Fn.args()) {
862 if (Param.getType()->isPointerTy()) {
863 auto ParamInfo = Sets.find(&Param);
864 if (ParamInfo.hasValue())
865 AddToRetParamRelations(I + 1, ParamInfo->Index);
866 }
867 ++I;
868 }
869 }
870
871 // Builds the graph + StratifiedSets for a function.
872 CFLSteensAAResult::FunctionInfo CFLSteensAAResult::buildSetsFrom(Function *Fn) {
873 CFLGraphBuilder GraphBuilder(*this, TLI, *Fn);
874 StratifiedSetsBuilder SetBuilder;
875
876 auto &Graph = GraphBuilder.getCFLGraph();
877 SmallVector Worklist;
878 for (auto Node : Graph.nodes())
879 Worklist.push_back(Node);
880
881 while (!Worklist.empty()) {
882 auto *CurValue = Worklist.pop_back_val();
883 SetBuilder.add(CurValue);
884 if (canSkipAddingToSets(CurValue))
885 continue;
886
887 auto Attr = Graph.attrFor(CurValue);
888 SetBuilder.noteAttributes(CurValue, Attr);
889
890 for (const auto &Edge : Graph.edgesFor(CurValue)) {
891 auto Label = Edge.Type;
892 auto *OtherValue = Edge.Other;
893
894 if (canSkipAddingToSets(OtherValue))
895 continue;
896
897 bool Added;
898 switch (directionOfEdgeType(Label)) {
899 case Level::Above:
900 Added = SetBuilder.addAbove(CurValue, OtherValue);
901 break;
902 case Level::Below:
903 Added = SetBuilder.addBelow(CurValue, OtherValue);
904 break;
905 case Level::Same:
906 Added = SetBuilder.addWith(CurValue, OtherValue);
907 break;
908 }
909
910 if (Added)
911 Worklist.push_back(OtherValue);
912 }
913 }
914
915 // Special handling for globals and arguments
916 for (auto *External : GraphBuilder.getExternalValues()) {
917 SetBuilder.add(External);
918 auto Attr = valueToAttr(External);
919 if (Attr.hasValue()) {
920 SetBuilder.noteAttributes(External, *Attr);
921 if (*Attr == AttrGlobal)
922 SetBuilder.addAttributesBelow(External, 1, AttrUnknown);
923 else
924 SetBuilder.addAttributesBelow(External, 1, AttrCaller);
925 }
926 }
927
928 // Special handling for interprocedural aliases
929 for (auto &Edge : GraphBuilder.getInterprocEdges()) {
930 auto FromVal = Edge.From.Val;
931 auto ToVal = Edge.To.Val;
932 SetBuilder.add(FromVal);
933 SetBuilder.add(ToVal);
934 SetBuilder.addBelowWith(FromVal, Edge.From.DerefLevel, ToVal,
935 Edge.To.DerefLevel);
936 }
937
938 // Special handling for interprocedural attributes
939 for (auto &IPAttr : GraphBuilder.getInterprocAttrs()) {
940 auto Val = IPAttr.Node.Val;
941 SetBuilder.add(Val);
942 SetBuilder.addAttributesBelow(Val, IPAttr.Node.DerefLevel, IPAttr.Attr);
943 }
944
945 // Special handling for opaque external functions
946 for (auto *Escape : GraphBuilder.getEscapedValues()) {
947 SetBuilder.add(Escape);
948 SetBuilder.noteAttributes(Escape, AttrEscaped);
949 SetBuilder.addAttributesBelow(Escape, 1, AttrUnknown);
950 }
951
952 return FunctionInfo(*Fn, GraphBuilder.getReturnValues(), SetBuilder.build());
953 }
954
955 void CFLSteensAAResult::scan(Function *Fn) {
956 auto InsertPair = Cache.insert(std::make_pair(Fn, Optional()));
957 (void)InsertPair;
958 assert(InsertPair.second &&
959 "Trying to scan a function that has already been cached");
960
961 // Note that we can't do Cache[Fn] = buildSetsFrom(Fn) here: the function call
962 // may get evaluated after operator[], potentially triggering a DenseMap
963 // resize and invalidating the reference returned by operator[]
964 auto FunInfo = buildSetsFrom(Fn);
965 Cache[Fn] = std::move(FunInfo);
966
967 Handles.push_front(FunctionHandle(Fn, this));
968 }
969
970 void CFLSteensAAResult::evict(Function *Fn) { Cache.erase(Fn); }
971
972 /// Ensures that the given function is available in the cache, and returns the
973 /// entry.
974 const Optional &
975 CFLSteensAAResult::ensureCached(Function *Fn) {
976 auto Iter = Cache.find(Fn);
977 if (Iter == Cache.end()) {
978 scan(Fn);
979 Iter = Cache.find(Fn);
980 assert(Iter != Cache.end());
981 assert(Iter->second.hasValue());
982 }
983 return Iter->second;
984 }
985
986 AliasResult CFLSteensAAResult::query(const MemoryLocation &LocA,
987 const MemoryLocation &LocB) {
988 auto *ValA = const_cast(LocA.Ptr);
989 auto *ValB = const_cast(LocB.Ptr);
990
991 if (!ValA->getType()->isPointerTy() || !ValB->getType()->isPointerTy())
992 return NoAlias;
993
994 Function *Fn = nullptr;
995 auto MaybeFnA = parentFunctionOfValue(ValA);
996 auto MaybeFnB = parentFunctionOfValue(ValB);
997 if (!MaybeFnA.hasValue() && !MaybeFnB.hasValue()) {
998 // The only times this is known to happen are when globals + InlineAsm are
999 // involved
1000 DEBUG(dbgs()
1001 << "CFLSteensAA: could not extract parent function information.\n");
1002 return MayAlias;
1003 }
1004
1005 if (MaybeFnA.hasValue()) {
1006 Fn = *MaybeFnA;
1007 assert((!MaybeFnB.hasValue() || *MaybeFnB == *MaybeFnA) &&
1008 "Interprocedural queries not supported");
1009 } else {
1010 Fn = *MaybeFnB;
1011 }
1012
1013 assert(Fn != nullptr);
1014 auto &MaybeInfo = ensureCached(Fn);
1015 assert(MaybeInfo.hasValue());
1016
1017 auto &Sets = MaybeInfo->getStratifiedSets();
1018 auto MaybeA = Sets.find(ValA);
1019 if (!MaybeA.hasValue())
1020 return MayAlias;
1021
1022 auto MaybeB = Sets.find(ValB);
1023 if (!MaybeB.hasValue())
1024 return MayAlias;
1025
1026 auto SetA = *MaybeA;
1027 auto SetB = *MaybeB;
1028 auto AttrsA = Sets.getLink(SetA.Index).Attrs;
1029 auto AttrsB = Sets.getLink(SetB.Index).Attrs;
1030
1031 // If both values are local (meaning the corresponding set has attribute
1032 // AttrNone or AttrEscaped), then we know that CFLSteensAA fully models them:
1033 // they may-alias each other if and only if they are in the same set.
1034 // If at least one value is non-local (meaning it either is global/argument or
1035 // it comes from unknown sources like integer cast), the situation becomes a
1036 // bit more interesting. We follow three general rules described below:
1037 // - Non-local values may alias each other
1038 // - AttrNone values do not alias any non-local values
1039 // - AttrEscaped do not alias globals/arguments, but they may alias
1040 // AttrUnknown values
1041 if (SetA.Index == SetB.Index)
1042 return MayAlias;
1043 if (AttrsA.none() || AttrsB.none())
1044 return NoAlias;
1045 if (isUnknownAttr(AttrsA) || isUnknownAttr(AttrsB))
1046 return MayAlias;
1047 if (isGlobalOrArgAttr(AttrsA) && isGlobalOrArgAttr(AttrsB))
1048 return MayAlias;
1049 return NoAlias;
1050 }
1051
1052 ModRefInfo CFLSteensAAResult::getArgModRefInfo(ImmutableCallSite CS,
1053 unsigned ArgIdx) {
1054 if (auto CalledFunc = CS.getCalledFunction()) {
1055 auto &MaybeInfo = ensureCached(const_cast(CalledFunc));
1056 if (!MaybeInfo.hasValue())
1057 return MRI_ModRef;
1058 auto &RetParamAttributes = MaybeInfo->getRetParamAttributes();
1059 auto &RetParamRelations = MaybeInfo->getRetParamRelations();
1060
1061 bool ArgAttributeIsWritten =
1062 std::any_of(RetParamAttributes.begin(), RetParamAttributes.end(),
1063 [ArgIdx](const ExternalAttribute &ExtAttr) {
1064 return ExtAttr.IValue.Index == ArgIdx + 1;
1065 });
1066 bool ArgIsAccessed =
1067 std::any_of(RetParamRelations.begin(), RetParamRelations.end(),
1068 [ArgIdx](const ExternalRelation &ExtRelation) {
1069 return ExtRelation.To.Index == ArgIdx + 1 ||
1070 ExtRelation.From.Index == ArgIdx + 1;
1071 });
1072
1073 return (!ArgIsAccessed && !ArgAttributeIsWritten) ? MRI_NoModRef
1074 : MRI_ModRef;
1075 }
1076
1077 return MRI_ModRef;
1078 }
1079
1080 FunctionModRefBehavior
1081 CFLSteensAAResult::getModRefBehavior(ImmutableCallSite CS) {
1082 // If we know the callee, try analyzing it
1083 if (auto CalledFunc = CS.getCalledFunction())
1084 return getModRefBehavior(CalledFunc);
1085
1086 // Otherwise, be conservative
1087 return FMRB_UnknownModRefBehavior;
1088 }
1089
1090 FunctionModRefBehavior CFLSteensAAResult::getModRefBehavior(const Function *F) {
1091 assert(F != nullptr);
1092
1093 // TODO: Remove the const_cast
1094 auto &MaybeInfo = ensureCached(const_cast(F));
1095 if (!MaybeInfo.hasValue())
1096 return FMRB_UnknownModRefBehavior;
1097 auto &RetParamAttributes = MaybeInfo->getRetParamAttributes();
1098 auto &RetParamRelations = MaybeInfo->getRetParamRelations();
1099
1100 // First, if any argument is marked Escpaed, Unknown or Global, anything may
1101 // happen to them and thus we can't draw any conclusion.
1102 if (!RetParamAttributes.empty())
1103 return FMRB_UnknownModRefBehavior;
1104
1105 // Currently we don't (and can't) distinguish reads from writes in
1106 // RetParamRelations. All we can say is whether there may be memory access or
1107 // not.
1108 if (RetParamRelations.empty())
1109 return FMRB_DoesNotAccessMemory;
1110
1111 // Check if something beyond argmem gets touched.
1112 bool AccessArgMemoryOnly =
1113 std::all_of(RetParamRelations.begin(), RetParamRelations.end(),
1114 [](const ExternalRelation &ExtRelation) {
1115 // Both DerefLevels has to be 0, since we don't know which
1116 // one is a read and which is a write.
1117 return ExtRelation.From.DerefLevel == 0 &&
1118 ExtRelation.To.DerefLevel == 0;
1119 });
1120 return AccessArgMemoryOnly ? FMRB_OnlyAccessesArgumentPointees
1121 : FMRB_UnknownModRefBehavior;
1122 }
1123
1124 char CFLSteensAA::PassID;
1125
1126 CFLSteensAAResult CFLSteensAA::run(Function &F, AnalysisManager &AM) {
1127 return CFLSteensAAResult(AM.getResult(F));
1128 }
1129
1130 char CFLSteensAAWrapperPass::ID = 0;
1131 INITIALIZE_PASS(CFLSteensAAWrapperPass, "cfl-steens-aa",
1132 "Unification-Based CFL Alias Analysis", false, true)
1133
1134 ImmutablePass *llvm::createCFLSteensAAWrapperPass() {
1135 return new CFLSteensAAWrapperPass();
1136 }
1137
1138 CFLSteensAAWrapperPass::CFLSteensAAWrapperPass() : ImmutablePass(ID) {
1139 initializeCFLSteensAAWrapperPassPass(*PassRegistry::getPassRegistry());
1140 }
1141
1142 void CFLSteensAAWrapperPass::initializePass() {
1143 auto &TLIWP = getAnalysis();
1144 Result.reset(new CFLSteensAAResult(TLIWP.getTLI()));
1145 }
1146
1147 void CFLSteensAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
1148 AU.setPreservesAll();
1149 AU.addRequired();
1150 }
99 BranchProbabilityInfo.cpp
1010 CFG.cpp
1111 CFGPrinter.cpp
12 CFLAliasAnalysis.cpp
12 CFLAndersAliasAnalysis.cpp
13 CFLSteensAliasAnalysis.cpp
1314 CGSCCPassManager.cpp
1415 CallGraph.cpp
1516 CallGraphSCCPass.cpp
1414 #include "llvm/CodeGen/TargetPassConfig.h"
1515
1616 #include "llvm/Analysis/BasicAliasAnalysis.h"
17 #include "llvm/Analysis/CFLAliasAnalysis.h"
17 #include "llvm/Analysis/CFLAndersAliasAnalysis.h"
18 #include "llvm/Analysis/CFLSteensAliasAnalysis.h"
1819 #include "llvm/Analysis/CallGraphSCCPass.h"
1920 #include "llvm/Analysis/Passes.h"
2021 #include "llvm/Analysis/ScopedNoAliasAA.h"
109110 static cl::opt EarlyLiveIntervals("early-live-intervals", cl::Hidden,
110111 cl::desc("Run live interval analysis earlier in the pipeline"));
111112
112 static cl::opt UseCFLAA("use-cfl-aa-in-codegen",
113 cl::init(false), cl::Hidden,
114 cl::desc("Enable the new, experimental CFL alias analysis in CodeGen"));
113 // Experimental option to use CFL-AA in codegen
114 enum class CFLAAType { None, Steensgaard, Andersen, Both };
115 static cl::opt UseCFLAA(
116 "use-cfl-aa-in-codegen", cl::init(CFLAAType::None), cl::Hidden,
117 cl::desc("Enable the new, experimental CFL alias analysis in CodeGen"),
118 cl::values(clEnumValN(CFLAAType::None, "none", "Disable CFL-AA"),
119 clEnumValN(CFLAAType::Steensgaard, "steens",
120 "Enable unification-based CFL-AA"),
121 clEnumValN(CFLAAType::Andersen, "anders",
122 "Enable inclusion-based CFL-AA"),
123 clEnumValN(CFLAAType::Both, "both",
124 "Enable both variants of CFL-AA"),
125 clEnumValEnd));
115126
116127 cl::opt UseIPRA("enable-ipra", cl::init(false), cl::Hidden,
117128 cl::desc("Enable interprocedural register allocation "
413424 /// Add common target configurable passes that perform LLVM IR to IR transforms
414425 /// following machine independent optimization.
415426 void TargetPassConfig::addIRPasses() {
427 switch (UseCFLAA) {
428 case CFLAAType::Steensgaard:
429 addPass(createCFLSteensAAWrapperPass());
430 break;
431 case CFLAAType::Andersen:
432 addPass(createCFLAndersAAWrapperPass());
433 break;
434 case CFLAAType::Both:
435 addPass(createCFLAndersAAWrapperPass());
436 addPass(createCFLSteensAAWrapperPass());
437 break;
438 default:
439 break;
440 }
441
416442 // Basic AliasAnalysis support.
417443 // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
418444 // BasicAliasAnalysis wins if they disagree. This is intended to help
419445 // support "obvious" type-punning idioms.
420 if (UseCFLAA)
421 addPass(createCFLAAWrapperPass());
422446 addPass(createTypeBasedAAWrapperPass());
423447 addPass(createScopedNoAliasAAWrapperPass());
424448 addPass(createBasicAAWrapperPass());
2323 #include "llvm/Analysis/BlockFrequencyInfo.h"
2424 #include "llvm/Analysis/BlockFrequencyInfoImpl.h"
2525 #include "llvm/Analysis/BranchProbabilityInfo.h"
26 #include "llvm/Analysis/CFLAliasAnalysis.h"
26 #include "llvm/Analysis/CFLAndersAliasAnalysis.h"
27 #include "llvm/Analysis/CFLSteensAliasAnalysis.h"
2728 #include "llvm/Analysis/CGSCCPassManager.h"
2829 #include "llvm/Analysis/CallGraph.h"
2930 #include "llvm/Analysis/DemandedBits.h"
691692 DebugLogging) ||
692693 !PipelineText.empty())
693694 return false;
694 MPM.addPass(createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM), DebugLogging));
695 MPM.addPass(
696 createModuleToPostOrderCGSCCPassAdaptor(std::move(CGPM), DebugLogging));
695697 return true;
696698 }
697699
2626 MODULE_ANALYSIS("verify", VerifierAnalysis())
2727
2828 #ifndef MODULE_ALIAS_ANALYSIS
29 #define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
29 #define MODULE_ALIAS_ANALYSIS(NAME, CREATE_PASS) \
3030 MODULE_ANALYSIS(NAME, CREATE_PASS)
3131 #endif
3232 MODULE_ALIAS_ANALYSIS("globals-aa", GlobalsAA())
109109 FUNCTION_ANALYSIS(NAME, CREATE_PASS)
110110 #endif
111111 FUNCTION_ALIAS_ANALYSIS("basic-aa", BasicAA())
112 FUNCTION_ALIAS_ANALYSIS("cfl-aa", CFLAA())
112 FUNCTION_ALIAS_ANALYSIS("cfl-anders-aa", CFLAndersAA())
113 FUNCTION_ALIAS_ANALYSIS("cfl-steens-aa", CFLSteensAA())
113114 FUNCTION_ALIAS_ANALYSIS("scev-aa", SCEVAA())
114115 FUNCTION_ALIAS_ANALYSIS("scoped-noalias-aa", ScopedNoAliasAA())
115116 FUNCTION_ALIAS_ANALYSIS("type-based-aa", TypeBasedAA())
1515 #include "llvm-c/Transforms/PassManagerBuilder.h"
1616 #include "llvm/ADT/SmallVector.h"
1717 #include "llvm/Analysis/BasicAliasAnalysis.h"
18 #include "llvm/Analysis/CFLAliasAnalysis.h"
18 #include "llvm/Analysis/CFLAndersAliasAnalysis.h"
19 #include "llvm/Analysis/CFLSteensAliasAnalysis.h"
1920 #include "llvm/Analysis/GlobalsModRef.h"
2021 #include "llvm/Analysis/Passes.h"
2122 #include "llvm/Analysis/ScopedNoAliasAA.h"
7879 cl::desc("Run the SLP vectorizer (and BB vectorizer) after the Loop "
7980 "vectorizer instead of before"));
8081
81 static cl::opt UseCFLAA("use-cfl-aa",
82 cl::init(false), cl::Hidden,
83 cl::desc("Enable the new, experimental CFL alias analysis"));
82 // Experimental option to use CFL-AA
83 enum class CFLAAType { None, Steensgaard, Andersen, Both };
84 static cl::opt
85 UseCFLAA("use-cfl-aa", cl::init(CFLAAType::None), cl::Hidden,
86 cl::desc("Enable the new, experimental CFL alias analysis"),
87 cl::values(clEnumValN(CFLAAType::None, "none", "Disable CFL-AA"),
88 clEnumValN(CFLAAType::Steensgaard, "steens",
89 "Enable unification-based CFL-AA"),
90 clEnumValN(CFLAAType::Andersen, "anders",
91 "Enable inclusion-based CFL-AA"),
92 clEnumValN(CFLAAType::Both, "both",
93 "Enable both variants of CFL-aa"),
94 clEnumValEnd));
8495
8596 static cl::opt
8697 EnableMLSM("mlsm", cl::init(true), cl::Hidden,
168179
169180 void PassManagerBuilder::addInitialAliasAnalysisPasses(
170181 legacy::PassManagerBase &PM) const {
182 switch (UseCFLAA) {
183 case CFLAAType::Steensgaard:
184 PM.add(createCFLSteensAAWrapperPass());
185 break;
186 case CFLAAType::Andersen:
187 PM.add(createCFLAndersAAWrapperPass());
188 break;
189 case CFLAAType::Both:
190 PM.add(createCFLSteensAAWrapperPass());
191 PM.add(createCFLAndersAAWrapperPass());
192 break;
193 default:
194 break;
195 }
196
171197 // Add TypeBasedAliasAnalysis before BasicAliasAnalysis so that
172198 // BasicAliasAnalysis wins if they disagree. This is intended to help
173199 // support "obvious" type-punning idioms.
174 if (UseCFLAA)
175 PM.add(createCFLAAWrapperPass());
176200 PM.add(createTypeBasedAAWrapperPass());
177201 PM.add(createScopedNoAliasAAWrapperPass());
178202 }
0 ; This testcase ensures that CFL AA gives conservative answers on variables
1 ; that involve arguments.
2 ; (Everything should alias everything, because args can alias globals, so the
3 ; aliasing sets should of args+alloca+global should be combined)
4
5 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s
6
7 ; CHECK: Function: test
8
9 @g = external global i32
10
11 define void @test(i1 %c, i32* %arg1, i32* %arg2) {
12 ; CHECK: 15 Total Alias Queries Performed
13 ; CHECK: 0 no alias responses
14 %A = alloca i32, align 4
15 %B = select i1 %c, i32* %arg1, i32* %arg2
16 %C = select i1 %c, i32* @g, i32* %A
17
18 ret void
19 }
0 ; This testcase ensures that CFL AA gives conservative answers on variables
1 ; that involve arguments.
2
3 ; RUN: opt < %s -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s
4
5 ; CHECK: Function: test
6
7 define void @test(i1 %c, i32* %arg1, i32* %arg2) {
8 ; CHECK: 6 Total Alias Queries Performed
9 ; CHECK: 3 no alias responses
10 %a = alloca i32, align 4
11 %b = select i1 %c, i32* %arg1, i32* %arg2
12
13 ret void
14 }
0 ; Test case for a bug where we would crash when we were requested to report
1 ; whether two values that didn't belong to a function (i.e. two globals, etc)
2 ; aliased.
3
4 ; RUN: opt < %s -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s
5
6 @G = private unnamed_addr constant [1 x i8] c"\00", align 1
7
8 ; CHECK: Function: test_no_crash
9 ; CHECK: 0 no alias responses
10 define void @test_no_crash() #0 {
11 entry:
12 call i8* asm "nop", "=r,r"(
13 i8* getelementptr inbounds ([1 x i8], [1 x i8]* @G, i64 0, i64 0))
14 ret void
15 }
0 ; This testcase ensures that CFL AA handles escaped values no more conservative than it should
1
2 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
3 ; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
4
5 ; CHECK-LABEL: Function: test_local
6 ; CHECK: NoAlias: i32* %a, i32* %b
7 ; CHECK: MayAlias: i32* %a, i32* %aAlias
8 ; CHECK: NoAlias: i32* %aAlias, i32* %b
9 define void @test_local() {
10 %a = alloca i32, align 4
11 %b = alloca i32, align 4
12 %aint = ptrtoint i32* %a to i64
13 %aAlias = inttoptr i64 %aint to i32*
14 ret void
15 }
16
17 ; CHECK-LABEL: Function: test_global_param
18 ; CHECK: NoAlias: i32* %a, i32** %x
19 ; CHECK: MayAlias: i32* %a, i32* %xload
20 ; CHECK: MayAlias: i32* %a, i32* %gload
21 ; CHECK: MayAlias: i32* %gload, i32* %xload
22 ; CHECK: MayAlias: i32** %x, i32** @ext_global
23 ; CHECK: NoAlias: i32* %a, i32** @ext_global
24 @ext_global = external global i32*
25 define void @test_global_param(i32** %x) {
26 %a = alloca i32, align 4
27 %aint = ptrtoint i32* %a to i64
28 %xload = load i32*, i32** %x
29 %gload = load i32*, i32** @ext_global
30 ret void
31 }
32
33 declare void @external_func(i32**)
34 ; CHECK-LABEL: Function: test_external_call
35 ; CHECK: NoAlias: i32* %b, i32* %x
36 ; CHECK: NoAlias: i32* %b, i32** %a
37 ; CHECK: MayAlias: i32* %c, i32* %x
38 ; CHECK: MayAlias: i32* %c, i32** %a
39 ; CHECK: NoAlias: i32* %b, i32* %c
40 define void @test_external_call(i32* %x) {
41 %a = alloca i32*, align 8
42 %b = alloca i32, align 4
43 call void @external_func(i32** %a)
44 %c = load i32*, i32** %a
45 ret void
46 }
47
48 declare void @external_func_readonly(i32**) readonly
49 ; CHECK-LABEL: Function: test_external_call_func_readonly
50 ; CHECK: MayAlias: i32* %c, i32* %x
51 ; CHECK: NoAlias: i32* %c, i32** %a
52 define void @test_external_call_func_readonly(i32* %x) {
53 %a = alloca i32*, align 8
54 %b = alloca i32, align 4
55 store i32* %x, i32** %a, align 4
56 call void @external_func_readonly(i32** %a)
57 %c = load i32*, i32** %a
58 ret void
59 }
60
61 ; CHECK-LABEL: Function: test_external_call_callsite_readonly
62 ; CHECK: MayAlias: i32* %c, i32* %x
63 ; CHECK: NoAlias: i32* %c, i32** %a
64 define void @test_external_call_callsite_readonly(i32* %x) {
65 %a = alloca i32*, align 8
66 %b = alloca i32, align 4
67 store i32* %x, i32** %a, align 4
68 call void @external_func(i32** %a) readonly
69 %c = load i32*, i32** %a
70 ret void
71 }
72
73 declare i32* @external_func_normal_return(i32*)
74 ; CHECK-LABEL: Function: test_external_call_normal_return
75 ; CHECK: MayAlias: i32* %c, i32* %x
76 ; CHECK: MayAlias: i32* %a, i32* %c
77 define void @test_external_call_normal_return(i32* %x) {
78 %a = alloca i32, align 8
79 %b = alloca i32, align 4
80 %c = call i32* @external_func_normal_return(i32* %a)
81 ret void
82 }
83
84 declare noalias i32* @external_func_noalias_return(i32*)
85 ; CHECK-LABEL: Function: test_external_call_noalias_return
86 ; CHECK: NoAlias: i32* %c, i32* %x
87 ; CHECK: NoAlias: i32* %a, i32* %c
88 define void @test_external_call_noalias_return(i32* %x) {
89 %a = alloca i32, align 8
90 %b = alloca i32, align 4
91 %c = call i32* @external_func_noalias_return(i32* %a)
92 ret void
93 }
0 ; This testcase ensures that CFL AA won't be too conservative when trying to do
1 ; interprocedural analysis on simple callee
2
3 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
4 ; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
5
6 ; CHECK-LABEL: Function: noop_callee
7 ; CHECK: MayAlias: i32* %arg1, i32* %arg2
8 define void @noop_callee(i32* %arg1, i32* %arg2) {
9 store i32 0, i32* %arg1
10 store i32 0, i32* %arg2
11 ret void
12 }
13 ; CHECK-LABEL: Function: test_noop
14 ; CHECK: NoAlias: i32* %a, i32* %b
15 define void @test_noop() {
16 %a = alloca i32, align 4
17 %b = alloca i32, align 4
18 call void @noop_callee(i32* %a, i32* %b)
19
20 ret void
21 }
0 ; Makes sure that we give up on some pathological cases with inttoptr/ptrtoint
1 ;
2 ; @ptr_test was generated from the following C code:
3 ; void ptr_test() {
4 ; int* A;
5 ; unsigned long RefCopy = 0;
6 ; for (int i = 0; i < 8*sizeof(&A); ++i) {
7 ; if ((unsigned long)&A & (1UL << i))
8 ; RefCopy |= 1UL << i;
9 ; }
10 ;
11 ; int** AliasA1 = (int**)RefCopy;
12 ; int* ShouldAliasA = *AliasA1;
13 ; }
14
15 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s
16
17 ; CHECK: Function: ptr_test
18 define void @ptr_test() #0 {
19 ; CHECK: MayAlias: i32** %A, i32** %ShouldAliasA
20 ; CHECK-NOT: %AliasA1
21 entry:
22 %A = alloca i32*, align 8
23 %RefCopy = alloca i64, align 8
24 %i = alloca i32, align 4
25 %AliasA1 = alloca i32**, align 8
26 %ShouldAliasA = alloca i32*, align 8
27 store i64 0, i64* %RefCopy, align 8
28 store i32 0, i32* %i, align 4
29 br label %for.cond
30
31 for.cond: ; preds = %for.inc, %entry
32 %0 = load i32, i32* %i, align 4
33 %conv = sext i32 %0 to i64
34 %cmp = icmp ult i64 %conv, 64
35 br i1 %cmp, label %for.body, label %for.end
36
37 for.body: ; preds = %for.cond
38 %1 = ptrtoint i32** %A to i64
39 %2 = load i32, i32* %i, align 4
40 %sh_prom = zext i32 %2 to i64
41 %shl = shl i64 1, %sh_prom
42 %and = and i64 %1, %shl
43 %tobool = icmp ne i64 %and, 0
44 br i1 %tobool, label %if.then, label %if.end
45
46 if.then: ; preds = %for.body
47 %3 = load i32, i32* %i, align 4
48 %sh_prom2 = zext i32 %3 to i64
49 %shl3 = shl i64 1, %sh_prom2
50 %4 = load i64, i64* %RefCopy, align 8
51 %or = or i64 %4, %shl3
52 store i64 %or, i64* %RefCopy, align 8
53 br label %if.end
54
55 if.end: ; preds = %if.then, %for.body
56 br label %for.inc
57
58 for.inc: ; preds = %if.end
59 %5 = load i32, i32* %i, align 4
60 %inc = add nsw i32 %5, 1
61 store i32 %inc, i32* %i, align 4
62 br label %for.cond
63
64 for.end: ; preds = %for.cond
65 %6 = load i64, i64* %RefCopy, align 8
66 %7 = inttoptr i64 %6 to i32**
67 store i32** %7, i32*** %AliasA1, align 8
68 %8 = load i32**, i32*** %AliasA1, align 8
69 %9 = load i32*, i32** %8, align 8
70 store i32* %9, i32** %ShouldAliasA, align 8
71 ret void
72 }
0 ; This testcase consists of alias relations which should be completely
1 ; resolvable by cfl-steens-aa, but require analysis of getelementptr constant exprs.
2 ; Derived from BasicAA/2003-12-11-ConstExprGEP.ll
3
4 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-may-aliases -disable-output 2>&1 | FileCheck %s
5
6 %T = type { i32, [10 x i8] }
7
8 @G = external global %T
9 @G2 = external global %T
10
11 ; TODO: Quite a few of these are MayAlias because we don't yet consider
12 ; constant offsets in CFLSteensAA. If we start doing so, then we'll need to
13 ; change these test cases
14
15 ; CHECK: Function: test
16 ; CHECK: MayAlias: i32* %D, i32* %F
17 ; CHECK: MayAlias: i32* %D, i8* %X
18 ; CHECK: MayAlias: i32* %F, i8* %X
19 define void @test() {
20 %D = getelementptr %T, %T* @G, i64 0, i32 0
21 %F = getelementptr i32, i32* getelementptr (%T, %T* @G, i64 0, i32 0), i64 0
22 %X = getelementptr [10 x i8], [10 x i8]* getelementptr (%T, %T* @G, i64 0, i32 1), i64 0, i64 5
23
24 ret void
25 }
26
27 ; CHECK: Function: simplecheck
28 ; CHECK: MayAlias: i32* %F, i32* %arg0
29 ; CHECK: MayAlias: i32* %H, i32* %arg0
30 ; CHECK: MayAlias: i32* %F, i32* %H
31 define void @simplecheck(i32* %arg0) {
32 %F = getelementptr i32, i32* getelementptr (%T, %T* @G, i64 0, i32 0), i64 0
33 %H = getelementptr %T, %T* @G2, i64 0, i32 0
34
35 ret void
36 }
37
38 ; Ensure that CFLSteensAA properly identifies and handles escaping variables (i.e.
39 ; globals) in nested ConstantExprs
40
41 ; CHECK: Function: checkNesting
42 ; CHECK: MayAlias: i32* %A, i32* %arg0
43
44 %NestedT = type { [1 x [1 x i32]] }
45 @NT = external global %NestedT
46
47 define void @checkNesting(i32* %arg0) {
48 %A = getelementptr [1 x i32],
49 [1 x i32]* getelementptr
50 ([1 x [1 x i32]], [1 x [1 x i32]]* getelementptr (%NestedT, %NestedT* @NT, i64 0, i32 0),
51 i64 0,
52 i32 0),
53 i64 0,
54 i32 0
55 ret void
56 }
0 ; RUN: opt < %s -cfl-steens-aa -aa-eval -print-all-alias-modref-info 2>&1 | FileCheck %s
1
2 ; CFL AA currently returns PartialAlias, BasicAA returns MayAlias, both seem
3 ; acceptable (although we might decide that we don't want PartialAlias, and if
4 ; so, we should update this test case accordingly).
5 ; CHECK: {{PartialAlias|MayAlias}}: double* %p.0.i.0, double* %p3
6
7 ; %p3 is equal to %p.0.i.0 on the second iteration of the loop,
8 ; so MayAlias is needed.
9
10 define void @foo([3 x [3 x double]]* noalias %p) {
11 entry:
12 %p3 = getelementptr [3 x [3 x double]], [3 x [3 x double]]* %p, i64 0, i64 0, i64 3
13 br label %loop
14
15 loop:
16 %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
17
18 %p.0.i.0 = getelementptr [3 x [3 x double]], [3 x [3 x double]]* %p, i64 0, i64 %i, i64 0
19
20 store volatile double 0.0, double* %p3
21 store volatile double 0.1, double* %p.0.i.0
22
23 %i.next = add i64 %i, 1
24 %cmp = icmp slt i64 %i.next, 3
25 br i1 %cmp, label %loop, label %exit
26
27 exit:
28 ret void
29 }
0 ; RUN: opt < %s -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
1
2 target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
3
4 ; CHECK: Function: foo:
5 ; CHECK-NEXT: NoAlias: {}* %p, {}* %q
6
7 define void @foo({}* %p, {}* %q) {
8 store {} {}, {}* %p
9 store {} {}, {}* %q
10 ret void
11 }
0 ; RUN: opt -S -disable-basicaa -tbaa -cfl-steens-aa -gvn < %s | FileCheck -check-prefix=CFLSteensAA %s
1 ; RUN: opt -S -disable-basicaa -tbaa -gvn < %s | FileCheck %s
2 ; Adapted from the BasicAA full-store-partial-alias.ll test.
3
4 ; CFL AA could notice that the store stores to the entire %u object,
5 ; so the %tmp5 load is PartialAlias with the store and suppress TBAA.
6 ; FIXME: However, right now, CFLSteensAA cannot prove PartialAlias here
7 ; Without CFL AA, TBAA should say that %tmp5 is NoAlias with the store.
8
9 target datalayout = "e-p:64:64:64"
10
11 %union.anon = type { double }
12
13 @u = global %union.anon { double -2.500000e-01 }, align 8
14 @endianness_test = global i64 1, align 8
15
16 define i32 @signbit(double %x) nounwind {
17 ; FIXME: This would be ret i32 %tmp5.lobit if CFLSteensAA could prove PartialAlias
18 ; CFLSteensAA: ret i32 0
19 ; CHECK: ret i32 0
20 entry:
21 %u = alloca %union.anon, align 8
22 %tmp9 = getelementptr inbounds %union.anon, %union.anon* %u, i64 0, i32 0
23 store double %x, double* %tmp9, align 8, !tbaa !0
24 %tmp2 = load i32, i32* bitcast (i64* @endianness_test to i32*), align 8, !tbaa !3
25 %idxprom = sext i32 %tmp2 to i64
26 %tmp4 = bitcast %union.anon* %u to [2 x i32]*
27 %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* %tmp4, i64 0, i64 %idxprom
28 %tmp5 = load i32, i32* %arrayidx, align 4, !tbaa !3
29 %tmp5.lobit = lshr i32 %tmp5, 31
30 ret i32 %tmp5.lobit
31 }
32
33 !0 = !{!4, !4, i64 0}
34 !1 = !{!"omnipotent char", !2}
35 !2 = !{!"Simple C/C++ TBAA", null}
36 !3 = !{!5, !5, i64 0}
37 !4 = !{!"double", !1}
38 !5 = !{!"int", !1}
0 ; This testcase ensures that gep result does not alias gep indices
1
2 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-no-aliases -disable-output 2>&1 | FileCheck %s
3 ; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-no-aliases -disable-output 2>&1 | FileCheck %s
4
5 ; CHECK: Function: foo
6 ; CHECK: [2 x i32]* %a, [2 x i32]* %b
7 define void @foo(i32 %n) {
8 %a = alloca [2 x i32], align 4
9 %b = alloca [2 x i32], align 4
10 %c = getelementptr inbounds [2 x i32], [2 x i32]* %a, i32 0, i32 %n
11 %d = getelementptr inbounds [2 x i32], [2 x i32]* %b, i32 0, i32 %n
12 ret void
13 }
0 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
1 ; Derived from BasicAA/2010-09-15-GEP-SignedArithmetic.ll
2
3 target datalayout = "e-p:32:32:32"
4
5 ; FIXME: This could be PartialAlias but CFLSteensAA can't currently prove it
6 ; CHECK: 1 may alias response
7
8 define i32 @test(i32 %indvar) nounwind {
9 %tab = alloca i32, align 4
10 %tmp31 = mul i32 %indvar, -2
11 %tmp32 = add i32 %tmp31, 30
12 %t.5 = getelementptr i32, i32* %tab, i32 %tmp32
13 %loada = load i32, i32* %tab
14 store i32 0, i32* %t.5
15 %loadb = load i32, i32* %tab
16 %rval = add i32 %loada, %loadb
17 ret i32 %rval
18 }
0 ; This testcase ensures that CFL AA answers queries soundly when callee tries
1 ; to escape the memory pointed to by its parameters
2
3 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
4 ; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
5
6 declare void @opaque(i32*)
7 define void @escape_arg_deref(i32** %arg) {
8 %arg_deref = load i32*, i32** %arg
9 call void @opaque(i32* %arg_deref)
10 ret void
11 }
12 ; CHECK-LABEL: Function: test_arg_deref_escape
13 ; CHECK: NoAlias: i32* %a, i32** %x
14 ; CHECK: NoAlias: i32* %b, i32** %x
15 ; CHECK: NoAlias: i32* %a, i32* %b
16 ; CHECK: NoAlias: i32** %p, i32** %x
17 ; CHECK: NoAlias: i32* %a, i32** %p
18 ; CHECK: NoAlias: i32* %b, i32** %p
19 ; CHECK: MayAlias: i32* %a, i32* %c
20 ; CHECK: NoAlias: i32* %b, i32* %c
21 ; CHECK: NoAlias: i32* %c, i32** %p
22 define void @test_arg_deref_escape(i32** %x) {
23 %a = alloca i32, align 4
24 %b = alloca i32, align 4
25 %p = alloca i32*, align 4
26
27 store i32* %a, i32** %p
28 call void @escape_arg_deref(i32** %p)
29 %c = load i32*, i32** %x
30
31 ret void
32 }
0 ; This testcase ensures that CFL AA answers queries soundly when callee tries
1 ; to escape its parameters
2
3 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
4 ; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
5
6 declare void @opaque(i32*)
7 define void @escape_arg(i32* %arg) {
8 call void @opaque(i32* %arg)
9 ret void
10 }
11 ; CHECK-LABEL: Function: test_arg_escape
12 ; CHECK: NoAlias: i32* %a, i32** %x
13 ; CHECK: NoAlias: i32* %b, i32** %x
14 ; CHECK: NoAlias: i32* %a, i32* %b
15 ; CHECK: NoAlias: i32* %c, i32** %x
16 ; CHECK: NoAlias: i32* %a, i32* %c
17 ; CHECK: NoAlias: i32* %b, i32* %c
18 ; CHECK: MayAlias: i32* %a, i32* %d
19 ; CHECK: MayAlias: i32* %b, i32* %d
20 ; CHECK: NoAlias: i32* %c, i32* %d
21 define void @test_arg_escape(i32** %x) {
22 %a = alloca i32, align 4
23 %b = alloca i32, align 4
24 %c = alloca i32, align 4
25 call void @escape_arg(i32* %a)
26 call void @escape_arg(i32* %b)
27 %d = load i32*, i32** %x
28
29 ret void
30 }
0 ; This testcase ensures that CFL AA answers queries soundly when callee tries
1 ; to return one of its parameters
2
3 ; RUN: opt < %s -disable-basicaa -cfl-steens-aa -aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
4 ; RUN: opt < %s -aa-pipeline=cfl-steens-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
5
6 define i32* @return_arg_callee(i32* %arg1, i32* %arg2) {
7 ret i32* %arg1
8 }
9 ; CHECK-LABEL: Function: test_return_arg
10 ; CHECK: NoAlias: i32* %a, i32* %b
11 ; CHECK: MayAlias: i32* %a, i32* %c
12 ; CHECK: NoAlias: i32* %b, i32* %c
13
14 ; CHECK: NoModRef: Ptr: i32* %b <-> %c = call i32* @return_arg_callee(i32* %a, i32* %b)
15 define void @test_return_arg() {
16 %a = alloca i32, align 4
17 %b = alloca i32, align 4
18
19 %c = call i32* @return_arg_callee(i32* %a, i32* %b)
20