#include "llvm/IntrinsicInst.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Target/TargetData.h"
-#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
STATISTIC(NumCtorsEvaluated, "Number of static ctors evaluated");
namespace {
- struct GlobalOpt : public ModulePass {
+ struct VISIBILITY_HIDDEN GlobalOpt : public ModulePass {
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<TargetData>();
}
+ static char ID; // Pass identification, replacement for typeid
+ GlobalOpt() : ModulePass((intptr_t)&ID) {}
bool runOnModule(Module &M);
bool ProcessInternalGlobal(GlobalVariable *GV,Module::global_iterator &GVI);
};
+ char GlobalOpt::ID = 0;
RegisterPass<GlobalOpt> X("globalopt", "Global Variable Optimizer");
}
/// 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 GlobalStatus {
+struct VISIBILITY_HIDDEN GlobalStatus {
/// isLoaded - True if the global is ever loaded. If the global isn't ever
/// loaded it can be deleted.
bool isLoaded;
if (IdxV < CS->getNumOperands()) return CS->getOperand(IdxV);
} else if (ConstantArray *CA = dyn_cast<ConstantArray>(Agg)) {
if (IdxV < CA->getNumOperands()) return CA->getOperand(IdxV);
- } else if (ConstantPacked *CP = dyn_cast<ConstantPacked>(Agg)) {
+ } else if (ConstantVector *CP = dyn_cast<ConstantVector>(Agg)) {
if (IdxV < CP->getNumOperands()) return CP->getOperand(IdxV);
} else if (isa<ConstantAggregateZero>(Agg)) {
if (const StructType *STy = dyn_cast<StructType>(Agg->getType())) {
assert(In && "Couldn't get element of initializer?");
GlobalVariable *NGV = new GlobalVariable(STy->getElementType(i), false,
GlobalVariable::InternalLinkage,
- In, GV->getName()+"."+utostr(i));
+ In, GV->getName()+"."+utostr(i),
+ (Module *)NULL,
+ GV->isThreadLocal());
Globals.insert(GV, NGV);
NewGlobals.push_back(NGV);
}
unsigned NumElements = 0;
if (const ArrayType *ATy = dyn_cast<ArrayType>(STy))
NumElements = ATy->getNumElements();
- else if (const PackedType *PTy = dyn_cast<PackedType>(STy))
+ else if (const VectorType *PTy = dyn_cast<VectorType>(STy))
NumElements = PTy->getNumElements();
else
assert(0 && "Unknown aggregate sequential type!");
GlobalVariable *NGV = new GlobalVariable(STy->getElementType(), false,
GlobalVariable::InternalLinkage,
- In, GV->getName()+"."+utostr(i));
+ In, GV->getName()+"."+utostr(i),
+ (Module *)NULL,
+ GV->isThreadLocal());
Globals.insert(GV, NGV);
NewGlobals.push_back(NGV);
}
// Form a shorter GEP if needed.
if (GEP->getNumOperands() > 3)
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(GEP)) {
- std::vector<Constant*> Idxs;
+ SmallVector<Constant*, 8> Idxs;
Idxs.push_back(NullInt);
for (unsigned i = 3, e = CE->getNumOperands(); i != e; ++i)
Idxs.push_back(CE->getOperand(i));
- NewPtr = ConstantExpr::getGetElementPtr(cast<Constant>(NewPtr), Idxs);
+ NewPtr = ConstantExpr::getGetElementPtr(cast<Constant>(NewPtr),
+ &Idxs[0], Idxs.size());
} else {
GetElementPtrInst *GEPI = cast<GetElementPtrInst>(GEP);
- std::vector<Value*> Idxs;
+ SmallVector<Value*, 8> Idxs;
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,
+ NewPtr = new GetElementPtrInst(NewPtr, &Idxs[0], Idxs.size(),
GEPI->getName()+"."+utostr(Val), GEPI);
}
GEP->replaceAllUsesWith(NewPtr);
}
} else if (GetElementPtrInst *GEPI = dyn_cast<GetElementPtrInst>(I)) {
// Should handle GEP here.
- std::vector<Constant*> Indices;
- Indices.reserve(GEPI->getNumOperands()-1);
+ 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)))
- Indices.push_back(C);
+ Idxs.push_back(C);
else
break;
- if (Indices.size() == GEPI->getNumOperands()-1)
+ if (Idxs.size() == GEPI->getNumOperands()-1)
Changed |= OptimizeAwayTrappingUsesOfValue(GEPI,
- ConstantExpr::getGetElementPtr(NewV, Indices));
+ ConstantExpr::getGetElementPtr(NewV, &Idxs[0],
+ Idxs.size()));
if (GEPI->use_empty()) {
Changed = true;
GEPI->eraseFromParent();
Loads.push_back(LI);
Changed |= OptimizeAwayTrappingUsesOfValue(LI, LV);
} else {
- assert(isa<StoreInst>(*GUI) && "Only expect load and stores!");
+ // 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)) &&
+ "Only expect load and stores!");
}
if (Changed) {
MallocInst *NewMI =
new MallocInst(NewTy, Constant::getNullValue(Type::Int32Ty),
MI->getAlignment(), MI->getName(), MI);
- std::vector<Value*> Indices;
- Indices.push_back(Constant::getNullValue(Type::Int32Ty));
- Indices.push_back(Indices[0]);
- Value *NewGEP = new GetElementPtrInst(NewMI, Indices,
+ Value* Indices[2];
+ Indices[0] = Indices[1] = Constant::getNullValue(Type::Int32Ty);
+ Value *NewGEP = new GetElementPtrInst(NewMI, Indices, 2,
NewMI->getName()+".el0", MI);
MI->replaceAllUsesWith(NewGEP);
MI->eraseFromParent();
Constant *Init = UndefValue::get(MI->getAllocatedType());
GlobalVariable *NewGV = new GlobalVariable(MI->getAllocatedType(), false,
GlobalValue::InternalLinkage, Init,
- GV->getName()+".body");
+ GV->getName()+".body",
+ (Module *)NULL,
+ GV->isThreadLocal());
GV->getParent()->getGlobalList().insert(GV, NewGV);
// Anything that used the malloc now uses the global directly.
// 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::BoolTy, false, GlobalValue::InternalLinkage,
- ConstantInt::getFalse(), GV->getName()+".init");
+ new GlobalVariable(Type::Int1Ty, false, GlobalValue::InternalLinkage,
+ ConstantInt::getFalse(), GV->getName()+".init",
+ (Module *)NULL, GV->isThreadLocal());
bool InitBoolUsed = false;
// Loop over all uses of GV, processing them in turn.
Value *NewPtr = InsertedLoadsForPtr[FieldNo];
// Create the new GEP idx vector.
- std::vector<Value*> GEPIdx;
+ SmallVector<Value*, 8> GEPIdx;
GEPIdx.push_back(GEPI->getOperand(1));
- GEPIdx.insert(GEPIdx.end(), GEPI->op_begin()+3, GEPI->op_end());
+ GEPIdx.append(GEPI->op_begin()+3, GEPI->op_end());
- Value *NGEPI = new GetElementPtrInst(NewPtr, GEPIdx, GEPI->getName(), GEPI);
+ Value *NGEPI = new GetElementPtrInst(NewPtr, &GEPIdx[0], GEPIdx.size(),
+ GEPI->getName(), GEPI);
GEPI->replaceAllUsesWith(NGEPI);
GEPI->eraseFromParent();
}
GlobalVariable *NGV =
new GlobalVariable(PFieldTy, false, GlobalValue::InternalLinkage,
Constant::getNullValue(PFieldTy),
- GV->getName() + ".f" + utostr(FieldNo), GV);
+ GV->getName() + ".f" + utostr(FieldNo), GV,
+ GV->isThreadLocal());
FieldGlobals.push_back(NGV);
MallocInst *NMI = new MallocInst(FieldTy, MI->getArraySize(),
/// values ever stored into GV are its initializer and OtherVal.
static void ShrinkGlobalToBoolean(GlobalVariable *GV, Constant *OtherVal) {
// Create the new global, initializing it to false.
- GlobalVariable *NewGV = new GlobalVariable(Type::BoolTy, false,
+ GlobalVariable *NewGV = new GlobalVariable(Type::Int1Ty, false,
GlobalValue::InternalLinkage, ConstantInt::getFalse(),
- GV->getName()+".b");
+ GV->getName()+".b",
+ (Module *)NULL,
+ GV->isThreadLocal());
GV->getParent()->getGlobalList().insert(GV, NewGV);
Constant *InitVal = GV->getInitializer();
- assert(InitVal->getType() != Type::BoolTy && "No reason to shrink to bool!");
+ assert(InitVal->getType() != Type::Int1Ty && "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.
bool IsOneZero = false;
if (ConstantInt *CI = dyn_cast<ConstantInt>(OtherVal))
- IsOneZero = InitVal->isNullValue() && CI->equalsInt(1);
+ IsOneZero = InitVal->isNullValue() && CI->isOne();
while (!GV->use_empty()) {
Instruction *UI = cast<Instruction>(GV->use_back());
// Only do this if we weren't storing a loaded value.
Value *StoreVal;
if (StoringOther || SI->getOperand(0) == InitVal)
- StoreVal = ConstantInt::get(StoringOther);
+ StoreVal = ConstantInt::get(Type::Int1Ty, 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
} else if (!UI->use_empty()) {
// Change the load into a load of bool then a select.
LoadInst *LI = cast<LoadInst>(UI);
-
- std::string Name = LI->getName(); LI->setName("");
- LoadInst *NLI = new LoadInst(NewGV, Name+".b", LI);
+ LoadInst *NLI = new LoadInst(NewGV, LI->getName()+".b", LI);
Value *NSI;
if (IsOneZero)
- NSI = new ZExtInst(NLI, LI->getType(), Name, LI);
+ NSI = new ZExtInst(NLI, LI->getType(), "", LI);
else
- NSI = new SelectInst(NLI, OtherVal, InitVal, Name, LI);
+ NSI = new SelectInst(NLI, OtherVal, InitVal, "", LI);
+ NSI->takeName(LI);
LI->replaceAllUsesWith(NSI);
}
UI->eraseFromParent();
// 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::BoolTy &&
+ if (GV->getType()->getElementType() != Type::Int1Ty &&
!GV->getType()->getElementType()->isFloatingPoint() &&
- !GS.HasPHIUser) {
+ !isa<VectorType>(GV->getType()->getElementType()) &&
+ !GS.HasPHIUser && !GS.isNotSuitableForSRA) {
DOUT << " *** SHRINKING TO BOOL: " << *GV;
ShrinkGlobalToBoolean(GV, SOVConstant);
++NumShrunkToBool;
// Create the new global and insert it next to the existing list.
GlobalVariable *NGV = new GlobalVariable(CA->getType(), GCL->isConstant(),
- GCL->getLinkage(), CA,
- GCL->getName());
- GCL->setName("");
+ GCL->getLinkage(), CA, "",
+ (Module *)NULL,
+ GCL->isThreadLocal());
GCL->getParent()->getGlobalList().insert(GCL, NGV);
+ NGV->takeName(GCL);
// Nuke the old list, replacing any uses with the new one.
if (!GCL->use_empty()) {
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
if (!GV->hasExternalLinkage() && !GV->hasInternalLinkage())
return false; // do not allow weak/linkonce/dllimport/dllexport linkage.
- return !GV->isExternal(); // reject external globals.
+ return !GV->isDeclaration(); // reject external globals.
}
if (ConstantExpr *CE = dyn_cast<ConstantExpr>(C))
// Handle a constantexpr gep.
Elts[Idx] = EvaluateStoreInto(Elts[Idx], Val, Addr, OpNo+1);
// Return the modified struct.
- return ConstantStruct::get(Elts);
+ return ConstantStruct::get(&Elts[0], Elts.size(), STy->isPacked());
} else {
ConstantInt *CI = cast<ConstantInt>(Addr->getOperand(OpNo));
const ArrayType *ATy = cast<ArrayType>(Init->getType());
InstResult = ConstantExpr::get(BO->getOpcode(),
getVal(Values, BO->getOperand(0)),
getVal(Values, BO->getOperand(1)));
- } else if (ShiftInst *SI = dyn_cast<ShiftInst>(CurInst)) {
- InstResult = ConstantExpr::get(SI->getOpcode(),
- getVal(Values, SI->getOperand(0)),
- getVal(Values, SI->getOperand(1)));
} else if (CmpInst *CI = dyn_cast<CmpInst>(CurInst)) {
InstResult = ConstantExpr::getCompare(CI->getPredicate(),
getVal(Values, CI->getOperand(0)),
getVal(Values, SI->getOperand(2)));
} else if (GetElementPtrInst *GEP = dyn_cast<GetElementPtrInst>(CurInst)) {
Constant *P = getVal(Values, GEP->getOperand(0));
- std::vector<Constant*> GEPOps;
+ SmallVector<Constant*, 8> GEPOps;
for (unsigned i = 1, e = GEP->getNumOperands(); i != e; ++i)
GEPOps.push_back(getVal(Values, GEP->getOperand(i)));
- InstResult = ConstantExpr::getGetElementPtr(P, GEPOps);
+ InstResult = 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)),
for (unsigned i = 1, e = CI->getNumOperands(); i != e; ++i)
Formals.push_back(getVal(Values, CI->getOperand(i)));
- if (Callee->isExternal()) {
+ if (Callee->isDeclaration()) {
// If this is a function we can constant fold, do it.
- if (Constant *C = ConstantFoldCall(Callee, Formals)) {
+ if (Constant *C = ConstantFoldCall(Callee, &Formals[0],
+ Formals.size())) {
InstResult = C;
} else {
return false;
} else {
ConstantInt *Cond =
dyn_cast<ConstantInt>(getVal(Values, BI->getCondition()));
+ if (!Cond) return false; // Cannot determine.
- // Cannot determine.
- if (!Cond || Cond->getType() != Type::BoolTy)
- return false;
- NewBB = BI->getSuccessor(!Cond->getBoolValue());
+ NewBB = BI->getSuccessor(!Cond->getZExtValue());
}
} else if (SwitchInst *SI = dyn_cast<SwitchInst>(CurInst)) {
ConstantInt *Val =