#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/IntrinsicInst.h"
+#include "llvm/LLVMContext.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Analysis/ConstantFolding.h"
+#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Support/CallSite.h"
-#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
using namespace llvm;
STATISTIC(NumAliasesRemoved, "Number of global aliases eliminated");
namespace {
- struct VISIBILITY_HIDDEN GlobalOpt : public ModulePass {
+ struct GlobalOpt : public ModulePass {
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.addRequired<TargetData>();
}
static char ID; // Pass identification, replacement for typeid
GlobalOpt() : ModulePass(&ID) {}
/// 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.
-struct VISIBILITY_HIDDEN GlobalStatus {
+struct GlobalStatus {
/// isLoaded - True if the global is ever loaded. If the global isn't ever
/// loaded it can be deleted.
bool isLoaded;
}
-/// ConstantIsDead - Return true if the specified constant is (transitively)
-/// dead. The constant may be used by other constants (e.g. constant arrays and
-/// constant exprs) as long as they are dead, but it cannot be used by anything
-/// else.
-static bool ConstantIsDead(Constant *C) {
+// SafeToDestroyConstant - It is safe to destroy a constant iff it is only used
+// by constants itself. Note that constants cannot be cyclic, so this test is
+// pretty easy to implement recursively.
+//
+static bool SafeToDestroyConstant(Constant *C) {
if (isa<GlobalValue>(C)) return false;
for (Value::use_iterator UI = C->use_begin(), E = C->use_end(); UI != E; ++UI)
if (Constant *CU = dyn_cast<Constant>(*UI)) {
- if (!ConstantIsDead(CU)) return false;
+ if (!SafeToDestroyConstant(CU)) return false;
} else
return false;
return true;
} else if (Constant *C = dyn_cast<Constant>(*UI)) {
GS.HasNonInstructionUser = true;
// We might have a dead and dangling constant hanging off of here.
- if (!ConstantIsDead(C))
+ if (!SafeToDestroyConstant(C))
return true;
} else {
GS.HasNonInstructionUser = true;
return false;
}
-static Constant *getAggregateConstantElement(Constant *Agg, Constant *Idx) {
+static Constant *getAggregateConstantElement(Constant *Agg, Constant *Idx,
+ LLVMContext &Context) {
ConstantInt *CI = dyn_cast<ConstantInt>(Idx);
if (!CI) return 0;
unsigned IdxV = CI->getZExtValue();
/// users of the global, cleaning up the obvious ones. This is largely just a
/// quick scan over the use list to clean up the easy and obvious cruft. This
/// returns true if it made a change.
-static bool CleanupConstantGlobalUsers(Value *V, Constant *Init) {
+static bool CleanupConstantGlobalUsers(Value *V, Constant *Init,
+ LLVMContext &Context) {
bool Changed = false;
for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;) {
User *U = *UI++;
Constant *SubInit = 0;
if (Init)
SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE);
- Changed |= CleanupConstantGlobalUsers(CE, SubInit);
+ Changed |= CleanupConstantGlobalUsers(CE, SubInit, Context);
} else if (CE->getOpcode() == Instruction::BitCast &&
isa<PointerType>(CE->getType())) {
// Pointer cast, delete any stores and memsets to the global.
- Changed |= CleanupConstantGlobalUsers(CE, 0);
+ Changed |= CleanupConstantGlobalUsers(CE, 0, Context);
}
if (CE->use_empty()) {
Constant *SubInit = 0;
if (!isa<ConstantExpr>(GEP->getOperand(0))) {
ConstantExpr *CE =
- dyn_cast_or_null<ConstantExpr>(ConstantFoldInstruction(GEP));
+ dyn_cast_or_null<ConstantExpr>(ConstantFoldInstruction(GEP, Context));
if (Init && CE && CE->getOpcode() == Instruction::GetElementPtr)
SubInit = ConstantFoldLoadThroughGEPConstantExpr(Init, CE);
}
- Changed |= CleanupConstantGlobalUsers(GEP, SubInit);
+ Changed |= CleanupConstantGlobalUsers(GEP, SubInit, Context);
if (GEP->use_empty()) {
GEP->eraseFromParent();
} else if (Constant *C = dyn_cast<Constant>(U)) {
// If we have a chain of dead constantexprs or other things dangling from
// us, and if they are all dead, nuke them without remorse.
- if (ConstantIsDead(C)) {
+ if (SafeToDestroyConstant(C)) {
C->destroyConstant();
// This could have invalidated UI, start over from scratch.
- CleanupConstantGlobalUsers(V, Init);
+ CleanupConstantGlobalUsers(V, Init, Context);
return true;
}
}
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);
+ return SafeToDestroyConstant(C);
Instruction *I = dyn_cast<Instruction>(V);
if (!I) return false;
// 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 != E;
++GEPI) {
uint64_t NumElements;
if (const ArrayType *SubArrayTy = dyn_cast<ArrayType>(*GEPI))
NumElements = SubArrayTy->getNumElements();
- else
- NumElements = cast<VectorType>(*GEPI)->getNumElements();
+ else if (const VectorType *SubVectorTy = dyn_cast<VectorType>(*GEPI))
+ NumElements = SubVectorTy->getNumElements();
+ else {
+ assert(isa<StructType>(*GEPI) &&
+ "Indexed GEP type is not array, vector, or struct!");
+ continue;
+ }
ConstantInt *IdxVal = dyn_cast<ConstantInt>(GEPI.getOperand());
if (!IdxVal || IdxVal->getZExtValue() >= NumElements)
/// 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, const TargetData &TD) {
+static GlobalVariable *SRAGlobal(GlobalVariable *GV, const TargetData &TD,
+ LLVMContext &Context) {
// Make sure this global only has simple uses that we can SRA.
if (!GlobalUsersSafeToSRA(GV))
return 0;
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));
+ ConstantInt::get(Type::getInt32Ty(Context), i),
+ Context);
assert(In && "Couldn't get element of initializer?");
- GlobalVariable *NGV = new GlobalVariable(STy->getElementType(i), false,
+ GlobalVariable *NGV = new GlobalVariable(Context,
+ STy->getElementType(i), false,
GlobalVariable::InternalLinkage,
- In, GV->getName()+"."+utostr(i),
- (Module *)NULL,
+ In, GV->getName()+"."+Twine(i),
GV->isThreadLocal(),
- GV->getType()->getAddressSpace());
+ GV->getType()->getAddressSpace());
Globals.insert(GV, NGV);
NewGlobals.push_back(NGV);
return 0; // It's not worth it.
NewGlobals.reserve(NumElements);
- uint64_t EltSize = TD.getTypePaddedSize(STy->getElementType());
+ uint64_t EltSize = TD.getTypeAllocSize(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));
+ ConstantInt::get(Type::getInt32Ty(Context), i),
+ Context);
assert(In && "Couldn't get element of initializer?");
- GlobalVariable *NGV = new GlobalVariable(STy->getElementType(), false,
+ GlobalVariable *NGV = new GlobalVariable(Context,
+ STy->getElementType(), false,
GlobalVariable::InternalLinkage,
- In, GV->getName()+"."+utostr(i),
- (Module *)NULL,
+ In, GV->getName()+"."+Twine(i),
GV->isThreadLocal(),
- GV->getType()->getAddressSpace());
+ GV->getType()->getAddressSpace());
Globals.insert(GV, NGV);
NewGlobals.push_back(NGV);
if (NewGlobals.empty())
return 0;
- DOUT << "PERFORMING GLOBAL SRA ON: " << *GV;
+ DEBUG(errs() << "PERFORMING GLOBAL SRA ON: " << *GV);
- Constant *NullInt = Constant::getNullValue(Type::Int32Ty);
+ Constant *NullInt = Constant::getNullValue(Type::getInt32Ty(Context));
// Loop over all of the uses of the global, replacing the constantexpr geps,
// with smaller constantexpr geps or direct references.
for (unsigned i = 3, e = GEPI->getNumOperands(); i != e; ++i)
Idxs.push_back(GEPI->getOperand(i));
NewPtr = GetElementPtrInst::Create(NewPtr, Idxs.begin(), Idxs.end(),
- GEPI->getName()+"."+utostr(Val), GEPI);
+ GEPI->getName()+"."+Twine(Val),GEPI);
}
}
GEP->replaceAllUsesWith(NewPtr);
return true;
}
-static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV) {
+static bool OptimizeAwayTrappingUsesOfValue(Value *V, Constant *NewV,
+ LLVMContext &Context) {
bool Changed = false;
for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; ) {
Instruction *I = cast<Instruction>(*UI++);
} else if (CastInst *CI = dyn_cast<CastInst>(I)) {
Changed |= OptimizeAwayTrappingUsesOfValue(CI,
ConstantExpr::getCast(CI->getOpcode(),
- NewV, CI->getType()));
+ NewV, CI->getType()), Context);
if (CI->use_empty()) {
Changed = true;
CI->eraseFromParent();
break;
if (Idxs.size() == GEPI->getNumOperands()-1)
Changed |= OptimizeAwayTrappingUsesOfValue(GEPI,
- ConstantExpr::getGetElementPtr(NewV, &Idxs[0],
- Idxs.size()));
+ ConstantExpr::getGetElementPtr(NewV, &Idxs[0],
+ Idxs.size()), Context);
if (GEPI->use_empty()) {
Changed = true;
GEPI->eraseFromParent();
/// value stored into it. If there are uses of the loaded value that would trap
/// if the loaded value is dynamically null, then we know that they cannot be
/// reachable with a null optimize away the load.
-static bool OptimizeAwayTrappingUsesOfLoads(GlobalVariable *GV, Constant *LV) {
+static bool OptimizeAwayTrappingUsesOfLoads(GlobalVariable *GV, Constant *LV,
+ LLVMContext &Context) {
bool Changed = false;
// Keep track of whether we are able to remove all the uses of the global
for (Value::use_iterator GUI = GV->use_begin(), E = GV->use_end(); GUI != E;){
User *GlobalUser = *GUI++;
if (LoadInst *LI = dyn_cast<LoadInst>(GlobalUser)) {
- Changed |= OptimizeAwayTrappingUsesOfValue(LI, LV);
+ Changed |= OptimizeAwayTrappingUsesOfValue(LI, LV, Context);
// If we were able to delete all uses of the loads
if (LI->use_empty()) {
LI->eraseFromParent();
}
if (Changed) {
- DOUT << "OPTIMIZED LOADS FROM STORED ONCE POINTER: " << *GV;
+ DEBUG(errs() << "OPTIMIZED LOADS FROM STORED ONCE POINTER: " << *GV);
++NumGlobUses;
}
// If we nuked all of the loads, then none of the stores are needed either,
// nor is the global.
if (AllNonStoreUsesGone) {
- DOUT << " *** GLOBAL NOW DEAD!\n";
- CleanupConstantGlobalUsers(GV, 0);
+ DEBUG(errs() << " *** GLOBAL NOW DEAD!\n");
+ CleanupConstantGlobalUsers(GV, 0, Context);
if (GV->use_empty()) {
GV->eraseFromParent();
++NumDeleted;
/// ConstantPropUsersOf - Walk the use list of V, constant folding all of the
/// instructions that are foldable.
-static void ConstantPropUsersOf(Value *V) {
+static void ConstantPropUsersOf(Value *V, LLVMContext &Context) {
for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E; )
if (Instruction *I = dyn_cast<Instruction>(*UI++))
- if (Constant *NewC = ConstantFoldInstruction(I)) {
+ if (Constant *NewC = ConstantFoldInstruction(I, Context)) {
I->replaceAllUsesWith(NewC);
// Advance UI to the next non-I use to avoid invalidating it!
/// malloc, there is no reason to actually DO the malloc. Instead, turn the
/// malloc into a global, and any loads of GV as uses of the new global.
static GlobalVariable *OptimizeGlobalAddressOfMalloc(GlobalVariable *GV,
- MallocInst *MI) {
- DOUT << "PROMOTING MALLOC GLOBAL: " << *GV << " MALLOC = " << *MI;
- ConstantInt *NElements = cast<ConstantInt>(MI->getArraySize());
+ CallInst *CI,
+ BitCastInst *BCI,
+ Value* NElems,
+ LLVMContext &Context,
+ TargetData* TD) {
+ DEBUG(errs() << "PROMOTING MALLOC GLOBAL: " << *GV
+ << " CALL = " << *CI << " BCI = " << *BCI << '\n');
+ const Type *IntPtrTy = TD->getIntPtrType(Context);
+
+ ConstantInt *NElements = cast<ConstantInt>(NElems);
if (NElements->getZExtValue() != 1) {
// If we have an array allocation, transform it to a single element
// allocation to make the code below simpler.
- Type *NewTy = ArrayType::get(MI->getAllocatedType(),
+ Type *NewTy = ArrayType::get(getMallocAllocatedType(CI),
NElements->getZExtValue());
- MallocInst *NewMI =
- new MallocInst(NewTy, Constant::getNullValue(Type::Int32Ty),
- MI->getAlignment(), MI->getName(), MI);
+ Value* NewM = CallInst::CreateMalloc(CI, IntPtrTy, NewTy);
+ Instruction* NewMI = cast<Instruction>(NewM);
Value* Indices[2];
- Indices[0] = Indices[1] = Constant::getNullValue(Type::Int32Ty);
+ Indices[0] = Indices[1] = Constant::getNullValue(IntPtrTy);
Value *NewGEP = GetElementPtrInst::Create(NewMI, Indices, Indices + 2,
- NewMI->getName()+".el0", MI);
- MI->replaceAllUsesWith(NewGEP);
- MI->eraseFromParent();
- MI = NewMI;
+ NewMI->getName()+".el0", CI);
+ BCI->replaceAllUsesWith(NewGEP);
+ BCI->eraseFromParent();
+ CI->eraseFromParent();
+ BCI = cast<BitCastInst>(NewMI);
+ CI = extractMallocCallFromBitCast(NewMI);
}
// Create the new global variable. The contents of the malloc'd memory is
// undefined, so initialize with an undef value.
- Constant *Init = UndefValue::get(MI->getAllocatedType());
- GlobalVariable *NewGV = new GlobalVariable(MI->getAllocatedType(), false,
+ const Type *MAT = getMallocAllocatedType(CI);
+ Constant *Init = UndefValue::get(MAT);
+ GlobalVariable *NewGV = new GlobalVariable(*GV->getParent(),
+ MAT, false,
GlobalValue::InternalLinkage, Init,
GV->getName()+".body",
- (Module *)NULL,
+ GV,
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.
- MI->replaceAllUsesWith(NewGV);
+ BCI->replaceAllUsesWith(NewGV);
Constant *RepValue = NewGV;
if (NewGV->getType() != GV->getType()->getElementType())
// If there is a comparison against null, we will insert a global bool to
// keep track of whether the global was initialized yet or not.
GlobalVariable *InitBool =
- new GlobalVariable(Type::Int1Ty, false, GlobalValue::InternalLinkage,
- ConstantInt::getFalse(), GV->getName()+".init",
- (Module *)NULL, GV->isThreadLocal());
+ new GlobalVariable(Context, Type::getInt1Ty(Context), false,
+ GlobalValue::InternalLinkage,
+ ConstantInt::getFalse(Context), GV->getName()+".init",
+ GV->isThreadLocal());
bool InitBoolUsed = false;
// Loop over all uses of GV, processing them in turn.
if (!isa<ICmpInst>(LoadUse.getUser()))
LoadUse = RepValue;
else {
- ICmpInst *CI = cast<ICmpInst>(LoadUse.getUser());
+ ICmpInst *ICI = cast<ICmpInst>(LoadUse.getUser());
// Replace the cmp X, 0 with a use of the bool value.
- Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", CI);
+ Value *LV = new LoadInst(InitBool, InitBool->getName()+".val", ICI);
InitBoolUsed = true;
- switch (CI->getPredicate()) {
- default: assert(0 && "Unknown ICmp Predicate!");
+ switch (ICI->getPredicate()) {
+ default: llvm_unreachable("Unknown ICmp Predicate!");
case ICmpInst::ICMP_ULT:
case ICmpInst::ICMP_SLT:
- LV = ConstantInt::getFalse(); // X < null -> always false
+ LV = ConstantInt::getFalse(Context); // X < null -> always false
break;
case ICmpInst::ICMP_ULE:
case ICmpInst::ICMP_SLE:
case ICmpInst::ICMP_EQ:
- LV = BinaryOperator::CreateNot(LV, "notinit", CI);
+ LV = BinaryOperator::CreateNot(LV, "notinit", ICI);
break;
case ICmpInst::ICMP_NE:
case ICmpInst::ICMP_UGE:
case ICmpInst::ICMP_SGT:
break; // no change.
}
- CI->replaceAllUsesWith(LV);
- CI->eraseFromParent();
+ ICI->replaceAllUsesWith(LV);
+ ICI->eraseFromParent();
}
}
LI->eraseFromParent();
} else {
StoreInst *SI = cast<StoreInst>(GV->use_back());
// The global is initialized when the store to it occurs.
- new StoreInst(ConstantInt::getTrue(), InitBool, SI);
+ new StoreInst(ConstantInt::getTrue(Context), InitBool, SI);
SI->eraseFromParent();
}
// Now the GV is dead, nuke it and the malloc.
GV->eraseFromParent();
- MI->eraseFromParent();
+ BCI->eraseFromParent();
+ CI->eraseFromParent();
// To further other optimizations, loop over all users of NewGV and try to
// constant prop them. This will promote GEP instructions with constant
// indices into GEP constant-exprs, which will allow global-opt to hack on it.
- ConstantPropUsersOf(NewGV);
+ ConstantPropUsersOf(NewGV, Context);
if (RepValue != NewGV)
- ConstantPropUsersOf(RepValue);
+ ConstantPropUsersOf(RepValue, Context);
return NewGV;
}
GlobalVariable *GV,
SmallPtrSet<PHINode*, 8> &PHIs) {
for (Value::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
- Instruction *Inst = dyn_cast<Instruction>(*UI);
- if (Inst == 0) return false;
+ Instruction *Inst = cast<Instruction>(*UI);
if (isa<LoadInst>(Inst) || isa<CmpInst>(Inst)) {
continue; // Fine, ignore.
/// 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(Value *V,
- SmallPtrSet<PHINode*, 32> &LoadUsingPHIs) {
+ SmallPtrSet<PHINode*, 32> &LoadUsingPHIs,
+ SmallPtrSet<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::use_iterator UI = V->use_begin(), E = V->use_end(); UI != E;++UI){
}
if (PHINode *PN = dyn_cast<PHINode>(User)) {
- // If we have already recursively analyzed this PHI, then it is safe.
- if (LoadUsingPHIs.insert(PN))
+ if (!LoadUsingPHIsPerLoad.insert(PN))
+ // This means some phi nodes are dependent on each other.
+ // Avoid infinite looping!
+ return false;
+ if (!LoadUsingPHIs.insert(PN))
+ // If we have already analyzed this PHI, then it is safe.
continue;
// Make sure all uses of the PHI are simple enough to transform.
- if (!LoadUsesSimpleEnoughForHeapSRA(PN, LoadUsingPHIs))
+ if (!LoadUsesSimpleEnoughForHeapSRA(PN,
+ LoadUsingPHIs, LoadUsingPHIsPerLoad))
return false;
continue;
/// AllGlobalLoadUsesSimpleEnoughForHeapSRA - If all users of values loaded from
/// GV are simple enough to perform HeapSRA, return true.
static bool AllGlobalLoadUsesSimpleEnoughForHeapSRA(GlobalVariable *GV,
- MallocInst *MI) {
+ Instruction *StoredVal) {
SmallPtrSet<PHINode*, 32> LoadUsingPHIs;
+ SmallPtrSet<PHINode*, 32> LoadUsingPHIsPerLoad;
for (Value::use_iterator UI = GV->use_begin(), E = GV->use_end(); UI != E;
++UI)
- if (LoadInst *LI = dyn_cast<LoadInst>(*UI))
- if (!LoadUsesSimpleEnoughForHeapSRA(LI, LoadUsingPHIs))
+ if (LoadInst *LI = dyn_cast<LoadInst>(*UI)) {
+ if (!LoadUsesSimpleEnoughForHeapSRA(LI, LoadUsingPHIs,
+ LoadUsingPHIsPerLoad))
return false;
+ LoadUsingPHIsPerLoad.clear();
+ }
// If we reach here, we know that all uses of the loads and transitive uses
// (through PHI nodes) are simple enough to transform. However, we don't know
Value *InVal = PN->getIncomingValue(op);
// PHI of the stored value itself is ok.
- if (InVal == MI) continue;
+ if (InVal == StoredVal) continue;
if (PHINode *InPN = dyn_cast<PHINode>(InVal)) {
// One of the PHIs in our set is (optimistically) ok.
static Value *GetHeapSROAValue(Value *V, unsigned FieldNo,
DenseMap<Value*, std::vector<Value*> > &InsertedScalarizedValues,
- std::vector<std::pair<PHINode*, unsigned> > &PHIsToRewrite) {
+ std::vector<std::pair<PHINode*, unsigned> > &PHIsToRewrite,
+ LLVMContext &Context) {
std::vector<Value*> &FieldVals = InsertedScalarizedValues[V];
if (FieldNo >= FieldVals.size())
// a new Load of the scalarized global.
Result = new LoadInst(GetHeapSROAValue(LI->getOperand(0), FieldNo,
InsertedScalarizedValues,
- PHIsToRewrite),
- LI->getName()+".f" + utostr(FieldNo), LI);
+ PHIsToRewrite, Context),
+ LI->getName()+".f"+Twine(FieldNo), LI);
} else if (PHINode *PN = dyn_cast<PHINode>(V)) {
// PN's type is pointer to struct. Make a new PHI of pointer to struct
// field.
const StructType *ST =
cast<StructType>(cast<PointerType>(PN->getType())->getElementType());
- Result =PHINode::Create(PointerType::getUnqual(ST->getElementType(FieldNo)),
- PN->getName()+".f"+utostr(FieldNo), PN);
+ Result =
+ PHINode::Create(PointerType::getUnqual(ST->getElementType(FieldNo)),
+ PN->getName()+".f"+Twine(FieldNo), PN);
PHIsToRewrite.push_back(std::make_pair(PN, FieldNo));
} else {
- assert(0 && "Unknown usable value");
+ llvm_unreachable("Unknown usable value");
Result = 0;
}
/// the load, rewrite the derived value to use the HeapSRoA'd load.
static void RewriteHeapSROALoadUser(Instruction *LoadUser,
DenseMap<Value*, std::vector<Value*> > &InsertedScalarizedValues,
- std::vector<std::pair<PHINode*, unsigned> > &PHIsToRewrite) {
+ std::vector<std::pair<PHINode*, unsigned> > &PHIsToRewrite,
+ LLVMContext &Context) {
// 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 = GetHeapSROAValue(SCI->getOperand(0), 0,
- InsertedScalarizedValues, PHIsToRewrite);
+ InsertedScalarizedValues, PHIsToRewrite,
+ Context);
- Value *New = new ICmpInst(SCI->getPredicate(), NPtr,
- Constant::getNullValue(NPtr->getType()),
- SCI->getName(), SCI);
+ Value *New = new ICmpInst(SCI, SCI->getPredicate(), NPtr,
+ Constant::getNullValue(NPtr->getType()),
+ SCI->getName());
SCI->replaceAllUsesWith(New);
SCI->eraseFromParent();
return;
// Load the pointer for this field.
unsigned FieldNo = cast<ConstantInt>(GEPI->getOperand(2))->getZExtValue();
Value *NewPtr = GetHeapSROAValue(GEPI->getOperand(0), FieldNo,
- InsertedScalarizedValues, PHIsToRewrite);
+ InsertedScalarizedValues, PHIsToRewrite,
+ Context);
// Create the new GEP idx vector.
SmallVector<Value*, 8> GEPIdx;
// users.
for (Value::use_iterator UI = PN->use_begin(), E = PN->use_end(); UI != E; ) {
Instruction *User = cast<Instruction>(*UI++);
- RewriteHeapSROALoadUser(User, InsertedScalarizedValues, PHIsToRewrite);
+ RewriteHeapSROALoadUser(User, InsertedScalarizedValues, PHIsToRewrite,
+ Context);
}
}
/// AllGlobalLoadUsesSimpleEnoughForHeapSRA.
static void RewriteUsesOfLoadForHeapSRoA(LoadInst *Load,
DenseMap<Value*, std::vector<Value*> > &InsertedScalarizedValues,
- std::vector<std::pair<PHINode*, unsigned> > &PHIsToRewrite) {
+ std::vector<std::pair<PHINode*, unsigned> > &PHIsToRewrite,
+ LLVMContext &Context) {
for (Value::use_iterator UI = Load->use_begin(), E = Load->use_end();
UI != E; ) {
Instruction *User = cast<Instruction>(*UI++);
- RewriteHeapSROALoadUser(User, InsertedScalarizedValues, PHIsToRewrite);
+ RewriteHeapSROALoadUser(User, InsertedScalarizedValues, PHIsToRewrite,
+ Context);
}
if (Load->use_empty()) {
}
}
-/// PerformHeapAllocSRoA - MI is an allocation of an array of structures. Break
+/// PerformHeapAllocSRoA - CI is an allocation of an array of structures. Break
/// it up into multiple allocations of arrays of the fields.
-static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV, MallocInst *MI){
- DOUT << "SROA HEAP ALLOC: " << *GV << " MALLOC = " << *MI;
- const StructType *STy = cast<StructType>(MI->getAllocatedType());
+static GlobalVariable *PerformHeapAllocSRoA(GlobalVariable *GV,
+ CallInst *CI, BitCastInst* BCI,
+ Value* NElems,
+ LLVMContext &Context,
+ TargetData *TD) {
+ DEBUG(errs() << "SROA HEAP ALLOC: " << *GV << " MALLOC CALL = " << *CI
+ << " BITCAST = " << *BCI << '\n');
+ const Type* MAT = getMallocAllocatedType(CI);
+ const StructType *STy = cast<StructType>(MAT);
// There is guaranteed to be at least one use of the malloc (storing
// it into GV). If there are other uses, change them to be uses of
// the global to simplify later code. This also deletes the store
// into GV.
- ReplaceUsesOfMallocWithGlobal(MI, GV);
+ ReplaceUsesOfMallocWithGlobal(BCI, GV);
// Okay, at this point, there are no users of the malloc. Insert N
- // new mallocs at the same place as MI, and N globals.
+ // new mallocs at the same place as CI, and N globals.
std::vector<Value*> FieldGlobals;
- std::vector<MallocInst*> FieldMallocs;
+ std::vector<Value*> FieldMallocs;
for (unsigned FieldNo = 0, e = STy->getNumElements(); FieldNo != e;++FieldNo){
const Type *FieldTy = STy->getElementType(FieldNo);
- const Type *PFieldTy = PointerType::getUnqual(FieldTy);
+ const PointerType *PFieldTy = PointerType::getUnqual(FieldTy);
GlobalVariable *NGV =
- new GlobalVariable(PFieldTy, false, GlobalValue::InternalLinkage,
+ new GlobalVariable(*GV->getParent(),
+ PFieldTy, false, GlobalValue::InternalLinkage,
Constant::getNullValue(PFieldTy),
- GV->getName() + ".f" + utostr(FieldNo), GV,
+ GV->getName() + ".f" + Twine(FieldNo), GV,
GV->isThreadLocal());
FieldGlobals.push_back(NGV);
- MallocInst *NMI = new MallocInst(FieldTy, MI->getArraySize(),
- MI->getName() + ".f" + utostr(FieldNo),MI);
+ Value *NMI = CallInst::CreateMalloc(CI, TD->getIntPtrType(Context),
+ FieldTy, NElems,
+ BCI->getName() + ".f" + Twine(FieldNo));
FieldMallocs.push_back(NMI);
- new StoreInst(NMI, NGV, MI);
+ new StoreInst(NMI, NGV, BCI);
}
// The tricky aspect of this transformation is handling the case when malloc
// }
Value *RunningOr = 0;
for (unsigned i = 0, e = FieldMallocs.size(); i != e; ++i) {
- Value *Cond = new ICmpInst(ICmpInst::ICMP_EQ, FieldMallocs[i],
- Constant::getNullValue(FieldMallocs[i]->getType()),
- "isnull", MI);
+ Value *Cond = new ICmpInst(BCI, ICmpInst::ICMP_EQ, FieldMallocs[i],
+ Constant::getNullValue(FieldMallocs[i]->getType()),
+ "isnull");
if (!RunningOr)
RunningOr = Cond; // First seteq
else
- RunningOr = BinaryOperator::CreateOr(RunningOr, Cond, "tmp", MI);
+ RunningOr = BinaryOperator::CreateOr(RunningOr, Cond, "tmp", BCI);
}
// Split the basic block at the old malloc.
- BasicBlock *OrigBB = MI->getParent();
- BasicBlock *ContBB = OrigBB->splitBasicBlock(MI, "malloc_cont");
+ BasicBlock *OrigBB = BCI->getParent();
+ BasicBlock *ContBB = OrigBB->splitBasicBlock(BCI, "malloc_cont");
// 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 = BasicBlock::Create("malloc_ret_null",
+ BasicBlock *NullPtrBlock = BasicBlock::Create(Context, "malloc_ret_null",
OrigBB->getParent());
// Remove the uncond branch from OrigBB to ContBB, turning it into a cond
// pointer, because some may be null while others are not.
for (unsigned i = 0, e = FieldGlobals.size(); i != e; ++i) {
Value *GVVal = new LoadInst(FieldGlobals[i], "tmp", NullPtrBlock);
- Value *Cmp = new ICmpInst(ICmpInst::ICMP_NE, GVVal,
+ Value *Cmp = new ICmpInst(*NullPtrBlock, ICmpInst::ICMP_NE, GVVal,
Constant::getNullValue(GVVal->getType()),
- "tmp", NullPtrBlock);
- BasicBlock *FreeBlock = BasicBlock::Create("free_it", OrigBB->getParent());
- BasicBlock *NextBlock = BasicBlock::Create("next", OrigBB->getParent());
- BranchInst::Create(FreeBlock, NextBlock, Cmp, NullPtrBlock);
+ "tmp");
+ BasicBlock *FreeBlock = BasicBlock::Create(Context, "free_it",
+ OrigBB->getParent());
+ BasicBlock *NextBlock = BasicBlock::Create(Context, "next",
+ OrigBB->getParent());
+ Instruction *BI = BranchInst::Create(FreeBlock, NextBlock,
+ Cmp, NullPtrBlock);
// Fill in FreeBlock.
- new FreeInst(GVVal, FreeBlock);
+ CallInst::CreateFree(GVVal, BI);
new StoreInst(Constant::getNullValue(GVVal->getType()), FieldGlobals[i],
FreeBlock);
BranchInst::Create(NextBlock, FreeBlock);
BranchInst::Create(ContBB, NullPtrBlock);
- // MI is no longer needed, remove it.
- MI->eraseFromParent();
+ // CI and BCI are no longer needed, remove them.
+ BCI->eraseFromParent();
+ CI->eraseFromParent();
/// InsertedScalarizedLoads - As we process loads, if we can't immediately
/// update all uses of the load, keep track of what scalarized loads are
Instruction *User = cast<Instruction>(*UI++);
if (LoadInst *LI = dyn_cast<LoadInst>(User)) {
- RewriteUsesOfLoadForHeapSRoA(LI, InsertedScalarizedValues, PHIsToRewrite);
+ RewriteUsesOfLoadForHeapSRoA(LI, InsertedScalarizedValues, PHIsToRewrite,
+ Context);
continue;
}
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
Value *InVal = PN->getIncomingValue(i);
InVal = GetHeapSROAValue(InVal, FieldNo, InsertedScalarizedValues,
- PHIsToRewrite);
+ PHIsToRewrite, Context);
FieldPN->addIncoming(InVal, PN->getIncomingBlock(i));
}
}
/// pointer global variable with a single value stored it that is a malloc or
/// cast of malloc.
static bool TryToOptimizeStoreOfMallocToGlobal(GlobalVariable *GV,
- MallocInst *MI,
+ CallInst *CI,
+ BitCastInst *BCI,
Module::global_iterator &GVI,
- TargetData &TD) {
+ TargetData *TD,
+ LLVMContext &Context) {
+ // If we can't figure out the type being malloced, then we can't optimize.
+ const Type *AllocTy = getMallocAllocatedType(CI);
+ assert(AllocTy);
+
// If this is a malloc of an abstract type, don't touch it.
- if (!MI->getAllocatedType()->isSized())
+ if (!AllocTy->isSized())
return false;
-
+
// We can't optimize this global unless all uses of it are *known* to be
// of the malloc value, not of the null initializer value (consider a use
// that compares the global's value against zero to see if the malloc has
// happen after the malloc.
if (!AllUsesOfLoadedValueWillTrapIfNull(GV))
return false;
-
+
// We can't optimize this if the malloc itself is used in a complex way,
// for example, being stored into multiple globals. This allows the
// malloc to be stored into the specified global, loaded setcc'd, and
// for.
{
SmallPtrSet<PHINode*, 8> PHIs;
- if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(MI, GV, PHIs))
+ if (!ValueIsOnlyUsedLocallyOrStoredToOneGlobal(BCI, 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.
- if (ConstantInt *NElements = dyn_cast<ConstantInt>(MI->getArraySize())) {
- // 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.getTypePaddedSize(MI->getAllocatedType()) < 2048) {
- GVI = OptimizeGlobalAddressOfMalloc(GV, MI);
- return true;
- }
- }
+ Value *NElems = getMallocArraySize(CI, Context, TD);
+ // We cannot optimize the malloc if we cannot determine malloc array size.
+ if (NElems) {
+ 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, BCI, NElems, Context, 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.
- const Type *AllocTy = MI->getAllocatedType();
-
- // 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 (!MI->isArrayAllocation())
- 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, MI)) {
+ // 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, BCI)) {
+
+ // 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))) {
+ Value* NumElements = ConstantInt::get(Type::getInt32Ty(Context),
+ AT->getNumElements());
+ Value* NewMI = CallInst::CreateMalloc(CI, TD->getIntPtrType(Context),
+ AllocSTy, NumElements,
+ BCI->getName());
+ Value *Cast = new BitCastInst(NewMI, getMallocType(CI), "tmp", CI);
+ BCI->replaceAllUsesWith(Cast);
+ BCI->eraseFromParent();
+ CI->eraseFromParent();
+ BCI = cast<BitCastInst>(NewMI);
+ CI = extractMallocCallFromBitCast(NewMI);
+ }
- // 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>(MI->getAllocatedType())) {
- MallocInst *NewMI =
- new MallocInst(AllocSTy,
- ConstantInt::get(Type::Int32Ty, AT->getNumElements()),
- "", MI);
- NewMI->takeName(MI);
- Value *Cast = new BitCastInst(NewMI, MI->getType(), "tmp", MI);
- MI->replaceAllUsesWith(Cast);
- MI->eraseFromParent();
- MI = NewMI;
+ GVI = PerformHeapAllocSRoA(GV, CI, BCI, NElems, Context, TD);
+ return true;
}
-
- GVI = PerformHeapAllocSRoA(GV, MI);
- return true;
}
}
// that only one value (besides its initializer) is ever stored to the global.
static bool OptimizeOnceStoredGlobal(GlobalVariable *GV, Value *StoredOnceVal,
Module::global_iterator &GVI,
- TargetData &TD) {
+ TargetData *TD, LLVMContext &Context) {
// Ignore no-op GEPs and bitcasts.
StoredOnceVal = StoredOnceVal->stripPointerCasts();
GV->getInitializer()->isNullValue()) {
if (Constant *SOVC = dyn_cast<Constant>(StoredOnceVal)) {
if (GV->getInitializer()->getType() != SOVC->getType())
- SOVC = ConstantExpr::getBitCast(SOVC, GV->getInitializer()->getType());
+ SOVC =
+ ConstantExpr::getBitCast(SOVC, GV->getInitializer()->getType());
// Optimize away any trapping uses of the loaded value.
- if (OptimizeAwayTrappingUsesOfLoads(GV, SOVC))
- return true;
- } else if (MallocInst *MI = dyn_cast<MallocInst>(StoredOnceVal)) {
- if (TryToOptimizeStoreOfMallocToGlobal(GV, MI, GVI, TD))
+ if (OptimizeAwayTrappingUsesOfLoads(GV, SOVC, Context))
return true;
+ } else if (CallInst *CI = extractMallocCall(StoredOnceVal)) {
+ if (getMallocAllocatedType(CI)) {
+ BitCastInst* BCI = NULL;
+ for (Value::use_iterator UI = CI->use_begin(), E = CI->use_end();
+ UI != E; )
+ BCI = dyn_cast<BitCastInst>(cast<Instruction>(*UI++));
+ if (BCI &&
+ TryToOptimizeStoreOfMallocToGlobal(GV, CI, BCI, GVI, TD, Context))
+ return true;
+ }
}
}
/// 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) {
+static bool TryToShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal,
+ LLVMContext &Context) {
const Type *GVElType = GV->getType()->getElementType();
// If GVElType is already i1, it is already shrunk. If the type of the GV is
// between them is very expensive and unlikely to lead to later
// simplification. In these cases, we typically end up with "cond ? v1 : v2"
// where v1 and v2 both require constant pool loads, a big loss.
- if (GVElType == Type::Int1Ty || GVElType->isFloatingPoint() ||
+ if (GVElType == Type::getInt1Ty(Context) || GVElType->isFloatingPoint() ||
isa<PointerType>(GVElType) || isa<VectorType>(GVElType))
return false;
if (!isa<LoadInst>(I) && !isa<StoreInst>(I))
return false;
- DOUT << " *** SHRINKING TO BOOL: " << *GV;
+ DEBUG(errs() << " *** SHRINKING TO BOOL: " << *GV);
// Create the new global, initializing it to false.
- GlobalVariable *NewGV = new GlobalVariable(Type::Int1Ty, false,
- GlobalValue::InternalLinkage, ConstantInt::getFalse(),
+ GlobalVariable *NewGV = new GlobalVariable(Context,
+ Type::getInt1Ty(Context), false,
+ GlobalValue::InternalLinkage, ConstantInt::getFalse(Context),
GV->getName()+".b",
- (Module *)NULL,
GV->isThreadLocal());
GV->getParent()->getGlobalList().insert(GV, NewGV);
Constant *InitVal = GV->getInitializer();
- assert(InitVal->getType() != Type::Int1Ty && "No reason to shrink to bool!");
+ assert(InitVal->getType() != Type::getInt1Ty(Context) &&
+ "No reason to shrink to bool!");
// If initialized to zero and storing one into the global, we can use a cast
// instead of a select to synthesize the desired value.
// Only do this if we weren't storing a loaded value.
Value *StoreVal;
if (StoringOther || SI->getOperand(0) == InitVal)
- StoreVal = ConstantInt::get(Type::Int1Ty, StoringOther);
+ StoreVal = ConstantInt::get(Type::getInt1Ty(Context), StoringOther);
else {
// Otherwise, we are storing a previously loaded copy. To do this,
// change the copy from copying the original value to just copying the
GV->removeDeadConstantUsers();
if (GV->use_empty()) {
- DOUT << "GLOBAL DEAD: " << *GV;
+ DEBUG(errs() << "GLOBAL DEAD: " << *GV);
GV->eraseFromParent();
++NumDeleted;
return true;
//
// NOTE: It doesn't make sense to promote non single-value types since we
// are just replacing static memory to stack memory.
+ //
+ // If the global is in different address space, don't bring it to stack.
if (!GS.HasMultipleAccessingFunctions &&
GS.AccessingFunction && !GS.HasNonInstructionUser &&
GV->getType()->getElementType()->isSingleValueType() &&
GS.AccessingFunction->getName() == "main" &&
- GS.AccessingFunction->hasExternalLinkage()) {
- DOUT << "LOCALIZING GLOBAL: " << *GV;
+ GS.AccessingFunction->hasExternalLinkage() &&
+ GV->getType()->getAddressSpace() == 0) {
+ DEBUG(errs() << "LOCALIZING GLOBAL: " << *GV);
Instruction* FirstI = GS.AccessingFunction->getEntryBlock().begin();
const Type* ElemTy = GV->getType()->getElementType();
// FIXME: Pass Global's alignment when globals have alignment
// If the global is never loaded (but may be stored to), it is dead.
// Delete it now.
if (!GS.isLoaded) {
- DOUT << "GLOBAL NEVER LOADED: " << *GV;
+ DEBUG(errs() << "GLOBAL NEVER LOADED: " << *GV);
// Delete any stores we can find to the global. We may not be able to
// make it completely dead though.
- bool Changed = CleanupConstantGlobalUsers(GV, GV->getInitializer());
+ bool Changed = CleanupConstantGlobalUsers(GV, GV->getInitializer(),
+ GV->getContext());
// If the global is dead now, delete it.
if (GV->use_empty()) {
return Changed;
} else if (GS.StoredType <= GlobalStatus::isInitializerStored) {
- DOUT << "MARKING CONSTANT: " << *GV;
+ DEBUG(errs() << "MARKING CONSTANT: " << *GV);
GV->setConstant(true);
// Clean up any obviously simplifiable users now.
- CleanupConstantGlobalUsers(GV, GV->getInitializer());
+ CleanupConstantGlobalUsers(GV, GV->getInitializer(), GV->getContext());
// If the global is dead now, just nuke it.
if (GV->use_empty()) {
- DOUT << " *** Marking constant allowed us to simplify "
- << "all users and delete global!\n";
+ DEBUG(errs() << " *** Marking constant allowed us to simplify "
+ << "all users and delete global!\n");
GV->eraseFromParent();
++NumDeleted;
}
++NumMarked;
return true;
} else if (!GV->getInitializer()->getType()->isSingleValueType()) {
- if (GlobalVariable *FirstNewGV = SRAGlobal(GV,
- getAnalysis<TargetData>())) {
- GVI = FirstNewGV; // Don't skip the newly produced globals!
- return true;
- }
+ if (TargetData *TD = getAnalysisIfAvailable<TargetData>())
+ if (GlobalVariable *FirstNewGV = SRAGlobal(GV, *TD,
+ GV->getContext())) {
+ GVI = FirstNewGV; // Don't skip the newly produced globals!
+ return true;
+ }
} else if (GS.StoredType == GlobalStatus::isStoredOnce) {
// If the initial value for the global was an undef value, and if only
// one other value was stored into it, we can just change the
GV->setInitializer(SOVConstant);
// Clean up any obviously simplifiable users now.
- CleanupConstantGlobalUsers(GV, GV->getInitializer());
+ CleanupConstantGlobalUsers(GV, GV->getInitializer(),
+ GV->getContext());
if (GV->use_empty()) {
- DOUT << " *** Substituting initializer allowed us to "
- << "simplify all users and delete global!\n";
+ DEBUG(errs() << " *** Substituting initializer allowed us to "
+ << "simplify all users and delete global!\n");
GV->eraseFromParent();
++NumDeleted;
} else {
// Try to optimize globals based on the knowledge that only one value
// (besides its initializer) is ever stored to the global.
if (OptimizeOnceStoredGlobal(GV, GS.StoredOnceValue, GVI,
- getAnalysis<TargetData>()))
+ getAnalysisIfAvailable<TargetData>(),
+ GV->getContext()))
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 (TryToShrinkGlobalToBoolean(GV, SOVConstant)) {
+ if (TryToShrinkGlobalToBoolean(GV, SOVConstant, GV->getContext())) {
++NumShrunkToBool;
return true;
}
return false;
}
-/// OnlyCalledDirectly - Return true if the specified function is only called
-/// directly. In other words, its address is never taken.
-static bool OnlyCalledDirectly(Function *F) {
- for (Value::use_iterator UI = F->use_begin(), E = F->use_end(); UI != E;++UI){
- Instruction *User = dyn_cast<Instruction>(*UI);
- if (!User) return false;
- if (!isa<CallInst>(User) && !isa<InvokeInst>(User)) return false;
-
- // See if the function address is passed as an argument.
- for (User::op_iterator i = User->op_begin() + 1, e = User->op_end();
- i != e; ++i)
- if (*i == F) return false;
- }
- return true;
-}
-
/// ChangeCalleesToFastCall - Walk all of the direct calls of the specified
/// function, changing them to FastCC.
static void ChangeCalleesToFastCall(Function *F) {
++NumFnDeleted;
} else if (F->hasLocalLinkage()) {
if (F->getCallingConv() == CallingConv::C && !F->isVarArg() &&
- OnlyCalledDirectly(F)) {
+ !F->hasAddressTaken()) {
// 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.
}
if (F->getAttributes().hasAttrSomewhere(Attribute::Nest) &&
- OnlyCalledDirectly(F)) {
+ !F->hasAddressTaken()) {
// The function is not used by a trampoline intrinsic, so it is safe
// to remove the 'nest' attribute.
RemoveNestAttribute(F);
if (!ATy) return 0;
const StructType *STy = dyn_cast<StructType>(ATy->getElementType());
if (!STy || STy->getNumElements() != 2 ||
- STy->getElementType(0) != Type::Int32Ty) return 0;
+ STy->getElementType(0) != Type::getInt32Ty(M.getContext())) return 0;
const PointerType *PFTy = dyn_cast<PointerType>(STy->getElementType(1));
if (!PFTy) return 0;
const FunctionType *FTy = dyn_cast<FunctionType>(PFTy->getElementType());
- if (!FTy || FTy->getReturnType() != Type::VoidTy || FTy->isVarArg() ||
- FTy->getNumParams() != 0)
+ if (!FTy || FTy->getReturnType() != Type::getVoidTy(M.getContext()) ||
+ FTy->isVarArg() || FTy->getNumParams() != 0)
return 0;
// Verify that the initializer is simple enough for us to handle.
- if (!I->hasInitializer()) return 0;
+ if (!I->hasDefinitiveInitializer()) return 0;
ConstantArray *CA = dyn_cast<ConstantArray>(I->getInitializer());
if (!CA) return 0;
for (User::op_iterator i = CA->op_begin(), e = CA->op_end(); i != e; ++i)
/// InstallGlobalCtors - Given a specified llvm.global_ctors list, install the
/// specified array, returning the new global to use.
static GlobalVariable *InstallGlobalCtors(GlobalVariable *GCL,
- const std::vector<Function*> &Ctors) {
+ const std::vector<Function*> &Ctors,
+ LLVMContext &Context) {
// If we made a change, reassemble the initializer list.
std::vector<Constant*> CSVals;
- CSVals.push_back(ConstantInt::get(Type::Int32Ty, 65535));
+ CSVals.push_back(ConstantInt::get(Type::getInt32Ty(Context), 65535));
CSVals.push_back(0);
// Create the new init list.
if (Ctors[i]) {
CSVals[1] = Ctors[i];
} else {
- const Type *FTy = FunctionType::get(Type::VoidTy,
- std::vector<const Type*>(), false);
+ const Type *FTy = FunctionType::get(Type::getVoidTy(Context), false);
const PointerType *PFTy = PointerType::getUnqual(FTy);
CSVals[1] = Constant::getNullValue(PFTy);
- CSVals[0] = ConstantInt::get(Type::Int32Ty, 2147483647);
+ CSVals[0] = ConstantInt::get(Type::getInt32Ty(Context), 2147483647);
}
- CAList.push_back(ConstantStruct::get(CSVals));
+ CAList.push_back(ConstantStruct::get(Context, CSVals, false));
}
// Create the array initializer.
const Type *StructTy =
- cast<ArrayType>(GCL->getType()->getElementType())->getElementType();
- Constant *CA = ConstantArray::get(ArrayType::get(StructTy, CAList.size()),
- CAList);
+ cast<ArrayType>(GCL->getType()->getElementType())->getElementType();
+ Constant *CA = ConstantArray::get(ArrayType::get(StructTy,
+ CAList.size()), CAList);
// If we didn't change the number of elements, don't create a new GV.
if (CA->getType() == GCL->getInitializer()->getType()) {
}
// Create the new global and insert it next to the existing list.
- GlobalVariable *NGV = new GlobalVariable(CA->getType(), GCL->isConstant(),
+ GlobalVariable *NGV = new GlobalVariable(Context, CA->getType(),
+ GCL->isConstant(),
GCL->getLinkage(), CA, "",
- (Module *)NULL,
GCL->isThreadLocal());
GCL->getParent()->getGlobalList().insert(GCL, NGV);
NGV->takeName(GCL);
/// enough for us to understand. In particular, if it is a cast of something,
/// we punt. We basically just support direct accesses to globals and GEP's of
/// globals. This should be kept up to date with CommitValueTo.
-static bool isSimpleEnoughPointerToCommit(Constant *C) {
- if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
- if (!GV->hasExternalLinkage() && !GV->hasLocalLinkage())
- return false; // do not allow weak/linkonce/dllimport/dllexport linkage.
- return !GV->isDeclaration(); // reject external globals.
- }
+static bool isSimpleEnoughPointerToCommit(Constant *C, LLVMContext &Context) {
+ // Conservatively, avoid aggregate types. This is because we don't
+ // want to worry about them partially overlapping other stores.
+ if (!cast<PointerType>(C->getType())->getElementType()->isSingleValueType())
+ return false;
+
+ if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C))
+ // Do not allow weak/linkonce/dllimport/dllexport linkage or
+ // external globals.
+ return GV->hasDefinitiveInitializer();
+
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
// Handle a constantexpr gep.
if (CE->getOpcode() == Instruction::GetElementPtr &&
- isa<GlobalVariable>(CE->getOperand(0))) {
+ isa<GlobalVariable>(CE->getOperand(0)) &&
+ cast<GEPOperator>(CE)->isInBounds()) {
GlobalVariable *GV = cast<GlobalVariable>(CE->getOperand(0));
- if (!GV->hasExternalLinkage() && !GV->hasLocalLinkage())
- return false; // do not allow weak/linkonce/dllimport/dllexport linkage.
- return GV->hasInitializer() &&
- ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE);
+ // Do not allow weak/linkonce/dllimport/dllexport linkage or
+ // external globals.
+ if (!GV->hasDefinitiveInitializer())
+ return false;
+
+ // The first index must be zero.
+ ConstantInt *CI = dyn_cast<ConstantInt>(*next(CE->op_begin()));
+ if (!CI || !CI->isZero()) return false;
+
+ // The remaining indices must be compile-time known integers within the
+ // notional bounds of the corresponding static array types.
+ if (!CE->isGEPWithNoNotionalOverIndexing())
+ return false;
+
+ return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE);
}
return false;
}
/// initializer. This returns 'Init' modified to reflect 'Val' stored into it.
/// At this point, the GEP operands of Addr [0, OpNo) have been stepped into.
static Constant *EvaluateStoreInto(Constant *Init, Constant *Val,
- ConstantExpr *Addr, unsigned OpNo) {
+ ConstantExpr *Addr, unsigned OpNo,
+ LLVMContext &Context) {
// Base case of the recursion.
if (OpNo == Addr->getNumOperands()) {
assert(Val->getType() == Init->getType() && "Type mismatch!");
for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
Elts.push_back(UndefValue::get(STy->getElementType(i)));
} else {
- assert(0 && "This code is out of sync with "
+ llvm_unreachable("This code is out of sync with "
" ConstantFoldLoadThroughGEPConstantExpr");
}
ConstantInt *CU = cast<ConstantInt>(Addr->getOperand(OpNo));
unsigned Idx = CU->getZExtValue();
assert(Idx < STy->getNumElements() && "Struct index out of range!");
- Elts[Idx] = EvaluateStoreInto(Elts[Idx], Val, Addr, OpNo+1);
+ Elts[Idx] = EvaluateStoreInto(Elts[Idx], Val, Addr, OpNo+1, Context);
// Return the modified struct.
- return ConstantStruct::get(&Elts[0], Elts.size(), STy->isPacked());
+ return ConstantStruct::get(Context, &Elts[0], Elts.size(), STy->isPacked());
} else {
ConstantInt *CI = cast<ConstantInt>(Addr->getOperand(OpNo));
const ArrayType *ATy = cast<ArrayType>(Init->getType());
Constant *Elt = UndefValue::get(ATy->getElementType());
Elts.assign(ATy->getNumElements(), Elt);
} else {
- assert(0 && "This code is out of sync with "
+ llvm_unreachable("This code is out of sync with "
" ConstantFoldLoadThroughGEPConstantExpr");
}
assert(CI->getZExtValue() < ATy->getNumElements());
Elts[CI->getZExtValue()] =
- EvaluateStoreInto(Elts[CI->getZExtValue()], Val, Addr, OpNo+1);
+ EvaluateStoreInto(Elts[CI->getZExtValue()], Val, Addr, OpNo+1, Context);
return ConstantArray::get(ATy, Elts);
}
}
/// CommitValueTo - We have decided that Addr (which satisfies the predicate
/// isSimpleEnoughPointerToCommit) should get Val as its value. Make it happen.
-static void CommitValueTo(Constant *Val, Constant *Addr) {
+static void CommitValueTo(Constant *Val, Constant *Addr,
+ LLVMContext &Context) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Addr)) {
assert(GV->hasInitializer());
GV->setInitializer(Val);
GlobalVariable *GV = cast<GlobalVariable>(CE->getOperand(0));
Constant *Init = GV->getInitializer();
- Init = EvaluateStoreInto(Init, Val, CE, 2);
+ Init = EvaluateStoreInto(Init, Val, CE, 2, Context);
GV->setInitializer(Init);
}
/// P after the stores reflected by 'memory' have been performed. If we can't
/// decide, return null.
static Constant *ComputeLoadResult(Constant *P,
- const DenseMap<Constant*, Constant*> &Memory) {
+ const DenseMap<Constant*, Constant*> &Memory,
+ LLVMContext &Context) {
// If this memory location has been recently stored, use the stored value: it
// is the most up-to-date.
DenseMap<Constant*, Constant*>::const_iterator I = Memory.find(P);
// Access it.
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(P)) {
- if (GV->hasInitializer())
+ if (GV->hasDefinitiveInitializer())
return GV->getInitializer();
return 0;
}
if (CE->getOpcode() == Instruction::GetElementPtr &&
isa<GlobalVariable>(CE->getOperand(0))) {
GlobalVariable *GV = cast<GlobalVariable>(CE->getOperand(0));
- if (GV->hasInitializer())
+ if (GV->hasDefinitiveInitializer())
return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE);
}
/// successful, false if we can't evaluate it. ActualArgs contains the formal
/// arguments for the function.
static bool EvaluateFunction(Function *F, Constant *&RetVal,
- const std::vector<Constant*> &ActualArgs,
+ const SmallVectorImpl<Constant*> &ActualArgs,
std::vector<Function*> &CallStack,
DenseMap<Constant*, Constant*> &MutatedMemory,
std::vector<GlobalVariable*> &AllocaTmps) {
if (std::find(CallStack.begin(), CallStack.end(), F) != CallStack.end())
return false;
+ LLVMContext &Context = F->getContext();
+
CallStack.push_back(F);
/// Values - As we compute SSA register values, we store their contents here.
if (StoreInst *SI = dyn_cast<StoreInst>(CurInst)) {
if (SI->isVolatile()) return false; // no volatile accesses.
Constant *Ptr = getVal(Values, SI->getOperand(1));
- if (!isSimpleEnoughPointerToCommit(Ptr))
+ if (!isSimpleEnoughPointerToCommit(Ptr, Context))
// If this is too complex for us to commit, reject it.
return false;
Constant *Val = getVal(Values, SI->getOperand(0));
getVal(Values, CI->getOperand(0)),
CI->getType());
} else if (SelectInst *SI = dyn_cast<SelectInst>(CurInst)) {
- InstResult = ConstantExpr::getSelect(getVal(Values, SI->getOperand(0)),
+ InstResult =
+ ConstantExpr::getSelect(getVal(Values, SI->getOperand(0)),
getVal(Values, SI->getOperand(1)),
getVal(Values, SI->getOperand(2)));
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurInst)) {
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());
+ InstResult = cast<GEPOperator>(GEP)->isInBounds() ?
+ ConstantExpr::getInBoundsGetElementPtr(P, &GEPOps[0], GEPOps.size()) :
+ ConstantExpr::getGetElementPtr(P, &GEPOps[0], GEPOps.size());
} else if (LoadInst *LI = dyn_cast<LoadInst>(CurInst)) {
if (LI->isVolatile()) return false; // no volatile accesses.
InstResult = ComputeLoadResult(getVal(Values, LI->getOperand(0)),
- MutatedMemory);
+ MutatedMemory, Context);
if (InstResult == 0) return false; // Could not evaluate load.
} else if (AllocaInst *AI = dyn_cast<AllocaInst>(CurInst)) {
if (AI->isArrayAllocation()) return false; // Cannot handle array allocs.
const Type *Ty = AI->getType()->getElementType();
- AllocaTmps.push_back(new GlobalVariable(Ty, false,
+ AllocaTmps.push_back(new GlobalVariable(Context, Ty, false,
GlobalValue::InternalLinkage,
UndefValue::get(Ty),
AI->getName()));
InstResult = AllocaTmps.back();
} else if (CallInst *CI = dyn_cast<CallInst>(CurInst)) {
+
+ // Debug info can safely be ignored here.
+ if (isa<DbgInfoIntrinsic>(CI)) {
+ ++CurInst;
+ continue;
+ }
+
// Cannot handle inline asm.
if (isa<InlineAsm>(CI->getOperand(0))) return false;
Function *Callee = dyn_cast<Function>(getVal(Values, CI->getOperand(0)));
if (!Callee) return false; // Cannot resolve.
- std::vector<Constant*> Formals;
+ SmallVector<Constant*, 8> Formals;
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.
- if (Constant *C = ConstantFoldCall(Callee, &Formals[0],
+ if (Constant *C = ConstantFoldCall(Callee, Formals.data(),
Formals.size())) {
InstResult = C;
} else {
return false;
Constant *RetVal;
-
// Execute the call, if successful, use the return value.
if (!EvaluateFunction(Callee, RetVal, Formals, CallStack,
MutatedMemory, AllocaTmps))
dyn_cast<ConstantInt>(getVal(Values, SI->getCondition()));
if (!Val) return false; // Cannot determine.
NewBB = SI->getSuccessor(SI->findCaseValue(Val));
+ } else if (IndirectBrInst *IBI = dyn_cast<IndirectBrInst>(CurInst)) {
+ Value *Val = getVal(Values, IBI->getAddress())->stripPointerCasts();
+ if (BlockAddress *BA = dyn_cast<BlockAddress>(Val))
+ NewBB = BA->getBasicBlock();
+ if (NewBB == 0) return false; // Cannot determine.
} else if (ReturnInst *RI = dyn_cast<ReturnInst>(CurInst)) {
if (RI->getNumOperands())
RetVal = getVal(Values, RI->getOperand(0));
// Call the function.
Constant *RetValDummy;
- bool EvalSuccess = EvaluateFunction(F, RetValDummy, std::vector<Constant*>(),
- CallStack, MutatedMemory, AllocaTmps);
+ bool EvalSuccess = EvaluateFunction(F, RetValDummy,
+ SmallVector<Constant*, 0>(), CallStack,
+ MutatedMemory, AllocaTmps);
if (EvalSuccess) {
// We succeeded at evaluation: commit the result.
- DOUT << "FULLY EVALUATED GLOBAL CTOR FUNCTION '"
- << F->getName() << "' to " << MutatedMemory.size()
- << " stores.\n";
+ DEBUG(errs() << "FULLY EVALUATED GLOBAL CTOR FUNCTION '"
+ << F->getName() << "' to " << MutatedMemory.size()
+ << " stores.\n");
for (DenseMap<Constant*, Constant*>::iterator I = MutatedMemory.begin(),
E = MutatedMemory.end(); I != E; ++I)
- CommitValueTo(I->second, I->first);
+ CommitValueTo(I->second, I->first, F->getContext());
}
// At this point, we are done interpreting. If we created any 'alloca'
if (!MadeChange) return false;
- GCL = InstallGlobalCtors(GCL, Ctors);
+ GCL = InstallGlobalCtors(GCL, Ctors, GCL->getContext());
return true;
}