changeset 1286:23b23b74e326

Remove calls to some runtime functions if their results are unused
author Frits van Bommel <fvbommel wxs.nl>
date Sat, 02 May 2009 11:58:50 +0200
parents 91d9386d4a5a
children 6c8af78364f5
files gen/passes/SimplifyDRuntimeCalls.cpp
diffstat 1 files changed, 31 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/gen/passes/SimplifyDRuntimeCalls.cpp	Sat May 02 11:58:50 2009 +0200
+++ b/gen/passes/SimplifyDRuntimeCalls.cpp	Sat May 02 11:58:50 2009 +0200
@@ -145,6 +145,15 @@
     }
 };
 
+/// DeleteUnusedOpt - remove libcall if the return value is unused.
+struct VISIBILITY_HIDDEN DeleteUnusedOpt : public LibCallOptimization {
+    virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
+        if (CI->use_empty())
+            return CI;
+        return 0;
+    }
+};
+
 // TODO: More optimizations! :)
 
 } // end anonymous namespace.
@@ -163,6 +172,9 @@
         ArraySetLengthOpt ArraySetLength;
         ArrayCastLenOpt ArrayCastLen;
         
+        // GC allocations
+        DeleteUnusedOpt DeleteUnused;
+        
         public:
         static char ID; // Pass identification
         SimplifyDRuntimeCalls() : FunctionPass(&ID) {}
@@ -188,9 +200,28 @@
 /// Optimizations - Populate the Optimizations map with all the optimizations
 /// we know.
 void SimplifyDRuntimeCalls::InitOptimizations() {
+    // Some array-related optimizations
     Optimizations["_d_arraysetlengthT"] = &ArraySetLength;
     Optimizations["_d_arraysetlengthiT"] = &ArraySetLength;
     Optimizations["_d_array_cast_len"] = &ArrayCastLen;
+    
+    /* Delete calls to runtime functions which aren't needed if their result is
+     * unused. That comes down to functions that don't do anything but
+     * GC-allocate and initialize some memory.
+     * We don't need to do this for functions which are marked 'readnone' or
+     * 'readonly', since LLVM doesn't need our help figuring out when those can
+     * be deleted.
+     * (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;
 }