diff options
Diffstat (limited to 'lib/Transforms/IPO/GlobalOpt.cpp')
| -rw-r--r-- | lib/Transforms/IPO/GlobalOpt.cpp | 223 | 
1 files changed, 120 insertions, 103 deletions
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp index ddff5ef8b36c..b429213a7db3 100644 --- a/lib/Transforms/IPO/GlobalOpt.cpp +++ b/lib/Transforms/IPO/GlobalOpt.cpp @@ -143,7 +143,8 @@ struct GlobalStatus {  static bool SafeToDestroyConstant(const Constant *C) {    if (isa<GlobalValue>(C)) return false; -  for (Value::const_use_iterator UI = C->use_begin(), E = C->use_end(); UI != E; ++UI) +  for (Value::const_use_iterator UI = C->use_begin(), E = C->use_end(); UI != E; +       ++UI)      if (const Constant *CU = dyn_cast<Constant>(*UI)) {        if (!SafeToDestroyConstant(CU)) return false;      } else @@ -158,7 +159,8 @@ static bool SafeToDestroyConstant(const Constant *C) {  ///  static bool AnalyzeGlobal(const Value *V, GlobalStatus &GS,                            SmallPtrSet<const PHINode*, 16> &PHIUsers) { -  for (Value::const_use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) +  for (Value::const_use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; +       ++UI)      if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(*UI)) {        GS.HasNonInstructionUser = true; @@ -185,7 +187,8 @@ static bool AnalyzeGlobal(const Value *V, GlobalStatus &GS,          // value, not an aggregate), keep more specific information about          // stores.          if (GS.StoredType != GlobalStatus::isStored) { -          if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(SI->getOperand(1))){ +          if (const GlobalVariable *GV = dyn_cast<GlobalVariable>( +                                                           SI->getOperand(1))) {              Value *StoredVal = SI->getOperand(0);              if (StoredVal == GV->getInitializer()) {                if (GS.StoredType < GlobalStatus::isInitializerStored) @@ -610,62 +613,69 @@ static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) {  /// AllUsesOfValueWillTrapIfNull - Return true if all users of the specified  /// value will trap if the value is dynamically null.  PHIs keeps track of any   /// phi nodes we've seen to avoid reprocessing them. -static bool AllUsesOfValueWillTrapIfNull(Value *V, -                                         SmallPtrSet<PHINode*, 8> &PHIs) { -  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI) -    if (isa<LoadInst>(*UI)) { +static bool AllUsesOfValueWillTrapIfNull(const Value *V, +                                         SmallPtrSet<const PHINode*, 8> &PHIs) { +  for (Value::const_use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; +       ++UI) { +    const User *U = *UI; + +    if (isa<LoadInst>(U)) {        // Will trap. -    } else if (StoreInst *SI = dyn_cast<StoreInst>(*UI)) { +    } else if (const StoreInst *SI = dyn_cast<StoreInst>(U)) {        if (SI->getOperand(0) == V) { -        //cerr << "NONTRAPPING USE: " << **UI; +        //cerr << "NONTRAPPING USE: " << *U;          return false;  // Storing the value.        } -    } else if (CallInst *CI = dyn_cast<CallInst>(*UI)) { +    } else if (const CallInst *CI = dyn_cast<CallInst>(U)) {        if (CI->getCalledValue() != V) { -        //cerr << "NONTRAPPING USE: " << **UI; +        //cerr << "NONTRAPPING USE: " << *U;          return false;  // Not calling the ptr        } -    } else if (InvokeInst *II = dyn_cast<InvokeInst>(*UI)) { +    } else if (const InvokeInst *II = dyn_cast<InvokeInst>(U)) {        if (II->getCalledValue() != V) { -        //cerr << "NONTRAPPING USE: " << **UI; +        //cerr << "NONTRAPPING USE: " << *U;          return false;  // Not calling the ptr        } -    } else if (BitCastInst *CI = dyn_cast<BitCastInst>(*UI)) { +    } else if (const BitCastInst *CI = dyn_cast<BitCastInst>(U)) {        if (!AllUsesOfValueWillTrapIfNull(CI, PHIs)) return false; -    } else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*UI)) { +    } else if (const GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(U)) {        if (!AllUsesOfValueWillTrapIfNull(GEPI, PHIs)) return false; -    } else if (PHINode *PN = dyn_cast<PHINode>(*UI)) { +    } else if (const PHINode *PN = dyn_cast<PHINode>(U)) {        // If we've already seen this phi node, ignore it, it has already been        // checked.        if (PHIs.insert(PN) && !AllUsesOfValueWillTrapIfNull(PN, PHIs))          return false; -    } else if (isa<ICmpInst>(*UI) && +    } else if (isa<ICmpInst>(U) &&                 isa<ConstantPointerNull>(UI->getOperand(1))) {        // Ignore icmp X, null      } else { -      //cerr << "NONTRAPPING USE: " << **UI; +      //cerr << "NONTRAPPING USE: " << *U;        return false;      } +  }    return true;  }  /// AllUsesOfLoadedValueWillTrapIfNull - Return true if all uses of any loads  /// from GV will trap if the loaded value is null.  Note that this also permits  /// comparisons of the loaded value against null, as a special case. -static bool AllUsesOfLoadedValueWillTrapIfNull(GlobalVariable *GV) { -  for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI!=E; ++UI) -    if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) { -      SmallPtrSet<PHINode*, 8> PHIs; +static bool AllUsesOfLoadedValueWillTrapIfNull(const GlobalVariable *GV) { +  for (Value::const_use_iterator UI = GV->use_begin(), E = GV->use_end(); +       UI != E; ++UI) { +    const User *U = *UI; + +    if (const LoadInst *LI = dyn_cast<LoadInst>(U)) { +      SmallPtrSet<const PHINode*, 8> PHIs;        if (!AllUsesOfValueWillTrapIfNull(LI, PHIs))          return false; -    } else if (isa<StoreInst>(*UI)) { +    } else if (isa<StoreInst>(U)) {        // Ignore stores to the global.      } else {        // We don't know or understand this user, bail out. -      //cerr << "UNKNOWN USER OF GLOBAL!: " << **UI; +      //cerr << "UNKNOWN USER OF GLOBAL!: " << *U;        return false;      } - +  }    return true;  } @@ -682,16 +692,17 @@ static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV) {          Changed = true;        }      } else if (isa<CallInst>(I) || isa<InvokeInst>(I)) { -      if (I->getOperand(0) == V) { +      CallSite CS(I); +      if (CS.getCalledValue() == V) {          // Calling through the pointer!  Turn into a direct call, but be careful          // that the pointer is not also being passed as an argument. -        I->setOperand(0, NewV); +        CS.setCalledFunction(NewV);          Changed = true;          bool PassedAsArg = false; -        for (unsigned i = 1, e = I->getNumOperands(); i != e; ++i) -          if (I->getOperand(i) == V) { +        for (unsigned i = 0, e = CS.arg_size(); i != e; ++i) +          if (CS.getArgument(i) == V) {              PassedAsArg = true; -            I->setOperand(i, NewV); +            CS.setArgument(i, NewV);            }          if (PassedAsArg) { @@ -938,29 +949,31 @@ static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV,  /// to make sure that there are no complex uses of V.  We permit simple things  /// like dereferencing the pointer, but not storing through the address, unless  /// it is to the specified global. -static bool ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Instruction *V, -                                                      GlobalVariable *GV, -                                              SmallPtrSet<PHINode*, 8> &PHIs) { -  for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ -    Instruction *Inst = cast<Instruction>(*UI); -     +static bool ValueIsOnlyUsedLocallyOrStoredToOneGlobal(const Instruction *V, +                                                      const GlobalVariable *GV, +                                         SmallPtrSet<const PHINode*, 8> &PHIs) { +  for (Value::const_use_iterator UI = V->use_begin(), E = V->use_end(); +       UI != E; ++UI) { +    const Instruction *Inst = cast<Instruction>(*UI); +      if (isa<LoadInst>(Inst) || isa<CmpInst>(Inst)) {        continue; // Fine, ignore.      } -    if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { +    if (const StoreInst *SI = dyn_cast<StoreInst>(Inst)) {        if (SI->getOperand(0) == V && SI->getOperand(1) != GV)          return false;  // Storing the pointer itself... bad.        continue; // Otherwise, storing through it, or storing into GV... fine.      } -    if (isa<GetElementPtrInst>(Inst)) { +    // Must index into the array and into the struct. +    if (isa<GetElementPtrInst>(Inst) && Inst->getNumOperands() >= 3) {        if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Inst, GV, PHIs))          return false;        continue;      } -    if (PHINode *PN = dyn_cast<PHINode>(Inst)) { +    if (const PHINode *PN = dyn_cast<PHINode>(Inst)) {        // PHIs are ok if all uses are ok.  Don't infinitely recurse through PHI        // cycles.        if (PHIs.insert(PN)) @@ -969,7 +982,7 @@ static bool ValueIsOnlyUsedLocallyOrStoredToOneGlobal(Instruction *V,        continue;      } -    if (BitCastInst *BCI = dyn_cast<BitCastInst>(Inst)) { +    if (const BitCastInst *BCI = dyn_cast<BitCastInst>(Inst)) {        if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(BCI, GV, PHIs))          return false;        continue; @@ -1029,11 +1042,12 @@ static void ReplaceUsesOfMallocWithGlobal(Instruction *Alloc,  /// of a load) are simple enough to perform heap SRA on.  This permits GEP's  /// that index through the array and struct field, icmps of null, and PHIs.  static bool LoadUsesSimpleEnoughForHeapSRA(const Value *V, -                              SmallPtrSet<const PHINode*, 32> &LoadUsingPHIs, -                              SmallPtrSet<const PHINode*, 32> &LoadUsingPHIsPerLoad) { +                        SmallPtrSet<const PHINode*, 32> &LoadUsingPHIs, +                        SmallPtrSet<const PHINode*, 32> &LoadUsingPHIsPerLoad) {    // We permit two users of the load: setcc comparing against the null    // pointer, and a getelementptr of a specific form. -  for (Value::const_use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){ +  for (Value::const_use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; +       ++UI) {      const Instruction *User = cast<Instruction>(*UI);      // Comparison against null is ok. @@ -1084,8 +1098,8 @@ static bool AllGlobalLoadUsesSimpleEnoughForHeapSRA(const GlobalVariable *GV,                                                      Instruction *StoredVal) {    SmallPtrSet<const PHINode*, 32> LoadUsingPHIs;    SmallPtrSet<const PHINode*, 32> LoadUsingPHIsPerLoad; -  for (Value::const_use_iterator UI = GV->use_begin(), E = GV->use_end(); UI != E;  -       ++UI) +  for (Value::const_use_iterator UI = GV->use_begin(), E = GV->use_end(); +       UI != E; ++UI)      if (const LoadInst *LI = dyn_cast<LoadInst>(*UI)) {        if (!LoadUsesSimpleEnoughForHeapSRA(LI, LoadUsingPHIs,                                            LoadUsingPHIsPerLoad)) @@ -1098,8 +1112,8 @@ static bool AllGlobalLoadUsesSimpleEnoughForHeapSRA(const GlobalVariable *GV,    // that all inputs the to the PHI nodes are in the same equivalence sets.     // Check to verify that all operands of the PHIs are either PHIS that can be    // transformed, loads from GV, or MI itself. -  for (SmallPtrSet<const PHINode*, 32>::const_iterator I = LoadUsingPHIs.begin(), -       E = LoadUsingPHIs.end(); I != E; ++I) { +  for (SmallPtrSet<const PHINode*, 32>::const_iterator I = LoadUsingPHIs.begin() +       , E = LoadUsingPHIs.end(); I != E; ++I) {      const PHINode *PN = *I;      for (unsigned op = 0, e = PN->getNumIncomingValues(); op != e; ++op) {        Value *InVal = PN->getIncomingValue(op); @@ -1448,6 +1462,9 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,                                                 const Type *AllocTy,                                                 Module::global_iterator &GVI,                                                 TargetData *TD) { +  if (!TD) +    return false; +              // If this is a malloc of an abstract type, don't touch it.    if (!AllocTy->isSized())      return false; @@ -1466,66 +1483,66 @@ static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,    // malloc to be stored into the specified global, loaded setcc'd, and    // GEP'd.  These are all things we could transform to using the global    // for. -  { -    SmallPtrSet<PHINode*, 8> PHIs; -    if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(CI, GV, PHIs)) -      return false; -  }   +  SmallPtrSet<const PHINode*, 8> PHIs; +  if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(CI, GV, PHIs)) +    return false;    // If we have a global that is only initialized with a fixed size malloc,    // transform the program to use global memory instead of malloc'd memory.    // This eliminates dynamic allocation, avoids an indirection accessing the    // data, and exposes the resultant global to further GlobalOpt.    // We cannot optimize the malloc if we cannot determine malloc array size. -  if (Value *NElems = getMallocArraySize(CI, TD, true)) { -    if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems)) -      // Restrict this transformation to only working on small allocations -      // (2048 bytes currently), as we don't want to introduce a 16M global or -      // something. -      if (TD &&  -          NElements->getZExtValue() * TD->getTypeAllocSize(AllocTy) < 2048) { -        GVI = OptimizeGlobalAddressOfMalloc(GV, CI, AllocTy, NElements, TD); -        return true; -      } +  Value *NElems = getMallocArraySize(CI, TD, true); +  if (!NElems) +    return false; + +  if (ConstantInt *NElements = dyn_cast<ConstantInt>(NElems)) +    // Restrict this transformation to only working on small allocations +    // (2048 bytes currently), as we don't want to introduce a 16M global or +    // something. +    if (NElements->getZExtValue() * TD->getTypeAllocSize(AllocTy) < 2048) { +      GVI = OptimizeGlobalAddressOfMalloc(GV, CI, AllocTy, NElements, TD); +      return true; +    } -    // If the allocation is an array of structures, consider transforming this -    // into multiple malloc'd arrays, one for each field.  This is basically -    // SRoA for malloc'd memory. - -    // If this is an allocation of a fixed size array of structs, analyze as a -    // variable size array.  malloc [100 x struct],1 -> malloc struct, 100 -    if (NElems == ConstantInt::get(CI->getOperand(1)->getType(), 1)) -      if (const ArrayType *AT = dyn_cast<ArrayType>(AllocTy)) -        AllocTy = AT->getElementType(); +  // If the allocation is an array of structures, consider transforming this +  // into multiple malloc'd arrays, one for each field.  This is basically +  // SRoA for malloc'd memory. + +  // If this is an allocation of a fixed size array of structs, analyze as a +  // variable size array.  malloc [100 x struct],1 -> malloc struct, 100 +  if (NElems == ConstantInt::get(CI->getOperand(1)->getType(), 1)) +    if (const ArrayType *AT = dyn_cast<ArrayType>(AllocTy)) +      AllocTy = AT->getElementType(); -    if (const StructType *AllocSTy = dyn_cast<StructType>(AllocTy)) { -      // This the structure has an unreasonable number of fields, leave it -      // alone. -      if (AllocSTy->getNumElements() <= 16 && AllocSTy->getNumElements() != 0 && -          AllGlobalLoadUsesSimpleEnoughForHeapSRA(GV, CI)) { - -        // If this is a fixed size array, transform the Malloc to be an alloc of -        // structs.  malloc [100 x struct],1 -> malloc struct, 100 -        if (const ArrayType *AT = -                              dyn_cast<ArrayType>(getMallocAllocatedType(CI))) { -          const Type *IntPtrTy = TD->getIntPtrType(CI->getContext()); -          unsigned TypeSize = TD->getStructLayout(AllocSTy)->getSizeInBytes(); -          Value *AllocSize = ConstantInt::get(IntPtrTy, TypeSize); -          Value *NumElements = ConstantInt::get(IntPtrTy, AT->getNumElements()); -          Instruction *Malloc = CallInst::CreateMalloc(CI, IntPtrTy, AllocSTy, -                                                       AllocSize, NumElements, -                                                       CI->getName()); -          Instruction *Cast = new BitCastInst(Malloc, CI->getType(), "tmp", CI); -          CI->replaceAllUsesWith(Cast); -          CI->eraseFromParent(); -          CI = dyn_cast<BitCastInst>(Malloc) ? -               extractMallocCallFromBitCast(Malloc) : cast<CallInst>(Malloc); -        } -       -        GVI = PerformHeapAllocSRoA(GV, CI, getMallocArraySize(CI, TD, true),TD); -        return true; -      } +  const StructType *AllocSTy = dyn_cast<StructType>(AllocTy); +  if (!AllocSTy) +    return false; + +  // This the structure has an unreasonable number of fields, leave it +  // alone. +  if (AllocSTy->getNumElements() <= 16 && AllocSTy->getNumElements() != 0 && +      AllGlobalLoadUsesSimpleEnoughForHeapSRA(GV, CI)) { + +    // If this is a fixed size array, transform the Malloc to be an alloc of +    // structs.  malloc [100 x struct],1 -> malloc struct, 100 +    if (const ArrayType *AT = dyn_cast<ArrayType>(getMallocAllocatedType(CI))) { +      const Type *IntPtrTy = TD->getIntPtrType(CI->getContext()); +      unsigned TypeSize = TD->getStructLayout(AllocSTy)->getSizeInBytes(); +      Value *AllocSize = ConstantInt::get(IntPtrTy, TypeSize); +      Value *NumElements = ConstantInt::get(IntPtrTy, AT->getNumElements()); +      Instruction *Malloc = CallInst::CreateMalloc(CI, IntPtrTy, AllocSTy, +                                                   AllocSize, NumElements, +                                                   CI->getName()); +      Instruction *Cast = new BitCastInst(Malloc, CI->getType(), "tmp", CI); +      CI->replaceAllUsesWith(Cast); +      CI->eraseFromParent(); +      CI = dyn_cast<BitCastInst>(Malloc) ? +        extractMallocCallFromBitCast(Malloc) : cast<CallInst>(Malloc);      } +       +    GVI = PerformHeapAllocSRoA(GV, CI, getMallocArraySize(CI, TD, true),TD); +    return true;    }    return false; @@ -1689,8 +1706,8 @@ bool GlobalOpt::ProcessInternalGlobal(GlobalVariable *GV,      if (GS.StoredType == GlobalStatus::isStoredOnce && GS.StoredOnceValue)        DEBUG(dbgs() << "  StoredOnceValue = " << *GS.StoredOnceValue << "\n");      if (GS.AccessingFunction && !GS.HasMultipleAccessingFunctions) -      DEBUG(dbgs() << "  AccessingFunction = " << GS.AccessingFunction->getName() -                  << "\n"); +      DEBUG(dbgs() << "  AccessingFunction = " +                   << GS.AccessingFunction->getName() << "\n");      DEBUG(dbgs() << "  HasMultipleAccessingFunctions =  "                   << GS.HasMultipleAccessingFunctions << "\n");      DEBUG(dbgs() << "  HasNonInstructionUser = "  @@ -2278,10 +2295,10 @@ static bool EvaluateFunction(Function *F, Constant *&RetVal,        }        // Cannot handle inline asm. -      if (isa<InlineAsm>(CI->getOperand(0))) return false; +      if (isa<InlineAsm>(CI->getCalledValue())) return false;        // Resolve function pointers. -      Function *Callee = dyn_cast<Function>(getVal(Values, CI->getOperand(0))); +      Function *Callee = dyn_cast<Function>(getVal(Values, CI->getCalledValue()));        if (!Callee) return false;  // Cannot resolve.        SmallVector<Constant*, 8> Formals; @@ -2500,7 +2517,7 @@ bool GlobalOpt::OptimizeGlobalAliases(Module &M) {          continue;        // Do not perform the transform if multiple aliases potentially target the -      // aliasee.  This check also ensures that it is safe to replace the section +      // aliasee. This check also ensures that it is safe to replace the section        // and other attributes of the aliasee with those of the alias.        if (!hasOneUse)          continue;  | 
