# HG changeset patch # User Christian Kamm # Date 1245517924 -7200 # Node ID e07f15c4ab4d7af8a57b32910e71806e5d6c7620 # Parent f86fd3b7728580b80eae42aa37faef9688c5ca5f# Parent e1e93343fc1182102162e96e0fa404552b76b40c Automated merge with http://hg.dsource.org/projects/ldc diff -r e1e93343fc11 -r e07f15c4ab4d gen/declarations.cpp --- a/gen/declarations.cpp Sat Jun 20 19:11:44 2009 +0200 +++ b/gen/declarations.cpp Sat Jun 20 19:12:04 2009 +0200 @@ -96,7 +96,7 @@ // global variable #if DMDV2 // taken from dmd2/structs - if (isDataseg() || (storage_class & (STCconst | STCinvariant) && init)) + if (isDataseg() || (storage_class & (STCconst | STCimmutable) && init)) #else if (isDataseg()) #endif diff -r e1e93343fc11 -r e07f15c4ab4d gen/llvmhelpers.cpp --- a/gen/llvmhelpers.cpp Sat Jun 20 19:11:44 2009 +0200 +++ b/gen/llvmhelpers.cpp Sat Jun 20 19:12:04 2009 +0200 @@ -1480,3 +1480,76 @@ } ////////////////////////////////////////////////////////////////////////////////////////// + +Type * stripModifiers( Type * type ) +{ +#if DMDV2 + Type *t = type; + while (t->mod) + { + switch (t->mod) + { + case MODconst: + t = type->cto; + break; + case MODshared: + t = type->sto; + break; + case MODinvariant: + t = type->ito; + break; + case MODshared | MODconst: + t = type->scto; + break; + default: + assert(0 && "Unhandled type modifier"); + } + + if (!t) + { + unsigned sz = type->sizeTy[type->ty]; + t = (Type *)malloc(sz); + memcpy(t, type, sz); + t->mod = 0; + t->deco = NULL; + t->arrayof = NULL; + t->pto = NULL; + t->rto = NULL; + t->cto = NULL; + t->ito = NULL; + t->sto = NULL; + t->scto = NULL; + t->vtinfo = NULL; + t = t->merge(); + + t->fixTo(type); + switch (type->mod) + { + case MODconst: + t->cto = type; + break; + + case MODinvariant: + t->ito = type; + break; + + case MODshared: + t->sto = type; + break; + + case MODshared | MODconst: + t->scto = type; + break; + + default: + assert(0); + } + } + } + return t; +#else + return type; +#endif +} + +////////////////////////////////////////////////////////////////////////////////////////// diff -r e1e93343fc11 -r e07f15c4ab4d gen/llvmhelpers.h --- a/gen/llvmhelpers.h Sat Jun 20 19:11:44 2009 +0200 +++ b/gen/llvmhelpers.h Sat Jun 20 19:12:04 2009 +0200 @@ -171,4 +171,6 @@ /// DValue* DtoCallFunction(Loc& loc, Type* resulttype, DValue* fnval, Expressions* arguments); +Type* stripModifiers(Type* type); + #endif diff -r e1e93343fc11 -r e07f15c4ab4d gen/optimizer.cpp --- a/gen/optimizer.cpp Sat Jun 20 19:11:44 2009 +0200 +++ b/gen/optimizer.cpp Sat Jun 20 19:12:04 2009 +0200 @@ -135,6 +135,7 @@ addPass(pm, createFunctionAttrsPass()); addPass(pm, createTailCallEliminationPass()); addPass(pm, createCFGSimplificationPass()); + addPass(pm, createGVNPass()); } // -inline @@ -145,33 +146,34 @@ // Run some optimizations to clean up after inlining. addPass(pm, createScalarReplAggregatesPass()); addPass(pm, createInstructionCombiningPass()); + // -instcombine + gvn == devirtualization :) + addPass(pm, createGVNPass()); - // Inline again, to catch things like foreach delegates - // passed to inlined opApply's where the function wasn't - // known during the first inliner pass. + // Inline again, to catch things like now nonvirtual + // function calls, foreach delegates passed to inlined + // 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) { diff -r e1e93343fc11 -r e07f15c4ab4d gen/passes/SimplifyDRuntimeCalls.cpp --- a/gen/passes/SimplifyDRuntimeCalls.cpp Sat Jun 20 19:11:44 2009 +0200 +++ b/gen/passes/SimplifyDRuntimeCalls.cpp Sat Jun 20 19:12:04 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(*I++); + + if (ICmpInst* Cmp = dyn_cast(User)) { + if (!Cmp->isEquality()) + continue; + Constant* C = 0; + if ((C = dyn_cast(Cmp->getOperand(0))) + || (C = dyn_cast(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; diff -r e1e93343fc11 -r e07f15c4ab4d gen/runtime.cpp --- a/gen/runtime.cpp Sat Jun 20 19:11:44 2009 +0200 +++ b/gen/runtime.cpp Sat Jun 20 19:12:04 2009 +0200 @@ -329,7 +329,7 @@ std::string fname("_d_allocclass"); std::vector types; types.push_back(classInfoTy); - const llvm::FunctionType* fty = llvm::FunctionType::get(objectTy, types, false); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M) ->setAttributes(Attr_NoAlias); } diff -r e1e93343fc11 -r e07f15c4ab4d gen/todebug.cpp --- a/gen/todebug.cpp Sat Jun 20 19:11:44 2009 +0200 +++ b/gen/todebug.cpp Sat Jun 20 19:12:04 2009 +0200 @@ -408,7 +408,7 @@ static llvm::DIGlobalVariable dwarfGlobalVariable(LLGlobalVariable* ll, VarDeclaration* vd) { #if DMDV2 - assert(vd->isDataseg() || (vd->storage_class & (STCconst | STCinvariant) && vd->init)); + assert(vd->isDataseg() || (vd->storage_class & (STCconst | STCimmutable) && vd->init)); #else assert(vd->isDataseg()); #endif diff -r e1e93343fc11 -r e07f15c4ab4d gen/tollvm.cpp --- a/gen/tollvm.cpp Sat Jun 20 19:11:44 2009 +0200 +++ b/gen/tollvm.cpp Sat Jun 20 19:12:04 2009 +0200 @@ -54,9 +54,7 @@ const LLType* DtoType(Type* t) { -#if DMDV2 - t = t->mutableOf(); -#endif + t = stripModifiers( t ); if (t->irtype) { diff -r e1e93343fc11 -r e07f15c4ab4d runtime/internal/lifetime.d --- a/runtime/internal/lifetime.d Sat Jun 20 19:11:44 2009 +0200 +++ b/runtime/internal/lifetime.d Sat Jun 20 19:12:04 2009 +0200 @@ -107,7 +107,7 @@ /** * */ -extern (C) Object _d_allocclass(ClassInfo ci) +extern (C) void* _d_allocclass(ClassInfo ci) { void* p; @@ -150,7 +150,7 @@ //(cast(byte*) p)[0 .. ci.init.length] = ci.init[]; debug(PRINTF) printf("initialization done\n"); - return cast(Object) p; + return p; } /**