Statistic<> NumMarked ("globalopt", "Number of globals marked constant");
Statistic<> NumSRA ("globalopt", "Number of aggregate globals broken "
"into scalars");
+ Statistic<> NumSubstitute("globalopt",
+ "Number of globals with initializers stored into them");
Statistic<> NumDeleted ("globalopt", "Number of globals deleted");
Statistic<> NumFnDeleted("globalopt", "Number of functions deleted");
Statistic<> NumGlobUses ("globalopt", "Number of global uses devirtualized");
if (IdxV < CA->getNumOperands()) return CA->getOperand(IdxV);
} else if (ConstantPacked *CP = dyn_cast<ConstantPacked>(Agg)) {
if (IdxV < CP->getNumOperands()) return CP->getOperand(IdxV);
- } else if (ConstantAggregateZero *CAZ =
- dyn_cast<ConstantAggregateZero>(Agg)) {
+ } else if (isa<ConstantAggregateZero>(Agg)) {
if (const StructType *STy = dyn_cast<StructType>(Agg->getType())) {
if (IdxV < STy->getNumElements())
return Constant::getNullValue(STy->getElementType(IdxV));
dyn_cast<SequentialType>(Agg->getType())) {
return Constant::getNullValue(STy->getElementType());
}
+ } else if (isa<UndefValue>(Agg)) {
+ if (const StructType *STy = dyn_cast<StructType>(Agg->getType())) {
+ if (IdxV < STy->getNumElements())
+ return UndefValue::get(STy->getElementType(IdxV));
+ } else if (const SequentialType *STy =
+ dyn_cast<SequentialType>(Agg->getType())) {
+ return UndefValue::get(STy->getElementType());
+ }
}
return 0;
}
if (LoadInst *LI = dyn_cast<LoadInst>(U)) {
// Replace the load with the initializer.
LI->replaceAllUsesWith(Init);
- LI->getParent()->getInstList().erase(LI);
+ LI->eraseFromParent();
Changed = true;
} else if (StoreInst *SI = dyn_cast<StoreInst>(U)) {
// Store must be unreachable or storing Init into the global.
- SI->getParent()->getInstList().erase(SI);
+ SI->eraseFromParent();
Changed = true;
} else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(U)) {
if (CE->getOpcode() == Instruction::GetElementPtr) {
for (Value::use_iterator GUI = GEP->use_begin(), E = GEP->use_end();
GUI != E;)
if (StoreInst *SI = dyn_cast<StoreInst>(*GUI++)) {
- SI->getParent()->getInstList().erase(SI);
+ SI->eraseFromParent();
Changed = true;
}
}
if (GEP->use_empty()) {
- GEP->getParent()->getInstList().erase(GEP);
+ GEP->eraseFromParent();
Changed = true;
}
} else if (Constant *C = dyn_cast<Constant>(U)) {
GEP->replaceAllUsesWith(NewPtr);
if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(GEP))
- GEPI->getParent()->getInstList().erase(GEPI);
+ GEPI->eraseFromParent();
else
cast<ConstantExpr>(GEP)->destroyConstant();
}
ConstantExpr::getCast(NewV, CI->getType()));
if (CI->use_empty()) {
Changed = true;
- CI->getParent()->getInstList().erase(CI);
+ CI->eraseFromParent();
}
} else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
// Should handle GEP here.
ConstantExpr::getGetElementPtr(NewV, Indices));
if (GEPI->use_empty()) {
Changed = true;
- GEPI->getParent()->getInstList().erase(GEPI);
+ GEPI->eraseFromParent();
}
}
}
while (!Loads.empty()) {
LoadInst *L = Loads.back();
if (L->use_empty()) {
- L->getParent()->getInstList().erase(L);
+ L->eraseFromParent();
Changed = true;
} else {
AllLoadsGone = false;
DEBUG(std::cerr << " *** GLOBAL NOW DEAD!\n");
CleanupConstantGlobalUsers(GV, 0);
if (GV->use_empty()) {
- GV->getParent()->getGlobalList().erase(GV);
+ GV->eraseFromParent();
++NumDeleted;
}
Changed = true;
AtBegin = true;
else
--UI;
- I->getParent()->getInstList().erase(I);
+ I->eraseFromParent();
if (AtBegin)
UI = V->use_begin();
else
Value *NewGEP = new GetElementPtrInst(NewMI, Indices,
NewMI->getName()+".el0", MI);
MI->replaceAllUsesWith(NewGEP);
- MI->getParent()->getInstList().erase(MI);
+ MI->eraseFromParent();
MI = NewMI;
}
- // Create the new global variable.
- Constant *Init = Constant::getNullValue(MI->getAllocatedType());
+ // 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,
GlobalValue::InternalLinkage, Init,
GV->getName()+".body");
// Anything that used the malloc now uses the global directly.
MI->replaceAllUsesWith(NewGV);
- MI->getParent()->getInstList().erase(MI);
+ MI->eraseFromParent();
Constant *RepValue = NewGV;
if (NewGV->getType() != GV->getType()->getElementType())
while (!GV->use_empty())
if (LoadInst *LI = dyn_cast<LoadInst>(GV->use_back())) {
LI->replaceAllUsesWith(RepValue);
- LI->getParent()->getInstList().erase(LI);
+ LI->eraseFromParent();
} else {
StoreInst *SI = cast<StoreInst>(GV->use_back());
- SI->getParent()->getInstList().erase(SI);
+ SI->eraseFromParent();
}
// Now the GV is dead, nuke it.
- GV->getParent()->getGlobalList().erase(GV);
+ GV->eraseFromParent();
// To further other optimizations, loop over all users of NewGV and try to
// constant prop them. This will promote GEP instructions with constant
if (GV->use_empty()) {
DEBUG(std::cerr << "GLOBAL DEAD: " << *GV);
- GV->getParent()->getGlobalList().erase(GV);
+ GV->eraseFromParent();
++NumDeleted;
return true;
}
// If the global is dead now, delete it.
if (GV->use_empty()) {
- GV->getParent()->getGlobalList().erase(GV);
+ GV->eraseFromParent();
++NumDeleted;
Changed = true;
}
if (GV->use_empty()) {
DEBUG(std::cerr << " *** Marking constant allowed us to simplify "
"all users and delete global!\n");
- GV->getParent()->getGlobalList().erase(GV);
+ GV->eraseFromParent();
++NumDeleted;
}
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 initializer to
+ // be an undef value, then delete all stores to the global. This allows
+ // us to mark it constant.
+ if (isa<UndefValue>(GV->getInitializer()) &&
+ isa<Constant>(GS.StoredOnceValue)) {
+ // Change the initial value here.
+ GV->setInitializer(cast<Constant>(GS.StoredOnceValue));
+
+ // Clean up any obviously simplifiable users now.
+ CleanupConstantGlobalUsers(GV, GV->getInitializer());
+
+ if (GV->use_empty()) {
+ DEBUG(std::cerr << " *** Substituting initializer allowed us to "
+ "simplify all users and delete global!\n");
+ GV->eraseFromParent();
+ ++NumDeleted;
+ } else {
+ GVI = GV;
+ }
+ ++NumSubstitute;
+ return true;
+ }
+
// 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,