//
// The LLVM Compiler Infrastructure
//
-// This file was developed by the LLVM research group and is distributed under
-// the University of Illinois Open Source License. See LICENSE.TXT for details.
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
#include "llvm/Pass.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Target/TargetData.h"
+#include "llvm/Support/CallSite.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
+#include <map>
#include <set>
using namespace llvm;
STATISTIC(NumShrunkToBool , "Number of global vars shrunk to booleans");
STATISTIC(NumFastCallFns , "Number of functions converted to fastcc");
STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated");
+STATISTIC(NumNestRemoved , "Number of nest attributes removed");
namespace {
struct VISIBILITY_HIDDEN GlobalOpt : public ModulePass {
bool OptimizeGlobalCtorsList(GlobalVariable *&GCL);
bool ProcessInternalGlobal(GlobalVariable *GV,Module::global_iterator &GVI);
};
-
- char GlobalOpt::ID = 0;
- RegisterPass<GlobalOpt> X("globalopt", "Global Variable Optimizer");
}
+char GlobalOpt::ID = 0;
+static RegisterPass<GlobalOpt> X("globalopt", "Global Variable Optimizer");
+
ModulePass *llvm::createGlobalOptimizerPass() { return new GlobalOpt(); }
+namespace {
+
/// GlobalStatus - As we analyze each global, keep track of some information
/// about it. If we find out that the address of the global is taken, none of
/// this info will be accurate.
/// HasPHIUser - Set to true if this global has a user that is a PHI node.
bool HasPHIUser;
- /// isNotSuitableForSRA - Keep track of whether any SRA preventing users of
- /// the global exist. Such users include GEP instruction with variable
- /// indexes, and non-gep/load/store users like constant expr casts.
- bool isNotSuitableForSRA;
-
GlobalStatus() : isLoaded(false), StoredType(NotStored), StoredOnceValue(0),
AccessingFunction(0), HasMultipleAccessingFunctions(false),
- HasNonInstructionUser(false), HasPHIUser(false),
- isNotSuitableForSRA(false) {}
+ HasNonInstructionUser(false), HasPHIUser(false) {}
};
-
+}
/// ConstantIsDead - Return true if the specified constant is (transitively)
/// dead. The constant may be used by other constants (e.g. constant arrays and
GS.HasNonInstructionUser = true;
if (AnalyzeGlobal(CE, GS, PHIUsers)) return true;
- if (CE->getOpcode() != Instruction::GetElementPtr)
- GS.isNotSuitableForSRA = true;
- else if (!GS.isNotSuitableForSRA) {
- // Check to see if this ConstantExpr GEP is SRA'able. In particular, we
- // don't like < 3 operand CE's, and we don't like non-constant integer
- // indices.
- if (CE->getNumOperands() < 3 || !CE->getOperand(1)->isNullValue())
- GS.isNotSuitableForSRA = true;
- else {
- for (unsigned i = 1, e = CE->getNumOperands(); i != e; ++i)
- if (!isa<ConstantInt>(CE->getOperand(i))) {
- GS.isNotSuitableForSRA = true;
- break;
- }
- }
- }
} else if (Instruction *I = dyn_cast<Instruction>(*UI)) {
if (!GS.HasMultipleAccessingFunctions) {
else if (GS.AccessingFunction != F)
GS.HasMultipleAccessingFunctions = true;
}
- if (isa<LoadInst>(I)) {
+ if (LoadInst *LI = dyn_cast<LoadInst>(I)) {
GS.isLoaded = true;
+ if (LI->isVolatile()) return true; // Don't hack on volatile loads.
} else if (StoreInst *SI = dyn_cast<StoreInst>(I)) {
// Don't allow a store OF the address, only stores TO the address.
if (SI->getOperand(0) == V) return true;
+ if (SI->isVolatile()) return true; // Don't hack on volatile stores.
+
// If this is a direct store to the global (i.e., the global is a scalar
// value, not an aggregate), keep more specific information about
// stores.
- if (GS.StoredType != GlobalStatus::isStored)
+ if (GS.StoredType != GlobalStatus::isStored) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(SI->getOperand(1))){
Value *StoredVal = SI->getOperand(0);
if (StoredVal == GV->getInitializer()) {
} else {
GS.StoredType = GlobalStatus::isStored;
}
+ }
} else if (isa<GetElementPtrInst>(I)) {
if (AnalyzeGlobal(I, GS, PHIUsers)) return true;
-
- // If the first two indices are constants, this can be SRA'd.
- if (isa<GlobalVariable>(I->getOperand(0))) {
- if (I->getNumOperands() < 3 || !isa<Constant>(I->getOperand(1)) ||
- !cast<Constant>(I->getOperand(1))->isNullValue() ||
- !isa<ConstantInt>(I->getOperand(2)))
- GS.isNotSuitableForSRA = true;
- } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(I->getOperand(0))){
- if (CE->getOpcode() != Instruction::GetElementPtr ||
- CE->getNumOperands() < 3 || I->getNumOperands() < 2 ||
- !isa<Constant>(I->getOperand(0)) ||
- !cast<Constant>(I->getOperand(0))->isNullValue())
- GS.isNotSuitableForSRA = true;
- } else {
- GS.isNotSuitableForSRA = true;
- }
} else if (isa<SelectInst>(I)) {
if (AnalyzeGlobal(I, GS, PHIUsers)) return true;
- GS.isNotSuitableForSRA = true;
} else if (PHINode *PN = dyn_cast<PHINode>(I)) {
// PHI nodes we can check just like select or GEP instructions, but we
// have to be careful about infinite recursion.
if (PHIUsers.insert(PN).second) // Not already visited.
if (AnalyzeGlobal(I, GS, PHIUsers)) return true;
- GS.isNotSuitableForSRA = true;
GS.HasPHIUser = true;
} else if (isa<CmpInst>(I)) {
- GS.isNotSuitableForSRA = true;
} else if (isa<MemCpyInst>(I) || isa<MemMoveInst>(I)) {
if (I->getOperand(1) == V)
GS.StoredType = GlobalStatus::isStored;
if (I->getOperand(2) == V)
GS.isLoaded = true;
- GS.isNotSuitableForSRA = true;
} else if (isa<MemSetInst>(I)) {
assert(I->getOperand(1) == V && "Memset only takes one pointer!");
GS.StoredType = GlobalStatus::isStored;
- GS.isNotSuitableForSRA = true;
} else {
return true; // Any other non-load instruction might take address!
}
Changed = true;
}
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(U)) {
+ // Do not transform "gepinst (gep constexpr (GV))" here, because forming
+ // "gepconstexpr (gep constexpr (GV))" will cause the two gep's to fold
+ // and will invalidate our notion of what Init is.
Constant *SubInit = 0;
- ConstantExpr *CE =
- dyn_cast_or_null<ConstantExpr>(ConstantFoldInstruction(GEP));
- if (Init && CE && CE->getOpcode() == Instruction::GetElementPtr)
- SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE);
+ if (!isa<ConstantExpr>(GEP->getOperand(0))) {
+ ConstantExpr *CE =
+ dyn_cast_or_null<ConstantExpr>(ConstantFoldInstruction(GEP));
+ if (Init && CE && CE->getOpcode() == Instruction::GetElementPtr)
+ SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE);
+ }
Changed |= CleanupConstantGlobalUsers(GEP, SubInit);
if (GEP->use_empty()) {
return Changed;
}
+/// isSafeSROAElementUse - Return true if the specified instruction is a safe
+/// user of a derived expression from a global that we want to SROA.
+static bool isSafeSROAElementUse(Value *V) {
+ // We might have a dead and dangling constant hanging off of here.
+ if (Constant *C = dyn_cast<Constant>(V))
+ return ConstantIsDead(C);
+
+ Instruction *I = dyn_cast<Instruction>(V);
+ if (!I) return false;
+
+ // Loads are ok.
+ if (isa<LoadInst>(I)) return true;
+
+ // Stores *to* the pointer are ok.
+ if (StoreInst *SI = dyn_cast<StoreInst>(I))
+ return SI->getOperand(0) != V;
+
+ // Otherwise, it must be a GEP.
+ GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I);
+ if (GEPI == 0) return false;
+
+ if (GEPI->getNumOperands() < 3 || !isa<Constant>(GEPI->getOperand(1)) ||
+ !cast<Constant>(GEPI->getOperand(1))->isNullValue())
+ return false;
+
+ for (Value::use_iterator I = GEPI->use_begin(), E = GEPI->use_end();
+ I != E; ++I)
+ if (!isSafeSROAElementUse(*I))
+ return false;
+ return true;
+}
+
+
+/// IsUserOfGlobalSafeForSRA - U is a direct user of the specified global value.
+/// Look at it and its uses and decide whether it is safe to SROA this global.
+///
+static bool IsUserOfGlobalSafeForSRA(User *U, GlobalValue *GV) {
+ // The user of the global must be a GEP Inst or a ConstantExpr GEP.
+ if (!isa<GetElementPtrInst>(U) &&
+ (!isa<ConstantExpr>(U) ||
+ cast<ConstantExpr>(U)->getOpcode() != Instruction::GetElementPtr))
+ return false;
+
+ // Check to see if this ConstantExpr GEP is SRA'able. In particular, we
+ // don't like < 3 operand CE's, and we don't like non-constant integer
+ // indices. This enforces that all uses are 'gep GV, 0, C, ...' for some
+ // value of C.
+ if (U->getNumOperands() < 3 || !isa<Constant>(U->getOperand(1)) ||
+ !cast<Constant>(U->getOperand(1))->isNullValue() ||
+ !isa<ConstantInt>(U->getOperand(2)))
+ return false;
+
+ gep_type_iterator GEPI = gep_type_begin(U), E = gep_type_end(U);
+ ++GEPI; // Skip over the pointer index.
+
+ // If this is a use of an array allocation, do a bit more checking for sanity.
+ if (const ArrayType *AT = dyn_cast<ArrayType>(*GEPI)) {
+ uint64_t NumElements = AT->getNumElements();
+ ConstantInt *Idx = cast<ConstantInt>(U->getOperand(2));
+
+ // Check to make sure that index falls within the array. If not,
+ // something funny is going on, so we won't do the optimization.
+ //
+ if (Idx->getZExtValue() >= NumElements)
+ return false;
+
+ // We cannot scalar repl this level of the array unless any array
+ // sub-indices are in-range constants. In particular, consider:
+ // A[0][i]. We cannot know that the user isn't doing invalid things like
+ // allowing i to index an out-of-range subscript that accesses A[1].
+ //
+ // Scalar replacing *just* the outer index of the array is probably not
+ // going to be a win anyway, so just give up.
+ for (++GEPI; // Skip array index.
+ GEPI != E && (isa<ArrayType>(*GEPI) || isa<VectorType>(*GEPI));
+ ++GEPI) {
+ uint64_t NumElements;
+ if (const ArrayType *SubArrayTy = dyn_cast<ArrayType>(*GEPI))
+ NumElements = SubArrayTy->getNumElements();
+ else
+ NumElements = cast<VectorType>(*GEPI)->getNumElements();
+
+ ConstantInt *IdxVal = dyn_cast<ConstantInt>(GEPI.getOperand());
+ if (!IdxVal || IdxVal->getZExtValue() >= NumElements)
+ return false;
+ }
+ }
+
+ for (Value::use_iterator I = U->use_begin(), E = U->use_end(); I != E; ++I)
+ if (!isSafeSROAElementUse(*I))
+ return false;
+ return true;
+}
+
+/// GlobalUsersSafeToSRA - Look at all uses of the global and decide whether it
+/// is safe for us to perform this transformation.
+///
+static bool GlobalUsersSafeToSRA(GlobalValue *GV) {
+ for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end();
+ UI != E; ++UI) {
+ if (!IsUserOfGlobalSafeForSRA(*UI, GV))
+ return false;
+ }
+ return true;
+}
+
+
/// SRAGlobal - Perform scalar replacement of aggregates on the specified global
/// variable. This opens the door for other optimizations by exposing the
/// behavior of the program in a more fine-grained way. We have determined that
/// this transformation is safe already. We return the first global variable we
/// insert so that the caller can reprocess it.
-static GlobalVariable *SRAGlobal(GlobalVariable *GV) {
+static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD) {
+ // Make sure this global only has simple uses that we can SRA.
+ if (!GlobalUsersSafeToSRA(GV))
+ return 0;
+
assert(GV->hasInternalLinkage() && !GV->isConstant());
Constant *Init = GV->getInitializer();
const Type *Ty = Init->getType();
std::vector<GlobalVariable*> NewGlobals;
Module::GlobalListType &Globals = GV->getParent()->getGlobalList();
+ // Get the alignment of the global, either explicit or target-specific.
+ unsigned StartAlignment = GV->getAlignment();
+ if (StartAlignment == 0)
+ StartAlignment = TD.getABITypeAlignment(GV->getType());
+
if (const StructType *STy = dyn_cast<StructType>(Ty)) {
NewGlobals.reserve(STy->getNumElements());
+ const StructLayout &Layout = *TD.getStructLayout(STy);
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
Constant *In = getAggregateConstantElement(Init,
ConstantInt::get(Type::Int32Ty, i));
GV->isThreadLocal());
Globals.insert(GV, NGV);
NewGlobals.push_back(NGV);
+
+ // Calculate the known alignment of the field. If the original aggregate
+ // had 256 byte alignment for example, something might depend on that:
+ // propagate info to each field.
+ uint64_t FieldOffset = Layout.getElementOffset(i);
+ unsigned NewAlign = (unsigned)MinAlign(StartAlignment, FieldOffset);
+ if (NewAlign > TD.getABITypeAlignment(STy->getElementType(i)))
+ NGV->setAlignment(NewAlign);
}
} else if (const SequentialType *STy = dyn_cast<SequentialType>(Ty)) {
unsigned NumElements = 0;
if (const ArrayType *ATy = dyn_cast<ArrayType>(STy))
NumElements = ATy->getNumElements();
- else if (const VectorType *PTy = dyn_cast<VectorType>(STy))
- NumElements = PTy->getNumElements();
else
- assert(0 && "Unknown aggregate sequential type!");
+ NumElements = cast<VectorType>(STy)->getNumElements();
if (NumElements > 16 && GV->hasNUsesOrMore(16))
return 0; // It's not worth it.
NewGlobals.reserve(NumElements);
+
+ uint64_t EltSize = TD.getABITypeSize(STy->getElementType());
+ unsigned EltAlign = TD.getABITypeAlignment(STy->getElementType());
for (unsigned i = 0, e = NumElements; i != e; ++i) {
Constant *In = getAggregateConstantElement(Init,
ConstantInt::get(Type::Int32Ty, i));
GV->isThreadLocal());
Globals.insert(GV, NGV);
NewGlobals.push_back(NGV);
+
+ // Calculate the known alignment of the field. If the original aggregate
+ // had 256 byte alignment for example, something might depend on that:
+ // propagate info to each field.
+ unsigned NewAlign = (unsigned)MinAlign(StartAlignment, EltSize*i);
+ if (NewAlign > EltAlign)
+ NGV->setAlignment(NewAlign);
}
}
Value *NewPtr = NewGlobals[Val];
// Form a shorter GEP if needed.
- if (GEP->getNumOperands() > 3)
+ if (GEP->getNumOperands() > 3) {
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GEP)) {
SmallVector<Constant*, 8> Idxs;
Idxs.push_back(NullInt);
Idxs.push_back(NullInt);
for (unsigned i = 3, e = GEPI->getNumOperands(); i != e; ++i)
Idxs.push_back(GEPI->getOperand(i));
- NewPtr = new GetElementPtrInst(NewPtr, Idxs.begin(), Idxs.end(),
- GEPI->getName()+"."+utostr(Val), GEPI);
+ NewPtr = GetElementPtrInst::Create(NewPtr, Idxs.begin(), Idxs.end(),
+ GEPI->getName()+"."+utostr(Val), GEPI);
}
+ }
GEP->replaceAllUsesWith(NewPtr);
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(GEP))
// Should handle GEP here.
SmallVector<Constant*, 8> Idxs;
Idxs.reserve(GEPI->getNumOperands()-1);
- for (unsigned i = 1, e = GEPI->getNumOperands(); i != e; ++i)
- if (Constant *C = dyn_cast<Constant>(GEPI->getOperand(i)))
+ for (User::op_iterator i = GEPI->op_begin() + 1, e = GEPI->op_end();
+ i != e; ++i)
+ if (Constant *C = dyn_cast<Constant>(*i))
Idxs.push_back(C);
else
break;
// If we get here we could have stores, selects, or phi nodes whose values
// are loaded.
assert((isa<StoreInst>(*GUI) || isa<PHINode>(*GUI) ||
- isa<SelectInst>(*GUI)) &&
+ isa<SelectInst>(*GUI) || isa<ConstantExpr>(*GUI)) &&
"Only expect load and stores!");
}
MI->getAlignment(), MI->getName(), MI);
Value* Indices[2];
Indices[0] = Indices[1] = Constant::getNullValue(Type::Int32Ty);
- Value *NewGEP = new GetElementPtrInst(NewMI, Indices, Indices + 2,
- NewMI->getName()+".el0", MI);
+ Value *NewGEP = GetElementPtrInst::Create(NewMI, Indices, Indices + 2,
+ NewMI->getName()+".el0", MI);
MI->replaceAllUsesWith(NewGEP);
MI->eraseFromParent();
MI = NewMI;
GV->getName()+".body",
(Module *)NULL,
GV->isThreadLocal());
+ // FIXME: This new global should have the alignment returned by malloc. Code
+ // could depend on malloc returning large alignment (on the mac, 16 bytes) but
+ // this would only guarantee some lower alignment.
GV->getParent()->getGlobalList().insert(GV, NewGV);
// Anything that used the malloc now uses the global directly.
case ICmpInst::ICMP_ULE:
case ICmpInst::ICMP_SLE:
case ICmpInst::ICMP_EQ:
- LV = BinaryOperator::createNot(LV, "notinit", CI);
+ LV = BinaryOperator::CreateNot(LV, "notinit", CI);
break;
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_UGE:
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)
+ for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ++UI)
if (isa<LoadInst>(*UI) || isa<CmpInst>(*UI)) {
// Fine, ignore.
} else if (StoreInst *SI = dyn_cast<StoreInst>(*UI)) {
if (SI->getOperand(0) == V && SI->getOperand(1) != GV)
return false; // Storing the pointer itself... bad.
// Otherwise, storing through it, or storing into GV... fine.
- } else if (isa<GetElementPtrInst>(*UI) || isa<SelectInst>(*UI) ||
- isa<BitCastInst>(*UI)) {
+ } else if (isa<GetElementPtrInst>(*UI)) {
if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(cast<Instruction>(*UI),
GV, PHIs))
return false;
// PHIs are ok if all uses are ok. Don't infinitely recurse through PHI
// cycles.
if (PHIs.insert(PN))
- return ValueIsOnlyUsedLocallyOrStoredToOneGlobal(PN, GV, PHIs);
+ if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(PN, GV, PHIs))
+ return false;
} else {
return false;
}
static void ReplaceUsesOfMallocWithGlobal(Instruction *Alloc,
GlobalVariable *GV) {
while (!Alloc->use_empty()) {
- Instruction *U = Alloc->use_back();
+ Instruction *U = cast<Instruction>(*Alloc->use_begin());
+ Instruction *InsertPt = U;
if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
// If this is the store of the allocation into the global, remove it.
if (SI->getOperand(1) == GV) {
SI->eraseFromParent();
continue;
}
+ } else if (PHINode *PN = dyn_cast<PHINode>(U)) {
+ // Insert the load in the corresponding predecessor, not right before the
+ // PHI.
+ unsigned PredNo = Alloc->use_begin().getOperandNo()/2;
+ InsertPt = PN->getIncomingBlock(PredNo)->getTerminator();
}
// Insert a load from the global, and use it instead of the malloc.
- Value *NL = new LoadInst(GV, GV->getName()+".val", U);
+ Value *NL = new LoadInst(GV, GV->getName()+".val", InsertPt);
U->replaceUsesOfWith(Alloc, NL);
}
}
/// GlobalLoadUsesSimpleEnoughForHeapSRA - If all users of values loaded from
/// GV are simple enough to perform HeapSRA, return true.
-static bool GlobalLoadUsesSimpleEnoughForHeapSRA(GlobalVariable *GV) {
+static bool GlobalLoadUsesSimpleEnoughForHeapSRA(GlobalVariable *GV,
+ MallocInst *MI) {
for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI != E;
++UI)
if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) {
// We permit two users of the load: setcc comparing against the null
// pointer, and a getelementptr of a specific form.
- for (Value::use_iterator UI = LI->use_begin(), E = LI->use_end(); UI != E;
- ++UI) {
+ for (Value::use_iterator UI = LI->use_begin(), E = LI->use_end();
+ UI != E; ++UI) {
// Comparison against null is ok.
if (ICmpInst *ICI = dyn_cast<ICmpInst>(*UI)) {
if (!isa<ConstantPointerNull>(ICI->getOperand(1)))
}
// getelementptr is also ok, but only a simple form.
- GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*UI);
- if (!GEPI) return false;
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(*UI)) {
+ // Must index into the array and into the struct.
+ if (GEPI->getNumOperands() < 3)
+ return false;
+
+ // Otherwise the GEP is ok.
+ continue;
+ }
- // Must index into the array and into the struct.
- if (GEPI->getNumOperands() < 3)
- return false;
+ if (PHINode *PN = dyn_cast<PHINode>(*UI)) {
+ // We have a phi of a load from the global. We can only handle this
+ // if the other PHI'd values are actually the same. In this case,
+ // the rewriter will just drop the phi entirely.
+ for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
+ Value *IV = PN->getIncomingValue(i);
+ if (IV == LI) continue; // Trivial the same.
+
+ // If the phi'd value is from the malloc that initializes the value,
+ // we can xform it.
+ if (IV == MI) continue;
+
+ // Otherwise, we don't know what it is.
+ return false;
+ }
+ return true;
+ }
- // Otherwise the GEP is ok.
- continue;
+ // Otherwise we don't know what this is, not ok.
+ return false;
}
}
return true;
}
-/// RewriteUsesOfLoadForHeapSRoA - We are performing Heap SRoA on a global. Ptr
-/// is a value loaded from the global. Eliminate all uses of Ptr, making them
-/// use FieldGlobals instead. All uses of loaded values satisfy
-/// GlobalLoadUsesSimpleEnoughForHeapSRA.
-static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Ptr,
- const std::vector<GlobalVariable*> &FieldGlobals) {
- std::vector<Value *> InsertedLoadsForPtr;
- //InsertedLoadsForPtr.resize(FieldGlobals.size());
- while (!Ptr->use_empty()) {
- Instruction *User = Ptr->use_back();
-
- // If this is a comparison against null, handle it.
- if (ICmpInst *SCI = dyn_cast<ICmpInst>(User)) {
- assert(isa<ConstantPointerNull>(SCI->getOperand(1)));
- // If we have a setcc of the loaded pointer, we can use a setcc of any
- // field.
- Value *NPtr;
- if (InsertedLoadsForPtr.empty()) {
- NPtr = new LoadInst(FieldGlobals[0], Ptr->getName()+".f0", Ptr);
- InsertedLoadsForPtr.push_back(Ptr);
- } else {
- NPtr = InsertedLoadsForPtr.back();
- }
-
- Value *New = new ICmpInst(SCI->getPredicate(), NPtr,
- Constant::getNullValue(NPtr->getType()),
- SCI->getName(), SCI);
- SCI->replaceAllUsesWith(New);
- SCI->eraseFromParent();
- continue;
+/// GetHeapSROALoad - Return the load for the specified field of the HeapSROA'd
+/// value, lazily creating it on demand.
+static Value *GetHeapSROALoad(Instruction *Load, unsigned FieldNo,
+ const std::vector<GlobalVariable*> &FieldGlobals,
+ std::vector<Value *> &InsertedLoadsForPtr) {
+ if (InsertedLoadsForPtr.size() <= FieldNo)
+ InsertedLoadsForPtr.resize(FieldNo+1);
+ if (InsertedLoadsForPtr[FieldNo] == 0)
+ InsertedLoadsForPtr[FieldNo] = new LoadInst(FieldGlobals[FieldNo],
+ Load->getName()+".f" +
+ utostr(FieldNo), Load);
+ return InsertedLoadsForPtr[FieldNo];
+}
+
+/// RewriteHeapSROALoadUser - Given a load instruction and a value derived from
+/// the load, rewrite the derived value to use the HeapSRoA'd load.
+static void RewriteHeapSROALoadUser(LoadInst *Load, Instruction *LoadUser,
+ const std::vector<GlobalVariable*> &FieldGlobals,
+ std::vector<Value *> &InsertedLoadsForPtr) {
+ // If this is a comparison against null, handle it.
+ if (ICmpInst *SCI = dyn_cast<ICmpInst>(LoadUser)) {
+ assert(isa<ConstantPointerNull>(SCI->getOperand(1)));
+ // If we have a setcc of the loaded pointer, we can use a setcc of any
+ // field.
+ Value *NPtr;
+ if (InsertedLoadsForPtr.empty()) {
+ NPtr = GetHeapSROALoad(Load, 0, FieldGlobals, InsertedLoadsForPtr);
+ } else {
+ NPtr = InsertedLoadsForPtr.back();
}
- // Otherwise, this should be: 'getelementptr Ptr, Idx, uint FieldNo ...'
- GetElementPtrInst *GEPI = cast<GetElementPtrInst>(User);
+ Value *New = new ICmpInst(SCI->getPredicate(), NPtr,
+ Constant::getNullValue(NPtr->getType()),
+ SCI->getName(), SCI);
+ SCI->replaceAllUsesWith(New);
+ SCI->eraseFromParent();
+ return;
+ }
+
+ // Handle 'getelementptr Ptr, Idx, uint FieldNo ...'
+ if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(LoadUser)) {
assert(GEPI->getNumOperands() >= 3 && isa<ConstantInt>(GEPI->getOperand(2))
&& "Unexpected GEPI!");
-
+
// Load the pointer for this field.
unsigned FieldNo = cast<ConstantInt>(GEPI->getOperand(2))->getZExtValue();
- if (InsertedLoadsForPtr.size() <= FieldNo)
- InsertedLoadsForPtr.resize(FieldNo+1);
- if (InsertedLoadsForPtr[FieldNo] == 0)
- InsertedLoadsForPtr[FieldNo] = new LoadInst(FieldGlobals[FieldNo],
- Ptr->getName()+".f" +
- utostr(FieldNo), Ptr);
- Value *NewPtr = InsertedLoadsForPtr[FieldNo];
-
+ Value *NewPtr = GetHeapSROALoad(Load, FieldNo,
+ FieldGlobals, InsertedLoadsForPtr);
+
// Create the new GEP idx vector.
SmallVector<Value*, 8> GEPIdx;
GEPIdx.push_back(GEPI->getOperand(1));
GEPIdx.append(GEPI->op_begin()+3, GEPI->op_end());
-
- Value *NGEPI = new GetElementPtrInst(NewPtr, GEPIdx.begin(), GEPIdx.end(),
- GEPI->getName(), GEPI);
+
+ Value *NGEPI = GetElementPtrInst::Create(NewPtr,
+ GEPIdx.begin(), GEPIdx.end(),
+ GEPI->getName(), GEPI);
GEPI->replaceAllUsesWith(NGEPI);
GEPI->eraseFromParent();
+ return;
+ }
+
+ // Handle PHI nodes. PHI nodes must be merging in the same values, plus
+ // potentially the original malloc. Insert phi nodes for each field, then
+ // process uses of the PHI.
+ PHINode *PN = cast<PHINode>(LoadUser);
+ std::vector<Value *> PHIsForField;
+ PHIsForField.resize(FieldGlobals.size());
+ for (unsigned i = 0, e = FieldGlobals.size(); i != e; ++i) {
+ Value *LoadV = GetHeapSROALoad(Load, i, FieldGlobals, InsertedLoadsForPtr);
+
+ PHINode *FieldPN = PHINode::Create(LoadV->getType(),
+ PN->getName()+"."+utostr(i), PN);
+ // Fill in the predecessor values.
+ for (unsigned pred = 0, e = PN->getNumIncomingValues(); pred != e; ++pred) {
+ // Each predecessor either uses the load or the original malloc.
+ Value *InVal = PN->getIncomingValue(pred);
+ BasicBlock *BB = PN->getIncomingBlock(pred);
+ Value *NewVal;
+ if (isa<MallocInst>(InVal)) {
+ // Insert a reload from the global in the predecessor.
+ NewVal = GetHeapSROALoad(BB->getTerminator(), i, FieldGlobals,
+ PHIsForField);
+ } else {
+ NewVal = InsertedLoadsForPtr[i];
+ }
+ FieldPN->addIncoming(NewVal, BB);
+ }
+ PHIsForField[i] = FieldPN;
}
+
+ // Since PHIsForField specifies a phi for every input value, the lazy inserter
+ // will never insert a load.
+ while (!PN->use_empty())
+ RewriteHeapSROALoadUser(Load, PN->use_back(), FieldGlobals, PHIsForField);
+ PN->eraseFromParent();
+}
+
+/// RewriteUsesOfLoadForHeapSRoA - We are performing Heap SRoA on a global. Ptr
+/// is a value loaded from the global. Eliminate all uses of Ptr, making them
+/// use FieldGlobals instead. All uses of loaded values satisfy
+/// GlobalLoadUsesSimpleEnoughForHeapSRA.
+static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Load,
+ const std::vector<GlobalVariable*> &FieldGlobals) {
+ std::vector<Value *> InsertedLoadsForPtr;
+ //InsertedLoadsForPtr.resize(FieldGlobals.size());
+ while (!Load->use_empty())
+ RewriteHeapSROALoadUser(Load, Load->use_back(),
+ FieldGlobals, InsertedLoadsForPtr);
}
/// PerformHeapAllocSRoA - MI is an allocation of an array of structures. Break
for (unsigned FieldNo = 0, e = STy->getNumElements(); FieldNo != e;++FieldNo){
const Type *FieldTy = STy->getElementType(FieldNo);
- const Type *PFieldTy = PointerType::get(FieldTy);
+ const Type *PFieldTy = PointerType::getUnqual(FieldTy);
GlobalVariable *NGV =
new GlobalVariable(PFieldTy, false, GlobalValue::InternalLinkage,
if (!RunningOr)
RunningOr = Cond; // First seteq
else
- RunningOr = BinaryOperator::createOr(RunningOr, Cond, "tmp", MI);
+ RunningOr = BinaryOperator::CreateOr(RunningOr, Cond, "tmp", MI);
}
// Split the basic block at the old malloc.
// Create the block to check the first condition. Put all these blocks at the
// end of the function as they are unlikely to be executed.
- BasicBlock *NullPtrBlock = new BasicBlock("malloc_ret_null",
- OrigBB->getParent());
+ BasicBlock *NullPtrBlock = BasicBlock::Create("malloc_ret_null",
+ OrigBB->getParent());
// Remove the uncond branch from OrigBB to ContBB, turning it into a cond
// branch on RunningOr.
OrigBB->getTerminator()->eraseFromParent();
- new BranchInst(NullPtrBlock, ContBB, RunningOr, OrigBB);
+ BranchInst::Create(NullPtrBlock, ContBB, RunningOr, OrigBB);
// Within the NullPtrBlock, we need to emit a comparison and branch for each
// pointer, because some may be null while others are not.
Value *Cmp = new ICmpInst(ICmpInst::ICMP_NE, GVVal,
Constant::getNullValue(GVVal->getType()),
"tmp", NullPtrBlock);
- BasicBlock *FreeBlock = new BasicBlock("free_it", OrigBB->getParent());
- BasicBlock *NextBlock = new BasicBlock("next", OrigBB->getParent());
- new BranchInst(FreeBlock, NextBlock, Cmp, NullPtrBlock);
+ BasicBlock *FreeBlock = BasicBlock::Create("free_it", OrigBB->getParent());
+ BasicBlock *NextBlock = BasicBlock::Create("next", OrigBB->getParent());
+ BranchInst::Create(FreeBlock, NextBlock, Cmp, NullPtrBlock);
// Fill in FreeBlock.
new FreeInst(GVVal, FreeBlock);
new StoreInst(Constant::getNullValue(GVVal->getType()), FieldGlobals[i],
FreeBlock);
- new BranchInst(NextBlock, FreeBlock);
+ BranchInst::Create(NextBlock, FreeBlock);
NullPtrBlock = NextBlock;
}
- new BranchInst(ContBB, NullPtrBlock);
-
+ BranchInst::Create(ContBB, NullPtrBlock);
// MI is no longer needed, remove it.
MI->eraseFromParent();
else if (GetElementPtrInst *GEPI =dyn_cast<GetElementPtrInst>(StoredOnceVal)){
// "getelementptr Ptr, 0, 0, 0" is really just a cast.
bool IsJustACast = true;
- for (unsigned i = 1, e = GEPI->getNumOperands(); i != e; ++i)
- if (!isa<Constant>(GEPI->getOperand(i)) ||
- !cast<Constant>(GEPI->getOperand(i))->isNullValue()) {
+ for (User::op_iterator i = GEPI->op_begin() + 1, e = GEPI->op_end();
+ i != e; ++i)
+ if (!isa<Constant>(*i) ||
+ !cast<Constant>(*i)->isNullValue()) {
IsJustACast = false;
break;
}
// (2048 bytes currently), as we don't want to introduce a 16M global or
// something.
if (NElements->getZExtValue()*
- TD.getTypeSize(MI->getAllocatedType()) < 2048) {
+ TD.getABITypeSize(MI->getAllocatedType()) < 2048) {
GVI = OptimizeGlobalAddressOfMalloc(GV, MI);
return true;
}
// This the structure has an unreasonable number of fields, leave it
// alone.
if (AllocTy->getNumElements() <= 16 && AllocTy->getNumElements() > 0 &&
- GlobalLoadUsesSimpleEnoughForHeapSRA(GV)) {
+ GlobalLoadUsesSimpleEnoughForHeapSRA(GV, MI)) {
GVI = PerformHeapAllocSRoA(GV, MI);
return true;
}
return false;
}
-/// ShrinkGlobalToBoolean - At this point, we have learned that the only two
-/// values ever stored into GV are its initializer and OtherVal.
-static void ShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) {
+/// TryToShrinkGlobalToBoolean - At this point, we have learned that the only
+/// two values ever stored into GV are its initializer and OtherVal. See if we
+/// can shrink the global into a boolean and select between the two values
+/// whenever it is used. This exposes the values to other scalar optimizations.
+static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) {
+ const Type *GVElType = GV->getType()->getElementType();
+
+ // If GVElType is already i1, it is already shrunk. If the type of the GV is
+ // an FP value or vector, don't do this optimization because a select between
+ // them is very expensive and unlikely to lead to later simplification.
+ if (GVElType == Type::Int1Ty || GVElType->isFloatingPoint() ||
+ isa<VectorType>(GVElType))
+ return false;
+
+ // Walk the use list of the global seeing if all the uses are load or store.
+ // If there is anything else, bail out.
+ for (Value::use_iterator I = GV->use_begin(), E = GV->use_end(); I != E; ++I)
+ if (!isa<LoadInst>(I) && !isa<StoreInst>(I))
+ return false;
+
+ DOUT << " *** SHRINKING TO BOOL: " << *GV;
+
// Create the new global, initializing it to false.
GlobalVariable *NewGV = new GlobalVariable(Type::Int1Ty, false,
GlobalValue::InternalLinkage, ConstantInt::getFalse(),
}
}
new StoreInst(StoreVal, NewGV, SI);
- } else if (!UI->use_empty()) {
+ } else {
// Change the load into a load of bool then a select.
LoadInst *LI = cast<LoadInst>(UI);
LoadInst *NLI = new LoadInst(NewGV, LI->getName()+".b", LI);
if (IsOneZero)
NSI = new ZExtInst(NLI, LI->getType(), "", LI);
else
- NSI = new SelectInst(NLI, OtherVal, InitVal, "", LI);
+ NSI = SelectInst::Create(NLI, OtherVal, InitVal, "", LI);
NSI->takeName(LI);
LI->replaceAllUsesWith(NSI);
}
}
GV->eraseFromParent();
+ return true;
}
cerr << " HasMultipleAccessingFunctions = "
<< GS.HasMultipleAccessingFunctions << "\n";
cerr << " HasNonInstructionUser = " << GS.HasNonInstructionUser<<"\n";
- cerr << " isNotSuitableForSRA = " << GS.isNotSuitableForSRA << "\n";
cerr << "\n";
#endif
// this global a local variable) we replace the global with a local alloca
// in this function.
//
- // NOTE: It doesn't make sense to promote non first class types since we
+ // NOTE: It doesn't make sense to promote non single-value types since we
// are just replacing static memory to stack memory.
if (!GS.HasMultipleAccessingFunctions &&
GS.AccessingFunction && !GS.HasNonInstructionUser &&
- GV->getType()->getElementType()->isFirstClassType() &&
+ GV->getType()->getElementType()->isSingleValueType() &&
GS.AccessingFunction->getName() == "main" &&
GS.AccessingFunction->hasExternalLinkage()) {
DOUT << "LOCALIZING GLOBAL: " << *GV;
++NumMarked;
return true;
- } else if (!GS.isNotSuitableForSRA &&
- !GV->getInitializer()->getType()->isFirstClassType()) {
- if (GlobalVariable *FirstNewGV = SRAGlobal(GV)) {
+ } else if (!GV->getInitializer()->getType()->isSingleValueType()) {
+ if (GlobalVariable *FirstNewGV = SRAGlobal(GV,
+ getAnalysis<TargetData>())) {
GVI = FirstNewGV; // Don't skip the newly produced globals!
return true;
}
// Otherwise, if the global was not a boolean, we can shrink it to be a
// boolean.
if (Constant *SOVConstant = dyn_cast<Constant>(GS.StoredOnceValue))
- if (GV->getType()->getElementType() != Type::Int1Ty &&
- !GV->getType()->getElementType()->isFloatingPoint() &&
- !isa<VectorType>(GV->getType()->getElementType()) &&
- !GS.HasPHIUser && !GS.isNotSuitableForSRA) {
- DOUT << " *** SHRINKING TO BOOL: " << *GV;
- ShrinkGlobalToBoolean(GV, SOVConstant);
+ if (TryToShrinkGlobalToBoolean(GV, SOVConstant)) {
++NumShrunkToBool;
return true;
}
if (!isa<CallInst>(User) && !isa<InvokeInst>(User)) return false;
// See if the function address is passed as an argument.
- for (unsigned i = 1, e = User->getNumOperands(); i != e; ++i)
- if (User->getOperand(i) == F) return false;
+ for (User::op_iterator i = User->op_begin() + 1, e = User->op_end();
+ i != e; ++i)
+ if (*i == F) return false;
}
return true;
}
/// function, changing them to FastCC.
static void ChangeCalleesToFastCall(Function *F) {
for (Value::use_iterator UI = F->use_begin(), E = F->use_end(); UI != E;++UI){
- Instruction *User = cast<Instruction>(*UI);
- if (CallInst *CI = dyn_cast<CallInst>(User))
- CI->setCallingConv(CallingConv::Fast);
- else
- cast<InvokeInst>(User)->setCallingConv(CallingConv::Fast);
+ CallSite User(cast<Instruction>(*UI));
+ User.setCallingConv(CallingConv::Fast);
+ }
+}
+
+static PAListPtr StripNest(const PAListPtr &Attrs) {
+ for (unsigned i = 0, e = Attrs.getNumSlots(); i != e; ++i) {
+ if ((Attrs.getSlot(i).Attrs & ParamAttr::Nest) == 0)
+ continue;
+
+ // There can be only one.
+ return Attrs.removeAttr(Attrs.getSlot(i).Index, ParamAttr::Nest);
+ }
+
+ return Attrs;
+}
+
+static void RemoveNestAttribute(Function *F) {
+ F->setParamAttrs(StripNest(F->getParamAttrs()));
+ for (Value::use_iterator UI = F->use_begin(), E = F->use_end(); UI != E;++UI){
+ CallSite User(cast<Instruction>(*UI));
+ User.setParamAttrs(StripNest(User.getParamAttrs()));
}
}
M.getFunctionList().erase(F);
Changed = true;
++NumFnDeleted;
- } else if (F->hasInternalLinkage() &&
- F->getCallingConv() == CallingConv::C && !F->isVarArg() &&
- OnlyCalledDirectly(F)) {
- // If this function has C calling conventions, is not a varargs
- // function, and is only called directly, promote it to use the Fast
- // calling convention.
- F->setCallingConv(CallingConv::Fast);
- ChangeCalleesToFastCall(F);
- ++NumFastCallFns;
- Changed = true;
+ } else if (F->hasInternalLinkage()) {
+ if (F->getCallingConv() == CallingConv::C && !F->isVarArg() &&
+ OnlyCalledDirectly(F)) {
+ // If this function has C calling conventions, is not a varargs
+ // function, and is only called directly, promote it to use the Fast
+ // calling convention.
+ F->setCallingConv(CallingConv::Fast);
+ ChangeCalleesToFastCall(F);
+ ++NumFastCallFns;
+ Changed = true;
+ }
+
+ if (F->getParamAttrs().hasAttrSomewhere(ParamAttr::Nest) &&
+ OnlyCalledDirectly(F)) {
+ // The function is not used by a trampoline intrinsic, so it is safe
+ // to remove the 'nest' attribute.
+ RemoveNestAttribute(F);
+ ++NumNestRemoved;
+ Changed = true;
+ }
}
}
return Changed;
if (!I->hasInitializer()) return 0;
ConstantArray *CA = dyn_cast<ConstantArray>(I->getInitializer());
if (!CA) return 0;
- for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
- if (ConstantStruct *CS = dyn_cast<ConstantStruct>(CA->getOperand(i))) {
+ for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i)
+ if (ConstantStruct *CS = dyn_cast<ConstantStruct>(*i)) {
if (isa<ConstantPointerNull>(CS->getOperand(1)))
continue;
ConstantArray *CA = cast<ConstantArray>(GV->getInitializer());
std::vector<Function*> Result;
Result.reserve(CA->getNumOperands());
- for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i) {
- ConstantStruct *CS = cast<ConstantStruct>(CA->getOperand(i));
+ for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i) {
+ ConstantStruct *CS = cast<ConstantStruct>(*i);
Result.push_back(dyn_cast<Function>(CS->getOperand(1)));
}
return Result;
} else {
const Type *FTy = FunctionType::get(Type::VoidTy,
std::vector<const Type*>(), false);
- const PointerType *PFTy = PointerType::get(FTy);
+ const PointerType *PFTy = PointerType::getUnqual(FTy);
CSVals[1] = Constant::getNullValue(PFTy);
CSVals[0] = ConstantInt::get(Type::Int32Ty, 2147483647);
}
// Break up the constant into its elements.
if (ConstantStruct *CS = dyn_cast<ConstantStruct>(Init)) {
- for (unsigned i = 0, e = CS->getNumOperands(); i != e; ++i)
- Elts.push_back(CS->getOperand(i));
+ for (User::op_iterator i = CS->op_begin(), e = CS->op_end(); i != e; ++i)
+ Elts.push_back(cast<Constant>(*i));
} else if (isa<ConstantAggregateZero>(Init)) {
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
Elts.push_back(Constant::getNullValue(STy->getElementType(i)));
// Break up the array into elements.
std::vector<Constant*> Elts;
if (ConstantArray *CA = dyn_cast<ConstantArray>(Init)) {
- for (unsigned i = 0, e = CA->getNumOperands(); i != e; ++i)
- Elts.push_back(CA->getOperand(i));
+ for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i)
+ Elts.push_back(cast<Constant>(*i));
} else if (isa<ConstantAggregateZero>(Init)) {
Constant *Elt = Constant::getNullValue(ATy->getElementType());
Elts.assign(ATy->getNumElements(), Elt);
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurInst)) {
Constant *P = getVal(Values, GEP->getOperand(0));
SmallVector<Constant*, 8> GEPOps;
- for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i)
- GEPOps.push_back(getVal(Values, GEP->getOperand(i)));
+ for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end();
+ i != e; ++i)
+ GEPOps.push_back(getVal(Values, *i));
InstResult = ConstantExpr::getGetElementPtr(P, &GEPOps[0], GEPOps.size());
} else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) {
if (LI->isVolatile()) return false; // no volatile accesses.
if (!Callee) return false; // Cannot resolve.
std::vector<Constant*> Formals;
- for (unsigned i = 1, e = CI->getNumOperands(); i != e; ++i)
- Formals.push_back(getVal(Values, CI->getOperand(i)));
+ for (User::op_iterator i = CI->op_begin() + 1, e = CI->op_end();
+ i != e; ++i)
+ Formals.push_back(getVal(Values, *i));
if (Callee->isDeclaration()) {
// If this is a function we can constant fold, do it.