changeset 1306:b61db48127fd

Some refactoring
author Frits van Bommel <fvbommel wxs.nl>
date Wed, 06 May 2009 15:58:15 +0200
parents 8215dbf0e09f
children e2ec50329af1
files gen/passes/GarbageCollect2Stack.cpp
diffstat 1 files changed, 115 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/gen/passes/GarbageCollect2Stack.cpp	Wed May 06 14:11:37 2009 +0200
+++ b/gen/passes/GarbageCollect2Stack.cpp	Wed May 06 15:58:15 2009 +0200
@@ -47,14 +47,102 @@
 //===----------------------------------------------------------------------===//
 
 namespace {
-    struct FunctionInfo {
+    struct Analysis {
+        TargetData& TD;
+        const Module& M;
+        
+        const Type* getTypeFor(Value* typeinfo) const;
+    };
+    
+    class FunctionInfo {
+    protected:
+        const Type* Ty;
+        
+    public:
         unsigned TypeInfoArgNr;
-        int ArrSizeArgNr;
         bool SafeToDelete;
         
-        FunctionInfo(unsigned typeInfoArgNr, int arrSizeArgNr, bool safeToDelete)
-        : TypeInfoArgNr(typeInfoArgNr), ArrSizeArgNr(arrSizeArgNr),
-          SafeToDelete(safeToDelete) {}
+        // Analyze the current call, filling in some fields. Returns true if
+        // this is an allocation we can stack-allocate.
+        virtual bool analyze(CallSite CS, const Analysis& A) {
+            Value* TypeInfo = CS.getArgument(TypeInfoArgNr);
+            Ty = A.getTypeFor(TypeInfo);
+            return (Ty != NULL);
+        }
+        
+        // Returns the alloca to replace this call.
+        // It will always be inserted before the call.
+        virtual AllocaInst* promote(CallSite CS) {
+            NumGcToStack++;
+            
+            Instruction* Begin = CS.getCaller()->getEntryBlock().begin();
+            return new AllocaInst(Ty, ".nongc_mem", Begin);
+        }
+        
+        FunctionInfo(unsigned typeInfoArgNr, bool safeToDelete)
+        : TypeInfoArgNr(typeInfoArgNr), SafeToDelete(safeToDelete) {}
+    };
+    
+    class ArrayFI : public FunctionInfo {
+        Value* arrSize;
+        int ArrSizeArgNr;
+        
+    public:
+        ArrayFI(unsigned tiArgNr, bool safeToDelete, unsigned arrSizeArgNr)
+        : FunctionInfo(tiArgNr, safeToDelete), ArrSizeArgNr(arrSizeArgNr) {}
+        
+        virtual bool analyze(CallSite CS, const Analysis& A) {
+            if (!FunctionInfo::analyze(CS, A))
+                return false;
+            
+            arrSize = CS.getArgument(ArrSizeArgNr);
+            const IntegerType* SizeType =
+                dyn_cast<IntegerType>(arrSize->getType());
+            if (!SizeType)
+                return false;
+            unsigned bits = SizeType->getBitWidth();
+            if (bits > 32) {
+                // The array size of an alloca must be an i32, so make sure
+                // the conversion is safe.
+                APInt Mask = APInt::getHighBitsSet(bits, bits - 32);
+                APInt KnownZero(bits, 0), KnownOne(bits, 0);
+                ComputeMaskedBits(arrSize, Mask, KnownZero, KnownOne, &A.TD);
+                if ((KnownZero & Mask) != Mask)
+                    return false;
+            }
+            // Extract the element type from the array type.
+            const StructType* ArrTy = dyn_cast<StructType>(Ty);
+            assert(ArrTy && "Dynamic array type not a struct?");
+            assert(isa<IntegerType>(ArrTy->getElementType(0)));
+            const PointerType* PtrTy =
+                cast<PointerType>(ArrTy->getElementType(1));
+            Ty = PtrTy->getElementType();
+            return true;
+        }
+        
+        virtual AllocaInst* promote(CallSite CS) {
+            Instruction* I = CS.getInstruction();
+            IRBuilder<> Builder(I->getParent(), I);
+            
+            // If the allocation is of constant size it's best to put it in the
+            // entry block, so do so if we're not already there.
+            // For dynamically-sized allocations it's best to avoid the overhead
+            // of allocating them if possible, so leave those where they are.
+            // While we're at it, update statistics too.
+            if (isa<Constant>(arrSize)) {
+                BasicBlock& Entry = CS.getCaller()->getEntryBlock();
+                if (Builder.GetInsertBlock() != &Entry)
+                    Builder.SetInsertPoint(&Entry, Entry.begin());
+                NumGcToStack++;
+            } else {
+                NumToDynSize++;
+            }
+            
+            // Convert array size to 32 bits if necessary
+            arrSize = Builder.CreateIntCast(arrSize, Type::Int32Ty, false);
+            
+            return Builder.CreateAlloca(Ty, arrSize, ".nongc_mem");
+        }
     };
     
     /// This pass replaces GC calls with alloca's
@@ -63,11 +151,16 @@
         StringMap<FunctionInfo*> KnownFunctions;
         Module* M;
         
-        public:
+        FunctionInfo AllocMemoryT;
+        ArrayFI NewArrayVT;
+        
+    public:
         static char ID; // Pass identification
-        GarbageCollect2Stack() : FunctionPass(&ID) {}
+        GarbageCollect2Stack();
         
-        bool doInitialization(Module &M);
+        bool doInitialization(Module &M) {
+            this->M = &M;
+        }
         
         bool runOnFunction(Function &F);
         
@@ -75,9 +168,6 @@
           AU.addRequired<TargetData>();
           AU.addRequired<LoopInfo>();
         }
-        
-        private:
-        const Type* getTypeFor(Value* typeinfo);
     };
     char GarbageCollect2Stack::ID = 0;
 } // end anonymous namespace.
@@ -90,10 +180,13 @@
   return new GarbageCollect2Stack(); 
 }
 
-bool GarbageCollect2Stack::doInitialization(Module &M) {
-    this->M = &M;
-    KnownFunctions["_d_allocmemoryT"] = new FunctionInfo(0, -1, true);
-    KnownFunctions["_d_newarrayvT"] = new FunctionInfo(0, 1, true);
+GarbageCollect2Stack::GarbageCollect2Stack()
+: FunctionPass(&ID),
+  AllocMemoryT(0, true),
+  NewArrayVT(0, true, 1)
+{
+    KnownFunctions["_d_allocmemoryT"] = &AllocMemoryT;
+    KnownFunctions["_d_newarrayvT"] = &NewArrayVT;
 }
 
 static void RemoveCall(Instruction* Inst) {
@@ -119,6 +212,8 @@
     TargetData &TD = getAnalysis<TargetData>();
     const LoopInfo &LI = getAnalysis<LoopInfo>();
     
+    Analysis A = { TD, *M };
+    
     BasicBlock& Entry = F.getEntryBlock();
     
     IRBuilder<> AllocaBuilder(&Entry, Entry.begin());
@@ -167,70 +262,18 @@
             
             DEBUG(DOUT << "GarbageCollect2Stack inspecting: " << *Inst);
             
-            Value* TypeInfo = CS.getArgument(info->TypeInfoArgNr);
-            const Type* Ty = getTypeFor(TypeInfo);
-            if (!Ty) {
+            if (!info->analyze(CS, A) || PointerMayBeCaptured(Inst, true))
                 continue;
-            }
-            
-            Value* arrSize = 0;
-            if (info->ArrSizeArgNr != -1) {
-                arrSize = CS.getArgument(info->ArrSizeArgNr);
-                const IntegerType* SizeType =
-                    dyn_cast<IntegerType>(arrSize->getType());
-                if (!SizeType)
-                    continue;
-                unsigned bits = SizeType->getBitWidth();
-                if (bits > 32) {
-                    // The array size of an alloca must be an i32, so make sure
-                    // the conversion is safe.
-                    APInt Mask = APInt::getHighBitsSet(bits, bits - 32);
-                    APInt KnownZero(bits, 0), KnownOne(bits, 0);
-                    ComputeMaskedBits(arrSize, Mask, KnownZero, KnownOne, &TD);
-                    if ((KnownZero & Mask) != Mask)
-                        continue;
-                }
-                // Extract the element type from the array type.
-                const StructType* ArrTy = dyn_cast<StructType>(Ty);
-                assert(ArrTy && "Dynamic array type not a struct?");
-                assert(isa<IntegerType>(ArrTy->getElementType(0)));
-                const PointerType* PtrTy =
-                    cast<PointerType>(ArrTy->getElementType(1));
-                Ty = PtrTy->getElementType();
-            }
-            
-            if (PointerMayBeCaptured(Inst, true)) {
-                continue;
-            }
             
             // Let's alloca this!
             Changed = true;
             
-            IRBuilder<> Builder(BB, I);
-            
-            // If the allocation is of constant size it's best to put it in the
-            // entry block, so do so if we're not already there.
-            // For dynamically-sized allocations it's best to avoid the overhead
-            // of allocating them if possible, so leave those where they are.
-            // While we're at it, update statistics too.
-            if (!arrSize || isa<Constant>(arrSize)) {
-                if (&*BB != &Entry)
-                    Builder = AllocaBuilder;
-                NumGcToStack++;
-            } else {
-                NumToDynSize++;
-            }
-            
-            // Convert array size to 32 bits if necessary
-            if (arrSize)
-                arrSize = Builder.CreateIntCast(arrSize, Type::Int32Ty, false);
-            
-            Value* newVal = Builder.CreateAlloca(Ty, arrSize, ".nongc_mem");
+            Value* newVal = info->promote(CS);
             
             // Make sure the type is the same as it was before, and replace all
             // uses of the runtime call with the alloca.
             if (newVal->getType() != Inst->getType())
-                newVal = Builder.CreateBitCast(newVal, Inst->getType());
+                newVal = new BitCastInst(newVal, Inst->getType(), "", Inst);
             Inst->replaceAllUsesWith(newVal);
             
             RemoveCall(Inst);
@@ -240,7 +283,7 @@
     return Changed;
 }
 
-const Type* GarbageCollect2Stack::getTypeFor(Value* typeinfo) {
+const Type* Analysis::getTypeFor(Value* typeinfo) const {
     GlobalVariable* ti_global = dyn_cast<GlobalVariable>(typeinfo->stripPointerCasts());
     if (!ti_global)
         return NULL;
@@ -248,7 +291,7 @@
     std::string metaname = TD_PREFIX;
     metaname.append(ti_global->getNameStart(), ti_global->getNameEnd());
     
-    GlobalVariable* global = M->getGlobalVariable(metaname);
+    GlobalVariable* global = M.getGlobalVariable(metaname);
     if (!global || !global->hasInitializer())
         return NULL;