Mercurial > projects > ldc
changeset 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 | 76936858d1c6 |
children | e07f15c4ab4d |
files | gen/optimizer.cpp gen/passes/SimplifyDRuntimeCalls.cpp |
diffstat | 2 files changed, 56 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/gen/optimizer.cpp Sat Jun 20 11:39:13 2009 +0200 +++ b/gen/optimizer.cpp Sat Jun 20 14:28:59 2009 +0200 @@ -154,28 +154,26 @@ // opApply's, etc. where the actual function being called // wasn't known during the first inliner pass. addPass(pm, createFunctionInliningPass()); - - // Run clean-up again. - addPass(pm, createScalarReplAggregatesPass()); - addPass(pm, createInstructionCombiningPass()); } } - if (optimizeLevel >= 2 && !disableLangSpecificPasses) { - if (!disableSimplifyRuntimeCalls) - addPass(pm, createSimplifyDRuntimeCalls()); - + if (optimizeLevel >= 2) { + if (!disableLangSpecificPasses) { + if (!disableSimplifyRuntimeCalls) + addPass(pm, createSimplifyDRuntimeCalls()); + #ifdef USE_METADATA - if (!disableGCToStack) { - addPass(pm, createGarbageCollect2Stack()); - // Run some clean-up - addPass(pm, createInstructionCombiningPass()); - addPass(pm, createScalarReplAggregatesPass()); - addPass(pm, createCFGSimplificationPass()); + if (!disableGCToStack) + addPass(pm, createGarbageCollect2Stack()); +#endif } -#endif + // Run some clean-up passes + addPass(pm, createInstructionCombiningPass()); + addPass(pm, createScalarReplAggregatesPass()); + addPass(pm, createCFGSimplificationPass()); + addPass(pm, createInstructionCombiningPass()); } - + // -O3 if (optimizeLevel >= 3) {
--- a/gen/passes/SimplifyDRuntimeCalls.cpp Sat Jun 20 11:39:13 2009 +0200 +++ b/gen/passes/SimplifyDRuntimeCalls.cpp Sat Jun 20 14:28:59 2009 +0200 @@ -43,6 +43,7 @@ class VISIBILITY_HIDDEN LibCallOptimization { protected: Function *Caller; + bool* Changed; const TargetData *TD; AliasAnalysis *AA; @@ -64,9 +65,10 @@ /// delete CI. virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B)=0; - Value *OptimizeCall(CallInst *CI, const TargetData &TD, + Value *OptimizeCall(CallInst *CI, bool& Changed, const TargetData &TD, AliasAnalysis& AA, IRBuilder<> &B) { Caller = CI->getParent()->getParent(); + this->Changed = &Changed; this->TD = &TD; this->AA = &AA; return CallOptimizer(CI->getCalledFunction(), CI, B); @@ -181,9 +183,36 @@ } }; -/// DeleteUnusedOpt - remove libcall if the return value is unused. -struct VISIBILITY_HIDDEN DeleteUnusedOpt : public LibCallOptimization { +/// AllocationOpt - Common optimizations for various GC allocations. +struct VISIBILITY_HIDDEN AllocationOpt : public LibCallOptimization { virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // Allocations are never equal to constants, so remove any equality + // comparisons to constants. (Most importantly comparisons to null at + // the start of inlined member functions) + for (CallInst::use_iterator I = CI->use_begin(), E = CI->use_end() ; I != E;) { + Instruction* User = cast<Instruction>(*I++); + + if (ICmpInst* Cmp = dyn_cast<ICmpInst>(User)) { + if (!Cmp->isEquality()) + continue; + Constant* C = 0; + if ((C = dyn_cast<Constant>(Cmp->getOperand(0))) + || (C = dyn_cast<Constant>(Cmp->getOperand(1)))) { + Value* Result = ConstantInt::get(Type::Int1Ty, !Cmp->isTrueWhenEqual()); + Cmp->replaceAllUsesWith(Result); + // Don't delete the comparison because there may be an + // iterator to it. Instead, set the operands to constants + // and let dead code elimination clean it up later. + // (It doesn't matter that this changes the value of the + // icmp because it's not used anymore anyway) + Cmp->setOperand(0, C); + Cmp->setOperand(1, C); + *Changed = true; + } + } + } + + // If it's not used (anymore), pre-emptively GC it. if (CI->use_empty()) return CI; return 0; @@ -245,7 +274,7 @@ ArraySliceCopyOpt ArraySliceCopy; // GC allocations - DeleteUnusedOpt DeleteUnused; + AllocationOpt Allocation; public: static char ID; // Pass identification @@ -290,14 +319,14 @@ * (We can't mark allocating calls as readonly/readnone because they don't * return the same pointer every time when called with the same arguments) */ - Optimizations["_d_allocmemoryT"] = &DeleteUnused; - Optimizations["_d_newarrayT"] = &DeleteUnused; - Optimizations["_d_newarrayiT"] = &DeleteUnused; - Optimizations["_d_newarrayvT"] = &DeleteUnused; - Optimizations["_d_newarraymT"] = &DeleteUnused; - Optimizations["_d_newarraymiT"] = &DeleteUnused; - Optimizations["_d_newarraymvT"] = &DeleteUnused; - Optimizations["_d_allocclass"] = &DeleteUnused; + Optimizations["_d_allocmemoryT"] = &Allocation; + Optimizations["_d_newarrayT"] = &Allocation; + Optimizations["_d_newarrayiT"] = &Allocation; + Optimizations["_d_newarrayvT"] = &Allocation; + Optimizations["_d_newarraymT"] = &Allocation; + Optimizations["_d_newarraymiT"] = &Allocation; + Optimizations["_d_newarraymvT"] = &Allocation; + Optimizations["_d_allocclass"] = &Allocation; } @@ -353,7 +382,7 @@ Builder.SetInsertPoint(BB, I); // Try to optimize this call. - Value *Result = OMI->second->OptimizeCall(CI, TD, AA, Builder); + Value *Result = OMI->second->OptimizeCall(CI, Changed, TD, AA, Builder); if (Result == 0) continue; DEBUG(DOUT << "SimplifyDRuntimeCalls simplified: " << *CI;