/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Analysis/ObjCARCAliasAnalysis.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ObjCARCAliasAnalysis.cpp - ObjC ARC Optimization -------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | /// \file |
10 | | /// This file defines a simple ARC-aware AliasAnalysis using special knowledge |
11 | | /// of Objective C to enhance other optimization passes which rely on the Alias |
12 | | /// Analysis infrastructure. |
13 | | /// |
14 | | /// WARNING: This file knows about certain library functions. It recognizes them |
15 | | /// by name, and hardwires knowledge of their semantics. |
16 | | /// |
17 | | /// WARNING: This file knows about how certain Objective-C library functions are |
18 | | /// used. Naive LLVM IR transformations which would otherwise be |
19 | | /// behavior-preserving may break these assumptions. |
20 | | /// |
21 | | /// TODO: Theoretically we could check for dependencies between objc_* calls |
22 | | /// and FMRB_OnlyAccessesArgumentPointees calls or other well-behaved calls. |
23 | | /// |
24 | | //===----------------------------------------------------------------------===// |
25 | | |
26 | | #include "llvm/Analysis/ObjCARCAliasAnalysis.h" |
27 | | #include "llvm/Analysis/ObjCARCAnalysisUtils.h" |
28 | | #include "llvm/IR/Function.h" |
29 | | #include "llvm/IR/Instruction.h" |
30 | | #include "llvm/IR/Value.h" |
31 | | #include "llvm/InitializePasses.h" |
32 | | #include "llvm/PassAnalysisSupport.h" |
33 | | #include "llvm/PassSupport.h" |
34 | | |
35 | | #define DEBUG_TYPE "objc-arc-aa" |
36 | | |
37 | | using namespace llvm; |
38 | | using namespace llvm::objcarc; |
39 | | |
40 | | AliasResult ObjCARCAAResult::alias(const MemoryLocation &LocA, |
41 | 1.33k | const MemoryLocation &LocB) { |
42 | 1.33k | if (!EnableARCOpts) |
43 | 0 | return AAResultBase::alias(LocA, LocB); |
44 | 1.33k | |
45 | 1.33k | // First, strip off no-ops, including ObjC-specific no-ops, and try making a |
46 | 1.33k | // precise alias query. |
47 | 1.33k | const Value *SA = GetRCIdentityRoot(LocA.Ptr); |
48 | 1.33k | const Value *SB = GetRCIdentityRoot(LocB.Ptr); |
49 | 1.33k | AliasResult Result = |
50 | 1.33k | AAResultBase::alias(MemoryLocation(SA, LocA.Size, LocA.AATags), |
51 | 1.33k | MemoryLocation(SB, LocB.Size, LocB.AATags)); |
52 | 1.33k | if (Result != MayAlias) |
53 | 0 | return Result; |
54 | 1.33k | |
55 | 1.33k | // If that failed, climb to the underlying object, including climbing through |
56 | 1.33k | // ObjC-specific no-ops, and try making an imprecise alias query. |
57 | 1.33k | const Value *UA = GetUnderlyingObjCPtr(SA, DL); |
58 | 1.33k | const Value *UB = GetUnderlyingObjCPtr(SB, DL); |
59 | 1.33k | if (UA != SA || 1.33k UB != SB1.24k ) { |
60 | 126 | Result = AAResultBase::alias(MemoryLocation(UA), MemoryLocation(UB)); |
61 | 126 | // We can't use MustAlias or PartialAlias results here because |
62 | 126 | // GetUnderlyingObjCPtr may return an offsetted pointer value. |
63 | 126 | if (Result == NoAlias) |
64 | 0 | return NoAlias; |
65 | 1.33k | } |
66 | 1.33k | |
67 | 1.33k | // If that failed, fail. We don't need to chain here, since that's covered |
68 | 1.33k | // by the earlier precise query. |
69 | 1.33k | return MayAlias; |
70 | 1.33k | } |
71 | | |
72 | | bool ObjCARCAAResult::pointsToConstantMemory(const MemoryLocation &Loc, |
73 | 1.35k | bool OrLocal) { |
74 | 1.35k | if (!EnableARCOpts) |
75 | 0 | return AAResultBase::pointsToConstantMemory(Loc, OrLocal); |
76 | 1.35k | |
77 | 1.35k | // First, strip off no-ops, including ObjC-specific no-ops, and try making |
78 | 1.35k | // a precise alias query. |
79 | 1.35k | const Value *S = GetRCIdentityRoot(Loc.Ptr); |
80 | 1.35k | if (AAResultBase::pointsToConstantMemory( |
81 | 1.35k | MemoryLocation(S, Loc.Size, Loc.AATags), OrLocal)) |
82 | 0 | return true; |
83 | 1.35k | |
84 | 1.35k | // If that failed, climb to the underlying object, including climbing through |
85 | 1.35k | // ObjC-specific no-ops, and try making an imprecise alias query. |
86 | 1.35k | const Value *U = GetUnderlyingObjCPtr(S, DL); |
87 | 1.35k | if (U != S) |
88 | 249 | return AAResultBase::pointsToConstantMemory(MemoryLocation(U), OrLocal); |
89 | 1.10k | |
90 | 1.10k | // If that failed, fail. We don't need to chain here, since that's covered |
91 | 1.10k | // by the earlier precise query. |
92 | 1.10k | return false; |
93 | 1.10k | } |
94 | | |
95 | 2.18k | FunctionModRefBehavior ObjCARCAAResult::getModRefBehavior(const Function *F) { |
96 | 2.18k | if (!EnableARCOpts) |
97 | 0 | return AAResultBase::getModRefBehavior(F); |
98 | 2.18k | |
99 | 2.18k | switch (GetFunctionClass(F)) { |
100 | 0 | case ARCInstKind::NoopCast: |
101 | 0 | return FMRB_DoesNotAccessMemory; |
102 | 2.18k | default: |
103 | 2.18k | break; |
104 | 2.18k | } |
105 | 2.18k | |
106 | 2.18k | return AAResultBase::getModRefBehavior(F); |
107 | 2.18k | } |
108 | | |
109 | | ModRefInfo ObjCARCAAResult::getModRefInfo(ImmutableCallSite CS, |
110 | 285 | const MemoryLocation &Loc) { |
111 | 285 | if (!EnableARCOpts) |
112 | 0 | return AAResultBase::getModRefInfo(CS, Loc); |
113 | 285 | |
114 | 285 | switch (GetBasicARCInstKind(CS.getInstruction())) { |
115 | 96 | case ARCInstKind::Retain: |
116 | 96 | case ARCInstKind::RetainRV: |
117 | 96 | case ARCInstKind::Autorelease: |
118 | 96 | case ARCInstKind::AutoreleaseRV: |
119 | 96 | case ARCInstKind::NoopCast: |
120 | 96 | case ARCInstKind::AutoreleasepoolPush: |
121 | 96 | case ARCInstKind::FusedRetainAutorelease: |
122 | 96 | case ARCInstKind::FusedRetainAutoreleaseRV: |
123 | 96 | // These functions don't access any memory visible to the compiler. |
124 | 96 | // Note that this doesn't include objc_retainBlock, because it updates |
125 | 96 | // pointers when it copies block data. |
126 | 96 | return MRI_NoModRef; |
127 | 189 | default: |
128 | 189 | break; |
129 | 189 | } |
130 | 189 | |
131 | 189 | return AAResultBase::getModRefInfo(CS, Loc); |
132 | 189 | } |
133 | | |
134 | 0 | ObjCARCAAResult ObjCARCAA::run(Function &F, FunctionAnalysisManager &AM) { |
135 | 0 | return ObjCARCAAResult(F.getParent()->getDataLayout()); |
136 | 0 | } |
137 | | |
138 | | char ObjCARCAAWrapperPass::ID = 0; |
139 | | INITIALIZE_PASS(ObjCARCAAWrapperPass, "objc-arc-aa", |
140 | | "ObjC-ARC-Based Alias Analysis", false, true) |
141 | | |
142 | 0 | ImmutablePass *llvm::createObjCARCAAWrapperPass() { |
143 | 0 | return new ObjCARCAAWrapperPass(); |
144 | 0 | } |
145 | | |
146 | 29 | ObjCARCAAWrapperPass::ObjCARCAAWrapperPass() : ImmutablePass(ID) { |
147 | 29 | initializeObjCARCAAWrapperPassPass(*PassRegistry::getPassRegistry()); |
148 | 29 | } |
149 | | |
150 | 29 | bool ObjCARCAAWrapperPass::doInitialization(Module &M) { |
151 | 29 | Result.reset(new ObjCARCAAResult(M.getDataLayout())); |
152 | 29 | return false; |
153 | 29 | } |
154 | | |
155 | 29 | bool ObjCARCAAWrapperPass::doFinalization(Module &M) { |
156 | 29 | Result.reset(); |
157 | 29 | return false; |
158 | 29 | } |
159 | | |
160 | 29 | void ObjCARCAAWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const { |
161 | 29 | AU.setPreservesAll(); |
162 | 29 | } |