llvm.org GIT mirror llvm / 9e89ba3
Rename AddReadAttrs to FunctionAttrs, and teach it how to work out (in a very simplistic way) which function arguments (pointer arguments only) are only dereferenced and so do not escape. Mark such arguments 'nocapture'. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@61525 91177308-0d34-0410-b5e6-96231b3b80d8 Duncan Sands 10 years ago
22 changed file(s) with 392 addition(s) and 242 deletion(s). Raw diff Collapse all Expand all
121121 (void) llvm::createPostDomFrontier();
122122 (void) llvm::createInstructionNamerPass();
123123 (void) llvm::createPartialSpecializationPass();
124 (void) llvm::createAddReadAttrsPass();
124 (void) llvm::createFunctionAttrsPass();
125125 (void) llvm::createMergeFunctionsPass();
126126 (void) llvm::createPrintModulePass(0);
127127 (void) llvm::createPrintFunctionPass("", 0);
195195 ModulePass *createPartialSpecializationPass();
196196
197197 //===----------------------------------------------------------------------===//
198 /// createAddReadAttrsPass - This pass discovers functions that do not access
198 /// createFunctionAttrsPass - This pass discovers functions that do not access
199199 /// memory, or only read memory, and gives them the readnone/readonly attribute.
200 ///
201 Pass *createAddReadAttrsPass();
200 /// It also discovers function arguments that are not captured by the function
201 /// and marks them with the nocapture attribute.
202 ///
203 Pass *createFunctionAttrsPass();
202204
203205 //===----------------------------------------------------------------------===//
204206 /// createMergeFunctionsPass - This pass discovers identical functions and
+0
-166
lib/Transforms/IPO/AddReadAttrs.cpp less more
None //===- AddReadAttrs.cpp - Pass which marks functions readnone or readonly -===//
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 simple interprocedural pass which walks the
10 // call-graph, looking for functions which do not access or only read
11 // non-local memory, and marking them readnone/readonly. It implements
12 // this as a bottom-up traversal of the call-graph.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #define DEBUG_TYPE "addreadattrs"
17 #include "llvm/Transforms/IPO.h"
18 #include "llvm/CallGraphSCCPass.h"
19 #include "llvm/GlobalVariable.h"
20 #include "llvm/Instructions.h"
21 #include "llvm/Analysis/CallGraph.h"
22 #include "llvm/ADT/SmallPtrSet.h"
23 #include "llvm/ADT/Statistic.h"
24 #include "llvm/Support/Compiler.h"
25 #include "llvm/Support/InstIterator.h"
26 using namespace llvm;
27
28 STATISTIC(NumReadNone, "Number of functions marked readnone");
29 STATISTIC(NumReadOnly, "Number of functions marked readonly");
30
31 namespace {
32 struct VISIBILITY_HIDDEN AddReadAttrs : public CallGraphSCCPass {
33 static char ID; // Pass identification, replacement for typeid
34 AddReadAttrs() : CallGraphSCCPass(&ID) {}
35
36 // runOnSCC - Analyze the SCC, performing the transformation if possible.
37 bool runOnSCC(const std::vector &SCC);
38
39 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
40 AU.setPreservesCFG();
41 CallGraphSCCPass::getAnalysisUsage(AU);
42 }
43
44 bool PointsToLocalMemory(Value *V);
45 };
46 }
47
48 char AddReadAttrs::ID = 0;
49 static RegisterPass
50 X("addreadattrs", "Mark functions readnone/readonly");
51
52 Pass *llvm::createAddReadAttrsPass() { return new AddReadAttrs(); }
53
54
55 /// PointsToLocalMemory - Returns whether the given pointer value points to
56 /// memory that is local to the function. Global constants are considered
57 /// local to all functions.
58 bool AddReadAttrs::PointsToLocalMemory(Value *V) {
59 V = V->getUnderlyingObject();
60 // An alloca instruction defines local memory.
61 if (isa(V))
62 return true;
63 // A global constant counts as local memory for our purposes.
64 if (GlobalVariable *GV = dyn_cast(V))
65 return GV->isConstant();
66 // Could look through phi nodes and selects here, but it doesn't seem
67 // to be useful in practice.
68 return false;
69 }
70
71 bool AddReadAttrs::runOnSCC(const std::vector &SCC) {
72 SmallPtrSet SCCNodes;
73 CallGraph &CG = getAnalysis();
74
75 // Fill SCCNodes with the elements of the SCC. Used for quickly
76 // looking up whether a given CallGraphNode is in this SCC.
77 for (unsigned i = 0, e = SCC.size(); i != e; ++i)
78 SCCNodes.insert(SCC[i]);
79
80 // Check if any of the functions in the SCC read or write memory. If they
81 // write memory then they can't be marked readnone or readonly.
82 bool ReadsMemory = false;
83 for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
84 Function *F = SCC[i]->getFunction();
85
86 if (F == 0)
87 // External node - may write memory. Just give up.
88 return false;
89
90 if (F->doesNotAccessMemory())
91 // Already perfect!
92 continue;
93
94 // Definitions with weak linkage may be overridden at linktime with
95 // something that writes memory, so treat them like declarations.
96 if (F->isDeclaration() || F->mayBeOverridden()) {
97 if (!F->onlyReadsMemory())
98 // May write memory. Just give up.
99 return false;
100
101 ReadsMemory = true;
102 continue;
103 }
104
105 // Scan the function body for instructions that may read or write memory.
106 for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) {
107 Instruction *I = &*II;
108
109 // Some instructions can be ignored even if they read or write memory.
110 // Detect these now, skipping to the next instruction if one is found.
111 CallSite CS = CallSite::get(I);
112 if (CS.getInstruction()) {
113 // Ignore calls to functions in the same SCC.
114 if (SCCNodes.count(CG[CS.getCalledFunction()]))
115 continue;
116 } else if (LoadInst *LI = dyn_cast(I)) {
117 // Ignore loads from local memory.
118 if (PointsToLocalMemory(LI->getPointerOperand()))
119 continue;
120 } else if (StoreInst *SI = dyn_cast(I)) {
121 // Ignore stores to local memory.
122 if (PointsToLocalMemory(SI->getPointerOperand()))
123 continue;
124 }
125
126 // Any remaining instructions need to be taken seriously! Check if they
127 // read or write memory.
128 if (I->mayWriteToMemory())
129 // Writes memory. Just give up.
130 return false;
131 // If this instruction may read memory, remember that.
132 ReadsMemory |= I->mayReadFromMemory();
133 }
134 }
135
136 // Success! Functions in this SCC do not access memory, or only read memory.
137 // Give them the appropriate attribute.
138 bool MadeChange = false;
139 for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
140 Function *F = SCC[i]->getFunction();
141
142 if (F->doesNotAccessMemory())
143 // Already perfect!
144 continue;
145
146 if (F->onlyReadsMemory() && ReadsMemory)
147 // No change.
148 continue;
149
150 MadeChange = true;
151
152 // Clear out any existing attributes.
153 F->removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone);
154
155 // Add in the new attribute.
156 F->addAttribute(~0, ReadsMemory ? Attribute::ReadOnly : Attribute::ReadNone);
157
158 if (ReadsMemory)
159 NumReadOnly++;
160 else
161 NumReadNone++;
162 }
163
164 return MadeChange;
165 }
0 add_llvm_library(LLVMipo
1 AddReadAttrs.cpp
1 FunctionAttrs.cpp
22 ArgumentPromotion.cpp
33 ConstantMerge.cpp
44 DeadArgumentElimination.cpp
0 //===- FunctionAttrs.cpp - Pass which marks functions readnone or readonly ===//
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 simple interprocedural pass which walks the
10 // call-graph, looking for functions which do not access or only read
11 // non-local memory, and marking them readnone/readonly. It implements
12 // this as a bottom-up traversal of the call-graph.
13 //
14 //===----------------------------------------------------------------------===//
15
16 #define DEBUG_TYPE "functionattrs"
17 #include "llvm/Transforms/IPO.h"
18 #include "llvm/CallGraphSCCPass.h"
19 #include "llvm/GlobalVariable.h"
20 #include "llvm/Instructions.h"
21 #include "llvm/Analysis/CallGraph.h"
22 #include "llvm/ADT/SmallPtrSet.h"
23 #include "llvm/ADT/Statistic.h"
24 #include "llvm/Support/Compiler.h"
25 #include "llvm/Support/InstIterator.h"
26 using namespace llvm;
27
28 STATISTIC(NumReadNone, "Number of functions marked readnone");
29 STATISTIC(NumReadOnly, "Number of functions marked readonly");
30 STATISTIC(NumNoCapture, "Number of arguments marked nocapture");
31
32 namespace {
33 struct VISIBILITY_HIDDEN FunctionAttrs : public CallGraphSCCPass {
34 static char ID; // Pass identification, replacement for typeid
35 FunctionAttrs() : CallGraphSCCPass(&ID) {}
36
37 // runOnSCC - Analyze the SCC, performing the transformation if possible.
38 bool runOnSCC(const std::vector &SCC);
39
40 // AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
41 bool AddReadAttrs(const std::vector &SCC);
42
43 // AddNoCaptureAttrs - Deduce nocapture attributes for the SCC.
44 bool AddNoCaptureAttrs(const std::vector &SCC);
45
46 // isCaptured - Returns whether this pointer value is captured.
47 bool isCaptured(Function &F, Value *V);
48
49 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
50 AU.setPreservesCFG();
51 CallGraphSCCPass::getAnalysisUsage(AU);
52 }
53
54 bool PointsToLocalMemory(Value *V);
55 };
56 }
57
58 char FunctionAttrs::ID = 0;
59 static RegisterPass
60 X("functionattrs", "Deduce function attributes");
61
62 Pass *llvm::createFunctionAttrsPass() { return new FunctionAttrs(); }
63
64
65 /// PointsToLocalMemory - Returns whether the given pointer value points to
66 /// memory that is local to the function. Global constants are considered
67 /// local to all functions.
68 bool FunctionAttrs::PointsToLocalMemory(Value *V) {
69 V = V->getUnderlyingObject();
70 // An alloca instruction defines local memory.
71 if (isa(V))
72 return true;
73 // A global constant counts as local memory for our purposes.
74 if (GlobalVariable *GV = dyn_cast(V))
75 return GV->isConstant();
76 // Could look through phi nodes and selects here, but it doesn't seem
77 // to be useful in practice.
78 return false;
79 }
80
81 /// AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
82 bool FunctionAttrs::AddReadAttrs(const std::vector &SCC) {
83 SmallPtrSet SCCNodes;
84 CallGraph &CG = getAnalysis();
85
86 // Fill SCCNodes with the elements of the SCC. Used for quickly
87 // looking up whether a given CallGraphNode is in this SCC.
88 for (unsigned i = 0, e = SCC.size(); i != e; ++i)
89 SCCNodes.insert(SCC[i]);
90
91 // Check if any of the functions in the SCC read or write memory. If they
92 // write memory then they can't be marked readnone or readonly.
93 bool ReadsMemory = false;
94 for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
95 Function *F = SCC[i]->getFunction();
96
97 if (F == 0)
98 // External node - may write memory. Just give up.
99 return false;
100
101 if (F->doesNotAccessMemory())
102 // Already perfect!
103 continue;
104
105 // Definitions with weak linkage may be overridden at linktime with
106 // something that writes memory, so treat them like declarations.
107 if (F->isDeclaration() || F->mayBeOverridden()) {
108 if (!F->onlyReadsMemory())
109 // May write memory. Just give up.
110 return false;
111
112 ReadsMemory = true;
113 continue;
114 }
115
116 // Scan the function body for instructions that may read or write memory.
117 for (inst_iterator II = inst_begin(F), E = inst_end(F); II != E; ++II) {
118 Instruction *I = &*II;
119
120 // Some instructions can be ignored even if they read or write memory.
121 // Detect these now, skipping to the next instruction if one is found.
122 CallSite CS = CallSite::get(I);
123 if (CS.getInstruction()) {
124 // Ignore calls to functions in the same SCC.
125 if (SCCNodes.count(CG[CS.getCalledFunction()]))
126 continue;
127 } else if (LoadInst *LI = dyn_cast(I)) {
128 // Ignore loads from local memory.
129 if (PointsToLocalMemory(LI->getPointerOperand()))
130 continue;
131 } else if (StoreInst *SI = dyn_cast(I)) {
132 // Ignore stores to local memory.
133 if (PointsToLocalMemory(SI->getPointerOperand()))
134 continue;
135 }
136
137 // Any remaining instructions need to be taken seriously! Check if they
138 // read or write memory.
139 if (I->mayWriteToMemory())
140 // Writes memory. Just give up.
141 return false;
142 // If this instruction may read memory, remember that.
143 ReadsMemory |= I->mayReadFromMemory();
144 }
145 }
146
147 // Success! Functions in this SCC do not access memory, or only read memory.
148 // Give them the appropriate attribute.
149 bool MadeChange = false;
150 for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
151 Function *F = SCC[i]->getFunction();
152
153 if (F->doesNotAccessMemory())
154 // Already perfect!
155 continue;
156
157 if (F->onlyReadsMemory() && ReadsMemory)
158 // No change.
159 continue;
160
161 MadeChange = true;
162
163 // Clear out any existing attributes.
164 F->removeAttribute(~0, Attribute::ReadOnly | Attribute::ReadNone);
165
166 // Add in the new attribute.
167 F->addAttribute(~0, ReadsMemory? Attribute::ReadOnly : Attribute::ReadNone);
168
169 if (ReadsMemory)
170 NumReadOnly++;
171 else
172 NumReadNone++;
173 }
174
175 return MadeChange;
176 }
177
178 /// isCaptured - Returns whether this pointer value is captured.
179 bool FunctionAttrs::isCaptured(Function &F, Value *V) {
180 SmallVector Worklist;
181 SmallPtrSet Visited;
182
183 for (Value::use_iterator UI = V->use_begin(), UE = V->use_end(); UI != UE;
184 ++UI) {
185 Use *U = &UI.getUse();
186 Visited.insert(U);
187 Worklist.push_back(U);
188 }
189
190 while (!Worklist.empty()) {
191 Use *U = Worklist.pop_back_val();
192 Instruction *I = cast(U->getUser());
193 V = U->get();
194
195 if (isa(I)) {
196 // Loading a pointer does not cause it to escape.
197 continue;
198 }
199
200 if (isa(I)) {
201 if (V == I->getOperand(0))
202 // Stored the pointer - escapes. TODO: improve this.
203 return true;
204 // Storing to the pointee does not cause the pointer to escape.
205 continue;
206 }
207
208 CallSite CS = CallSite::get(I);
209 if (CS.getInstruction()) {
210 // Does not escape if only passed via 'nocapture' arguments. Note
211 // that calling a function pointer does not in itself cause that
212 // function pointer to escape. This is a subtle point considering
213 // that (for example) the callee might return its own address. It
214 // is analogous to saying that loading a value from a pointer does
215 // not cause the pointer to escape, even though the loaded value
216 // might be the pointer itself (think of self-referential objects).
217 CallSite::arg_iterator B = CS.arg_begin(), E = CS.arg_end();
218 for (CallSite::arg_iterator A = B; A != E; ++A)
219 if (A->get() == V && !CS.paramHasAttr(A-B+1, Attribute::NoCapture))
220 // The parameter is not marked 'nocapture' - escapes.
221 return true;
222 // Only passed via 'nocapture' arguments, or is the called function.
223 // Does not escape.
224 continue;
225 }
226
227 if (isa(I) || isa(I)) {
228 // Type conversion or calculating an offset. Does not escape if the new
229 // value doesn't.
230 for (Instruction::use_iterator UI = I->use_begin(), UE = I->use_end();
231 UI != UE; ++UI) {
232 Use *U = &UI.getUse();
233 if (Visited.insert(U))
234 Worklist.push_back(U);
235 }
236 continue;
237 }
238
239 // Something else - be conservative and say it escapes.
240 return true;
241 }
242
243 return false;
244 }
245
246 /// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC.
247 bool FunctionAttrs::AddNoCaptureAttrs(const std::vector &SCC) {
248 bool Changed = false;
249
250 // Check each function in turn, determining which pointer arguments are not
251 // captured.
252 for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
253 Function *F = SCC[i]->getFunction();
254
255 if (F == 0)
256 // External node - skip it;
257 continue;
258
259 // Definitions with weak linkage may be overridden at linktime with
260 // something that writes memory, so treat them like declarations.
261 if (F->isDeclaration() || F->mayBeOverridden())
262 continue;
263
264 for (Function::arg_iterator A = F->arg_begin(), E = F->arg_end(); A!=E; ++A)
265 if (isa(A->getType()) && !isCaptured(*F, A)) {
266 A->addAttr(Attribute::NoCapture);
267 NumNoCapture++;
268 Changed = true;
269 }
270 }
271
272 return Changed;
273 }
274
275 bool FunctionAttrs::runOnSCC(const std::vector &SCC) {
276 bool Changed = AddReadAttrs(SCC);
277 Changed |= AddNoCaptureAttrs(SCC);
278 return Changed;
279 }
+0
-11
test/Transforms/AddReadAttrs/2008-09-03-Mutual.ll less more
None ; RUN: llvm-as < %s | opt -addreadattrs | llvm-dis | grep readnone
1
2 define i32 @a() {
3 %tmp = call i32 @b( ) ; [#uses=1]
4 ret i32 %tmp
5 }
6
7 define i32 @b() {
8 %tmp = call i32 @a( ) ; [#uses=1]
9 ret i32 %tmp
10 }
+0
-18
test/Transforms/AddReadAttrs/2008-09-03-ReadNone.ll less more
None ; RUN: llvm-as < %s | opt -addreadattrs | llvm-dis | grep readnone | count 4
1 @x = global i32 0
2
3 declare i32 @e() readnone
4
5 define i32 @f() {
6 %tmp = call i32 @e( ) ; [#uses=1]
7 ret i32 %tmp
8 }
9
10 define i32 @g() readonly {
11 ret i32 0
12 }
13
14 define i32 @h() readnone {
15 %tmp = load i32* @x ; [#uses=1]
16 ret i32 %tmp
17 }
+0
-9
test/Transforms/AddReadAttrs/2008-09-03-ReadOnly.ll less more
None ; RUN: llvm-as < %s | opt -addreadattrs | llvm-dis | grep readonly | count 2
1
2 define i32 @f() {
3 entry:
4 %tmp = call i32 @e( ) ; [#uses=1]
5 ret i32 %tmp
6 }
7
8 declare i32 @e() readonly
+0
-9
test/Transforms/AddReadAttrs/2008-09-13-VolatileRead.ll less more
None ; RUN: llvm-as < %s | opt -addreadattrs | llvm-dis | not grep read
1 ; PR2792
2
3 @g = global i32 0 ; [#uses=1]
4
5 define i32 @f() {
6 %t = volatile load i32* @g ; [#uses=1]
7 ret i32 %t
8 }
+0
-10
test/Transforms/AddReadAttrs/2008-10-04-LocalMemory.ll less more
None ; RUN: llvm-as < %s | opt -addreadattrs | llvm-dis | grep readnone | count 2
1
2 declare i32 @g(i32*) readnone
3
4 define i32 @f() {
5 %x = alloca i32 ; [#uses=2]
6 store i32 0, i32* %x
7 %y = call i32 @g(i32* %x) ; [#uses=1]
8 ret i32 %y
9 }
+0
-8
test/Transforms/AddReadAttrs/2008-12-29-Constant.ll less more
None ; RUN: llvm-as < %s | opt -addreadattrs | llvm-dis | grep readnone
1
2 @s = external constant i8 ; [#uses=1]
3
4 define i8 @f() {
5 %tmp = load i8* @s ; [#uses=1]
6 ret i8 %tmp
7 }
+0
-3
test/Transforms/AddReadAttrs/dg.exp less more
None load_lib llvm.exp
1
2 RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
0 ; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | grep readnone
1
2 define i32 @a() {
3 %tmp = call i32 @b( ) ; [#uses=1]
4 ret i32 %tmp
5 }
6
7 define i32 @b() {
8 %tmp = call i32 @a( ) ; [#uses=1]
9 ret i32 %tmp
10 }
0 ; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | grep readnone | count 4
1 @x = global i32 0
2
3 declare i32 @e() readnone
4
5 define i32 @f() {
6 %tmp = call i32 @e( ) ; [#uses=1]
7 ret i32 %tmp
8 }
9
10 define i32 @g() readonly {
11 ret i32 0
12 }
13
14 define i32 @h() readnone {
15 %tmp = load i32* @x ; [#uses=1]
16 ret i32 %tmp
17 }
0 ; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | grep readonly | count 2
1
2 define i32 @f() {
3 entry:
4 %tmp = call i32 @e( ) ; [#uses=1]
5 ret i32 %tmp
6 }
7
8 declare i32 @e() readonly
0 ; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | not grep read
1 ; PR2792
2
3 @g = global i32 0 ; [#uses=1]
4
5 define i32 @f() {
6 %t = volatile load i32* @g ; [#uses=1]
7 ret i32 %t
8 }
0 ; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | grep readnone | count 2
1
2 declare i32 @g(i32*) readnone
3
4 define i32 @f() {
5 %x = alloca i32 ; [#uses=2]
6 store i32 0, i32* %x
7 %y = call i32 @g(i32* %x) ; [#uses=1]
8 ret i32 %y
9 }
0 ; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | grep readnone
1
2 @s = external constant i8 ; [#uses=1]
3
4 define i8 @f() {
5 %tmp = load i8* @s ; [#uses=1]
6 ret i8 %tmp
7 }
0 ; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | not grep {@c.*nocapture}
1 ; RUN: llvm-as < %s | opt -functionattrs | llvm-dis | grep nocapture | count 3
2 @g = global i32* null ; [#uses=1]
3
4 define i32* @c1(i32* %p) {
5 ret i32* %p
6 }
7
8 define void @c2(i32* %p) {
9 store i32* %p, i32** @g
10 ret void
11 }
12
13 define void @c3(i32* %p) {
14 call void @c2(i32* %p)
15 ret void
16 }
17
18 define i32 @nc1(i32* %p) {
19 %tmp = bitcast i32* %p to i32* ; [#uses=2]
20 %val = load i32* %tmp ; [#uses=1]
21 store i32 0, i32* %tmp
22 ret i32 %val
23 }
24
25 define void @nc2(i32* %p) {
26 %1 = call i32 @nc1(i32* %p) ; [#uses=0]
27 ret void
28 }
29
30 define void @nc3(void ()* %f) {
31 call void %f()
32 ret void
33 }
0 load_lib llvm.exp
1
2 RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
290290 MPM.add(createCFGSimplificationPass()); // Clean up after IPCP & DAE
291291 if (UnitAtATime) {
292292 MPM.add(createPruneEHPass()); // Remove dead EH info
293 MPM.add(createAddReadAttrsPass()); // Set readonly/readnone attrs
293 MPM.add(createFunctionAttrsPass()); // Deduce function attrs
294294 }
295295 if (OptLevel > 1)
296296 MPM.add(createFunctionInliningPass()); // Inline small functions
362362 addPass(PM, createCFGSimplificationPass()); // Clean up after IPCP & DAE
363363
364364 addPass(PM, createPruneEHPass()); // Remove dead EH info
365 addPass(PM, createAddReadAttrsPass()); // Set readonly/readnone attrs
365 addPass(PM, createFunctionAttrsPass()); // Deduce function attrs
366366
367367 if (!DisableInline)
368368 addPass(PM, createFunctionInliningPass()); // Inline small functions
343343 Name="IPO"
344344 >
345345
346 RelativePath="..\..\lib\Transforms\IPO\AddReadAttrs.cpp"
346 RelativePath="..\..\lib\Transforms\IPO\FunctionAttrs.cpp"
347347 >
348348
349349