changeset 1509:e07f15c4ab4d

Automated merge with http://hg.dsource.org/projects/ldc
author Christian Kamm <kamm incasoftware de>
date Sat, 20 Jun 2009 19:12:04 +0200
parents f86fd3b77285 (diff) e1e93343fc11 (current diff)
children b6b6afc2dfc7
files gen/llvmhelpers.cpp
diffstat 9 files changed, 144 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
--- 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
--- 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)
     {
--- 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<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;
--- 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<const LLType*> 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);
     }
--- 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
--- 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)
     {
--- 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;
 }
 
 /**