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.
This commit is contained in:
Frits van Bommel 2009-06-20 14:28:59 +02:00
parent 465f15eda0
commit 5ecdf1a70a
2 changed files with 56 additions and 29 deletions

View file

@ -154,26 +154,24 @@ static void addPassesForOptLevel(PassManager& pm) {
// 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
}
// Run some clean-up passes
addPass(pm, createInstructionCombiningPass());
addPass(pm, createScalarReplAggregatesPass());
addPass(pm, createCFGSimplificationPass());
addPass(pm, createInstructionCombiningPass());
}
// -O3

View file

@ -43,6 +43,7 @@ namespace {
class VISIBILITY_HIDDEN LibCallOptimization {
protected:
Function *Caller;
bool* Changed;
const TargetData *TD;
AliasAnalysis *AA;
@ -64,9 +65,10 @@ namespace {
/// 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 @@ struct VISIBILITY_HIDDEN ArrayCastLenOpt : public LibCallOptimization {
}
};
/// 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 @@ namespace {
ArraySliceCopyOpt ArraySliceCopy;
// GC allocations
DeleteUnusedOpt DeleteUnused;
AllocationOpt Allocation;
public:
static char ID; // Pass identification
@ -290,14 +319,14 @@ void SimplifyDRuntimeCalls::InitOptimizations() {
* (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 @@ bool SimplifyDRuntimeCalls::runOnce(Function &F, const TargetData& TD, AliasAnal
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;