Mercurial > projects > ldc
comparison gen/passes/SimplifyDRuntimeCalls.cpp @ 1319:c32e27f9a61d
Some tweaks to -simplify-drtcalls.
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Sat, 09 May 2009 02:34:27 +0200 |
parents | 23b23b74e326 |
children | e5b57fd8307c |
comparison
equal
deleted
inserted
replaced
1318:bac742d3a72d | 1319:c32e27f9a61d |
---|---|
27 #include "llvm/Support/Compiler.h" | 27 #include "llvm/Support/Compiler.h" |
28 #include "llvm/Support/Debug.h" | 28 #include "llvm/Support/Debug.h" |
29 using namespace llvm; | 29 using namespace llvm; |
30 | 30 |
31 STATISTIC(NumSimplified, "Number of runtime calls simplified"); | 31 STATISTIC(NumSimplified, "Number of runtime calls simplified"); |
32 STATISTIC(NumDeleted, "Number of runtime calls deleted"); | |
32 | 33 |
33 //===----------------------------------------------------------------------===// | 34 //===----------------------------------------------------------------------===// |
34 // Optimizer Base Class | 35 // Optimizer Base Class |
35 //===----------------------------------------------------------------------===// | 36 //===----------------------------------------------------------------------===// |
36 | 37 |
77 if (Callee->arg_size() != 4 || !isa<PointerType>(FT->getReturnType()) || | 78 if (Callee->arg_size() != 4 || !isa<PointerType>(FT->getReturnType()) || |
78 !isa<IntegerType>(FT->getParamType(1)) || | 79 !isa<IntegerType>(FT->getParamType(1)) || |
79 FT->getParamType(1) != FT->getParamType(2) || | 80 FT->getParamType(1) != FT->getParamType(2) || |
80 FT->getParamType(3) != FT->getReturnType()) | 81 FT->getParamType(3) != FT->getReturnType()) |
81 return 0; | 82 return 0; |
83 | |
84 // Whether or not this allocates is irrelevant if the result isn't used. | |
85 // Just delete if that's the case. | |
86 if (CI->use_empty()) | |
87 return CI; | |
82 | 88 |
83 Value* NewLen = CI->getOperand(2); | 89 Value* NewLen = CI->getOperand(2); |
84 if (Constant* NewCst = dyn_cast<Constant>(NewLen)) { | 90 if (Constant* NewCst = dyn_cast<Constant>(NewLen)) { |
85 Value* Data = CI->getOperand(4); | 91 Value* Data = CI->getOperand(4); |
86 | 92 |
180 SimplifyDRuntimeCalls() : FunctionPass(&ID) {} | 186 SimplifyDRuntimeCalls() : FunctionPass(&ID) {} |
181 | 187 |
182 void InitOptimizations(); | 188 void InitOptimizations(); |
183 bool runOnFunction(Function &F); | 189 bool runOnFunction(Function &F); |
184 | 190 |
191 bool runOnce(Function &F, const TargetData& TD); | |
192 | |
185 virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 193 virtual void getAnalysisUsage(AnalysisUsage &AU) const { |
186 AU.addRequired<TargetData>(); | 194 AU.addRequired<TargetData>(); |
187 } | 195 } |
188 }; | 196 }; |
189 char SimplifyDRuntimeCalls::ID = 0; | 197 char SimplifyDRuntimeCalls::ID = 0; |
231 if (Optimizations.empty()) | 239 if (Optimizations.empty()) |
232 InitOptimizations(); | 240 InitOptimizations(); |
233 | 241 |
234 const TargetData &TD = getAnalysis<TargetData>(); | 242 const TargetData &TD = getAnalysis<TargetData>(); |
235 | 243 |
244 // Iterate to catch opportunities opened up by other optimizations, | |
245 // such as calls that are only used as arguments to unused calls: | |
246 // When the second call gets deleted the first call will become unused, but | |
247 // without iteration we wouldn't notice if we inspected the first call | |
248 // before the second one. | |
249 bool EverChanged = false; | |
250 bool Changed; | |
251 do { | |
252 Changed = runOnce(F, TD); | |
253 EverChanged |= Changed; | |
254 } while (Changed); | |
255 | |
256 return EverChanged; | |
257 } | |
258 | |
259 bool SimplifyDRuntimeCalls::runOnce(Function &F, const TargetData& TD) { | |
236 IRBuilder<> Builder; | 260 IRBuilder<> Builder; |
237 | 261 |
238 bool Changed = false; | 262 bool Changed = false; |
239 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { | 263 for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { |
240 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { | 264 for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) { |
266 DEBUG(DOUT << "SimplifyDRuntimeCalls simplified: " << *CI; | 290 DEBUG(DOUT << "SimplifyDRuntimeCalls simplified: " << *CI; |
267 DOUT << " into: " << *Result << "\n"); | 291 DOUT << " into: " << *Result << "\n"); |
268 | 292 |
269 // Something changed! | 293 // Something changed! |
270 Changed = true; | 294 Changed = true; |
271 ++NumSimplified; | 295 |
296 if (Result == CI) { | |
297 assert(CI->use_empty()); | |
298 ++NumDeleted; | |
299 } else { | |
300 ++NumSimplified; | |
301 | |
302 if (!CI->use_empty()) | |
303 CI->replaceAllUsesWith(Result); | |
304 | |
305 if (!Result->hasName()) | |
306 Result->takeName(CI); | |
307 } | |
272 | 308 |
273 // Inspect the instruction after the call (which was potentially just | 309 // Inspect the instruction after the call (which was potentially just |
274 // added) next. | 310 // added) next. |
275 I = CI; ++I; | 311 I = CI; ++I; |
276 | 312 |
277 if (CI != Result && !CI->use_empty()) { | |
278 CI->replaceAllUsesWith(Result); | |
279 if (!Result->hasName()) | |
280 Result->takeName(CI); | |
281 } | |
282 CI->eraseFromParent(); | 313 CI->eraseFromParent(); |
283 } | 314 } |
284 } | 315 } |
285 return Changed; | 316 return Changed; |
286 } | 317 } |