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;