comparison gen/passes/SimplifyDRuntimeCalls.cpp @ 1507:f86fd3b77285

Eliminate comparisons between GC allocations and constants. This removes some `assert(this !is null)`s when member functions get inlined. Also tweak pass order a bit.
author Frits van Bommel <fvbommel wxs.nl>
date Sat, 20 Jun 2009 14:28:59 +0200
parents e5b57fd8307c
children ad7f2f1862d6
comparison
equal deleted inserted replaced
1506:76936858d1c6 1507:f86fd3b77285
41 /// corresponds to one library call. 41 /// corresponds to one library call.
42 namespace { 42 namespace {
43 class VISIBILITY_HIDDEN LibCallOptimization { 43 class VISIBILITY_HIDDEN LibCallOptimization {
44 protected: 44 protected:
45 Function *Caller; 45 Function *Caller;
46 bool* Changed;
46 const TargetData *TD; 47 const TargetData *TD;
47 AliasAnalysis *AA; 48 AliasAnalysis *AA;
48 49
49 /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*. 50 /// CastToCStr - Return V if it is an i8*, otherwise cast it to i8*.
50 Value *CastToCStr(Value *V, IRBuilder<> &B); 51 Value *CastToCStr(Value *V, IRBuilder<> &B);
62 /// performed. If it returns CI, then it transformed the call and CI is to be 63 /// performed. If it returns CI, then it transformed the call and CI is to be
63 /// deleted. If it returns something else, replace CI with the new value and 64 /// deleted. If it returns something else, replace CI with the new value and
64 /// delete CI. 65 /// delete CI.
65 virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)=0; 66 virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)=0;
66 67
67 Value *OptimizeCall(CallInst *CI, const TargetData &TD, 68 Value *OptimizeCall(CallInst *CI, bool& Changed, const TargetData &TD,
68 AliasAnalysis& AA, IRBuilder<> &B) { 69 AliasAnalysis& AA, IRBuilder<> &B) {
69 Caller = CI->getParent()->getParent(); 70 Caller = CI->getParent()->getParent();
71 this->Changed = &Changed;
70 this->TD = &TD; 72 this->TD = &TD;
71 this->AA = &AA; 73 this->AA = &AA;
72 return CallOptimizer(CI->getCalledFunction(), CI, B); 74 return CallOptimizer(CI->getCalledFunction(), CI, B);
73 } 75 }
74 }; 76 };
179 } 181 }
180 return 0; 182 return 0;
181 } 183 }
182 }; 184 };
183 185
184 /// DeleteUnusedOpt - remove libcall if the return value is unused. 186 /// AllocationOpt - Common optimizations for various GC allocations.
185 struct VISIBILITY_HIDDEN DeleteUnusedOpt : public LibCallOptimization { 187 struct VISIBILITY_HIDDEN AllocationOpt : public LibCallOptimization {
186 virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { 188 virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
189 // Allocations are never equal to constants, so remove any equality
190 // comparisons to constants. (Most importantly comparisons to null at
191 // the start of inlined member functions)
192 for (CallInst::use_iterator I = CI->use_begin(), E = CI->use_end() ; I != E;) {
193 Instruction* User = cast<Instruction>(*I++);
194
195 if (ICmpInst* Cmp = dyn_cast<ICmpInst>(User)) {
196 if (!Cmp->isEquality())
197 continue;
198 Constant* C = 0;
199 if ((C = dyn_cast<Constant>(Cmp->getOperand(0)))
200 || (C = dyn_cast<Constant>(Cmp->getOperand(1)))) {
201 Value* Result = ConstantInt::get(Type::Int1Ty, !Cmp->isTrueWhenEqual());
202 Cmp->replaceAllUsesWith(Result);
203 // Don't delete the comparison because there may be an
204 // iterator to it. Instead, set the operands to constants
205 // and let dead code elimination clean it up later.
206 // (It doesn't matter that this changes the value of the
207 // icmp because it's not used anymore anyway)
208 Cmp->setOperand(0, C);
209 Cmp->setOperand(1, C);
210 *Changed = true;
211 }
212 }
213 }
214
215 // If it's not used (anymore), pre-emptively GC it.
187 if (CI->use_empty()) 216 if (CI->use_empty())
188 return CI; 217 return CI;
189 return 0; 218 return 0;
190 } 219 }
191 }; 220 };
243 ArraySetLengthOpt ArraySetLength; 272 ArraySetLengthOpt ArraySetLength;
244 ArrayCastLenOpt ArrayCastLen; 273 ArrayCastLenOpt ArrayCastLen;
245 ArraySliceCopyOpt ArraySliceCopy; 274 ArraySliceCopyOpt ArraySliceCopy;
246 275
247 // GC allocations 276 // GC allocations
248 DeleteUnusedOpt DeleteUnused; 277 AllocationOpt Allocation;
249 278
250 public: 279 public:
251 static char ID; // Pass identification 280 static char ID; // Pass identification
252 SimplifyDRuntimeCalls() : FunctionPass(&ID) {} 281 SimplifyDRuntimeCalls() : FunctionPass(&ID) {}
253 282
288 * 'readonly', since LLVM doesn't need our help figuring out when those can 317 * 'readonly', since LLVM doesn't need our help figuring out when those can
289 * be deleted. 318 * be deleted.
290 * (We can't mark allocating calls as readonly/readnone because they don't 319 * (We can't mark allocating calls as readonly/readnone because they don't
291 * return the same pointer every time when called with the same arguments) 320 * return the same pointer every time when called with the same arguments)
292 */ 321 */
293 Optimizations["_d_allocmemoryT"] = &DeleteUnused; 322 Optimizations["_d_allocmemoryT"] = &Allocation;
294 Optimizations["_d_newarrayT"] = &DeleteUnused; 323 Optimizations["_d_newarrayT"] = &Allocation;
295 Optimizations["_d_newarrayiT"] = &DeleteUnused; 324 Optimizations["_d_newarrayiT"] = &Allocation;
296 Optimizations["_d_newarrayvT"] = &DeleteUnused; 325 Optimizations["_d_newarrayvT"] = &Allocation;
297 Optimizations["_d_newarraymT"] = &DeleteUnused; 326 Optimizations["_d_newarraymT"] = &Allocation;
298 Optimizations["_d_newarraymiT"] = &DeleteUnused; 327 Optimizations["_d_newarraymiT"] = &Allocation;
299 Optimizations["_d_newarraymvT"] = &DeleteUnused; 328 Optimizations["_d_newarraymvT"] = &Allocation;
300 Optimizations["_d_allocclass"] = &DeleteUnused; 329 Optimizations["_d_allocclass"] = &Allocation;
301 } 330 }
302 331
303 332
304 /// runOnFunction - Top level algorithm. 333 /// runOnFunction - Top level algorithm.
305 /// 334 ///
351 380
352 // Set the builder to the instruction after the call. 381 // Set the builder to the instruction after the call.
353 Builder.SetInsertPoint(BB, I); 382 Builder.SetInsertPoint(BB, I);
354 383
355 // Try to optimize this call. 384 // Try to optimize this call.
356 Value *Result = OMI->second->OptimizeCall(CI, TD, AA, Builder); 385 Value *Result = OMI->second->OptimizeCall(CI, Changed, TD, AA, Builder);
357 if (Result == 0) continue; 386 if (Result == 0) continue;
358 387
359 DEBUG(DOUT << "SimplifyDRuntimeCalls simplified: " << *CI; 388 DEBUG(DOUT << "SimplifyDRuntimeCalls simplified: " << *CI;
360 DOUT << " into: " << *Result << "\n"); 389 DOUT << " into: " << *Result << "\n");
361 390