Wiki Roadmap Timeline Tickets New Ticket Source Search Help / Guide About Trac Login

Changeset 1297:8e8552601ecd

Show
Ignore:
Timestamp:
05/03/09 12:01:45 (3 years ago)
Author:
Frits van Bommel <fvbommel wxs.nl>
branch:
default
Message:

Stack promotion for _d_newarrayvT. Array literals, concatenations (a ~ b) and
such are eligible for stack-allocation now.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gen/passes/GarbageCollect2Stack.cpp

    r1295 r1297  
    3030#include "llvm/Support/IRBuilder.h" 
    3131#include "llvm/Analysis/CaptureTracking.h" 
     32#include "llvm/Analysis/ValueTracking.h" 
    3233#include "llvm/Analysis/LoopInfo.h" 
    3334#include "llvm/Target/TargetData.h" 
     
    3839using namespace llvm; 
    3940 
    40 STATISTIC(NumGcToStack, "Number of GC calls promoted to stack allocations"); 
     41STATISTIC(NumGcToStack, "Number of calls promoted to constant-size allocas"); 
     42STATISTIC(NumToDynSize, "Number of calls promoted to dynamically-sized allocas"); 
    4143STATISTIC(NumDeleted, "Number of GC calls deleted because the return value was unused"); 
    4244 
     
    4850    struct FunctionInfo { 
    4951        unsigned TypeInfoArgNr; 
     52        int ArrSizeArgNr; 
    5053        bool SafeToDelete; 
    5154         
    52         FunctionInfo(unsigned typeInfoArgNr, bool safeToDelete) 
    53         : TypeInfoArgNr(typeInfoArgNr), SafeToDelete(safeToDelete) {} 
    54          
    55         Value* getArraySize(CallSite CS) { 
    56             return 0; 
    57         } 
     55        FunctionInfo(unsigned typeInfoArgNr, int arrSizeArgNr, bool safeToDelete) 
     56        : TypeInfoArgNr(typeInfoArgNr), ArrSizeArgNr(arrSizeArgNr), 
     57          SafeToDelete(safeToDelete) {} 
    5858    }; 
    5959     
     
    9393bool GarbageCollect2Stack::doInitialization(Module &M) { 
    9494    this->M = &M; 
    95     KnownFunctions["_d_allocmemoryT"] = new FunctionInfo(0, true); 
     95    KnownFunctions["_d_allocmemoryT"] = new FunctionInfo(0, -1, true); 
     96    KnownFunctions["_d_newarrayvT"] = new FunctionInfo(0, 1, true); 
    9697} 
    9798 
     
    101102    DEBUG(DOUT << "Running -dgc2stack on function " << F.getName() << '\n'); 
    102103     
    103     const TargetData &TD = getAnalysis<TargetData>(); 
     104    TargetData &TD = getAnalysis<TargetData>(); 
    104105    const LoopInfo &LI = getAnalysis<LoopInfo>(); 
    105106     
     
    162163            } 
    163164             
     165            Value* arrSize = 0; 
     166            if (info->ArrSizeArgNr != -1) { 
     167                arrSize = CS.getArgument(info->ArrSizeArgNr); 
     168                const IntegerType* SizeType = 
     169                    dyn_cast<IntegerType>(arrSize->getType()); 
     170                if (!SizeType) 
     171                    continue; 
     172                unsigned bits = SizeType->getBitWidth(); 
     173                if (bits > 32) { 
     174                    // The array size of an alloca must be an i32, so make sure 
     175                    // the conversion is safe. 
     176                    APInt Mask = APInt::getHighBitsSet(bits, bits - 32); 
     177                    APInt KnownZero(bits, 0), KnownOne(bits, 0); 
     178                    ComputeMaskedBits(arrSize, Mask, KnownZero, KnownOne, &TD); 
     179                    if ((KnownZero & Mask) != Mask) 
     180                        continue; 
     181                } 
     182                // Extract the element type from the array type. 
     183                const StructType* ArrTy = dyn_cast<StructType>(Ty); 
     184                assert(ArrTy && "Dynamic array type not a struct?"); 
     185                assert(isa<IntegerType>(ArrTy->getElementType(0))); 
     186                const PointerType* PtrTy = 
     187                    cast<PointerType>(ArrTy->getElementType(1)); 
     188                Ty = PtrTy->getElementType(); 
     189            } 
     190             
    164191            // Let's alloca this! 
    165192            Changed = true; 
    166             NumGcToStack++; 
    167              
    168             Value* arrSize = info->getArraySize(CS); 
    169             Value* newVal = AllocaBuilder.CreateAlloca(Ty, arrSize, ".nongc_mem"); 
    170              
     193             
     194            IRBuilder<> Builder(BB, I); 
     195             
     196            // If the allocation is of constant size it's best to put it in the 
     197            // entry block, so do so if we're not already there. 
     198            // For dynamically-sized allocations it's best to avoid the overhead 
     199            // of allocating them if possible, so leave those where they are. 
     200            // While we're at it, update statistics too. 
     201            if (!arrSize || isa<Constant>(arrSize)) { 
     202                if (&*BB != &Entry) 
     203                    Builder = AllocaBuilder; 
     204                NumGcToStack++; 
     205            } else { 
     206                NumToDynSize++; 
     207            } 
     208             
     209            // Convert array size to 32 bits if necessary 
     210            if (arrSize) 
     211                arrSize = Builder.CreateIntCast(arrSize, Type::Int32Ty, false); 
     212             
     213            Value* newVal = Builder.CreateAlloca(Ty, arrSize, ".nongc_mem"); 
     214             
     215            // Make sure the type is the same as it was before, and replace all 
     216            // uses of the runtime call with the alloca. 
    171217            if (newVal->getType() != Inst->getType()) 
    172                 newVal = AllocaBuilder.CreateBitCast(newVal, Inst->getType()); 
    173              
     218                newVal = Builder.CreateBitCast(newVal, Inst->getType()); 
    174219            Inst->replaceAllUsesWith(newVal); 
    175220             
     221            // If this was an invoke instruction, update the control flow. 
    176222            if (InvokeInst* Invoke = dyn_cast<InvokeInst>(Inst)) { 
     223                // Notify the exception landing pad block that we won't be 
     224                // going there anymore. 
    177225                Invoke->getUnwindDest()->removePredecessor(Invoke->getParent()); 
    178226                // Create a branch to the "normal" destination. 
    179227                BranchInst::Create(Invoke->getNormalDest(), Invoke->getParent()); 
    180228            } 
     229             
     230            // Finally, remove the runtime call. 
    181231            Inst->eraseFromParent(); 
    182232        } 
    183233    } 
     234     
    184235    return Changed; 
    185236} 
Copyright © 2008, LDC Development Team.