forked from OSchip/llvm-project
parent
13f332cd3f
commit
01808caded
|
@ -1,10 +1,10 @@
|
|||
//===- AliasAnalysis.cpp - Generic Alias Analysis Interface Implementation -==//
|
||||
//
|
||||
//
|
||||
// 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 implements the generic AliasAnalysis interface which is used as the
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- AliasAnalysisCounter.cpp - Alias Analysis Query Counter ------------===//
|
||||
//
|
||||
//
|
||||
// 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 implements a pass which can be used to count how many alias queries
|
||||
|
@ -67,7 +67,7 @@ namespace {
|
|||
printLine("mod/ref", MR, MRSum);
|
||||
std::cerr
|
||||
<< " Mod/Ref Analysis Counter Summary: " << NoMR*100/MRSum<< "%/"
|
||||
<< JustRef*100/MRSum << "%/" << JustMod*100/MRSum << "%/"
|
||||
<< JustRef*100/MRSum << "%/" << JustMod*100/MRSum << "%/"
|
||||
<< MR*100/MRSum <<"%\n\n";
|
||||
}
|
||||
}
|
||||
|
@ -96,8 +96,8 @@ namespace {
|
|||
bool onlyReadsMemory(Function *F) {
|
||||
return getAnalysis<AliasAnalysis>().onlyReadsMemory(F);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Forwarding functions: just delegate to a real AA implementation, counting
|
||||
// the number of responses...
|
||||
AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
|
@ -118,11 +118,11 @@ ModulePass *llvm::createAliasAnalysisCounterPass() {
|
|||
return new AliasAnalysisCounter();
|
||||
}
|
||||
|
||||
AliasAnalysis::AliasResult
|
||||
AliasAnalysis::AliasResult
|
||||
AliasAnalysisCounter::alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size) {
|
||||
AliasResult R = getAnalysis<AliasAnalysis>().alias(V1, V1Size, V2, V2Size);
|
||||
|
||||
|
||||
const char *AliasString;
|
||||
switch (R) {
|
||||
default: assert(0 && "Unknown alias type!");
|
||||
|
@ -142,7 +142,7 @@ AliasAnalysisCounter::alias(const Value *V1, unsigned V1Size,
|
|||
return R;
|
||||
}
|
||||
|
||||
AliasAnalysis::ModRefResult
|
||||
AliasAnalysis::ModRefResult
|
||||
AliasAnalysisCounter::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
|
||||
ModRefResult R = getAnalysis<AliasAnalysis>().getModRefInfo(CS, P, Size);
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- AliasAnalysisEvaluator.cpp - Alias Analysis Accuracy Evaluator -----===//
|
||||
//
|
||||
//
|
||||
// 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 implements a simple N^2 alias analysis accuracy evaluator.
|
||||
|
@ -54,16 +54,16 @@ namespace {
|
|||
AU.addRequired<AliasAnalysis>();
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
||||
bool doInitialization(Module &M) {
|
||||
NoAlias = MayAlias = MustAlias = 0;
|
||||
|
||||
bool doInitialization(Module &M) {
|
||||
NoAlias = MayAlias = MustAlias = 0;
|
||||
NoModRef = Mod = Ref = ModRef = 0;
|
||||
|
||||
if (PrintAll) {
|
||||
PrintNoAlias = PrintMayAlias = PrintMustAlias = true;
|
||||
PrintNoModRef = PrintMod = PrintRef = PrintModRef = true;
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool runOnFunction(Function &F);
|
||||
|
@ -85,7 +85,7 @@ static inline void PrintResults(const char *Msg, bool P, Value *V1, Value *V2,
|
|||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
static inline void
|
||||
PrintModRefResults(const char *Msg, bool P, Instruction *I, Value *Ptr,
|
||||
Module *M) {
|
||||
if (P) {
|
||||
|
@ -99,7 +99,7 @@ bool AAEval::runOnFunction(Function &F) {
|
|||
AliasAnalysis &AA = getAnalysis<AliasAnalysis>();
|
||||
|
||||
const TargetData &TD = AA.getTargetData();
|
||||
|
||||
|
||||
std::set<Value *> Pointers;
|
||||
std::set<CallSite> CallSites;
|
||||
|
||||
|
@ -157,16 +157,16 @@ bool AAEval::runOnFunction(Function &F) {
|
|||
}
|
||||
|
||||
// Mod/ref alias analysis: compare all pairs of calls and values
|
||||
for (std::set<CallSite>::iterator C = CallSites.begin(),
|
||||
for (std::set<CallSite>::iterator C = CallSites.begin(),
|
||||
Ce = CallSites.end(); C != Ce; ++C) {
|
||||
Instruction *I = C->getInstruction();
|
||||
|
||||
|
||||
for (std::set<Value *>::iterator V = Pointers.begin(), Ve = Pointers.end();
|
||||
V != Ve; ++V) {
|
||||
unsigned Size = 0;
|
||||
const Type *ElTy = cast<PointerType>((*V)->getType())->getElementType();
|
||||
if (ElTy->isSized()) Size = TD.getTypeSize(ElTy);
|
||||
|
||||
|
||||
switch (AA.getModRefInfo(*C, *V, Size)) {
|
||||
case AliasAnalysis::NoModRef:
|
||||
PrintModRefResults("NoModRef", PrintNoModRef, I, *V, F.getParent());
|
||||
|
@ -185,7 +185,7 @@ bool AAEval::runOnFunction(Function &F) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,7 @@ bool AAEval::doFinalization(Module &M) {
|
|||
std::cerr << "===== Alias Analysis Evaluator Report =====\n";
|
||||
if (AliasSum == 0) {
|
||||
std::cerr << " Alias Analysis Evaluator Summary: No pointers!\n";
|
||||
} else {
|
||||
} else {
|
||||
std::cerr << " " << AliasSum << " Total Alias Queries Performed\n";
|
||||
std::cerr << " " << NoAlias << " no alias responses ";
|
||||
PrintPercent(NoAlias, AliasSum);
|
||||
|
@ -207,8 +207,8 @@ bool AAEval::doFinalization(Module &M) {
|
|||
PrintPercent(MayAlias, AliasSum);
|
||||
std::cerr << " " << MustAlias << " must alias responses ";
|
||||
PrintPercent(MustAlias, AliasSum);
|
||||
std::cerr << " Alias Analysis Evaluator Pointer Alias Summary: "
|
||||
<< NoAlias*100/AliasSum << "%/" << MayAlias*100/AliasSum << "%/"
|
||||
std::cerr << " Alias Analysis Evaluator Pointer Alias Summary: "
|
||||
<< NoAlias*100/AliasSum << "%/" << MayAlias*100/AliasSum << "%/"
|
||||
<< MustAlias*100/AliasSum << "%\n";
|
||||
}
|
||||
|
||||
|
@ -226,8 +226,8 @@ bool AAEval::doFinalization(Module &M) {
|
|||
PrintPercent(Ref, ModRefSum);
|
||||
std::cerr << " " << ModRef << " mod & ref responses ";
|
||||
PrintPercent(ModRef, ModRefSum);
|
||||
std::cerr << " Alias Analysis Evaluator Mod/Ref Summary: "
|
||||
<< NoModRef*100/ModRefSum << "%/" << Mod*100/ModRefSum << "%/"
|
||||
std::cerr << " Alias Analysis Evaluator Mod/Ref Summary: "
|
||||
<< NoModRef*100/ModRefSum << "%/" << Mod*100/ModRefSum << "%/"
|
||||
<< Ref*100/ModRefSum << "%/" << ModRef*100/ModRefSum << "%\n";
|
||||
}
|
||||
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
//===- AliasSetTracker.cpp - Alias Sets Tracker implementation-------------===//
|
||||
//
|
||||
//
|
||||
// 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 implements the AliasSetTracker and AliasSet classes.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/AliasSetTracker.h"
|
||||
|
@ -53,7 +53,7 @@ void AliasSet::mergeSetIn(AliasSet &AS, AliasSetTracker &AST) {
|
|||
CallSites.insert(CallSites.end(), AS.CallSites.begin(), AS.CallSites.end());
|
||||
AS.CallSites.clear();
|
||||
}
|
||||
|
||||
|
||||
AS.Forward = this; // Forward across AS now...
|
||||
addRef(); // AS is now pointing to us...
|
||||
|
||||
|
@ -506,7 +506,7 @@ void AliasSet::print(std::ostream &OS) const {
|
|||
for (unsigned i = 0, e = CallSites.size(); i != e; ++i) {
|
||||
if (i) OS << ", ";
|
||||
WriteAsOperand(OS, CallSites[i].getCalledValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
OS << "\n";
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- BasicAliasAnalysis.cpp - Local Alias Analysis Impl -----------------===//
|
||||
//
|
||||
//
|
||||
// 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 defines the default implementation of the Alias Analysis interface
|
||||
|
@ -39,7 +39,7 @@ namespace {
|
|||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.addRequired<TargetData>();
|
||||
}
|
||||
|
||||
|
||||
virtual void initializePass() {
|
||||
TD = &getAnalysis<TargetData>();
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ namespace {
|
|||
std::vector<PointerAccessInfo> *Info) {
|
||||
return UnknownModRefBehavior;
|
||||
}
|
||||
|
||||
|
||||
virtual void getArgumentAccesses(Function *F, CallSite CS,
|
||||
std::vector<PointerAccessInfo> &Info) {
|
||||
assert(0 && "This method may not be called on this function!");
|
||||
|
@ -72,7 +72,7 @@ namespace {
|
|||
virtual void deleteValue(Value *V) {}
|
||||
virtual void copyValue(Value *From, Value *To) {}
|
||||
};
|
||||
|
||||
|
||||
// Register this pass...
|
||||
RegisterOpt<NoAA>
|
||||
U("no-aa", "No Alias Analysis (always returns 'may' alias)");
|
||||
|
@ -106,7 +106,7 @@ namespace {
|
|||
|
||||
virtual ModRefBehavior getModRefBehavior(Function *F, CallSite CS,
|
||||
std::vector<PointerAccessInfo> *Info);
|
||||
|
||||
|
||||
private:
|
||||
// CheckGEPInstructions - Check two GEP instructions with known
|
||||
// must-aliasing base pointers. This checks to see if the index expressions
|
||||
|
@ -117,7 +117,7 @@ namespace {
|
|||
const Type *BasePtr2Ty, std::vector<Value*> &GEP2Ops,
|
||||
unsigned G2Size);
|
||||
};
|
||||
|
||||
|
||||
// Register this pass...
|
||||
RegisterOpt<BasicAliasAnalysis>
|
||||
X("basicaa", "Basic Alias Analysis (default AA impl)");
|
||||
|
@ -144,7 +144,7 @@ static const Value *getUnderlyingObject(const Value *V) {
|
|||
|
||||
// If we are at some type of object... return it.
|
||||
if (hasUniqueAddress(V) || isa<Argument>(V)) return V;
|
||||
|
||||
|
||||
// Traverse through different addressing mechanisms...
|
||||
if (const Instruction *I = dyn_cast<Instruction>(V)) {
|
||||
if (isa<CastInst>(I) || isa<GetElementPtrInst>(I))
|
||||
|
@ -307,7 +307,7 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
|
|||
if (!isa<Argument>(O1) && isa<ConstantPointerNull>(V2))
|
||||
return NoAlias; // Unique values don't alias null
|
||||
|
||||
if (isa<GlobalVariable>(O1) ||
|
||||
if (isa<GlobalVariable>(O1) ||
|
||||
(isa<AllocationInst>(O1) &&
|
||||
!cast<AllocationInst>(O1)->isArrayAllocation()))
|
||||
if (cast<PointerType>(O1->getType())->getElementType()->isSized()) {
|
||||
|
@ -351,12 +351,12 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
|
|||
do {
|
||||
BasePtr1 = cast<User>(BasePtr1)->getOperand(0);
|
||||
} while (isGEP(BasePtr1) &&
|
||||
cast<User>(BasePtr1)->getOperand(1) ==
|
||||
cast<User>(BasePtr1)->getOperand(1) ==
|
||||
Constant::getNullValue(cast<User>(BasePtr1)->getOperand(1)->getType()));
|
||||
do {
|
||||
BasePtr2 = cast<User>(BasePtr2)->getOperand(0);
|
||||
} while (isGEP(BasePtr2) &&
|
||||
cast<User>(BasePtr2)->getOperand(1) ==
|
||||
cast<User>(BasePtr2)->getOperand(1) ==
|
||||
Constant::getNullValue(cast<User>(BasePtr2)->getOperand(1)->getType()));
|
||||
|
||||
// Do the base pointers alias?
|
||||
|
@ -423,7 +423,7 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
|
|||
if (ConstantFound) {
|
||||
if (V2Size <= 1 && V1Size <= 1) // Just pointer check?
|
||||
return NoAlias;
|
||||
|
||||
|
||||
// Otherwise we have to check to see that the distance is more than
|
||||
// the size of the argument... build an index vector that is equal to
|
||||
// the arguments provided, except substitute 0's for any variable
|
||||
|
@ -443,7 +443,7 @@ BasicAliasAnalysis::alias(const Value *V1, unsigned V1Size,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return MayAlias;
|
||||
}
|
||||
|
||||
|
@ -503,7 +503,7 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
// If so, return mustalias.
|
||||
if (UnequalOper == MinOperands) {
|
||||
if (GEP1Ops.size() < GEP2Ops.size()) std::swap(GEP1Ops, GEP2Ops);
|
||||
|
||||
|
||||
bool AllAreZeros = true;
|
||||
for (unsigned i = UnequalOper; i != MaxOperands; ++i)
|
||||
if (!isa<Constant>(GEP1Ops[i]) ||
|
||||
|
@ -514,7 +514,7 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
if (AllAreZeros) return MustAlias;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// So now we know that the indexes derived from the base pointers,
|
||||
// which are known to alias, are different. We can still determine a
|
||||
// no-alias result if there are differing constant pairs in the index
|
||||
|
@ -530,7 +530,7 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
for (; FirstConstantOper != MinOperands; ++FirstConstantOper) {
|
||||
const Value *G1Oper = GEP1Ops[FirstConstantOper];
|
||||
const Value *G2Oper = GEP2Ops[FirstConstantOper];
|
||||
|
||||
|
||||
if (G1Oper != G2Oper) // Found non-equal constant indexes...
|
||||
if (Constant *G1OC = dyn_cast<ConstantInt>(const_cast<Value*>(G1Oper)))
|
||||
if (Constant *G2OC = dyn_cast<ConstantInt>(const_cast<Value*>(G2Oper))){
|
||||
|
@ -555,7 +555,7 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
}
|
||||
BasePtr1Ty = cast<CompositeType>(BasePtr1Ty)->getTypeAtIndex(G1Oper);
|
||||
}
|
||||
|
||||
|
||||
// No shared constant operands, and we ran out of common operands. At this
|
||||
// point, the GEP instructions have run through all of their operands, and we
|
||||
// haven't found evidence that there are any deltas between the GEP's.
|
||||
|
@ -585,13 +585,13 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
// Now crop off any constants from the end...
|
||||
GEP1Ops.resize(MinOperands);
|
||||
int64_t Offset2 = TD.getIndexedOffset(GEPPointerTy, GEP1Ops);
|
||||
|
||||
|
||||
// If the tail provided a bit enough offset, return noalias!
|
||||
if ((uint64_t)(Offset2-Offset1) >= SizeMax)
|
||||
return NoAlias;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Couldn't find anything useful.
|
||||
return MayAlias;
|
||||
}
|
||||
|
@ -604,7 +604,7 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
// Advance BasePtr[12]Ty over this first differing constant operand.
|
||||
BasePtr2Ty = cast<CompositeType>(BasePtr1Ty)->getTypeAtIndex(GEP2Ops[FirstConstantOper]);
|
||||
BasePtr1Ty = cast<CompositeType>(BasePtr1Ty)->getTypeAtIndex(GEP1Ops[FirstConstantOper]);
|
||||
|
||||
|
||||
// We are going to be using TargetData::getIndexedOffset to determine the
|
||||
// offset that each of the GEP's is reaching. To do this, we have to convert
|
||||
// all variable references to constant references. To do this, we convert the
|
||||
|
@ -614,7 +614,7 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
GEP1Ops[i] = GEP2Ops[i] = Constant::getNullValue(Type::UIntTy);
|
||||
|
||||
// We know that GEP1Ops[FirstConstantOper] & GEP2Ops[FirstConstantOper] are ok
|
||||
|
||||
|
||||
// Loop over the rest of the operands...
|
||||
for (unsigned i = FirstConstantOper+1; i != MaxOperands; ++i) {
|
||||
const Value *Op1 = i < GEP1Ops.size() ? GEP1Ops[i] : 0;
|
||||
|
@ -631,7 +631,7 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
if (const ArrayType *AT = dyn_cast<ArrayType>(BasePtr1Ty))
|
||||
if (Op1C->getRawValue() >= AT->getNumElements())
|
||||
return MayAlias; // Be conservative with out-of-range accesses
|
||||
|
||||
|
||||
} else {
|
||||
// GEP1 is known to produce a value less than GEP2. To be
|
||||
// conservatively correct, we must assume the largest possible
|
||||
|
@ -647,7 +647,7 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
GEP1Ops[i] = ConstantSInt::get(Type::LongTy,AT->getNumElements()-1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (Op2) {
|
||||
if (const ConstantInt *Op2C = dyn_cast<ConstantInt>(Op2)) {
|
||||
// If this is an array index, make sure the array element is in range.
|
||||
|
@ -674,14 +674,14 @@ CheckGEPInstructions(const Type* BasePtr1Ty, std::vector<Value*> &GEP1Ops,
|
|||
BasePtr2Ty = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (GEPPointerTy->getElementType()->isSized()) {
|
||||
int64_t Offset1 = getTargetData().getIndexedOffset(GEPPointerTy, GEP1Ops);
|
||||
int64_t Offset2 = getTargetData().getIndexedOffset(GEPPointerTy, GEP2Ops);
|
||||
assert(Offset1<Offset2 && "There is at least one different constant here!");
|
||||
|
||||
if ((uint64_t)(Offset2-Offset1) >= SizeMax) {
|
||||
//std::cerr << "Determined that these two GEP's don't alias ["
|
||||
//std::cerr << "Determined that these two GEP's don't alias ["
|
||||
// << SizeMax << " bytes]: \n" << *GEP1 << *GEP2;
|
||||
return NoAlias;
|
||||
}
|
||||
|
@ -706,11 +706,11 @@ static const char *DoesntAccessMemoryTable[] = {
|
|||
|
||||
"abs", "labs", "llabs", "imaxabs", "fabs", "fabsf", "fabsl",
|
||||
"trunc", "truncf", "truncl", "ldexp",
|
||||
|
||||
|
||||
"atan", "atanf", "atanl", "atan2", "atan2f", "atan2l",
|
||||
"cbrt",
|
||||
"cos", "cosf", "cosl", "cosh", "coshf", "coshl",
|
||||
"exp", "expf", "expl",
|
||||
"exp", "expf", "expl",
|
||||
"hypot",
|
||||
"sin", "sinf", "sinl", "sinh", "sinhf", "sinhl",
|
||||
"tan", "tanf", "tanl", "tanh", "tanhf", "tanhl",
|
||||
|
@ -723,9 +723,9 @@ static const char *DoesntAccessMemoryTable[] = {
|
|||
"iswalnum", "iswalpha", "iswcntrl", "iswdigit", "iswgraph", "iswlower",
|
||||
"iswprint", "iswpunct", "iswspace", "iswupper", "iswxdigit",
|
||||
|
||||
"iswctype", "towctrans", "towlower", "towupper",
|
||||
"iswctype", "towctrans", "towlower", "towupper",
|
||||
|
||||
"btowc", "wctob",
|
||||
"btowc", "wctob",
|
||||
|
||||
"isinf", "isnan", "finite",
|
||||
|
||||
|
@ -744,16 +744,16 @@ static const unsigned DAMTableSize =
|
|||
|
||||
static const char *OnlyReadsMemoryTable[] = {
|
||||
"atoi", "atol", "atof", "atoll", "atoq", "a64l",
|
||||
"bcmp", "memcmp", "memchr", "memrchr", "wmemcmp", "wmemchr",
|
||||
"bcmp", "memcmp", "memchr", "memrchr", "wmemcmp", "wmemchr",
|
||||
|
||||
// Strings
|
||||
"strcmp", "strcasecmp", "strcoll", "strncmp", "strncasecmp",
|
||||
"strchr", "strcspn", "strlen", "strpbrk", "strrchr", "strspn", "strstr",
|
||||
"strchr", "strcspn", "strlen", "strpbrk", "strrchr", "strspn", "strstr",
|
||||
"index", "rindex",
|
||||
|
||||
// Wide char strings
|
||||
"wcschr", "wcscmp", "wcscoll", "wcscspn", "wcslen", "wcsncmp", "wcspbrk",
|
||||
"wcsrchr", "wcsspn", "wcsstr",
|
||||
"wcsrchr", "wcsspn", "wcsstr",
|
||||
|
||||
// glibc
|
||||
"alphasort", "alphasort64", "versionsort", "versionsort64",
|
||||
|
@ -768,8 +768,8 @@ static const char *OnlyReadsMemoryTable[] = {
|
|||
|
||||
static const unsigned ORMTableSize =
|
||||
sizeof(OnlyReadsMemoryTable)/sizeof(OnlyReadsMemoryTable[0]);
|
||||
|
||||
AliasAnalysis::ModRefBehavior
|
||||
|
||||
AliasAnalysis::ModRefBehavior
|
||||
BasicAliasAnalysis::getModRefBehavior(Function *F, CallSite CS,
|
||||
std::vector<PointerAccessInfo> *Info) {
|
||||
if (!F->isExternal()) return UnknownModRefBehavior;
|
||||
|
@ -789,7 +789,7 @@ BasicAliasAnalysis::getModRefBehavior(Function *F, CallSite CS,
|
|||
F->getName().c_str(), StringCompare());
|
||||
if (Ptr != DoesntAccessMemoryTable+DAMTableSize && *Ptr == F->getName())
|
||||
return DoesNotAccessMemory;
|
||||
|
||||
|
||||
Ptr = std::lower_bound(OnlyReadsMemoryTable,
|
||||
OnlyReadsMemoryTable+ORMTableSize,
|
||||
F->getName().c_str(), StringCompare());
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- CFGPrinter.cpp - DOT printer for the control flow graph ------------===//
|
||||
//
|
||||
//
|
||||
// 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 defines a '-print-cfg' analysis pass, which emits the
|
||||
|
@ -92,7 +92,7 @@ namespace {
|
|||
std::string Filename = "cfg." + F.getName() + ".dot";
|
||||
std::cerr << "Writing '" << Filename << "'...";
|
||||
std::ofstream File(Filename.c_str());
|
||||
|
||||
|
||||
if (File.good())
|
||||
WriteGraph(File, (const Function*)&F);
|
||||
else
|
||||
|
@ -102,7 +102,7 @@ namespace {
|
|||
}
|
||||
|
||||
void print(std::ostream &OS, const Module* = 0) const {}
|
||||
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ namespace {
|
|||
return false;
|
||||
}
|
||||
void print(std::ostream &OS, const Module* = 0) const {}
|
||||
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
}
|
||||
|
@ -140,7 +140,7 @@ void Function::viewCFG() const {
|
|||
std::string Filename = "/tmp/cfg." + getName() + ".dot";
|
||||
std::cerr << "Writing '" << Filename << "'... ";
|
||||
std::ofstream F(Filename.c_str());
|
||||
|
||||
|
||||
if (!F.good()) {
|
||||
std::cerr << " error opening file for writing!\n";
|
||||
return;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- BottomUpClosure.cpp - Compute bottom-up interprocedural closure ----===//
|
||||
//
|
||||
//
|
||||
// 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 implements the BUDataStructures class, which represents the
|
||||
|
@ -26,7 +26,7 @@ namespace {
|
|||
Statistic<> MaxSCC("budatastructure", "Maximum SCC Size in Call Graph");
|
||||
Statistic<> NumBUInlines("budatastructures", "Number of graphs inlined");
|
||||
Statistic<> NumCallEdges("budatastructures", "Number of 'actual' call edges");
|
||||
|
||||
|
||||
RegisterAnalysis<BUDataStructures>
|
||||
X("budatastructure", "Bottom-up Data Structure Analysis");
|
||||
}
|
||||
|
@ -48,23 +48,23 @@ static void BuildGlobalECs(DSGraph &GG, std::set<GlobalValue*> &ECGlobals) {
|
|||
GlobalValue *First = GVs[0];
|
||||
for (unsigned i = 1, e = GVs.size(); i != e; ++i)
|
||||
GlobalECs.unionSets(First, GVs[i]);
|
||||
|
||||
|
||||
// Next, get the leader element.
|
||||
assert(First == GlobalECs.getLeaderValue(First) &&
|
||||
"First did not end up being the leader?");
|
||||
|
||||
|
||||
// Next, remove all globals from the scalar map that are not the leader.
|
||||
assert(GVs[0] == First && "First had to be at the front!");
|
||||
for (unsigned i = 1, e = GVs.size(); i != e; ++i) {
|
||||
ECGlobals.insert(GVs[i]);
|
||||
SM.erase(SM.find(GVs[i]));
|
||||
}
|
||||
|
||||
|
||||
// Finally, change the global node to only contain the leader.
|
||||
I->clearGlobals();
|
||||
I->addGlobal(First);
|
||||
}
|
||||
|
||||
|
||||
DEBUG(GG.AssertGraphOK());
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ bool BUDataStructures::runOnModule(Module &M) {
|
|||
// nothing! In particular, externally visible globals and unresolvable call
|
||||
// nodes at the end of the BU phase should make things that they point to
|
||||
// incomplete in the globals graph.
|
||||
//
|
||||
//
|
||||
GlobalsGraph->removeTriviallyDeadNodes();
|
||||
GlobalsGraph->maskIncompleteMarkers();
|
||||
|
||||
|
@ -186,7 +186,7 @@ bool BUDataStructures::runOnModule(Module &M) {
|
|||
if (MainFunc && !MainFunc->isExternal()) {
|
||||
DSGraph &MainGraph = getOrCreateGraph(MainFunc);
|
||||
const DSGraph &GG = *MainGraph.getGlobalsGraph();
|
||||
ReachabilityCloner RC(MainGraph, GG,
|
||||
ReachabilityCloner RC(MainGraph, GG,
|
||||
DSGraph::DontCloneCallNodes |
|
||||
DSGraph::DontCloneAuxCallNodes);
|
||||
|
||||
|
@ -197,7 +197,7 @@ bool BUDataStructures::runOnModule(Module &M) {
|
|||
RC.getClonedNH(GG.getNodeForValue(*I));
|
||||
|
||||
MainGraph.maskIncompleteMarkers();
|
||||
MainGraph.markIncompleteNodes(DSGraph::MarkFormalArgs |
|
||||
MainGraph.markIncompleteNodes(DSGraph::MarkFormalArgs |
|
||||
DSGraph::IgnoreGlobals);
|
||||
}
|
||||
|
||||
|
@ -210,7 +210,7 @@ DSGraph &BUDataStructures::getOrCreateGraph(Function *F) {
|
|||
if (Graph) return *Graph;
|
||||
|
||||
DSGraph &LocGraph = getAnalysis<LocalDataStructures>().getDSGraph(*F);
|
||||
|
||||
|
||||
// Steal the local graph.
|
||||
Graph = new DSGraph(GlobalECs, LocGraph.getTargetData());
|
||||
Graph->spliceFrom(LocGraph);
|
||||
|
@ -235,7 +235,7 @@ static bool isResolvableFunc(const Function* callee) {
|
|||
return !callee->isExternal() || isVAHackFn(callee);
|
||||
}
|
||||
|
||||
static void GetAllCallees(const DSCallSite &CS,
|
||||
static void GetAllCallees(const DSCallSite &CS,
|
||||
std::vector<Function*> &Callees) {
|
||||
if (CS.isDirectCall()) {
|
||||
if (isResolvableFunc(CS.getCalleeFunc()))
|
||||
|
@ -244,7 +244,7 @@ static void GetAllCallees(const DSCallSite &CS,
|
|||
// Get all callees.
|
||||
unsigned OldSize = Callees.size();
|
||||
CS.getCalleeNode()->addFullFunctionList(Callees);
|
||||
|
||||
|
||||
// If any of the callees are unresolvable, remove the whole batch!
|
||||
for (unsigned i = OldSize, e = Callees.size(); i != e; ++i)
|
||||
if (!isResolvableFunc(Callees[i])) {
|
||||
|
@ -265,7 +265,7 @@ static void GetAllAuxCallees(DSGraph &G, std::vector<Function*> &Callees) {
|
|||
|
||||
unsigned BUDataStructures::calculateGraphs(Function *F,
|
||||
std::vector<Function*> &Stack,
|
||||
unsigned &NextID,
|
||||
unsigned &NextID,
|
||||
hash_map<Function*, unsigned> &ValMap) {
|
||||
assert(!ValMap.count(F) && "Shouldn't revisit functions!");
|
||||
unsigned Min = NextID++, MyID = Min;
|
||||
|
@ -488,7 +488,7 @@ void BUDataStructures::calculateGraph(DSGraph &Graph) {
|
|||
if (!Printed)
|
||||
std::cerr << "In Fns: " << Graph.getFunctionNames() << "\n";
|
||||
std::cerr << " calls " << CalledFuncs.size()
|
||||
<< " fns from site: " << CS.getCallSite().getInstruction()
|
||||
<< " fns from site: " << CS.getCallSite().getInstruction()
|
||||
<< " " << *CS.getCallSite().getInstruction();
|
||||
std::cerr << " Fns =";
|
||||
unsigned NumPrinted = 0;
|
||||
|
@ -510,7 +510,7 @@ void BUDataStructures::calculateGraph(DSGraph &Graph) {
|
|||
if (IndCallGraph.first == 0) {
|
||||
std::vector<Function*>::iterator I = CalledFuncs.begin(),
|
||||
E = CalledFuncs.end();
|
||||
|
||||
|
||||
// Start with a copy of the first graph.
|
||||
GI = IndCallGraph.first = new DSGraph(getDSGraph(**I), GlobalECs);
|
||||
GI->setGlobalsGraph(Graph.getGlobalsGraph());
|
||||
|
@ -539,7 +539,7 @@ void BUDataStructures::calculateGraph(DSGraph &Graph) {
|
|||
for (e = NextArgs.size(); i != e; ++i)
|
||||
Args.push_back(NextArgs[i]);
|
||||
}
|
||||
|
||||
|
||||
// Clean up the final graph!
|
||||
GI->removeDeadNodes(DSGraph::KeepUnreachableGlobals);
|
||||
} else {
|
||||
|
@ -580,7 +580,7 @@ void BUDataStructures::calculateGraph(DSGraph &Graph) {
|
|||
// Clone everything reachable from globals in the function graph into the
|
||||
// globals graph.
|
||||
for (DSScalarMap::global_iterator I = MainSM.global_begin(),
|
||||
E = MainSM.global_end(); I != E; ++I)
|
||||
E = MainSM.global_end(); I != E; ++I)
|
||||
RC.getClonedNH(MainSM[*I]);
|
||||
|
||||
//Graph.writeGraphToFile(std::cerr, "bu_" + F.getName());
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- CompleteBottomUp.cpp - Complete Bottom-Up Data Structure Graphs ----===//
|
||||
//
|
||||
//
|
||||
// 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 is the exact same as the bottom-up graphs, but we use take a completed
|
||||
|
@ -52,7 +52,7 @@ bool CompleteBUDataStructures::runOnModule(Module &M) {
|
|||
} else {
|
||||
std::cerr << "CBU-DSA: No 'main' function found!\n";
|
||||
}
|
||||
|
||||
|
||||
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
|
||||
if (!I->isExternal() && !DSInfo.count(I))
|
||||
calculateSCCGraphs(getOrCreateGraph(*I), Stack, NextID, ValMap);
|
||||
|
@ -66,7 +66,7 @@ bool CompleteBUDataStructures::runOnModule(Module &M) {
|
|||
if (MainFunc && !MainFunc->isExternal()) {
|
||||
DSGraph &MainGraph = getOrCreateGraph(*MainFunc);
|
||||
const DSGraph &GG = *MainGraph.getGlobalsGraph();
|
||||
ReachabilityCloner RC(MainGraph, GG,
|
||||
ReachabilityCloner RC(MainGraph, GG,
|
||||
DSGraph::DontCloneCallNodes |
|
||||
DSGraph::DontCloneAuxCallNodes);
|
||||
|
||||
|
@ -77,7 +77,7 @@ bool CompleteBUDataStructures::runOnModule(Module &M) {
|
|||
RC.getClonedNH(GG.getNodeForValue(*I));
|
||||
|
||||
MainGraph.maskIncompleteMarkers();
|
||||
MainGraph.markIncompleteNodes(DSGraph::MarkFormalArgs |
|
||||
MainGraph.markIncompleteNodes(DSGraph::MarkFormalArgs |
|
||||
DSGraph::IgnoreGlobals);
|
||||
}
|
||||
|
||||
|
@ -107,7 +107,7 @@ DSGraph &CompleteBUDataStructures::getOrCreateGraph(Function &F) {
|
|||
|
||||
unsigned CompleteBUDataStructures::calculateSCCGraphs(DSGraph &FG,
|
||||
std::vector<DSGraph*> &Stack,
|
||||
unsigned &NextID,
|
||||
unsigned &NextID,
|
||||
hash_map<DSGraph*, unsigned> &ValMap) {
|
||||
assert(!ValMap.count(&FG) && "Shouldn't revisit functions!");
|
||||
unsigned Min = NextID++, MyID = Min;
|
||||
|
@ -157,7 +157,7 @@ unsigned CompleteBUDataStructures::calculateSCCGraphs(DSGraph &FG,
|
|||
// Remove NG from the ValMap since the pointer may get recycled.
|
||||
ValMap.erase(NG);
|
||||
delete NG;
|
||||
|
||||
|
||||
Stack.pop_back();
|
||||
IsMultiNodeSCC = true;
|
||||
}
|
||||
|
@ -165,7 +165,7 @@ unsigned CompleteBUDataStructures::calculateSCCGraphs(DSGraph &FG,
|
|||
// Clean up the graph before we start inlining a bunch again...
|
||||
if (IsMultiNodeSCC)
|
||||
FG.removeTriviallyDeadNodes();
|
||||
|
||||
|
||||
Stack.pop_back();
|
||||
processGraph(FG);
|
||||
ValMap[&FG] = ~0U;
|
||||
|
@ -187,7 +187,7 @@ void CompleteBUDataStructures::processGraph(DSGraph &G) {
|
|||
|
||||
assert(calls.insert(TheCall).second &&
|
||||
"Call instruction occurs multiple times in graph??");
|
||||
|
||||
|
||||
// Fast path for noop calls. Note that we don't care about merging globals
|
||||
// in the callee with nodes in the caller here.
|
||||
if (CS.getRetVal().isNull() && CS.getNumPtrArgs() == 0)
|
||||
|
@ -196,7 +196,7 @@ void CompleteBUDataStructures::processGraph(DSGraph &G) {
|
|||
// Loop over all of the potentially called functions...
|
||||
// Inline direct calls as well as indirect calls because the direct
|
||||
// callee may have indirect callees and so may have changed.
|
||||
//
|
||||
//
|
||||
callee_iterator I = callee_begin(TheCall),E = callee_end(TheCall);
|
||||
unsigned TNum = 0, Num = 0;
|
||||
DEBUG(Num = std::distance(I, E));
|
||||
|
@ -208,7 +208,7 @@ void CompleteBUDataStructures::processGraph(DSGraph &G) {
|
|||
// calls or for self recursion within an SCC.
|
||||
DSGraph &GI = getOrCreateGraph(*CalleeFunc);
|
||||
++NumCBUInlines;
|
||||
G.mergeInGraph(CS, *CalleeFunc, GI,
|
||||
G.mergeInGraph(CS, *CalleeFunc, GI,
|
||||
DSGraph::StripAllocaBit | DSGraph::DontCloneCallNodes |
|
||||
DSGraph::DontCloneAuxCallNodes);
|
||||
DEBUG(std::cerr << " Inlining graph [" << i << "/"
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- DataStructure.cpp - Implement the core data structure analysis -----===//
|
||||
//
|
||||
//
|
||||
// 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 implements the core data structure functionality.
|
||||
|
@ -95,7 +95,7 @@ DSNodeHandle &DSScalarMap::AddGlobal(GlobalValue *GV) {
|
|||
return I->second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Okay, this is either not an equivalenced global or it is the leader, it
|
||||
// will be inserted into the scalar map now.
|
||||
GlobalSet.insert(GV);
|
||||
|
@ -163,7 +163,7 @@ void DSNode::forwardNode(DSNode *To, unsigned Offset) {
|
|||
Ty = Type::VoidTy;
|
||||
|
||||
// Remove this node from the parent graph's Nodes list.
|
||||
ParentGraph->unlinkNode(this);
|
||||
ParentGraph->unlinkNode(this);
|
||||
ParentGraph = 0;
|
||||
}
|
||||
|
||||
|
@ -221,16 +221,16 @@ void DSNode::foldNodeCompletely() {
|
|||
DestNode->Ty = Type::VoidTy;
|
||||
DestNode->Size = 1;
|
||||
DestNode->Globals.swap(Globals);
|
||||
|
||||
|
||||
// Start forwarding to the destination node...
|
||||
forwardNode(DestNode, 0);
|
||||
|
||||
|
||||
if (!Links.empty()) {
|
||||
DestNode->Links.reserve(1);
|
||||
|
||||
|
||||
DSNodeHandle NH(DestNode);
|
||||
DestNode->Links.push_back(Links[0]);
|
||||
|
||||
|
||||
// If we have links, merge all of our outgoing links together...
|
||||
for (unsigned i = Links.size()-1; i != 0; --i)
|
||||
NH.getNode()->Links[0].mergeWith(Links[i]);
|
||||
|
@ -328,7 +328,7 @@ namespace {
|
|||
++SS.Idx;
|
||||
if (SS.Idx != ST->getNumElements()) {
|
||||
const StructLayout *SL = TD.getStructLayout(ST);
|
||||
SS.Offset +=
|
||||
SS.Offset +=
|
||||
unsigned(SL->MemberOffsets[SS.Idx]-SL->MemberOffsets[SS.Idx-1]);
|
||||
return;
|
||||
}
|
||||
|
@ -388,7 +388,7 @@ namespace {
|
|||
static bool ElementTypesAreCompatible(const Type *T1, const Type *T2,
|
||||
bool AllowLargerT1, const TargetData &TD){
|
||||
TypeElementWalker T1W(T1, TD), T2W(T2, TD);
|
||||
|
||||
|
||||
while (!T1W.isDone() && !T2W.isDone()) {
|
||||
if (T1W.getCurrentOffset() != T2W.getCurrentOffset())
|
||||
return false;
|
||||
|
@ -397,11 +397,11 @@ static bool ElementTypesAreCompatible(const Type *T1, const Type *T2,
|
|||
const Type *T2 = T2W.getCurrentType();
|
||||
if (T1 != T2 && !T1->isLosslesslyConvertibleTo(T2))
|
||||
return false;
|
||||
|
||||
|
||||
T1W.StepToNextType();
|
||||
T2W.StepToNextType();
|
||||
}
|
||||
|
||||
|
||||
return AllowLargerT1 || T1W.isDone();
|
||||
}
|
||||
|
||||
|
@ -573,13 +573,13 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset,
|
|||
if (isa<FunctionType>(SubType) &&
|
||||
isa<FunctionType>(NewTy)) return false;
|
||||
|
||||
unsigned SubTypeSize = SubType->isSized() ?
|
||||
unsigned SubTypeSize = SubType->isSized() ?
|
||||
(unsigned)TD.getTypeSize(SubType) : 0;
|
||||
|
||||
// Ok, we are getting desperate now. Check for physical subtyping, where we
|
||||
// just require each element in the node to be compatible.
|
||||
if (NewTySize <= SubTypeSize && NewTySize && NewTySize < 256 &&
|
||||
SubTypeSize && SubTypeSize < 256 &&
|
||||
SubTypeSize && SubTypeSize < 256 &&
|
||||
ElementTypesAreCompatible(NewTy, SubType, !isArray(), TD))
|
||||
return false;
|
||||
|
||||
|
@ -611,7 +611,7 @@ bool DSNode::mergeTypeInfo(const Type *NewTy, unsigned Offset,
|
|||
NextPadSize = NextSubTypeSize;
|
||||
break;
|
||||
default: ;
|
||||
// fall out
|
||||
// fall out
|
||||
}
|
||||
|
||||
if (NextSubType == 0)
|
||||
|
@ -707,14 +707,14 @@ static void MergeSortedVectors(std::vector<GlobalValue*> &Dest,
|
|||
} else {
|
||||
// Make a copy to the side of Dest...
|
||||
std::vector<GlobalValue*> Old(Dest);
|
||||
|
||||
|
||||
// Make space for all of the type entries now...
|
||||
Dest.resize(Dest.size()+Src.size());
|
||||
|
||||
|
||||
// Merge the two sorted ranges together... into Dest.
|
||||
std::merge(Old.begin(), Old.end(), Src.begin(), Src.end(), Dest.begin());
|
||||
|
||||
// Now erase any duplicate entries that may have accumulated into the
|
||||
|
||||
// Now erase any duplicate entries that may have accumulated into the
|
||||
// vectors (because they were in both of the input sets)
|
||||
Dest.erase(std::unique(Dest.begin(), Dest.end()), Dest.end());
|
||||
}
|
||||
|
@ -728,7 +728,7 @@ void DSNode::mergeGlobals(const std::vector<GlobalValue*> &RHS) {
|
|||
// This function does the hard work of merging two nodes, CurNodeH
|
||||
// and NH after filtering out trivial cases and making sure that
|
||||
// CurNodeH.offset >= NH.offset.
|
||||
//
|
||||
//
|
||||
// ***WARNING***
|
||||
// Since merging may cause either node to go away, we must always
|
||||
// use the node-handles to refer to the nodes. These node handles are
|
||||
|
@ -761,7 +761,7 @@ void DSNode::MergeNodes(DSNodeHandle& CurNodeH, DSNodeHandle& NH) {
|
|||
#endif
|
||||
}
|
||||
|
||||
// Merge the type entries of the two nodes together...
|
||||
// Merge the type entries of the two nodes together...
|
||||
if (NH.getNode()->Ty != Type::VoidTy)
|
||||
CurNodeH.getNode()->mergeTypeInfo(NH.getNode()->Ty, NOffset);
|
||||
assert(!CurNodeH.getNode()->isDeadNode());
|
||||
|
@ -916,7 +916,7 @@ DSNodeHandle ReachabilityCloner::getClonedNH(const DSNodeHandle &SrcNH) {
|
|||
DSNode *DN = new DSNode(*SN, &Dest, true /* Null out all links */);
|
||||
DN->maskNodeTypes(BitsToKeep);
|
||||
NH = DN;
|
||||
|
||||
|
||||
// Next, recursively clone all outgoing links as necessary. Note that
|
||||
// adding these links can cause the node to collapse itself at any time, and
|
||||
// the current node may be merged with arbitrary other nodes. For this
|
||||
|
@ -939,7 +939,7 @@ DSNodeHandle ReachabilityCloner::getClonedNH(const DSNodeHandle &SrcNH) {
|
|||
CN->addEdgeTo(MergeOffset, DestEdge);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If this node contains any globals, make sure they end up in the scalar
|
||||
// map with the correct offset.
|
||||
for (DSNode::globals_iterator I = SN->globals_begin(), E = SN->globals_end();
|
||||
|
@ -977,7 +977,7 @@ void ReachabilityCloner::merge(const DSNodeHandle &NH,
|
|||
SCNH.getOffset()+SrcNH.getOffset()));
|
||||
return; // Nothing to do!
|
||||
}
|
||||
|
||||
|
||||
// Okay, so the source node has not already been cloned. Instead of creating
|
||||
// a new DSNode, only to merge it into the one we already have, try to perform
|
||||
// the merge in-place. The only case we cannot handle here is when the offset
|
||||
|
@ -1006,8 +1006,8 @@ void ReachabilityCloner::merge(const DSNodeHandle &NH,
|
|||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Merge the type entries of the two nodes together...
|
||||
|
||||
// Merge the type entries of the two nodes together...
|
||||
if (SN->getType() != Type::VoidTy && !DN->isNodeCompletelyFolded()) {
|
||||
DN->mergeTypeInfo(SN->getType(), NH.getOffset()-SrcNH.getOffset());
|
||||
DN = NH.getNode();
|
||||
|
@ -1015,7 +1015,7 @@ void ReachabilityCloner::merge(const DSNodeHandle &NH,
|
|||
}
|
||||
|
||||
assert(!DN->isDeadNode());
|
||||
|
||||
|
||||
// Merge the NodeType information.
|
||||
DN->mergeNodeFlags(SN->getNodeFlags() & BitsToKeep);
|
||||
|
||||
|
@ -1060,7 +1060,7 @@ void ReachabilityCloner::merge(const DSNodeHandle &NH,
|
|||
// sure it is known that this is the representative node for the src node.
|
||||
SCNH = DSNodeHandle(NH.getNode(), NH.getOffset()-SrcNH.getOffset());
|
||||
|
||||
// If the source node contained any globals, make sure to create entries
|
||||
// If the source node contained any globals, make sure to create entries
|
||||
// in the scalar map for them!
|
||||
for (DSNode::globals_iterator I = SN->globals_begin(),
|
||||
E = SN->globals_end(); I != E; ++I) {
|
||||
|
@ -1092,7 +1092,7 @@ void ReachabilityCloner::merge(const DSNodeHandle &NH,
|
|||
DSNode *CN = SCNH.getNode();
|
||||
unsigned MergeOffset =
|
||||
((i << DS::PointerShift)+SCNH.getOffset()) % CN->getSize();
|
||||
|
||||
|
||||
DSNodeHandle Tmp = CN->getLink(MergeOffset);
|
||||
if (!Tmp.isNull()) {
|
||||
// Perform the recursive merging. Make sure to create a temporary NH,
|
||||
|
@ -1120,7 +1120,7 @@ void ReachabilityCloner::mergeCallSite(DSCallSite &DestCS,
|
|||
merge(DestCS.getRetVal(), SrcCS.getRetVal());
|
||||
unsigned MinArgs = DestCS.getNumPtrArgs();
|
||||
if (SrcCS.getNumPtrArgs() < MinArgs) MinArgs = SrcCS.getNumPtrArgs();
|
||||
|
||||
|
||||
for (unsigned a = 0; a != MinArgs; ++a)
|
||||
merge(DestCS.getPtrArg(a), SrcCS.getPtrArg(a));
|
||||
|
||||
|
@ -1253,11 +1253,11 @@ void DSGraph::cloneInto(const DSGraph &G, unsigned CloneFlags) {
|
|||
New->maskNodeTypes(~BitsToClear);
|
||||
OldNodeMap[I] = New;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NDEBUG
|
||||
Timer::addPeakMemoryMeasurement();
|
||||
#endif
|
||||
|
||||
|
||||
// Rewrite the links in the new nodes to point into the current graph now.
|
||||
// Note that we don't loop over the node's list to do this. The problem is
|
||||
// that remaping links can cause recursive merging to happen, which means
|
||||
|
@ -1314,7 +1314,7 @@ void DSGraph::spliceFrom(DSGraph &RHS) {
|
|||
I->setParentGraph(this);
|
||||
// Take all of the nodes.
|
||||
Nodes.splice(Nodes.end(), RHS.Nodes);
|
||||
|
||||
|
||||
// Take all of the calls.
|
||||
FunctionCalls.splice(FunctionCalls.end(), RHS.FunctionCalls);
|
||||
AuxFunctionCalls.splice(AuxFunctionCalls.end(), RHS.AuxFunctionCalls);
|
||||
|
@ -1376,7 +1376,7 @@ namespace {
|
|||
unsigned CurNodeId;
|
||||
std::vector<const DSNode*> SCCStack;
|
||||
std::map<const DSNode*, std::pair<unsigned, bool> > NodeInfo;
|
||||
|
||||
|
||||
HackedGraphSCCFinder(ReachabilityCloner &rc) : RC(rc), CurNodeId(1) {
|
||||
// Remove null pointer as a special case.
|
||||
NodeInfo[0] = std::make_pair(0, false);
|
||||
|
@ -1473,7 +1473,7 @@ OutOfLoop:
|
|||
/// call site (in this graph) with the bindings specified by the vector in G2.
|
||||
/// The two DSGraphs must be different.
|
||||
///
|
||||
void DSGraph::mergeInGraph(const DSCallSite &CS,
|
||||
void DSGraph::mergeInGraph(const DSCallSite &CS,
|
||||
std::vector<DSNodeHandle> &Args,
|
||||
const DSGraph &Graph, unsigned CloneFlags) {
|
||||
TIME_REGION(X, "mergeInGraph");
|
||||
|
@ -1485,12 +1485,12 @@ void DSGraph::mergeInGraph(const DSCallSite &CS,
|
|||
if (&Graph == this) {
|
||||
// Merge the return value with the return value of the context.
|
||||
Args[0].mergeWith(CS.getRetVal());
|
||||
|
||||
|
||||
// Resolve all of the function arguments.
|
||||
for (unsigned i = 0, e = CS.getNumPtrArgs(); i != e; ++i) {
|
||||
if (i == Args.size()-1)
|
||||
break;
|
||||
|
||||
|
||||
// Add the link from the argument scalar to the provided value.
|
||||
Args[i+1].mergeWith(CS.getPtrArg(i));
|
||||
}
|
||||
|
@ -1501,7 +1501,7 @@ void DSGraph::mergeInGraph(const DSCallSite &CS,
|
|||
// scalars in the old graph _used_ to point, and of the new nodes matching
|
||||
// nodes of the old graph.
|
||||
ReachabilityCloner RC(*this, Graph, CloneFlags);
|
||||
|
||||
|
||||
// Map the return node pointer over.
|
||||
if (!CS.getRetVal().isNull())
|
||||
RC.merge(CS.getRetVal(), Args[0]);
|
||||
|
@ -1510,11 +1510,11 @@ void DSGraph::mergeInGraph(const DSCallSite &CS,
|
|||
for (unsigned i = 0, e = CS.getNumPtrArgs(); i != e; ++i) {
|
||||
if (i == Args.size()-1)
|
||||
break;
|
||||
|
||||
|
||||
// Add the link from the argument scalar to the provided value.
|
||||
RC.merge(CS.getPtrArg(i), Args[i+1]);
|
||||
}
|
||||
|
||||
|
||||
// We generally don't want to copy global nodes or aux calls from the callee
|
||||
// graph to the caller graph. However, we have to copy them if there is a
|
||||
// path from the node to a node we have already copied which does not go
|
||||
|
@ -1548,7 +1548,7 @@ void DSGraph::mergeInGraph(const DSCallSite &CS,
|
|||
// Copy aux calls that are needed.
|
||||
for (unsigned i = 0, e = AuxCallToCopy.size(); i != e; ++i)
|
||||
AuxFunctionCalls.push_back(DSCallSite(*AuxCallToCopy[i], RC));
|
||||
|
||||
|
||||
// Copy globals that are needed.
|
||||
for (unsigned i = 0, e = GlobalsToCopy.size(); i != e; ++i)
|
||||
RC.getClonedNH(Graph.getNodeForValue(GlobalsToCopy[i]));
|
||||
|
@ -1759,7 +1759,7 @@ static void removeIdenticalCalls(std::list<DSCallSite> &Calls) {
|
|||
killIfUselessEdge(CS.getRetVal());
|
||||
for (unsigned a = 0, e = CS.getNumPtrArgs(); a != e; ++a)
|
||||
killIfUselessEdge(CS.getPtrArg(a));
|
||||
|
||||
|
||||
#if 0
|
||||
// If this call site calls the same function as the last call site, and if
|
||||
// the function pointer contains an external function, this node will
|
||||
|
@ -1776,7 +1776,7 @@ static void removeIdenticalCalls(std::list<DSCallSite> &Calls) {
|
|||
else
|
||||
LastCalleeContainsExternalFunction = LastCalleeFunc->isExternal();
|
||||
}
|
||||
|
||||
|
||||
// It is not clear why, but enabling this code makes DSA really
|
||||
// sensitive to node forwarding. Basically, with this enabled, DSA
|
||||
// performs different number of inlinings based on which nodes are
|
||||
|
@ -1791,11 +1791,11 @@ static void removeIdenticalCalls(std::list<DSCallSite> &Calls) {
|
|||
NumDuplicateCalls > 20
|
||||
#endif
|
||||
) {
|
||||
|
||||
|
||||
std::list<DSCallSite>::iterator PrevIt = OldIt;
|
||||
--PrevIt;
|
||||
PrevIt->mergeWith(CS);
|
||||
|
||||
|
||||
// No need to keep this call anymore.
|
||||
Calls.erase(OldIt);
|
||||
++NumDeleted;
|
||||
|
@ -1957,7 +1957,7 @@ void DSNode::markReachableNodes(hash_set<const DSNode*> &ReachableNodes) const {
|
|||
void DSCallSite::markReachableNodes(hash_set<const DSNode*> &Nodes) const {
|
||||
getRetVal().getNode()->markReachableNodes(Nodes);
|
||||
if (isIndirectCall()) getCalleeNode()->markReachableNodes(Nodes);
|
||||
|
||||
|
||||
for (unsigned i = 0, e = getNumPtrArgs(); i != e; ++i)
|
||||
getPtrArg(i).getNode()->markReachableNodes(Nodes);
|
||||
}
|
||||
|
@ -2055,7 +2055,7 @@ void DSGraph::removeDeadNodes(unsigned Flags) {
|
|||
|
||||
// Make sure that all globals are cloned over as roots.
|
||||
if (!(Flags & DSGraph::RemoveUnreachableGlobals) && GlobalsGraph) {
|
||||
DSGraph::ScalarMapTy::iterator SMI =
|
||||
DSGraph::ScalarMapTy::iterator SMI =
|
||||
GlobalsGraph->getScalarMap().find(I->first);
|
||||
if (SMI != GlobalsGraph->getScalarMap().end())
|
||||
GGCloner.merge(SMI->second, I->second);
|
||||
|
@ -2079,7 +2079,7 @@ void DSGraph::removeDeadNodes(unsigned Flags) {
|
|||
|
||||
// Now find globals and aux call nodes that are already live or reach a live
|
||||
// value (which makes them live in turn), and continue till no more are found.
|
||||
//
|
||||
//
|
||||
bool Iterate;
|
||||
hash_set<const DSNode*> Visited;
|
||||
hash_set<const DSCallSite*> AuxFCallsAlive;
|
||||
|
@ -2092,7 +2092,7 @@ void DSGraph::removeDeadNodes(unsigned Flags) {
|
|||
Iterate = false;
|
||||
if (!(Flags & DSGraph::RemoveUnreachableGlobals))
|
||||
for (unsigned i = 0; i != GlobalNodes.size(); ++i)
|
||||
if (CanReachAliveNodes(GlobalNodes[i].second, Alive, Visited,
|
||||
if (CanReachAliveNodes(GlobalNodes[i].second, Alive, Visited,
|
||||
Flags & DSGraph::RemoveUnreachableGlobals)) {
|
||||
std::swap(GlobalNodes[i--], GlobalNodes.back()); // Move to end to...
|
||||
GlobalNodes.pop_back(); // erase efficiently
|
||||
|
@ -2124,7 +2124,7 @@ void DSGraph::removeDeadNodes(unsigned Flags) {
|
|||
// Copy and merge global nodes and dead aux call nodes into the
|
||||
// GlobalsGraph, and all nodes reachable from those nodes. Update their
|
||||
// target pointers using the GGCloner.
|
||||
//
|
||||
//
|
||||
if (!(Flags & DSGraph::RemoveUnreachableGlobals))
|
||||
GlobalsGraph->AuxFunctionCalls.push_back(DSCallSite(*CI, GGCloner));
|
||||
|
||||
|
@ -2180,7 +2180,7 @@ void DSGraph::AssertCallSiteInGraph(const DSCallSite &CS) const {
|
|||
#if 0
|
||||
if (CS.getNumPtrArgs() && CS.getCalleeNode() == CS.getPtrArg(0).getNode() &&
|
||||
CS.getCalleeNode() && CS.getCalleeNode()->getGlobals().empty())
|
||||
std::cerr << "WARNING: WEIRD CALL SITE FOUND!\n";
|
||||
std::cerr << "WARNING: WEIRD CALL SITE FOUND!\n";
|
||||
#endif
|
||||
}
|
||||
AssertNodeInGraph(CS.getRetVal().getNode());
|
||||
|
@ -2250,7 +2250,7 @@ void DSGraph::computeNodeMapping(const DSNodeHandle &NH1,
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Entry.setTo(N2, NH2.getOffset()-NH1.getOffset());
|
||||
|
||||
// Loop over all of the fields that N1 and N2 have in common, recursively
|
||||
|
@ -2284,7 +2284,7 @@ void DSGraph::computeGToGGMapping(NodeMapTy &NodeMap) {
|
|||
E = SM.global_end(); I != E; ++I)
|
||||
DSGraph::computeNodeMapping(SM[*I], GG.getNodeForValue(*I), NodeMap);
|
||||
}
|
||||
|
||||
|
||||
/// computeGGToGMapping - Compute the mapping of nodes in the global graph to
|
||||
/// nodes in this graph. Note that any uses of this method are probably bugs,
|
||||
/// unless it is known that the globals graph has been merged into this graph!
|
||||
|
@ -2298,7 +2298,7 @@ void DSGraph::computeGGToGMapping(InvNodeMapTy &InvNodeMap) {
|
|||
NodeMap.erase(NodeMap.begin());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// computeCalleeCallerMapping - Given a call from a function in the current
|
||||
/// graph to the 'Callee' function (which lives in 'CalleeGraph'), compute the
|
||||
|
@ -2309,7 +2309,7 @@ void DSGraph::computeCalleeCallerMapping(DSCallSite CS, const Function &Callee,
|
|||
|
||||
DSCallSite CalleeArgs =
|
||||
CalleeGraph.getCallSiteForArguments(const_cast<Function&>(Callee));
|
||||
|
||||
|
||||
computeNodeMapping(CalleeArgs.getRetVal(), CS.getRetVal(), NodeMap);
|
||||
|
||||
unsigned NumArgs = CS.getNumPtrArgs();
|
||||
|
@ -2318,18 +2318,18 @@ void DSGraph::computeCalleeCallerMapping(DSCallSite CS, const Function &Callee,
|
|||
|
||||
for (unsigned i = 0; i != NumArgs; ++i)
|
||||
computeNodeMapping(CalleeArgs.getPtrArg(i), CS.getPtrArg(i), NodeMap);
|
||||
|
||||
|
||||
// Map the nodes that are pointed to by globals.
|
||||
DSScalarMap &CalleeSM = CalleeGraph.getScalarMap();
|
||||
DSScalarMap &CallerSM = getScalarMap();
|
||||
|
||||
if (CalleeSM.global_size() >= CallerSM.global_size()) {
|
||||
for (DSScalarMap::global_iterator GI = CallerSM.global_begin(),
|
||||
for (DSScalarMap::global_iterator GI = CallerSM.global_begin(),
|
||||
E = CallerSM.global_end(); GI != E; ++GI)
|
||||
if (CalleeSM.global_count(*GI))
|
||||
computeNodeMapping(CalleeSM[*GI], CallerSM[*GI], NodeMap);
|
||||
} else {
|
||||
for (DSScalarMap::global_iterator GI = CalleeSM.global_begin(),
|
||||
for (DSScalarMap::global_iterator GI = CalleeSM.global_begin(),
|
||||
E = CalleeSM.global_end(); GI != E; ++GI)
|
||||
if (CallerSM.global_count(*GI))
|
||||
computeNodeMapping(CalleeSM[*GI], CallerSM[*GI], NodeMap);
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- DataStructureAA.cpp - Data Structure Based Alias Analysis ----------===//
|
||||
//
|
||||
//
|
||||
// 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 pass uses the top-down data structure graphs to implement a simple
|
||||
|
@ -68,7 +68,7 @@ namespace {
|
|||
|
||||
//------------------------------------------------
|
||||
// Implement the AliasAnalysis API
|
||||
//
|
||||
//
|
||||
|
||||
AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size);
|
||||
|
@ -124,14 +124,14 @@ AliasAnalysis::AliasResult DSAA::alias(const Value *V1, unsigned V1Size,
|
|||
DSGraph *G1 = getGraphForValue(V1);
|
||||
DSGraph *G2 = getGraphForValue(V2);
|
||||
assert((!G1 || !G2 || G1 == G2) && "Alias query for 2 different functions?");
|
||||
|
||||
|
||||
// Get the graph to use...
|
||||
DSGraph &G = *(G1 ? G1 : (G2 ? G2 : &TD->getGlobalsGraph()));
|
||||
|
||||
const DSGraph::ScalarMapTy &GSM = G.getScalarMap();
|
||||
DSGraph::ScalarMapTy::const_iterator I = GSM.find((Value*)V1);
|
||||
if (I == GSM.end()) return NoAlias;
|
||||
|
||||
|
||||
DSGraph::ScalarMapTy::const_iterator J = GSM.find((Value*)V2);
|
||||
if (J == GSM.end()) return NoAlias;
|
||||
|
||||
|
@ -188,10 +188,10 @@ DSAA::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
|
|||
|
||||
HaveMappingInfo:
|
||||
assert(N && "Null pointer in scalar map??");
|
||||
|
||||
|
||||
typedef std::multimap<DSNode*, const DSNode*>::iterator NodeMapIt;
|
||||
std::pair<NodeMapIt, NodeMapIt> Range = CallerCalleeMap.equal_range(N);
|
||||
|
||||
|
||||
// Loop over all of the nodes in the callee that correspond to "N", keeping
|
||||
// track of aggregate mod/ref info.
|
||||
bool NeverReads = true, NeverWrites = true;
|
||||
|
@ -203,13 +203,13 @@ DSAA::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
|
|||
if (NeverReads == false && NeverWrites == false)
|
||||
return AliasAnalysis::getModRefInfo(CS, P, Size);
|
||||
}
|
||||
|
||||
|
||||
ModRefResult Result = ModRef;
|
||||
if (NeverWrites) // We proved it was not modified.
|
||||
Result = ModRefResult(Result & ~Mod);
|
||||
if (NeverReads) // We proved it was not read.
|
||||
Result = ModRefResult(Result & ~Ref);
|
||||
|
||||
|
||||
return ModRefResult(Result & AliasAnalysis::getModRefInfo(CS, P, Size));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- DataStructureOpt.cpp - Data Structure Analysis Based Optimizations -===//
|
||||
//
|
||||
//
|
||||
// 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 pass uses DSA to a series of simple optimizations, like marking
|
||||
|
@ -66,7 +66,7 @@ bool DSOpt::OptimizeGlobals(Module &M) {
|
|||
DSNode *GNode = 0;
|
||||
DSGraph::ScalarMapTy::const_iterator SMI = SM.find(I);
|
||||
if (SMI != SM.end()) GNode = SMI->second.getNode();
|
||||
|
||||
|
||||
if (GNode == 0 && I->hasInternalLinkage()) {
|
||||
// If there is no entry in the scalar map for this global, it was never
|
||||
// referenced in the program. If it has internal linkage, that means we
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- DataStructureStats.cpp - Various statistics for DS Graphs ----------===//
|
||||
//
|
||||
//
|
||||
// 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 defines a little pass that prints out statistics for DS Graphs.
|
||||
|
@ -76,7 +76,7 @@ void DSGraphStats::countCallees(const Function& F) {
|
|||
unsigned numIndirectCalls = 0, totalNumCallees = 0;
|
||||
|
||||
for (DSGraph::fc_iterator I = TDGraph->fc_begin(), E = TDGraph->fc_end();
|
||||
I != E; ++I)
|
||||
I != E; ++I)
|
||||
if (isIndirectCallee(I->getCallSite().getCalledValue())) {
|
||||
// This is an indirect function call
|
||||
std::vector<Function*> Callees;
|
||||
|
@ -90,10 +90,10 @@ void DSGraphStats::countCallees(const Function& F) {
|
|||
<< "' at call: \n"
|
||||
<< *I->getCallSite().getInstruction();
|
||||
}
|
||||
|
||||
|
||||
TotalNumCallees += totalNumCallees;
|
||||
NumIndirectCalls += numIndirectCalls;
|
||||
|
||||
|
||||
if (numIndirectCalls)
|
||||
std::cout << " In function " << F.getName() << ": "
|
||||
<< (totalNumCallees / (double) numIndirectCalls)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- EquivClassGraphs.cpp - Merge equiv-class graphs & inline bottom-up -===//
|
||||
//
|
||||
//
|
||||
// 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 pass is the same as the complete bottom-up graphs, but
|
||||
|
@ -50,12 +50,12 @@ static void CheckAllGraphs(Module *M, GT &ECGraphs) {
|
|||
|
||||
DSGraph::NodeMapTy GlobalsGraphNodeMapping;
|
||||
G.computeGToGGMapping(GlobalsGraphNodeMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// getSomeCalleeForCallSite - Return any one callee function at a call site.
|
||||
//
|
||||
//
|
||||
Function *EquivClassGraphs::getSomeCalleeForCallSite(const CallSite &CS) const{
|
||||
Function *thisFunc = CS.getCaller();
|
||||
assert(thisFunc && "getSomeCalleeForCallSite(): Not a valid call site?");
|
||||
|
@ -94,7 +94,7 @@ bool EquivClassGraphs::runOnModule(Module &M) {
|
|||
} else {
|
||||
std::cerr << "Fold Graphs: No 'main' function found!\n";
|
||||
}
|
||||
|
||||
|
||||
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
|
||||
if (!I->isExternal())
|
||||
processSCC(getOrCreateGraph(*I), Stack, NextID, ValMap);
|
||||
|
@ -110,7 +110,7 @@ bool EquivClassGraphs::runOnModule(Module &M) {
|
|||
if (MainFunc && !MainFunc->isExternal()) {
|
||||
DSGraph &MainGraph = getOrCreateGraph(*MainFunc);
|
||||
const DSGraph &GG = *MainGraph.getGlobalsGraph();
|
||||
ReachabilityCloner RC(MainGraph, GG,
|
||||
ReachabilityCloner RC(MainGraph, GG,
|
||||
DSGraph::DontCloneCallNodes |
|
||||
DSGraph::DontCloneAuxCallNodes);
|
||||
|
||||
|
@ -121,7 +121,7 @@ bool EquivClassGraphs::runOnModule(Module &M) {
|
|||
RC.getClonedNH(GG.getNodeForValue(*I));
|
||||
|
||||
MainGraph.maskIncompleteMarkers();
|
||||
MainGraph.markIncompleteNodes(DSGraph::MarkFormalArgs |
|
||||
MainGraph.markIncompleteNodes(DSGraph::MarkFormalArgs |
|
||||
DSGraph::IgnoreGlobals);
|
||||
}
|
||||
|
||||
|
@ -158,7 +158,7 @@ bool EquivClassGraphs::runOnModule(Module &M) {
|
|||
//
|
||||
void EquivClassGraphs::buildIndirectFunctionSets(Module &M) {
|
||||
const ActualCalleesTy& AC = CBU->getActualCallees();
|
||||
|
||||
|
||||
// Loop over all of the indirect calls in the program. If a call site can
|
||||
// call multiple different functions, we need to unify all of the callees into
|
||||
// the same equivalence class.
|
||||
|
@ -204,7 +204,7 @@ void EquivClassGraphs::buildIndirectFunctionSets(Module &M) {
|
|||
// equivalence class. More precisely, if F is in the class, and G(F) is
|
||||
// its graph, then we include all other functions that are also in G(F).
|
||||
// Currently, that is just the functions in the same call-graph-SCC as F.
|
||||
//
|
||||
//
|
||||
DSGraph& funcDSGraph = CBU->getDSGraph(*I->second);
|
||||
for (DSGraph::retnodes_iterator RI = funcDSGraph.retnodes_begin(),
|
||||
RE = funcDSGraph.retnodes_end(); RI != RE; ++RI)
|
||||
|
@ -242,24 +242,24 @@ void EquivClassGraphs::buildIndirectFunctionSets(Module &M) {
|
|||
DSGraph &MergedG = getOrCreateGraph(*LF);
|
||||
|
||||
// Record the argument nodes for use in merging later below.
|
||||
std::vector<DSNodeHandle> ArgNodes;
|
||||
std::vector<DSNodeHandle> ArgNodes;
|
||||
|
||||
for (Function::arg_iterator AI = LF->arg_begin(), E = LF->arg_end();
|
||||
AI != E; ++AI)
|
||||
if (DS::isPointerType(AI->getType()))
|
||||
ArgNodes.push_back(MergedG.getNodeForValue(AI));
|
||||
|
||||
|
||||
// Merge in the graphs of all other functions in this equiv. class. Note
|
||||
// that two or more functions may have the same graph, and it only needs
|
||||
// to be merged in once.
|
||||
std::set<DSGraph*> GraphsMerged;
|
||||
GraphsMerged.insert(&CBU->getDSGraph(*LF));
|
||||
|
||||
|
||||
for (++SI; SI != FuncECs.member_end(); ++SI) {
|
||||
Function *F = *SI;
|
||||
DSGraph *&FG = DSInfo[F];
|
||||
|
||||
DSGraph &CBUGraph = CBU->getDSGraph(*F);
|
||||
|
||||
DSGraph &CBUGraph = CBU->getDSGraph(*F);
|
||||
if (GraphsMerged.insert(&CBUGraph).second) {
|
||||
// Record the "folded" graph for the function.
|
||||
for (DSGraph::retnodes_iterator I = CBUGraph.retnodes_begin(),
|
||||
|
@ -267,14 +267,14 @@ void EquivClassGraphs::buildIndirectFunctionSets(Module &M) {
|
|||
assert(DSInfo[I->first] == 0 && "Graph already exists for Fn!");
|
||||
DSInfo[I->first] = &MergedG;
|
||||
}
|
||||
|
||||
|
||||
// Clone this member of the equivalence class into MergedG.
|
||||
MergedG.cloneInto(CBUGraph);
|
||||
}
|
||||
|
||||
|
||||
// Merge the return nodes of all functions together.
|
||||
MergedG.getReturnNodes()[LF].mergeWith(MergedG.getReturnNodes()[F]);
|
||||
|
||||
|
||||
// Merge the function arguments with all argument nodes found so far.
|
||||
// If there are extra function args, add them to the vector of argNodes
|
||||
Function::arg_iterator AI2 = F->arg_begin(), AI2end = F->arg_end();
|
||||
|
@ -282,7 +282,7 @@ void EquivClassGraphs::buildIndirectFunctionSets(Module &M) {
|
|||
arg != numArgs && AI2 != AI2end; ++AI2, ++arg)
|
||||
if (DS::isPointerType(AI2->getType()))
|
||||
ArgNodes[arg].mergeWith(MergedG.getNodeForValue(AI2));
|
||||
|
||||
|
||||
for ( ; AI2 != AI2end; ++AI2)
|
||||
if (DS::isPointerType(AI2->getType()))
|
||||
ArgNodes.push_back(MergedG.getNodeForValue(AI2));
|
||||
|
@ -319,7 +319,7 @@ DSGraph &EquivClassGraphs::getOrCreateGraph(Function &F) {
|
|||
|
||||
|
||||
unsigned EquivClassGraphs::
|
||||
processSCC(DSGraph &FG, std::vector<DSGraph*> &Stack, unsigned &NextID,
|
||||
processSCC(DSGraph &FG, std::vector<DSGraph*> &Stack, unsigned &NextID,
|
||||
std::map<DSGraph*, unsigned> &ValMap) {
|
||||
std::map<DSGraph*, unsigned>::iterator It = ValMap.lower_bound(&FG);
|
||||
if (It != ValMap.end() && It->first == &FG)
|
||||
|
@ -366,7 +366,7 @@ processSCC(DSGraph &FG, std::vector<DSGraph*> &Stack, unsigned &NextID,
|
|||
for (DSGraph::retnodes_iterator I = NG->retnodes_begin();
|
||||
I != NG->retnodes_end(); ++I)
|
||||
DSInfo[I->first] = &FG;
|
||||
|
||||
|
||||
// Remove NG from the ValMap since the pointer may get recycled.
|
||||
ValMap.erase(NG);
|
||||
delete NG;
|
||||
|
@ -404,14 +404,14 @@ void EquivClassGraphs::processGraph(DSGraph &G) {
|
|||
|
||||
assert(calls.insert(TheCall).second &&
|
||||
"Call instruction occurs multiple times in graph??");
|
||||
|
||||
|
||||
if (CS.getRetVal().isNull() && CS.getNumPtrArgs() == 0)
|
||||
continue;
|
||||
|
||||
// Inline the common callee graph into the current graph, if the callee
|
||||
// graph has not changed. Note that all callees should have the same
|
||||
// graph so we only need to do this once.
|
||||
//
|
||||
//
|
||||
DSGraph* CalleeGraph = NULL;
|
||||
callee_iterator I = callee_begin(TheCall), E = callee_end(TheCall);
|
||||
unsigned TNum, Num;
|
||||
|
@ -424,12 +424,12 @@ void EquivClassGraphs::processGraph(DSGraph &G) {
|
|||
// Now check if the graph has changed and if so, clone and inline it.
|
||||
if (I != E) {
|
||||
Function *CalleeFunc = I->second;
|
||||
|
||||
|
||||
// Merge the callee's graph into this graph, if not already the same.
|
||||
// Callees in the same equivalence class (which subsumes those
|
||||
// in the same SCCs) have the same graph. Note that all recursion
|
||||
// including self-recursion have been folded in the equiv classes.
|
||||
//
|
||||
//
|
||||
CalleeGraph = &getOrCreateGraph(*CalleeFunc);
|
||||
if (CalleeGraph != &G) {
|
||||
++NumFoldGraphInlines;
|
||||
|
@ -463,7 +463,7 @@ void EquivClassGraphs::processGraph(DSGraph &G) {
|
|||
// Recompute the Incomplete markers.
|
||||
G.maskIncompleteMarkers();
|
||||
G.markIncompleteNodes(DSGraph::MarkFormalArgs);
|
||||
|
||||
|
||||
// Delete dead nodes. Treat globals that are unreachable but that can
|
||||
// reach live nodes as live.
|
||||
G.removeDeadNodes(DSGraph::KeepUnreachableGlobals);
|
||||
|
@ -476,7 +476,7 @@ void EquivClassGraphs::processGraph(DSGraph &G) {
|
|||
// globals graph.
|
||||
DSScalarMap &MainSM = G.getScalarMap();
|
||||
for (DSScalarMap::global_iterator I = MainSM.global_begin(),
|
||||
E = MainSM.global_end(); I != E; ++I)
|
||||
E = MainSM.global_end(); I != E; ++I)
|
||||
RC.getClonedNH(MainSM[*I]);
|
||||
|
||||
DEBUG(std::cerr << " -- DONE ProcessGraph for function "
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- GraphChecker.cpp - Assert that various graph properties hold -------===//
|
||||
//
|
||||
//
|
||||
// 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 pass is used to test DSA with regression tests. It can be used to check
|
||||
|
@ -39,7 +39,7 @@ namespace {
|
|||
cl::desc("Specify which DSA pass the -datastructure-gc pass should use"),
|
||||
cl::values(clEnumVal(local, "Local pass"),
|
||||
clEnumVal(bu, "Bottom-up pass"),
|
||||
clEnumVal(td, "Top-down pass"),
|
||||
clEnumVal(td, "Top-down pass"),
|
||||
clEnumValEnd), cl::init(local));
|
||||
|
||||
cl::opt<bool>
|
||||
|
@ -133,7 +133,7 @@ void DSGC::verify(const DSGraph &G) {
|
|||
std::set<std::string> AbortIfMergedS(AbortIfMerged.begin(),
|
||||
AbortIfMerged.end());
|
||||
std::map<std::string, unsigned> CheckFlagsM;
|
||||
|
||||
|
||||
for (cl::list<std::string>::iterator I = CheckFlags.begin(),
|
||||
E = CheckFlags.end(); I != E; ++I) {
|
||||
std::string::size_type ColonPos = I->rfind(':');
|
||||
|
@ -158,18 +158,18 @@ void DSGC::verify(const DSGraph &G) {
|
|||
}
|
||||
CheckFlagsM[std::string(I->begin(), I->begin()+ColonPos)] = Flags;
|
||||
}
|
||||
|
||||
|
||||
// Now we loop over all of the scalars, checking to see if any are collapsed
|
||||
// that are not supposed to be, or if any are merged together.
|
||||
const DSGraph::ScalarMapTy &SM = G.getScalarMap();
|
||||
std::map<DSNode*, std::string> AbortIfMergedNodes;
|
||||
|
||||
|
||||
for (DSGraph::ScalarMapTy::const_iterator I = SM.begin(), E = SM.end();
|
||||
I != E; ++I)
|
||||
if (I->first->hasName() && I->second.getNode()) {
|
||||
const std::string &Name = I->first->getName();
|
||||
DSNode *N = I->second.getNode();
|
||||
|
||||
|
||||
// Verify it is not collapsed if it is not supposed to be...
|
||||
if (N->isNodeCompletelyFolded() && AbortIfCollapsedS.count(Name)) {
|
||||
std::cerr << "Node for value '%" << Name << "' is collapsed: ";
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- Local.cpp - Compute a local data structure graph for a function ----===//
|
||||
//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Compute the local version of the data structure graph for a function. The
|
||||
|
@ -76,7 +76,7 @@ namespace {
|
|||
std::list<DSCallSite> *FunctionCalls;
|
||||
|
||||
public:
|
||||
GraphBuilder(Function &f, DSGraph &g, DSNodeHandle &retNode,
|
||||
GraphBuilder(Function &f, DSGraph &g, DSNodeHandle &retNode,
|
||||
std::list<DSCallSite> &fc)
|
||||
: G(g), RetNode(&retNode), ScalarMap(G.getScalarMap()),
|
||||
FunctionCalls(&fc) {
|
||||
|
@ -148,7 +148,7 @@ namespace {
|
|||
///
|
||||
void setDestTo(Value &V, const DSNodeHandle &NH);
|
||||
|
||||
/// getValueDest - Return the DSNode that the actual value points to.
|
||||
/// getValueDest - Return the DSNode that the actual value points to.
|
||||
///
|
||||
DSNodeHandle getValueDest(Value &V);
|
||||
|
||||
|
@ -182,7 +182,7 @@ DSGraph::DSGraph(EquivalenceClasses<GlobalValue*> &ECs, const TargetData &td,
|
|||
// initializers into the local graph from the globals graph.
|
||||
if (ScalarMap.global_begin() != ScalarMap.global_end()) {
|
||||
ReachabilityCloner RC(*this, *GG, 0);
|
||||
|
||||
|
||||
for (DSScalarMap::global_iterator I = ScalarMap.global_begin();
|
||||
I != ScalarMap.global_end(); ++I)
|
||||
if (GlobalVariable *GV = dyn_cast<GlobalVariable>(*I))
|
||||
|
@ -313,7 +313,7 @@ void GraphBuilder::visitPHINode(PHINode &PN) {
|
|||
|
||||
void GraphBuilder::visitSelectInst(SelectInst &SI) {
|
||||
if (!isPointerType(SI.getType())) return; // Only pointer Selects
|
||||
|
||||
|
||||
DSNodeHandle &Dest = ScalarMap[&SI];
|
||||
Dest.mergeWith(getValueDest(*SI.getOperand(1)));
|
||||
Dest.mergeWith(getValueDest(*SI.getOperand(2)));
|
||||
|
@ -573,7 +573,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
AI != E; ++AI) {
|
||||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker();
|
||||
N->setReadMarker();
|
||||
}
|
||||
return;
|
||||
} else if (F->getName() == "read" || F->getName() == "pipe" ||
|
||||
|
@ -583,7 +583,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
AI != E; ++AI) {
|
||||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setModifiedMarker();
|
||||
N->setModifiedMarker();
|
||||
}
|
||||
return;
|
||||
} else if (F->getName() == "stat" || F->getName() == "fstat" ||
|
||||
|
@ -630,7 +630,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker();
|
||||
|
||||
|
||||
// fopen allocates in an unknown way and writes to the file
|
||||
// descriptor. Also, merge the allocated type into the node.
|
||||
DSNodeHandle Result = getValueDest(*CS.getInstruction());
|
||||
|
@ -661,7 +661,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
|
||||
}
|
||||
return;
|
||||
} else if (CS.arg_end()-CS.arg_begin() == 1 &&
|
||||
} else if (CS.arg_end()-CS.arg_begin() == 1 &&
|
||||
(F->getName() == "fflush" || F->getName() == "feof" ||
|
||||
F->getName() == "fileno" || F->getName() == "clearerr" ||
|
||||
F->getName() == "rewind" || F->getName() == "ftell" ||
|
||||
|
@ -672,13 +672,13 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
DSNodeHandle H = getValueDest(**CS.arg_begin());
|
||||
if (DSNode *N = H.getNode()) {
|
||||
N->setReadMarker()->setModifiedMarker();
|
||||
|
||||
|
||||
const Type *ArgTy = F->getFunctionType()->getParamType(0);
|
||||
if (const PointerType *PTy = dyn_cast<PointerType>(ArgTy))
|
||||
N->mergeTypeInfo(PTy->getElementType(), H.getOffset());
|
||||
}
|
||||
return;
|
||||
} else if (CS.arg_end()-CS.arg_begin() == 4 &&
|
||||
} else if (CS.arg_end()-CS.arg_begin() == 4 &&
|
||||
(F->getName() == "fwrite" || F->getName() == "fread")) {
|
||||
// fread writes the first operand, fwrite reads it. They both
|
||||
// read/write the FILE descriptor, and merges the FILE type.
|
||||
|
@ -739,7 +739,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
AI != E; ++AI)
|
||||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker();
|
||||
N->setReadMarker();
|
||||
return;
|
||||
} else if (F->getName() == "fseek" || F->getName() == "fgetpos" ||
|
||||
F->getName() == "fsetpos") {
|
||||
|
@ -789,7 +789,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
// printf reads all pointer arguments.
|
||||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker();
|
||||
N->setReadMarker();
|
||||
}
|
||||
return;
|
||||
} else if (F->getName() == "vprintf" || F->getName() == "vfprintf" ||
|
||||
|
@ -825,7 +825,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
N->setReadMarker();
|
||||
++AI;
|
||||
}
|
||||
|
||||
|
||||
// Read the valist, and the pointed-to objects.
|
||||
if (AI != E && isPointerType((*AI)->getType())) {
|
||||
const DSNodeHandle &VAList = getValueDest(**AI);
|
||||
|
@ -869,7 +869,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
// scanf writes all pointer arguments.
|
||||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setModifiedMarker();
|
||||
N->setModifiedMarker();
|
||||
}
|
||||
return;
|
||||
} else if (F->getName() == "strtok") {
|
||||
|
@ -905,7 +905,7 @@ void GraphBuilder::visitCallSite(CallSite CS) {
|
|||
if (isPointerType((*AI)->getType()))
|
||||
if (DSNode *N = getValueDest(**AI).getNode())
|
||||
N->setReadMarker();
|
||||
|
||||
|
||||
if (DSNode *N = H.getNode())
|
||||
N->setReadMarker();
|
||||
return;
|
||||
|
@ -1079,23 +1079,23 @@ static void BuildGlobalECs(DSGraph &GG, std::set<GlobalValue*> &ECGlobals) {
|
|||
GlobalValue *First = GVs[0];
|
||||
for (unsigned i = 1, e = GVs.size(); i != e; ++i)
|
||||
GlobalECs.unionSets(First, GVs[i]);
|
||||
|
||||
|
||||
// Next, get the leader element.
|
||||
assert(First == GlobalECs.getLeaderValue(First) &&
|
||||
"First did not end up being the leader?");
|
||||
|
||||
|
||||
// Next, remove all globals from the scalar map that are not the leader.
|
||||
assert(GVs[0] == First && "First had to be at the front!");
|
||||
for (unsigned i = 1, e = GVs.size(); i != e; ++i) {
|
||||
ECGlobals.insert(GVs[i]);
|
||||
SM.erase(SM.find(GVs[i]));
|
||||
}
|
||||
|
||||
|
||||
// Finally, change the global node to only contain the leader.
|
||||
I->clearGlobals();
|
||||
I->addGlobal(First);
|
||||
}
|
||||
|
||||
|
||||
DEBUG(GG.AssertGraphOK());
|
||||
}
|
||||
|
||||
|
@ -1151,7 +1151,7 @@ bool LocalDataStructures::runOnModule(Module &M) {
|
|||
GlobalsGraph = new DSGraph(GlobalECs, TD);
|
||||
{
|
||||
GraphBuilder GGB(*GlobalsGraph);
|
||||
|
||||
|
||||
// Add initializers for all of the globals to the globals graph.
|
||||
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
||||
I != E; ++I)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- Printer.cpp - Code for printing data structure graphs nicely -------===//
|
||||
//
|
||||
//
|
||||
// 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 implements the 'dot' graph printer.
|
||||
|
@ -76,7 +76,7 @@ static std::string getCaption(const DSNode *N, const DSGraph *G) {
|
|||
|
||||
EquivalenceClasses<GlobalValue*> *GlobalECs = 0;
|
||||
if (G) GlobalECs = &G->getGlobalECs();
|
||||
|
||||
|
||||
for (unsigned i = 0, e = N->getGlobalsList().size(); i != e; ++i) {
|
||||
WriteAsOperand(OS, N->getGlobalsList()[i], false, true, M);
|
||||
|
||||
|
@ -85,7 +85,7 @@ static std::string getCaption(const DSNode *N, const DSGraph *G) {
|
|||
EquivalenceClasses<GlobalValue*>::iterator I =
|
||||
GlobalECs->findValue(N->getGlobalsList()[i]);
|
||||
if (I != GlobalECs->end()) {
|
||||
unsigned NumMembers =
|
||||
unsigned NumMembers =
|
||||
std::distance(GlobalECs->member_begin(I), GlobalECs->member_end());
|
||||
if (NumMembers != 1) OS << " + " << (NumMembers-1) << " EC";
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
|
|||
return R;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// addCustomGraphFeatures - Use this graph writing hook to emit call nodes
|
||||
/// and the return node.
|
||||
///
|
||||
|
@ -156,7 +156,7 @@ struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
|
|||
std::stringstream OS;
|
||||
WriteAsOperand(OS, I->first, false, true, CurMod);
|
||||
GW.emitSimpleNode(I->first, "", OS.str());
|
||||
|
||||
|
||||
// Add edge from return node to real destination
|
||||
DSNode *DestNode = I->second.getNode();
|
||||
int EdgeDest = I->second.getOffset() >> DS::PointerShift;
|
||||
|
@ -241,7 +241,7 @@ void DSGraph::writeGraphToFile(std::ostream &O,
|
|||
std::string Filename = GraphName + ".dot";
|
||||
O << "Writing '" << Filename << "'...";
|
||||
std::ofstream F(Filename.c_str());
|
||||
|
||||
|
||||
if (F.good()) {
|
||||
print(F);
|
||||
unsigned NumCalls = shouldPrintAuxCalls() ?
|
||||
|
@ -329,7 +329,7 @@ static void printCollection(const Collection &C, std::ostream &O,
|
|||
<< GG.getGraphSize() << "+" << GG.getFunctionCalls().size() << "]\n";
|
||||
}
|
||||
|
||||
O << "\nGraphs contain [" << TotalNumNodes << "+" << TotalCallNodes
|
||||
O << "\nGraphs contain [" << TotalNumNodes << "+" << TotalCallNodes
|
||||
<< "] nodes total" << std::endl;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- Steensgaard.cpp - Context Insensitive Alias Analysis ---------------===//
|
||||
//
|
||||
//
|
||||
// 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 pass uses the data structure graphs to implement a simple context
|
||||
|
@ -59,7 +59,7 @@ namespace {
|
|||
|
||||
//------------------------------------------------
|
||||
// Implement the AliasAnalysis API
|
||||
//
|
||||
//
|
||||
|
||||
AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size);
|
||||
|
@ -140,12 +140,12 @@ bool Steens::runOnModule(Module &M) {
|
|||
for (std::list<DSCallSite>::iterator CI = Calls.begin(), E = Calls.end();
|
||||
CI != E;) {
|
||||
DSCallSite &CurCall = *CI++;
|
||||
|
||||
|
||||
// Loop over the called functions, eliminating as many as possible...
|
||||
std::vector<Function*> CallTargets;
|
||||
if (CurCall.isDirectCall())
|
||||
CallTargets.push_back(CurCall.getCalleeFunc());
|
||||
else
|
||||
else
|
||||
CurCall.getCalleeNode()->addFullFunctionList(CallTargets);
|
||||
|
||||
for (unsigned c = 0; c != CallTargets.size(); ) {
|
||||
|
@ -239,11 +239,11 @@ AliasAnalysis::AliasResult Steens::alias(const Value *V1, unsigned V1Size,
|
|||
AliasAnalysis::ModRefResult
|
||||
Steens::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
|
||||
AliasAnalysis::ModRefResult Result = ModRef;
|
||||
|
||||
|
||||
// Find the node in question.
|
||||
DSGraph::ScalarMapTy &GSM = ResultGraph->getScalarMap();
|
||||
DSGraph::ScalarMapTy::iterator I = GSM.find(P);
|
||||
|
||||
|
||||
if (I != GSM.end() && !I->second.isNull()) {
|
||||
DSNode *N = I->second.getNode();
|
||||
if (N->isComplete()) {
|
||||
|
@ -253,7 +253,7 @@ Steens::getModRefInfo(CallSite CS, Value *P, unsigned Size) {
|
|||
if (Function *F = CS.getCalledFunction())
|
||||
if (F->isExternal())
|
||||
return NoModRef;
|
||||
|
||||
|
||||
// Otherwise, if the node is complete, but it is only M or R, return this.
|
||||
// This can be useful for globals that should be marked const but are not.
|
||||
if (!N->isModified())
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- TopDownClosure.cpp - Compute the top-down interprocedure closure ---===//
|
||||
//
|
||||
//
|
||||
// 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 implements the TDDataStructures class, which represents the
|
||||
|
@ -135,7 +135,7 @@ bool TDDataStructures::runOnModule(Module &M) {
|
|||
delete IndCallMap.begin()->second;
|
||||
IndCallMap.erase(IndCallMap.begin());
|
||||
}
|
||||
|
||||
|
||||
|
||||
ArgsRemainIncomplete.clear();
|
||||
GlobalsGraph->removeTriviallyDeadNodes();
|
||||
|
@ -170,7 +170,7 @@ void TDDataStructures::ComputePostOrder(Function &F,hash_set<DSGraph*> &Visited,
|
|||
DSGraph &G = getOrCreateDSGraph(F);
|
||||
if (Visited.count(&G)) return;
|
||||
Visited.insert(&G);
|
||||
|
||||
|
||||
// Recursively traverse all of the callee graphs.
|
||||
for (DSGraph::fc_iterator CI = G.fc_begin(), CE = G.fc_end(); CI != CE; ++CI){
|
||||
Instruction *CallI = CI->getCallSite().getInstruction();
|
||||
|
@ -214,12 +214,12 @@ void TDDataStructures::InlineCallersIntoGraph(DSGraph &DSG) {
|
|||
// sites that call into this graph.
|
||||
std::vector<CallerCallEdge> EdgesFromCaller;
|
||||
std::map<DSGraph*, std::vector<CallerCallEdge> >::iterator
|
||||
CEI = CallerEdges.find(&DSG);
|
||||
CEI = CallerEdges.find(&DSG);
|
||||
if (CEI != CallerEdges.end()) {
|
||||
std::swap(CEI->second, EdgesFromCaller);
|
||||
CallerEdges.erase(CEI);
|
||||
}
|
||||
|
||||
|
||||
// Sort the caller sites to provide a by-caller-graph ordering.
|
||||
std::sort(EdgesFromCaller.begin(), EdgesFromCaller.end());
|
||||
|
||||
|
@ -267,7 +267,7 @@ void TDDataStructures::InlineCallersIntoGraph(DSGraph &DSG) {
|
|||
getParent()->getParent()->getName() << "'");
|
||||
DEBUG(std::cerr << ": " << CF.getFunctionType()->getNumParams()
|
||||
<< " args\n");
|
||||
|
||||
|
||||
// Get the formal argument and return nodes for the called function and
|
||||
// merge them with the cloned subgraph.
|
||||
DSCallSite T1 = DSG.getCallSiteForArguments(CF);
|
||||
|
@ -356,7 +356,7 @@ void TDDataStructures::InlineCallersIntoGraph(DSGraph &DSG) {
|
|||
// so we build up a new, private, graph that represents the calls of all
|
||||
// calls to this set of functions.
|
||||
std::vector<Function*> Callees;
|
||||
for (BUDataStructures::ActualCalleesTy::const_iterator I =
|
||||
for (BUDataStructures::ActualCalleesTy::const_iterator I =
|
||||
BUInfo->callee_begin(CallI), E = BUInfo->callee_end(CallI);
|
||||
I != E; ++I)
|
||||
if (!I->second->isExternal())
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
//===- Expressions.cpp - Expression Analysis Utilities --------------------===//
|
||||
//
|
||||
//
|
||||
// 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 defines a package of expression analysis utilties:
|
||||
//
|
||||
// ClassifyExpression: Analyze an expression to determine the complexity of the
|
||||
// expression, and which other variables it depends on.
|
||||
// expression, and which other variables it depends on.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -23,7 +23,7 @@
|
|||
using namespace llvm;
|
||||
|
||||
ExprType::ExprType(Value *Val) {
|
||||
if (Val)
|
||||
if (Val)
|
||||
if (ConstantInt *CPI = dyn_cast<ConstantInt>(Val)) {
|
||||
Offset = CPI;
|
||||
Var = 0;
|
||||
|
@ -37,7 +37,7 @@ ExprType::ExprType(Value *Val) {
|
|||
Scale = 0;
|
||||
}
|
||||
|
||||
ExprType::ExprType(const ConstantInt *scale, Value *var,
|
||||
ExprType::ExprType(const ConstantInt *scale, Value *var,
|
||||
const ConstantInt *offset) {
|
||||
Scale = var ? scale : 0; Var = var; Offset = offset;
|
||||
ExprTy = Scale ? ScaledLinear : (Var ? Linear : Constant);
|
||||
|
@ -67,12 +67,12 @@ namespace {
|
|||
inline operator const ConstantInt * () const { return Val; }
|
||||
inline const ConstantInt *operator->() const { return Val; }
|
||||
};
|
||||
|
||||
|
||||
struct DefZero : public DefVal {
|
||||
inline DefZero(const ConstantInt *val, const Type *ty) : DefVal(val, ty) {}
|
||||
inline DefZero(const ConstantInt *val) : DefVal(val, val->getType()) {}
|
||||
};
|
||||
|
||||
|
||||
struct DefOne : public DefVal {
|
||||
inline DefOne(const ConstantInt *val, const Type *ty) : DefVal(val, ty) {}
|
||||
};
|
||||
|
@ -160,7 +160,7 @@ static inline const ConstantInt *operator+(const DefOne &L, const DefOne &R) {
|
|||
// 3. If DefOne is true, a null return value indicates a value of 1, if DefOne
|
||||
// is false, a null return value indicates a value of 0.
|
||||
//
|
||||
static inline const ConstantInt *Mul(const ConstantInt *Arg1,
|
||||
static inline const ConstantInt *Mul(const ConstantInt *Arg1,
|
||||
const ConstantInt *Arg2, bool DefOne) {
|
||||
assert(Arg1 && Arg2 && "No null arguments should exist now!");
|
||||
assert(Arg1->getType() == Arg2->getType() && "Types must be compatible!");
|
||||
|
@ -168,7 +168,7 @@ static inline const ConstantInt *Mul(const ConstantInt *Arg1,
|
|||
// Actually perform the computation now!
|
||||
Constant *Result = ConstantExpr::get(Instruction::Mul, (Constant*)Arg1,
|
||||
(Constant*)Arg2);
|
||||
assert(Result && Result->getType() == Arg1->getType() &&
|
||||
assert(Result && Result->getType() == Arg1->getType() &&
|
||||
"Couldn't perform multiplication!");
|
||||
ConstantInt *ResultI = cast<ConstantInt>(Result);
|
||||
|
||||
|
@ -257,7 +257,7 @@ ExprType llvm::ClassifyExpr(Value *Expr) {
|
|||
return Expr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Instruction *I = cast<Instruction>(Expr);
|
||||
const Type *Ty = I->getType();
|
||||
|
||||
|
@ -277,7 +277,7 @@ ExprType llvm::ClassifyExpr(Value *Expr) {
|
|||
return handleAddition(Left, RightNeg, I);
|
||||
} // end case Instruction::Sub
|
||||
|
||||
case Instruction::Shl: {
|
||||
case Instruction::Shl: {
|
||||
ExprType Right(ClassifyExpr(I->getOperand(1)));
|
||||
if (Right.ExprTy != ExprType::Constant) break;
|
||||
ExprType Left(ClassifyExpr(I->getOperand(0)));
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- Andersens.cpp - Andersen's Interprocedural Alias Analysis ----------===//
|
||||
//
|
||||
//
|
||||
// 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 defines a very simple implementation of Andersen's interprocedural
|
||||
|
@ -43,8 +43,8 @@
|
|||
//
|
||||
// Future Improvements:
|
||||
// This implementation of Andersen's algorithm is extremely slow. To make it
|
||||
// scale reasonably well, the inclusion constraints could be sorted (easy),
|
||||
// offline variable substitution would be a huge win (straight-forward), and
|
||||
// scale reasonably well, the inclusion constraints could be sorted (easy),
|
||||
// offline variable substitution would be a huge win (straight-forward), and
|
||||
// online cycle elimination (trickier) might help as well.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -137,7 +137,7 @@ namespace {
|
|||
std::map<Value*, unsigned> ValueNodes;
|
||||
|
||||
/// ObjectNodes - This map contains entries for each memory object in the
|
||||
/// program: globals, alloca's and mallocs.
|
||||
/// program: globals, alloca's and mallocs.
|
||||
std::map<Value*, unsigned> ObjectNodes;
|
||||
|
||||
/// ReturnNodes - This map contains an entry for each function in the
|
||||
|
@ -161,7 +161,7 @@ namespace {
|
|||
Constraint(ConstraintType Ty, Node *D, Node *S)
|
||||
: Type(Ty), Dest(D), Src(S) {}
|
||||
};
|
||||
|
||||
|
||||
/// Constraints - This vector contains a list of all of the constraints
|
||||
/// identified by the program.
|
||||
std::vector<Constraint> Constraints;
|
||||
|
@ -193,7 +193,7 @@ namespace {
|
|||
NullPtr = 1,
|
||||
NullObject = 2,
|
||||
};
|
||||
|
||||
|
||||
public:
|
||||
bool runOnModule(Module &M) {
|
||||
InitializeAliasAnalysis(this);
|
||||
|
@ -209,7 +209,7 @@ namespace {
|
|||
ReturnNodes.clear();
|
||||
VarargNodes.clear();
|
||||
EscapingInternalFunctions.clear();
|
||||
std::vector<Constraint>().swap(Constraints);
|
||||
std::vector<Constraint>().swap(Constraints);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -232,7 +232,7 @@ namespace {
|
|||
|
||||
//------------------------------------------------
|
||||
// Implement the AliasAnalysis API
|
||||
//
|
||||
//
|
||||
AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size);
|
||||
ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size);
|
||||
|
@ -265,7 +265,7 @@ namespace {
|
|||
}
|
||||
return &GraphNodes[I->second];
|
||||
}
|
||||
|
||||
|
||||
/// getObject - Return the node corresponding to the memory object for the
|
||||
/// specified global or allocation instruction.
|
||||
Node *getObject(Value *V) {
|
||||
|
@ -415,7 +415,7 @@ void Andersens::getMustAliases(Value *P, std::vector<Value*> &RetVals) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
AliasAnalysis::getMustAliases(P, RetVals);
|
||||
}
|
||||
|
||||
|
@ -572,7 +572,7 @@ void Andersens::AddGlobalInitializerConstraints(Node *N, Constant *C) {
|
|||
if (C->getType()->isFirstClassType()) {
|
||||
if (isa<PointerType>(C->getType()))
|
||||
N->copyFrom(getNodeForConstantPointer(C));
|
||||
|
||||
|
||||
} else if (C->isNullValue()) {
|
||||
N->addPointerTo(&GraphNodes[NullObject]);
|
||||
return;
|
||||
|
@ -607,7 +607,7 @@ bool Andersens::AddConstraintsForExternalCall(CallSite CS, Function *F) {
|
|||
F->getName() == "atol" || F->getName() == "atoll" ||
|
||||
F->getName() == "remove" || F->getName() == "unlink" ||
|
||||
F->getName() == "rename" || F->getName() == "memcmp" ||
|
||||
F->getName() == "llvm.memset" ||
|
||||
F->getName() == "llvm.memset" ||
|
||||
F->getName() == "strcmp" || F->getName() == "strncmp" ||
|
||||
F->getName() == "execl" || F->getName() == "execlp" ||
|
||||
F->getName() == "execle" || F->getName() == "execv" ||
|
||||
|
@ -703,7 +703,7 @@ void Andersens::CollectConstraints(Module &M) {
|
|||
&GraphNodes[UniversalSet]));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
|
||||
// Make the function address point to the function object.
|
||||
getNodeValue(*F)->addPointerTo(getObject(F)->setValue(F));
|
||||
|
@ -902,7 +902,7 @@ void Andersens::AddConstraintsForCall(CallSite CS, Function *F) {
|
|||
&GraphNodes[UniversalSet],
|
||||
getReturnNode(F)));
|
||||
}
|
||||
|
||||
|
||||
Function::arg_iterator AI = F->arg_begin(), AE = F->arg_end();
|
||||
CallSite::arg_iterator ArgI = CS.arg_begin(), ArgE = CS.arg_end();
|
||||
for (; AI != AE && ArgI != ArgE; ++AI, ++ArgI)
|
||||
|
@ -920,7 +920,7 @@ void Andersens::AddConstraintsForCall(CallSite CS, Function *F) {
|
|||
&GraphNodes[UniversalSet],
|
||||
getNode(*ArgI)));
|
||||
}
|
||||
|
||||
|
||||
// Copy all pointers passed through the varargs section to the varargs node.
|
||||
if (F->getFunctionType()->isVarArg())
|
||||
for (; ArgI != ArgE; ++ArgI)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- CallGraph.cpp - Build a Module's call graph ------------------------===//
|
||||
//
|
||||
//
|
||||
// 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 implements the CallGraph class.
|
||||
|
@ -57,7 +57,7 @@ void CallGraph::addToCallGraph(Function *F) {
|
|||
Root = Node; // Found a main, keep track of it!
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// If this function is not defined in this translation unit, it could call
|
||||
// anything.
|
||||
if (F->isExternal() && !F->getIntrinsicID())
|
||||
|
@ -113,7 +113,7 @@ bool CallGraph::runOnModule(Module &M) {
|
|||
|
||||
// If we didn't find a main function, use the external call graph node
|
||||
if (Root == 0) Root = ExternalCallingNode;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ void CallGraph::print(std::ostream &OS, const Module *M) const {
|
|||
OS << F->getName() << "\n";
|
||||
else
|
||||
OS << "<<null function: 0x" << getRoot() << ">>\n";
|
||||
|
||||
|
||||
for (CallGraph::const_iterator I = begin(), E = end(); I != E; ++I)
|
||||
I->second->print(OS);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- CallGraphSCCPass.cpp - Pass that operates BU on call graph ---------===//
|
||||
//
|
||||
//
|
||||
// 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 implements the CallGraphSCCPass class, which is used for passes
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
//===- FindUnsafePointerTypes.cpp - Check pointer usage safety ------------===//
|
||||
//
|
||||
//
|
||||
// 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 defines a pass that can be used to determine, interprocedurally,
|
||||
// This file defines a pass that can be used to determine, interprocedurally,
|
||||
// which pointer types are accessed unsafely in a program. If there is an
|
||||
// "unsafe" access to a specific pointer type, transformations that depend on
|
||||
// type safety cannot be permitted.
|
||||
|
@ -20,7 +20,7 @@
|
|||
//
|
||||
// Currently, the only allowed operations on pointer types are:
|
||||
// alloca, malloc, free, getelementptr, load, and store
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Analysis/FindUnsafePointerTypes.h"
|
||||
|
@ -37,7 +37,7 @@ X("unsafepointertypes", "Find Unsafe Pointer Types");
|
|||
// Provide a command line option to turn on printing of which instructions cause
|
||||
// a type to become invalid
|
||||
//
|
||||
static cl::opt<bool>
|
||||
static cl::opt<bool>
|
||||
PrintFailures("printunsafeptrinst", cl::Hidden,
|
||||
cl::desc("Print Unsafe Pointer Access Instructions"));
|
||||
|
||||
|
@ -96,9 +96,9 @@ void FindUnsafePointerTypes::print(std::ostream &o, const Module *M) const {
|
|||
|
||||
o << "SafePointerAccess Analysis: Found these unsafe types:\n";
|
||||
unsigned Counter = 1;
|
||||
for (std::set<PointerType*>::const_iterator I = getUnsafeTypes().begin(),
|
||||
for (std::set<PointerType*>::const_iterator I = getUnsafeTypes().begin(),
|
||||
E = getUnsafeTypes().end(); I != E; ++I, ++Counter) {
|
||||
|
||||
|
||||
o << " #" << Counter << ". ";
|
||||
CW << **I << "\n";
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- FindUsedTypes.cpp - Find all Types used by a module ----------------===//
|
||||
//
|
||||
//
|
||||
// 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 pass is used to seek out all of the types in use by the program. Note
|
||||
|
@ -32,10 +32,10 @@ void FindUsedTypes::stub() {}
|
|||
// collection of used types.
|
||||
//
|
||||
void FindUsedTypes::IncorporateType(const Type *Ty) {
|
||||
// If ty doesn't already exist in the used types map, add it now, otherwise
|
||||
// If ty doesn't already exist in the used types map, add it now, otherwise
|
||||
// return.
|
||||
if (!UsedTypes.insert(Ty).second) return; // Already contain Ty.
|
||||
|
||||
|
||||
// Make sure to add any types this type references now.
|
||||
//
|
||||
for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end();
|
||||
|
@ -45,7 +45,7 @@ void FindUsedTypes::IncorporateType(const Type *Ty) {
|
|||
|
||||
void FindUsedTypes::IncorporateValue(const Value *V) {
|
||||
IncorporateType(V->getType());
|
||||
|
||||
|
||||
// If this is a constant, it could be using other types...
|
||||
if (const Constant *C = dyn_cast<Constant>(V)) {
|
||||
if (!isa<GlobalValue>(C))
|
||||
|
@ -71,21 +71,21 @@ bool FindUsedTypes::runOnModule(Module &m) {
|
|||
for (Module::iterator MI = m.begin(), ME = m.end(); MI != ME; ++MI) {
|
||||
IncorporateType(MI->getType());
|
||||
const Function &F = *MI;
|
||||
|
||||
|
||||
// Loop over all of the instructions in the function, adding their return
|
||||
// type as well as the types of their operands.
|
||||
//
|
||||
for (const_inst_iterator II = inst_begin(F), IE = inst_end(F);
|
||||
II != IE; ++II) {
|
||||
const Instruction &I = *II;
|
||||
|
||||
|
||||
IncorporateType(I.getType()); // Incorporate the type of the instruction
|
||||
for (User::const_op_iterator OI = I.op_begin(), OE = I.op_end();
|
||||
OI != OE; ++OI)
|
||||
IncorporateValue(*OI); // Insert inst operand types as well
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- GlobalsModRef.cpp - Simple Mod/Ref Analysis for Globals ------------===//
|
||||
//
|
||||
//
|
||||
// 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 simple pass provides alias and mod/ref information for global values
|
||||
|
@ -58,7 +58,7 @@ namespace {
|
|||
return I->second;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// FunctionEffect - Capture whether or not this function reads or writes to
|
||||
/// ANY memory. If not, we can do a lot of aggressive analysis on it.
|
||||
unsigned FunctionEffect;
|
||||
|
@ -92,7 +92,7 @@ namespace {
|
|||
|
||||
//------------------------------------------------
|
||||
// Implement the AliasAnalysis API
|
||||
//
|
||||
//
|
||||
AliasResult alias(const Value *V1, unsigned V1Size,
|
||||
const Value *V2, unsigned V2Size);
|
||||
ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size);
|
||||
|
@ -111,7 +111,7 @@ namespace {
|
|||
return DoesNotAccessMemory;
|
||||
else if ((FR->FunctionEffect & Mod) == 0)
|
||||
return OnlyReadsMemory;
|
||||
return AliasAnalysis::getModRefBehavior(F, CS, Info);
|
||||
return AliasAnalysis::getModRefBehavior(F, CS, Info);
|
||||
}
|
||||
|
||||
virtual void deleteValue(Value *V);
|
||||
|
@ -134,7 +134,7 @@ namespace {
|
|||
bool AnalyzeUsesOfGlobal(Value *V, std::vector<Function*> &Readers,
|
||||
std::vector<Function*> &Writers);
|
||||
};
|
||||
|
||||
|
||||
RegisterOpt<GlobalsModRef> X("globalsmodref-aa",
|
||||
"Simple mod/ref analysis for globals");
|
||||
RegisterAnalysisGroup<AliasAnalysis, GlobalsModRef> Y;
|
||||
|
@ -211,7 +211,7 @@ bool GlobalsModRef::AnalyzeUsesOfGlobal(Value *V,
|
|||
return true;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(*UI)) {
|
||||
if (AnalyzeUsesOfGlobal(GV, Readers, Writers)) return true;
|
||||
} else {
|
||||
|
@ -223,7 +223,7 @@ bool GlobalsModRef::AnalyzeUsesOfGlobal(Value *V,
|
|||
/// AnalyzeCallGraph - At this point, we know the functions where globals are
|
||||
/// immediately stored to and read from. Propagate this information up the call
|
||||
/// graph to all callers and compute the mod/ref info for all memory for each
|
||||
/// function.
|
||||
/// function.
|
||||
void GlobalsModRef::AnalyzeCallGraph(CallGraph &CG, Module &M) {
|
||||
// We do a bottom-up SCC traversal of the call graph. In other words, we
|
||||
// visit all callees before callers (leaf-first).
|
||||
|
@ -298,13 +298,13 @@ void GlobalsModRef::AnalyzeSCC(std::vector<CallGraphNode *> &SCC) {
|
|||
FunctionInfo.erase(SCC[i]->getFunction());
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise, unless we already know that this function mod/refs memory, scan
|
||||
// the function bodies to see if there are any explicit loads or stores.
|
||||
if (FunctionEffect != ModRef) {
|
||||
for (unsigned i = 0, e = SCC.size(); i != e && FunctionEffect != ModRef;++i)
|
||||
for (inst_iterator II = inst_begin(SCC[i]->getFunction()),
|
||||
E = inst_end(SCC[i]->getFunction());
|
||||
E = inst_end(SCC[i]->getFunction());
|
||||
II != E && FunctionEffect != ModRef; ++II)
|
||||
if (isa<LoadInst>(*II))
|
||||
FunctionEffect |= Ref;
|
||||
|
@ -334,7 +334,7 @@ static const GlobalValue *getUnderlyingObject(const Value *V) {
|
|||
|
||||
// If we are at some type of object... return it.
|
||||
if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) return GV;
|
||||
|
||||
|
||||
// Traverse through different addressing mechanisms...
|
||||
if (const Instruction *I = dyn_cast<Instruction>(V)) {
|
||||
if (isa<CastInst>(I) || isa<GetElementPtrInst>(I))
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- PrintSCC.cpp - Enumerate SCCs in some key graphs -------------------===//
|
||||
//
|
||||
//
|
||||
// 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 provides passes to print out SCCs in a CFG or a CallGraph.
|
||||
|
@ -17,10 +17,10 @@
|
|||
// analyze -cfgscc to print the SCCs in each CFG of a module.
|
||||
// analyze -cfgscc -stats to print the #SCCs and the maximum SCC size.
|
||||
// analyze -cfgscc -debug > /dev/null to watch the algorithm in action.
|
||||
//
|
||||
//
|
||||
// and similarly:
|
||||
// analyze -callscc [-stats] [-debug] to print SCCs in the CallGraph
|
||||
//
|
||||
//
|
||||
// (3) To test the scc_iterator.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
//===-- InstCount.cpp - Collects the count of all instructions ------------===//
|
||||
//
|
||||
//
|
||||
// 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 pass collects the count of all instructions and reports them
|
||||
// This pass collects the count of all instructions and reports them
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
@ -62,11 +62,11 @@ namespace {
|
|||
//
|
||||
bool InstCount::runOnFunction(Function &F) {
|
||||
unsigned StartMemInsts =
|
||||
NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst +
|
||||
NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst +
|
||||
NumInvokeInst + NumAllocaInst + NumMallocInst + NumFreeInst;
|
||||
visit(F);
|
||||
unsigned EndMemInsts =
|
||||
NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst +
|
||||
NumGetElementPtrInst + NumLoadInst + NumStoreInst + NumCallInst +
|
||||
NumInvokeInst + NumAllocaInst + NumMallocInst + NumFreeInst;
|
||||
TotalMemInst += EndMemInsts-StartMemInsts;
|
||||
return false;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- Interval.cpp - Interval class code ---------------------------------===//
|
||||
//
|
||||
//
|
||||
// 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 contains the definition of the Interval class, which represents a
|
||||
|
@ -39,7 +39,7 @@ bool Interval::isLoop() const {
|
|||
void Interval::print(std::ostream &o) const {
|
||||
o << "-------------------------------------------------------------\n"
|
||||
<< "Interval Contents:\n";
|
||||
|
||||
|
||||
// Print out all of the basic blocks in the interval...
|
||||
for (std::vector<BasicBlock*>::const_iterator I = Nodes.begin(),
|
||||
E = Nodes.end(); I != E; ++I)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- IntervalPartition.cpp - Interval Partition module code -------------===//
|
||||
//
|
||||
//
|
||||
// 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 contains the definition of the IntervalPartition class, which
|
||||
|
@ -55,7 +55,7 @@ void IntervalPartition::addIntervalToPartition(Interval *I) {
|
|||
//
|
||||
void IntervalPartition::updatePredecessors(Interval *Int) {
|
||||
BasicBlock *Header = Int->getHeaderNode();
|
||||
for (Interval::succ_iterator I = Int->Successors.begin(),
|
||||
for (Interval::succ_iterator I = Int->Successors.begin(),
|
||||
E = Int->Successors.end(); I != E; ++I)
|
||||
getBlockInterval(*I)->Predecessors.push_back(Header);
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- LoadValueNumbering.cpp - Load Value #'ing Implementation -*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// 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 implements a value numbering pass that value numbers load and call
|
||||
|
@ -39,16 +39,16 @@ using namespace llvm;
|
|||
namespace {
|
||||
// FIXME: This should not be a FunctionPass.
|
||||
struct LoadVN : public FunctionPass, public ValueNumbering {
|
||||
|
||||
|
||||
/// Pass Implementation stuff. This doesn't do any analysis.
|
||||
///
|
||||
bool runOnFunction(Function &) { return false; }
|
||||
|
||||
|
||||
/// getAnalysisUsage - Does not modify anything. It uses Value Numbering
|
||||
/// and Alias Analysis.
|
||||
///
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
|
||||
|
||||
/// getEqualNumberNodes - Return nodes with the same value number as the
|
||||
/// specified Value. This fills in the argument vector with any equal
|
||||
/// values.
|
||||
|
@ -63,7 +63,7 @@ namespace {
|
|||
virtual void deleteValue(Value *V) {
|
||||
getAnalysis<AliasAnalysis>().deleteValue(V);
|
||||
}
|
||||
|
||||
|
||||
/// copyValue - This method should be used whenever a preexisting value in
|
||||
/// the program is copied or cloned, introducing a new value. Note that
|
||||
/// analysis implementations should tolerate clients that use this method to
|
||||
|
@ -109,7 +109,7 @@ static bool isPathTransparentTo(BasicBlock *CurBlock, BasicBlock *Dom,
|
|||
// stop searching, returning success.
|
||||
if (CurBlock == Dom || !Visited.insert(CurBlock).second)
|
||||
return true;
|
||||
|
||||
|
||||
// Check whether this block is known transparent or not.
|
||||
std::map<BasicBlock*, bool>::iterator TBI =
|
||||
TransparentBlocks.lower_bound(CurBlock);
|
||||
|
@ -125,7 +125,7 @@ static bool isPathTransparentTo(BasicBlock *CurBlock, BasicBlock *Dom,
|
|||
} else if (!TBI->second)
|
||||
// This block is known non-transparent, so that path can't be either.
|
||||
return false;
|
||||
|
||||
|
||||
// The current block is known to be transparent. The entire path is
|
||||
// transparent if all of the predecessors paths to the parent is also
|
||||
// transparent to the memory location.
|
||||
|
@ -180,7 +180,7 @@ void LoadVN::getCallEqualNumberNodes(CallInst *CI,
|
|||
if (AllOperandsEqual)
|
||||
IdenticalCalls.push_back(C);
|
||||
}
|
||||
|
||||
|
||||
if (IdenticalCalls.empty()) return;
|
||||
|
||||
// Eliminate duplicates, which could occur if we chose a value that is passed
|
||||
|
@ -212,7 +212,7 @@ void LoadVN::getCallEqualNumberNodes(CallInst *CI,
|
|||
Instruction *First = CI, *Second = C;
|
||||
if (!DomSetInfo.dominates(CI, C))
|
||||
std::swap(First, Second);
|
||||
|
||||
|
||||
// Scan the instructions between the calls, checking for stores or
|
||||
// calls to dangerous functions.
|
||||
BasicBlock::iterator I = First;
|
||||
|
@ -283,7 +283,7 @@ void LoadVN::getEqualNumberNodes(Value *V,
|
|||
LoadInst *LI = cast<LoadInst>(V);
|
||||
if (LI->isVolatile())
|
||||
return getAnalysis<ValueNumbering>().getEqualNumberNodes(V, RetVals);
|
||||
|
||||
|
||||
Value *LoadPtr = LI->getOperand(0);
|
||||
BasicBlock *LoadBB = LI->getParent();
|
||||
Function *F = LoadBB->getParent();
|
||||
|
@ -351,14 +351,14 @@ void LoadVN::getEqualNumberNodes(Value *V,
|
|||
// no need to do any global analysis at all.
|
||||
if (LoadInvalidatedInBBBefore && LoadInvalidatedInBBAfter)
|
||||
return;
|
||||
|
||||
|
||||
// Now that we know the value is not neccesarily killed on entry or exit to
|
||||
// the BB, find out how many load and store instructions (to this location)
|
||||
// live in each BB in the function.
|
||||
//
|
||||
std::map<BasicBlock*, unsigned> CandidateLoads;
|
||||
std::set<BasicBlock*> CandidateStores;
|
||||
|
||||
|
||||
for (Value::use_iterator UI = LoadPtr->use_begin(), UE = LoadPtr->use_end();
|
||||
UI != UE; ++UI)
|
||||
if (LoadInst *Cand = dyn_cast<LoadInst>(*UI)) {// Is a load of source?
|
||||
|
@ -476,7 +476,7 @@ void LoadVN::getEqualNumberNodes(Value *V,
|
|||
|
||||
// Stores in the load-bb are handled above.
|
||||
CandidateStores.erase(LoadBB);
|
||||
|
||||
|
||||
for (std::set<BasicBlock*>::iterator I = CandidateStores.begin(),
|
||||
E = CandidateStores.end(); I != E; ++I)
|
||||
if (DomSetInfo.dominates(*I, LoadBB)) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- LoopInfo.cpp - Natural Loop Calculator -----------------------------===//
|
||||
//
|
||||
//
|
||||
// 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 defines the LoopInfo class that is used to identify natural loops
|
||||
|
@ -175,7 +175,7 @@ Loop *LoopInfo::ConsiderForLoop(BasicBlock *BB, const DominatorSet &DS) {
|
|||
std::find(SLP->SubLoops.begin(), SLP->SubLoops.end(), SubLoop);
|
||||
assert(I != SLP->SubLoops.end() && "SubLoop not a child of parent?");
|
||||
SLP->SubLoops.erase(I); // Remove from parent...
|
||||
|
||||
|
||||
// Add the subloop to THIS loop...
|
||||
SubLoop->ParentLoop = L;
|
||||
L->SubLoops.push_back(SubLoop);
|
||||
|
@ -183,7 +183,7 @@ Loop *LoopInfo::ConsiderForLoop(BasicBlock *BB, const DominatorSet &DS) {
|
|||
|
||||
// Normal case, add the block to our loop...
|
||||
L->Blocks.push_back(X);
|
||||
|
||||
|
||||
// Add all of the predecessors of X to the end of the work stack...
|
||||
TodoStack.insert(TodoStack.end(), pred_begin(X), pred_end(X));
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ Loop *LoopInfo::ConsiderForLoop(BasicBlock *BB, const DominatorSet &DS) {
|
|||
--i; // We just shrunk the SubLoops list.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,8 +263,8 @@ void LoopInfo::MoveSiblingLoopInto(Loop *NewChild, Loop *NewParent) {
|
|||
assert(I != OldParent->SubLoops.end() && "Parent fields incorrect??");
|
||||
OldParent->SubLoops.erase(I); // Remove from parent's subloops list
|
||||
NewChild->ParentLoop = 0;
|
||||
|
||||
InsertLoopInto(NewChild, NewParent);
|
||||
|
||||
InsertLoopInto(NewChild, NewParent);
|
||||
}
|
||||
|
||||
/// InsertLoopInto - This inserts loop L into the specified parent loop. If the
|
||||
|
@ -273,13 +273,13 @@ void LoopInfo::MoveSiblingLoopInto(Loop *NewChild, Loop *NewParent) {
|
|||
void LoopInfo::InsertLoopInto(Loop *L, Loop *Parent) {
|
||||
BasicBlock *LHeader = L->getHeader();
|
||||
assert(Parent->contains(LHeader) && "This loop should not be inserted here!");
|
||||
|
||||
|
||||
// Check to see if it belongs in a child loop...
|
||||
for (unsigned i = 0, e = Parent->SubLoops.size(); i != e; ++i)
|
||||
if (Parent->SubLoops[i]->contains(LHeader)) {
|
||||
InsertLoopInto(L, Parent->SubLoops[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If not, insert it here!
|
||||
Parent->SubLoops.push_back(L);
|
||||
|
@ -325,7 +325,7 @@ void LoopInfo::removeBlock(BasicBlock *BB) {
|
|||
if (I != BBMap.end()) {
|
||||
for (Loop *L = I->second; L; L = L->getParentLoop())
|
||||
L->removeBlockFromLoop(BB);
|
||||
|
||||
|
||||
BBMap.erase(I);
|
||||
}
|
||||
}
|
||||
|
@ -367,7 +367,7 @@ BasicBlock *Loop::getLoopPreheader() const {
|
|||
return 0; // Multiple predecessors outside the loop
|
||||
Out = *PI;
|
||||
}
|
||||
|
||||
|
||||
// Make sure there is only one exit out of the preheader...
|
||||
succ_iterator SI = succ_begin(Out);
|
||||
++SI;
|
||||
|
@ -439,7 +439,7 @@ Value *Loop::getTripCount() const {
|
|||
Instruction *Inc = getCanonicalInductionVariableIncrement();
|
||||
if (Inc == 0) return 0;
|
||||
PHINode *IV = cast<PHINode>(Inc->getOperand(0));
|
||||
|
||||
|
||||
BasicBlock *BackedgeBlock =
|
||||
IV->getIncomingBlock(contains(IV->getIncomingBlock(1)));
|
||||
|
||||
|
@ -453,7 +453,7 @@ Value *Loop::getTripCount() const {
|
|||
} else if (SCI->getOpcode() == Instruction::SetEQ) {
|
||||
return SCI->getOperand(1);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- PostDominators.cpp - Post-Dominator Calculation --------------------===//
|
||||
//
|
||||
//
|
||||
// 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 implements the post-dominator construction algorithms.
|
||||
|
@ -73,7 +73,7 @@ bool PostDominatorSet::runOnFunction(Function &F) {
|
|||
//
|
||||
while (Doms[*SI].size() == 0) ++SI;
|
||||
WorkingSet = Doms[*SI];
|
||||
|
||||
|
||||
for (++SI; SI != SE; ++SI) { // Intersect all of the successor sets
|
||||
DomSetType &SuccSet = Doms[*SI];
|
||||
if (SuccSet.size())
|
||||
|
@ -115,7 +115,7 @@ void ImmediatePostDominators::calcIDoms(const DominatorSetBase &DS) {
|
|||
// Loop over all of the nodes that have dominators... figuring out the IDOM
|
||||
// for each node...
|
||||
//
|
||||
for (DominatorSet::const_iterator DI = DS.begin(), DEnd = DS.end();
|
||||
for (DominatorSet::const_iterator DI = DS.begin(), DEnd = DS.end();
|
||||
DI != DEnd; ++DI) {
|
||||
BasicBlock *BB = DI->first;
|
||||
const DominatorSet::DomSetType &Dominators = DI->second;
|
||||
|
@ -133,7 +133,7 @@ void ImmediatePostDominators::calcIDoms(const DominatorSetBase &DS) {
|
|||
for (; I != End; ++I) { // Iterate over dominators...
|
||||
// All of our dominators should form a chain, where the number of elements
|
||||
// in the dominator set indicates what level the node is at in the chain.
|
||||
// We want the node immediately above us, so it will have an identical
|
||||
// We want the node immediately above us, so it will have an identical
|
||||
// dominator set, except that BB will not dominate it... therefore it's
|
||||
// dominator set size will be one less than BB's...
|
||||
//
|
||||
|
@ -191,12 +191,12 @@ void PostDominatorTree::calculate(const PostDominatorSet &DS) {
|
|||
// dominator set size will be one less than BB's...
|
||||
//
|
||||
if (DS.getDominators(*I).size() == DomSetSize - 1) {
|
||||
// We know that the immediate dominator should already have a node,
|
||||
// We know that the immediate dominator should already have a node,
|
||||
// because we are traversing the CFG in depth first order!
|
||||
//
|
||||
Node *IDomNode = Nodes[*I];
|
||||
assert(IDomNode && "No node for IDOM?");
|
||||
|
||||
|
||||
// Add a new tree node for this BasicBlock, and link it as a child of
|
||||
// IDomNode
|
||||
Nodes[BB] = IDomNode->addChild(new Node(BB, IDomNode));
|
||||
|
@ -214,7 +214,7 @@ static RegisterAnalysis<PostDominanceFrontier>
|
|||
H("postdomfrontier", "Post-Dominance Frontier Construction", true);
|
||||
|
||||
const DominanceFrontier::DomSetType &
|
||||
PostDominanceFrontier::calculate(const PostDominatorTree &DT,
|
||||
PostDominanceFrontier::calculate(const PostDominatorTree &DT,
|
||||
const DominatorTree::Node *Node) {
|
||||
// Loop over CFG successors to calculate DFlocal[Node]
|
||||
BasicBlock *BB = Node->getBlock();
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- ProfileInfo.cpp - Profile Info Interface ---------------------------===//
|
||||
//
|
||||
//
|
||||
// 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 implements the abstract ProfileInfo interface, and the default
|
||||
|
@ -83,7 +83,7 @@ unsigned ProfileInfo::getExecutionCount(BasicBlock *BB) const {
|
|||
|
||||
namespace {
|
||||
struct NoProfileInfo : public ImmutablePass, public ProfileInfo {};
|
||||
|
||||
|
||||
// Register this pass...
|
||||
RegisterOpt<NoProfileInfo>
|
||||
X("no-profile", "No Profile Information");
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- ProfileInfoLoad.cpp - Load profile information from disk -----------===//
|
||||
//
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// The ProfileInfoLoader class is used to load and represent profiling
|
||||
|
@ -26,9 +26,9 @@ using namespace llvm;
|
|||
//
|
||||
static inline unsigned ByteSwap(unsigned Var, bool Really) {
|
||||
if (!Really) return Var;
|
||||
return ((Var & (255<< 0)) << 24) |
|
||||
((Var & (255<< 8)) << 8) |
|
||||
((Var & (255<<16)) >> 8) |
|
||||
return ((Var & (255<< 0)) << 24) |
|
||||
((Var & (255<< 8)) << 8) |
|
||||
((Var & (255<<16)) >> 8) |
|
||||
((Var & (255<<24)) >> 24);
|
||||
}
|
||||
|
||||
|
@ -57,7 +57,7 @@ static void ReadProfilingBlock(const char *ToolName, FILE *F,
|
|||
// Make sure we have enough space...
|
||||
if (Data.size() < NumEntries)
|
||||
Data.resize(NumEntries);
|
||||
|
||||
|
||||
// Accumulate the data we just read into the data.
|
||||
if (!ShouldByteSwap) {
|
||||
for (unsigned i = 0; i != NumEntries; ++i)
|
||||
|
@ -112,11 +112,11 @@ ProfileInfoLoader::ProfileInfoLoader(const char *ToolName,
|
|||
CommandLines.push_back(std::string(&Chars[0], &Chars[ArgLength]));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case FunctionInfo:
|
||||
ReadProfilingBlock(ToolName, F, ShouldByteSwap, FunctionCounts);
|
||||
break;
|
||||
|
||||
|
||||
case BlockInfo:
|
||||
ReadProfilingBlock(ToolName, F, ShouldByteSwap, BlockCounts);
|
||||
break;
|
||||
|
@ -134,7 +134,7 @@ ProfileInfoLoader::ProfileInfoLoader(const char *ToolName,
|
|||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fclose(F);
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ void ProfileInfoLoader::getFunctionCounts(std::vector<std::pair<Function*,
|
|||
// their entry blocks were executed.
|
||||
std::vector<std::pair<BasicBlock*, unsigned> > BlockCounts;
|
||||
getBlockCounts(BlockCounts);
|
||||
|
||||
|
||||
for (unsigned i = 0, e = BlockCounts.size(); i != e; ++i)
|
||||
if (&BlockCounts[i].first->getParent()->front() == BlockCounts[i].first)
|
||||
Counts.push_back(std::make_pair(BlockCounts[i].first->getParent(),
|
||||
|
@ -161,7 +161,7 @@ void ProfileInfoLoader::getFunctionCounts(std::vector<std::pair<Function*,
|
|||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
unsigned Counter = 0;
|
||||
for (Module::iterator I = M.begin(), E = M.end();
|
||||
I != E && Counter != FunctionCounts.size(); ++I)
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- ProfileInfoLoaderPass.cpp - LLVM Pass to load profile info ---------===//
|
||||
//
|
||||
//
|
||||
// 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 implements a concrete implementation of profiling information that
|
||||
|
@ -48,7 +48,7 @@ namespace {
|
|||
/// run - Load the profile information from the specified file.
|
||||
virtual bool runOnModule(Module &M);
|
||||
};
|
||||
|
||||
|
||||
RegisterPass<LoaderPass>
|
||||
X("profile-loader", "Load profile information from llvmprof.out",
|
||||
PassInfo::Analysis|PassInfo::Optimization);
|
||||
|
@ -69,7 +69,7 @@ bool LoaderPass::runOnModule(Module &M) {
|
|||
ProfileInfoLoader PIL("profile-loader", Filename, M);
|
||||
EdgeCounts.clear();
|
||||
bool PrintedWarning = false;
|
||||
|
||||
|
||||
std::vector<std::pair<ProfileInfoLoader::Edge, unsigned> > ECs;
|
||||
PIL.getEdgeCounts(ECs);
|
||||
for (unsigned i = 0, e = ECs.size(); i != e; ++i) {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- ScalarEvolution.cpp - Scalar Evolution Analysis ----------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// 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 contains the implementation of the scalar evolution analysis
|
||||
|
@ -28,7 +28,7 @@
|
|||
// have folders that are used to build the *canonical* representation for a
|
||||
// particular expression. These folders are capable of using a variety of
|
||||
// rewrite rules to simplify the expressions.
|
||||
//
|
||||
//
|
||||
// Once the folders are defined, we can implement the more interesting
|
||||
// higher-level code, such as the code that recognizes PHI nodes of various
|
||||
// types, computes the execution count of a loop, etc.
|
||||
|
@ -163,7 +163,7 @@ bool SCEVCouldNotCompute::classof(const SCEV *S) {
|
|||
// particular value. Don't use a SCEVHandle here, or else the object will
|
||||
// never be deleted!
|
||||
static std::map<ConstantInt*, SCEVConstant*> SCEVConstants;
|
||||
|
||||
|
||||
|
||||
SCEVConstant::~SCEVConstant() {
|
||||
SCEVConstants.erase(V);
|
||||
|
@ -175,7 +175,7 @@ SCEVHandle SCEVConstant::get(ConstantInt *V) {
|
|||
const Type *NewTy = V->getType()->getUnsignedVersion();
|
||||
V = cast<ConstantUInt>(ConstantExpr::getCast(V, NewTy));
|
||||
}
|
||||
|
||||
|
||||
SCEVConstant *&R = SCEVConstants[V];
|
||||
if (R == 0) R = new SCEVConstant(V);
|
||||
return R;
|
||||
|
@ -337,7 +337,7 @@ replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym,
|
|||
for (++i; i != e; ++i)
|
||||
NewOps.push_back(getOperand(i)->
|
||||
replaceSymbolicValuesWithConcrete(Sym, Conc));
|
||||
|
||||
|
||||
return get(NewOps, L);
|
||||
}
|
||||
}
|
||||
|
@ -451,7 +451,7 @@ static void GroupByComplexity(std::vector<SCEVHandle> &Ops) {
|
|||
/// specified signed integer value and return a SCEV for the constant.
|
||||
SCEVHandle SCEVUnknown::getIntegerSCEV(int Val, const Type *Ty) {
|
||||
Constant *C;
|
||||
if (Val == 0)
|
||||
if (Val == 0)
|
||||
C = Constant::getNullValue(Ty);
|
||||
else if (Ty->isFloatingPoint())
|
||||
C = ConstantFP::get(Ty, Val);
|
||||
|
@ -483,7 +483,7 @@ static SCEVHandle getTruncateOrZeroExtend(const SCEVHandle &V, const Type *Ty) {
|
|||
SCEVHandle SCEV::getNegativeSCEV(const SCEVHandle &V) {
|
||||
if (SCEVConstant *VC = dyn_cast<SCEVConstant>(V))
|
||||
return SCEVUnknown::get(ConstantExpr::getNeg(VC->getValue()));
|
||||
|
||||
|
||||
return SCEVMulExpr::get(V, SCEVUnknown::getIntegerSCEV(-1, V->getType()));
|
||||
}
|
||||
|
||||
|
@ -511,7 +511,7 @@ static SCEVHandle PartialFact(SCEVHandle V, unsigned NumSteps) {
|
|||
const Type *Ty = V->getType();
|
||||
if (NumSteps == 0)
|
||||
return SCEVUnknown::getIntegerSCEV(1, Ty);
|
||||
|
||||
|
||||
SCEVHandle Result = V;
|
||||
for (unsigned i = 1; i != NumSteps; ++i)
|
||||
Result = SCEVMulExpr::get(Result, SCEV::getMinusSCEV(V,
|
||||
|
@ -623,7 +623,7 @@ SCEVHandle SCEVAddExpr::get(std::vector<SCEVHandle> &Ops) {
|
|||
}
|
||||
|
||||
if (Ops.size() == 1) return Ops[0];
|
||||
|
||||
|
||||
// Okay, check to see if the same value occurs in the operand list twice. If
|
||||
// so, merge them together into an multiply expression. Since we sorted the
|
||||
// list, these values are required to be adjacent.
|
||||
|
@ -696,7 +696,7 @@ SCEVHandle SCEVAddExpr::get(std::vector<SCEVHandle> &Ops) {
|
|||
Ops.push_back(OuterMul);
|
||||
return SCEVAddExpr::get(Ops);
|
||||
}
|
||||
|
||||
|
||||
// Check this multiply against other multiplies being added together.
|
||||
for (unsigned OtherMulIdx = Idx+1;
|
||||
OtherMulIdx < Ops.size() && isa<SCEVMulExpr>(Ops[OtherMulIdx]);
|
||||
|
@ -868,7 +868,7 @@ SCEVHandle SCEVMulExpr::get(std::vector<SCEVHandle> &Ops) {
|
|||
|
||||
if (Ops.size() == 1)
|
||||
return Ops[0];
|
||||
|
||||
|
||||
// If there are mul operands inline them all into this expression.
|
||||
if (Idx < Ops.size()) {
|
||||
bool DeletedMul = false;
|
||||
|
@ -1086,7 +1086,7 @@ namespace {
|
|||
/// properties. An instruction maps to null if we are unable to compute its
|
||||
/// exit value.
|
||||
std::map<PHINode*, Constant*> ConstantEvolutionLoopExitValue;
|
||||
|
||||
|
||||
public:
|
||||
ScalarEvolutionsImpl(Function &f, LoopInfo &li)
|
||||
: F(f), LI(li), UnknownValue(new SCEVCouldNotCompute()) {}
|
||||
|
@ -1230,7 +1230,7 @@ SCEVHandle ScalarEvolutionsImpl::createNodeForPHI(PHINode *PN) {
|
|||
// from outside the loop, and one from inside.
|
||||
unsigned IncomingEdge = L->contains(PN->getIncomingBlock(0));
|
||||
unsigned BackEdge = IncomingEdge^1;
|
||||
|
||||
|
||||
// While we are analyzing this PHI node, handle its value symbolically.
|
||||
SCEVHandle SymbolicName = SCEVUnknown::get(PN);
|
||||
assert(Scalars.find(PN) == Scalars.end() &&
|
||||
|
@ -1286,7 +1286,7 @@ SCEVHandle ScalarEvolutionsImpl::createNodeForPHI(PHINode *PN) {
|
|||
|
||||
return SymbolicName;
|
||||
}
|
||||
|
||||
|
||||
// If it's not a loop phi, we can't handle it yet.
|
||||
return SCEVUnknown::get(PN);
|
||||
}
|
||||
|
@ -1296,11 +1296,11 @@ SCEVHandle ScalarEvolutionsImpl::createNodeForPHI(PHINode *PN) {
|
|||
SCEVHandle ScalarEvolutionsImpl::createNodeForCast(CastInst *CI) {
|
||||
const Type *SrcTy = CI->getOperand(0)->getType();
|
||||
const Type *DestTy = CI->getType();
|
||||
|
||||
|
||||
// If this is a noop cast (ie, conversion from int to uint), ignore it.
|
||||
if (SrcTy->isLosslesslyConvertibleTo(DestTy))
|
||||
return getSCEV(CI->getOperand(0));
|
||||
|
||||
|
||||
if (SrcTy->isInteger() && DestTy->isInteger()) {
|
||||
// Otherwise, if this is a truncating integer cast, we can represent this
|
||||
// cast.
|
||||
|
@ -1486,7 +1486,7 @@ SCEVHandle ScalarEvolutionsImpl::ComputeIterationCount(const Loop *L) {
|
|||
if (CompVal) {
|
||||
// Form the constant range.
|
||||
ConstantRange CompRange(Cond, CompVal);
|
||||
|
||||
|
||||
// Now that we have it, if it's signed, convert it to an unsigned
|
||||
// range.
|
||||
if (CompRange.getLower()->getType()->isSigned()) {
|
||||
|
@ -1495,12 +1495,12 @@ SCEVHandle ScalarEvolutionsImpl::ComputeIterationCount(const Loop *L) {
|
|||
Constant *NewU = ConstantExpr::getCast(CompRange.getUpper(), NewTy);
|
||||
CompRange = ConstantRange(NewL, NewU);
|
||||
}
|
||||
|
||||
|
||||
SCEVHandle Ret = AddRec->getNumIterationsInRange(CompRange);
|
||||
if (!isa<SCEVCouldNotCompute>(Ret)) return Ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (Cond) {
|
||||
case Instruction::SetNE: // while (X != Y)
|
||||
// Convert to: while (X-Y != 0)
|
||||
|
@ -1545,7 +1545,7 @@ EvaluateConstantChrecAtConstant(const SCEVAddRecExpr *AddRec, Constant *C) {
|
|||
/// the addressed element of the initializer or null if the index expression is
|
||||
/// invalid.
|
||||
static Constant *
|
||||
GetAddressedElementFromGlobal(GlobalVariable *GV,
|
||||
GetAddressedElementFromGlobal(GlobalVariable *GV,
|
||||
const std::vector<ConstantInt*> &Indices) {
|
||||
Constant *Init = GV->getInitializer();
|
||||
for (unsigned i = 0, e = Indices.size(); i != e; ++i) {
|
||||
|
@ -1577,7 +1577,7 @@ GetAddressedElementFromGlobal(GlobalVariable *GV,
|
|||
/// ComputeLoadConstantCompareIterationCount - Given an exit condition of
|
||||
/// 'setcc load X, cst', try to se if we can compute the trip count.
|
||||
SCEVHandle ScalarEvolutionsImpl::
|
||||
ComputeLoadConstantCompareIterationCount(LoadInst *LI, Constant *RHS,
|
||||
ComputeLoadConstantCompareIterationCount(LoadInst *LI, Constant *RHS,
|
||||
const Loop *L, unsigned SetCCOpcode) {
|
||||
if (LI->isVolatile()) return UnknownValue;
|
||||
|
||||
|
@ -1656,7 +1656,7 @@ static bool CanConstantFold(const Instruction *I) {
|
|||
if (isa<BinaryOperator>(I) || isa<ShiftInst>(I) ||
|
||||
isa<SelectInst>(I) || isa<CastInst>(I) || isa<GetElementPtrInst>(I))
|
||||
return true;
|
||||
|
||||
|
||||
if (const CallInst *CI = dyn_cast<CallInst>(I))
|
||||
if (const Function *F = CI->getCalledFunction())
|
||||
return canConstantFoldCallTo((Function*)F); // FIXME: elim cast
|
||||
|
@ -1713,7 +1713,7 @@ static PHINode *getConstantEvolvingPHI(Value *V, const Loop *L) {
|
|||
// If we won't be able to constant fold this expression even if the operands
|
||||
// are constants, return early.
|
||||
if (!CanConstantFold(I)) return 0;
|
||||
|
||||
|
||||
// Otherwise, we can evaluate this instruction if all of its operands are
|
||||
// constant or derived from a PHI node themselves.
|
||||
PHINode *PHI = 0;
|
||||
|
@ -1765,7 +1765,7 @@ getConstantEvolutionLoopExitValue(PHINode *PN, uint64_t Its, const Loop *L) {
|
|||
if (I != ConstantEvolutionLoopExitValue.end())
|
||||
return I->second;
|
||||
|
||||
if (Its > MaxBruteForceIterations)
|
||||
if (Its > MaxBruteForceIterations)
|
||||
return ConstantEvolutionLoopExitValue[PN] = 0; // Not going to evaluate it.
|
||||
|
||||
Constant *&RetVal = ConstantEvolutionLoopExitValue[PN];
|
||||
|
@ -1842,7 +1842,7 @@ ComputeIterationCountExhaustively(const Loop *L, Value *Cond, bool ExitWhen) {
|
|||
++NumBruteForceTripCountsComputed;
|
||||
return SCEVConstant::get(ConstantUInt::get(Type::UIntTy, IterationNum));
|
||||
}
|
||||
|
||||
|
||||
// Compute the value of the PHI node for the next iteration.
|
||||
Constant *NextPHI = EvaluateExpression(BEValue, PHIVal);
|
||||
if (NextPHI == 0 || NextPHI == PHIVal)
|
||||
|
@ -1861,7 +1861,7 @@ SCEVHandle ScalarEvolutionsImpl::getSCEVAtScope(SCEV *V, const Loop *L) {
|
|||
// FIXME: this should be turned into a virtual method on SCEV!
|
||||
|
||||
if (isa<SCEVConstant>(V)) return V;
|
||||
|
||||
|
||||
// If this instruction is evolves from a constant-evolving PHI, compute the
|
||||
// exit value from the loop without using SCEVs.
|
||||
if (SCEVUnknown *SU = dyn_cast<SCEVUnknown>(V)) {
|
||||
|
@ -1966,7 +1966,7 @@ SCEVHandle ScalarEvolutionsImpl::getSCEVAtScope(SCEV *V, const Loop *L) {
|
|||
if (IterationCount == UnknownValue) return UnknownValue;
|
||||
IterationCount = getTruncateOrZeroExtend(IterationCount,
|
||||
AddRec->getType());
|
||||
|
||||
|
||||
// If the value is affine, simplify the expression evaluation to just
|
||||
// Start + Step*IterationCount.
|
||||
if (AddRec->isAffine())
|
||||
|
@ -1995,7 +1995,7 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
|
|||
SCEVConstant *L = dyn_cast<SCEVConstant>(AddRec->getOperand(0));
|
||||
SCEVConstant *M = dyn_cast<SCEVConstant>(AddRec->getOperand(1));
|
||||
SCEVConstant *N = dyn_cast<SCEVConstant>(AddRec->getOperand(2));
|
||||
|
||||
|
||||
// We currently can only solve this if the coefficients are constants.
|
||||
if (!L || !M || !N) {
|
||||
SCEV *CNC = new SCEVCouldNotCompute();
|
||||
|
@ -2003,7 +2003,7 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
|
|||
}
|
||||
|
||||
Constant *Two = ConstantInt::get(L->getValue()->getType(), 2);
|
||||
|
||||
|
||||
// Convert from chrec coefficients to polynomial coefficients AX^2+BX+C
|
||||
Constant *C = L->getValue();
|
||||
// The B coefficient is M-N/2
|
||||
|
@ -2012,7 +2012,7 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
|
|||
Two));
|
||||
// The A coefficient is N/2
|
||||
Constant *A = ConstantExpr::getDiv(N->getValue(), Two);
|
||||
|
||||
|
||||
// Compute the B^2-4ac term.
|
||||
Constant *SqrtTerm =
|
||||
ConstantExpr::getMul(ConstantInt::get(C->getType(), 4),
|
||||
|
@ -2035,16 +2035,16 @@ SolveQuadraticEquation(const SCEVAddRecExpr *AddRec) {
|
|||
|
||||
SqrtVal = ConstantUInt::get(Type::ULongTy, SqrtValV2);
|
||||
SqrtTerm = ConstantExpr::getCast(SqrtVal, SqrtTerm->getType());
|
||||
|
||||
|
||||
Constant *NegB = ConstantExpr::getNeg(B);
|
||||
Constant *TwoA = ConstantExpr::getMul(A, Two);
|
||||
|
||||
|
||||
// The divisions must be performed as signed divisions.
|
||||
const Type *SignedTy = NegB->getType()->getSignedVersion();
|
||||
NegB = ConstantExpr::getCast(NegB, SignedTy);
|
||||
TwoA = ConstantExpr::getCast(TwoA, SignedTy);
|
||||
SqrtTerm = ConstantExpr::getCast(SqrtTerm, SignedTy);
|
||||
|
||||
|
||||
Constant *Solution1 =
|
||||
ConstantExpr::getDiv(ConstantExpr::getAdd(NegB, SqrtTerm), TwoA);
|
||||
Constant *Solution2 =
|
||||
|
@ -2117,7 +2117,7 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToZero(SCEV *V, const Loop *L) {
|
|||
R2->getValue()))) {
|
||||
if (CB != ConstantBool::True)
|
||||
std::swap(R1, R2); // R1 is the minimum root now.
|
||||
|
||||
|
||||
// We can only use this value if the chrec ends up with an exact zero
|
||||
// value at this index. When solving for "X*X != 5", for example, we
|
||||
// should not accept a root of 2.
|
||||
|
@ -2128,7 +2128,7 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToZero(SCEV *V, const Loop *L) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return UnknownValue;
|
||||
}
|
||||
|
||||
|
@ -2139,7 +2139,7 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToNonZero(SCEV *V, const Loop *L) {
|
|||
// Loops that look like: while (X == 0) are very strange indeed. We don't
|
||||
// handle them yet except for the trivial case. This could be expanded in the
|
||||
// future as needed.
|
||||
|
||||
|
||||
// If the value is a constant, check to see if it is known to be non-zero
|
||||
// already. If so, the backedge will execute zero times.
|
||||
if (SCEVConstant *C = dyn_cast<SCEVConstant>(V)) {
|
||||
|
@ -2149,7 +2149,7 @@ SCEVHandle ScalarEvolutionsImpl::HowFarToNonZero(SCEV *V, const Loop *L) {
|
|||
return getSCEV(Zero);
|
||||
return UnknownValue; // Otherwise it will loop infinitely.
|
||||
}
|
||||
|
||||
|
||||
// We could implement others, but I really doubt anyone writes loops like
|
||||
// this, and if they did, they would already be constant folded.
|
||||
return UnknownValue;
|
||||
|
@ -2191,7 +2191,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
|||
// iteration exits.
|
||||
ConstantInt *Zero = ConstantInt::get(getType(), 0);
|
||||
if (!Range.contains(Zero)) return SCEVConstant::get(Zero);
|
||||
|
||||
|
||||
if (isAffine()) {
|
||||
// If this is an affine expression then we have this situation:
|
||||
// Solve {0,+,A} in Range === Ax in Range
|
||||
|
@ -2246,7 +2246,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
|||
R2->getValue()))) {
|
||||
if (CB != ConstantBool::True)
|
||||
std::swap(R1, R2); // R1 is the minimum root now.
|
||||
|
||||
|
||||
// Make sure the root is not off by one. The returned iteration should
|
||||
// not be in the range, but the previous one should be. When solving
|
||||
// for "X*X < 5", for example, we should not return a root of 2.
|
||||
|
@ -2257,13 +2257,13 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
|||
Constant *NextVal =
|
||||
ConstantExpr::getAdd(R1->getValue(),
|
||||
ConstantInt::get(R1->getType(), 1));
|
||||
|
||||
|
||||
R1Val = EvaluateConstantChrecAtConstant(this, NextVal);
|
||||
if (!Range.contains(R1Val))
|
||||
return SCEVUnknown::get(NextVal);
|
||||
return new SCEVCouldNotCompute(); // Something strange happened
|
||||
}
|
||||
|
||||
|
||||
// If R1 was not in the range, then it is a good return value. Make
|
||||
// sure that R1-1 WAS in the range though, just in case.
|
||||
Constant *NextVal =
|
||||
|
@ -2298,7 +2298,7 @@ SCEVHandle SCEVAddRecExpr::getNumIterationsInRange(ConstantRange Range) const {
|
|||
// Increment to test the next index.
|
||||
TestVal = cast<ConstantInt>(ConstantExpr::getAdd(TestVal, One));
|
||||
} while (TestVal != EndVal);
|
||||
|
||||
|
||||
return new SCEVCouldNotCompute();
|
||||
}
|
||||
|
||||
|
@ -2343,12 +2343,12 @@ void ScalarEvolution::deleteInstructionFromRecords(Instruction *I) const {
|
|||
return ((ScalarEvolutionsImpl*)Impl)->deleteInstructionFromRecords(I);
|
||||
}
|
||||
|
||||
static void PrintLoopInfo(std::ostream &OS, const ScalarEvolution *SE,
|
||||
static void PrintLoopInfo(std::ostream &OS, const ScalarEvolution *SE,
|
||||
const Loop *L) {
|
||||
// Print all inner loops first
|
||||
for (Loop::iterator I = L->begin(), E = L->end(); I != E; ++I)
|
||||
PrintLoopInfo(OS, SE, *I);
|
||||
|
||||
|
||||
std::cerr << "Loop " << L->getHeader()->getName() << ": ";
|
||||
|
||||
std::vector<BasicBlock*> ExitBlocks;
|
||||
|
@ -2377,7 +2377,7 @@ void ScalarEvolution::print(std::ostream &OS, const Module* ) const {
|
|||
SCEVHandle SV = getSCEV(&*I);
|
||||
SV->print(OS);
|
||||
OS << "\t\t";
|
||||
|
||||
|
||||
if ((*I).getType()->isIntegral()) {
|
||||
ConstantRange Bounds = SV->getValueRange();
|
||||
if (!Bounds.isFullSet())
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===- ValueNumbering.cpp - Value #'ing Implementation ----------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// 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 implements the non-abstract Value Numbering methods as well as a
|
||||
|
@ -103,7 +103,7 @@ void BVNImpl::visitCastInst(CastInst &CI) {
|
|||
Instruction &I = (Instruction&)CI;
|
||||
Value *Op = I.getOperand(0);
|
||||
Function *F = I.getParent()->getParent();
|
||||
|
||||
|
||||
for (Value::use_iterator UI = Op->use_begin(), UE = Op->use_end();
|
||||
UI != UE; ++UI)
|
||||
if (CastInst *Other = dyn_cast<CastInst>(*UI))
|
||||
|
@ -130,12 +130,12 @@ static inline bool isIdenticalBinaryInst(const Instruction &I1,
|
|||
if (I1.getOpcode() != I2->getOpcode() ||
|
||||
I1.getParent()->getParent() != I2->getParent()->getParent())
|
||||
return false;
|
||||
|
||||
|
||||
// They are identical if both operands are the same!
|
||||
if (I1.getOperand(0) == I2->getOperand(0) &&
|
||||
I1.getOperand(1) == I2->getOperand(1))
|
||||
return true;
|
||||
|
||||
|
||||
// If the instruction is commutative, the instruction can match if the
|
||||
// operands are swapped!
|
||||
//
|
||||
|
@ -149,12 +149,12 @@ static inline bool isIdenticalBinaryInst(const Instruction &I1,
|
|||
|
||||
void BVNImpl::handleBinaryInst(Instruction &I) {
|
||||
Value *LHS = I.getOperand(0);
|
||||
|
||||
|
||||
for (Value::use_iterator UI = LHS->use_begin(), UE = LHS->use_end();
|
||||
UI != UE; ++UI)
|
||||
if (Instruction *Other = dyn_cast<Instruction>(*UI))
|
||||
// Check to see if this new binary operator is not I, but same operand...
|
||||
if (Other != &I && isIdenticalBinaryInst(I, Other)) {
|
||||
if (Other != &I && isIdenticalBinaryInst(I, Other)) {
|
||||
// These instructions are identical. Handle the situation.
|
||||
RetVals.push_back(Other);
|
||||
}
|
||||
|
@ -164,7 +164,7 @@ void BVNImpl::handleBinaryInst(Instruction &I) {
|
|||
// using a brute force comparison. This is useful for instructions with an
|
||||
// arbitrary number of arguments.
|
||||
//
|
||||
static inline bool IdenticalComplexInst(const Instruction *I1,
|
||||
static inline bool IdenticalComplexInst(const Instruction *I1,
|
||||
const Instruction *I2) {
|
||||
assert(I1->getOpcode() == I2->getOpcode());
|
||||
// Equal if they are in the same function...
|
||||
|
@ -187,7 +187,7 @@ void BVNImpl::visitGetElementPtrInst(GetElementPtrInst &I) {
|
|||
Op = I.getOperand(i);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
for (Value::use_iterator UI = Op->use_begin(), UE = Op->use_end();
|
||||
UI != UE; ++UI)
|
||||
if (GetElementPtrInst *Other = dyn_cast<GetElementPtrInst>(*UI))
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===-- Archive.cpp - Generic LLVM archive functions ------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by Reid Spencer and is distributed under the
|
||||
// This file was developed by Reid Spencer and is distributed under the
|
||||
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains the implementation of the Archive and ArchiveMember
|
||||
|
@ -30,7 +30,7 @@ ArchiveMember::getMemberSize() const {
|
|||
result += path.toString().length() + 1;
|
||||
|
||||
// If its now odd lengthed, include the padding byte
|
||||
if (result % 2 != 0 )
|
||||
if (result % 2 != 0 )
|
||||
result++;
|
||||
|
||||
return result;
|
||||
|
@ -38,27 +38,27 @@ ArchiveMember::getMemberSize() const {
|
|||
|
||||
// This default constructor is only use by the ilist when it creates its
|
||||
// sentry node. We give it specific static values to make it stand out a bit.
|
||||
ArchiveMember::ArchiveMember()
|
||||
ArchiveMember::ArchiveMember()
|
||||
: next(0), prev(0), parent(0), path("<invalid>"), flags(0), data(0)
|
||||
{
|
||||
info.user = sys::Process::GetCurrentUserId();
|
||||
info.group = sys::Process::GetCurrentGroupId();
|
||||
info.mode = 0777;
|
||||
info.fileSize = 0;
|
||||
info.group = sys::Process::GetCurrentGroupId();
|
||||
info.mode = 0777;
|
||||
info.fileSize = 0;
|
||||
info.modTime = sys::TimeValue::now();
|
||||
}
|
||||
|
||||
// This is the constructor that the Archive class uses when it is building or
|
||||
// reading an archive. It just defaults a few things and ensures the parent is
|
||||
// set for the iplist. The Archive class fills in the ArchiveMember's data.
|
||||
// This is required because correctly setting the data may depend on other
|
||||
// set for the iplist. The Archive class fills in the ArchiveMember's data.
|
||||
// This is required because correctly setting the data may depend on other
|
||||
// things in the Archive.
|
||||
ArchiveMember::ArchiveMember(Archive* PAR)
|
||||
: next(0), prev(0), parent(PAR), path(), flags(0), data(0)
|
||||
{
|
||||
}
|
||||
|
||||
// This method allows an ArchiveMember to be replaced with the data for a
|
||||
// This method allows an ArchiveMember to be replaced with the data for a
|
||||
// different file, presumably as an update to the member. It also makes sure
|
||||
// the flags are reset correctly.
|
||||
void ArchiveMember::replaceWith(const sys::Path& newFile) {
|
||||
|
@ -128,9 +128,9 @@ void ArchiveMember::replaceWith(const sys::Path& newFile) {
|
|||
}
|
||||
|
||||
// Archive constructor - this is the only constructor that gets used for the
|
||||
// Archive class. Everything else (default,copy) is deprecated. This just
|
||||
// Archive class. Everything else (default,copy) is deprecated. This just
|
||||
// initializes and maps the file into memory, if requested.
|
||||
Archive::Archive(const sys::Path& filename, bool map )
|
||||
Archive::Archive(const sys::Path& filename, bool map )
|
||||
: archPath(filename), members(), mapfile(0), base(0), symTab(), strtab(),
|
||||
symTabSize(0), firstFileOffset(0), modules(), foreignST(0)
|
||||
{
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===-- lib/Bytecode/ArchiveInternals.h -------------------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by Reid Spencer and is distributed under the
|
||||
// This file was developed by Reid Spencer and is distributed under the
|
||||
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Internal implementation header for LLVM Archive files.
|
||||
|
@ -18,8 +18,8 @@
|
|||
#include "llvm/System/TimeValue.h"
|
||||
#include "llvm/ADT/StringExtras.h"
|
||||
|
||||
#define ARFILE_MAGIC "!<arch>\n" ///< magic string
|
||||
#define ARFILE_MAGIC_LEN (sizeof(ARFILE_MAGIC)-1) ///< length of magic string
|
||||
#define ARFILE_MAGIC "!<arch>\n" ///< magic string
|
||||
#define ARFILE_MAGIC_LEN (sizeof(ARFILE_MAGIC)-1) ///< length of magic string
|
||||
#define ARFILE_SVR4_SYMTAB_NAME "/ " ///< SVR4 symtab entry name
|
||||
#define ARFILE_LLVM_SYMTAB_NAME "#_LLVM_SYM_TAB_#" ///< LLVM symtab entry name
|
||||
#define ARFILE_BSD4_SYMTAB_NAME "__.SYMDEF SORTED" ///< BSD4 symtab entry name
|
||||
|
@ -29,9 +29,9 @@
|
|||
|
||||
namespace llvm {
|
||||
|
||||
/// The ArchiveMemberHeader structure is used internally for bytecode
|
||||
/// archives.
|
||||
/// The header precedes each file member in the archive. This structure is
|
||||
/// The ArchiveMemberHeader structure is used internally for bytecode
|
||||
/// archives.
|
||||
/// The header precedes each file member in the archive. This structure is
|
||||
/// defined using character arrays for direct and correct interpretation
|
||||
/// regardless of the endianess of the machine that produced it.
|
||||
/// @brief Archive File Member Header
|
||||
|
@ -39,7 +39,7 @@ namespace llvm {
|
|||
/// @name Data
|
||||
/// @{
|
||||
public:
|
||||
char name[16]; ///< Name of the file member.
|
||||
char name[16]; ///< Name of the file member.
|
||||
char date[12]; ///< File date, decimal seconds since Epoch
|
||||
char uid[6]; ///< user id in ASCII decimal
|
||||
char gid[6]; ///< group id in ASCII decimal
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===-- ArchiveReader.cpp - Read LLVM archive files -------------*- C++ -*-===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by Reid Spencer and is distributed under the
|
||||
// This file was developed by Reid Spencer and is distributed under the
|
||||
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Builds up standard unix archive files (.a) containing LLVM bytecode.
|
||||
|
@ -20,9 +20,9 @@ using namespace llvm;
|
|||
inline unsigned readInteger(const char*&At, const char*End) {
|
||||
unsigned Shift = 0;
|
||||
unsigned Result = 0;
|
||||
|
||||
|
||||
do {
|
||||
if (At == End)
|
||||
if (At == End)
|
||||
throw std::string("Ran out of data reading vbr_uint!");
|
||||
Result |= (unsigned)((*At++) & 0x7F) << Shift;
|
||||
Shift += 7;
|
||||
|
@ -49,7 +49,7 @@ Archive::parseSymbolTable(const void* data, unsigned size) {
|
|||
|
||||
// This member parses an ArchiveMemberHeader that is presumed to be pointed to
|
||||
// by At. The At pointer is updated to the byte just after the header, which
|
||||
// can be variable in size.
|
||||
// can be variable in size.
|
||||
ArchiveMember*
|
||||
Archive::parseMemberHeader(const char*& At, const char* End) {
|
||||
assert(At + sizeof(ArchiveMemberHeader) < End && "Not enough data");
|
||||
|
@ -61,7 +61,7 @@ Archive::parseMemberHeader(const char*& At, const char* End) {
|
|||
// Instantiate the ArchiveMember to be filled
|
||||
ArchiveMember* member = new ArchiveMember(this);
|
||||
|
||||
// Extract the size and determine if the file is
|
||||
// Extract the size and determine if the file is
|
||||
// compressed or not (negative length).
|
||||
int flags = 0;
|
||||
int MemberSize = atoi(Hdr->size);
|
||||
|
@ -79,14 +79,14 @@ Archive::parseMemberHeader(const char*& At, const char* End) {
|
|||
throw std::string("invalid file member signature");
|
||||
|
||||
// Convert and check the member name
|
||||
// The empty name ( '/' and 15 blanks) is for a foreign (non-LLVM) symbol
|
||||
// table. The special name "//" and 14 blanks is for a string table, used
|
||||
// The empty name ( '/' and 15 blanks) is for a foreign (non-LLVM) symbol
|
||||
// table. The special name "//" and 14 blanks is for a string table, used
|
||||
// for long file names. This library doesn't generate either of those but
|
||||
// it will accept them. If the name starts with #1/ and the remainder is
|
||||
// digits, then those digits specify the length of the name that is
|
||||
// stored immediately following the header. The special name
|
||||
// __LLVM_SYM_TAB__ identifies the symbol table for LLVM bytecode.
|
||||
// Anything else is a regular, short filename that is terminated with
|
||||
// it will accept them. If the name starts with #1/ and the remainder is
|
||||
// digits, then those digits specify the length of the name that is
|
||||
// stored immediately following the header. The special name
|
||||
// __LLVM_SYM_TAB__ identifies the symbol table for LLVM bytecode.
|
||||
// Anything else is a regular, short filename that is terminated with
|
||||
// a '/' and blanks.
|
||||
|
||||
std::string pathname;
|
||||
|
@ -101,7 +101,7 @@ Archive::parseMemberHeader(const char*& At, const char* End) {
|
|||
flags |= ArchiveMember::HasLongFilenameFlag;
|
||||
} else
|
||||
throw std::string("invalid long filename");
|
||||
} else if (Hdr->name[1] == '_' &&
|
||||
} else if (Hdr->name[1] == '_' &&
|
||||
(0 == memcmp(Hdr->name, ARFILE_LLVM_SYMTAB_NAME, 16))) {
|
||||
// The member is using a long file name (>15 chars) format.
|
||||
// This format is standard for 4.4BSD and Mac OSX operating
|
||||
|
@ -152,7 +152,7 @@ Archive::parseMemberHeader(const char*& At, const char* End) {
|
|||
}
|
||||
break;
|
||||
case '_':
|
||||
if (Hdr->name[1] == '_' &&
|
||||
if (Hdr->name[1] == '_' &&
|
||||
(0 == memcmp(Hdr->name, ARFILE_BSD4_SYMTAB_NAME, 16))) {
|
||||
pathname.assign(ARFILE_BSD4_SYMTAB_NAME);
|
||||
flags |= ArchiveMember::BSD4SymbolTableFlag;
|
||||
|
@ -208,7 +208,7 @@ Archive::checkSignature() {
|
|||
throw std::string("invalid signature for an archive file");
|
||||
}
|
||||
|
||||
// This function loads the entire archive and fully populates its ilist with
|
||||
// This function loads the entire archive and fully populates its ilist with
|
||||
// the members of the archive file. This is typically used in preparation for
|
||||
// editing the contents of the archive.
|
||||
void
|
||||
|
@ -226,7 +226,7 @@ Archive::loadArchive() {
|
|||
bool seenSymbolTable = false;
|
||||
bool foundFirstFile = false;
|
||||
while (At < End) {
|
||||
// parse the member header
|
||||
// parse the member header
|
||||
const char* Save = At;
|
||||
ArchiveMember* mbr = parseMemberHeader(At, End);
|
||||
|
||||
|
@ -253,7 +253,7 @@ Archive::loadArchive() {
|
|||
if ((intptr_t(At) & 1) == 1)
|
||||
At++;
|
||||
delete mbr;
|
||||
} else if (mbr->isLLVMSymbolTable()) {
|
||||
} else if (mbr->isLLVMSymbolTable()) {
|
||||
// This is the LLVM symbol table for the archive. If we've seen it
|
||||
// already, its an error. Otherwise, parse the symbol table and move on.
|
||||
if (seenSymbolTable)
|
||||
|
@ -300,9 +300,9 @@ Archive::getAllModules(std::vector<Module*>& Modules, std::string* ErrMessage) {
|
|||
|
||||
for (iterator I=begin(), E=end(); I != E; ++I) {
|
||||
if (I->isBytecode() || I->isCompressedBytecode()) {
|
||||
std::string FullMemberName = archPath.toString() +
|
||||
std::string FullMemberName = archPath.toString() +
|
||||
"(" + I->getPath().toString() + ")";
|
||||
Module* M = ParseBytecodeBuffer((const unsigned char*)I->getData(),
|
||||
Module* M = ParseBytecodeBuffer((const unsigned char*)I->getData(),
|
||||
I->getSize(), FullMemberName, ErrMessage);
|
||||
if (!M)
|
||||
return true;
|
||||
|
@ -365,8 +365,8 @@ Archive::loadSymbolTable() {
|
|||
FirstFile = At;
|
||||
} else {
|
||||
// There's no symbol table in the file. We have to rebuild it from scratch
|
||||
// because the intent of this method is to get the symbol table loaded so
|
||||
// it can be searched efficiently.
|
||||
// because the intent of this method is to get the symbol table loaded so
|
||||
// it can be searched efficiently.
|
||||
// Add the member to the members list
|
||||
members.push_back(mbr);
|
||||
}
|
||||
|
@ -391,19 +391,19 @@ Archive::OpenAndLoadSymbols(const sys::Path& file, std::string* ErrorMessage) {
|
|||
|
||||
// Look up one symbol in the symbol table and return a ModuleProvider for the
|
||||
// module that defines that symbol.
|
||||
ModuleProvider*
|
||||
ModuleProvider*
|
||||
Archive::findModuleDefiningSymbol(const std::string& symbol) {
|
||||
SymTabType::iterator SI = symTab.find(symbol);
|
||||
if (SI == symTab.end())
|
||||
return 0;
|
||||
|
||||
// The symbol table was previously constructed assuming that the members were
|
||||
// The symbol table was previously constructed assuming that the members were
|
||||
// written without the symbol table header. Because VBR encoding is used, the
|
||||
// values could not be adjusted to account for the offset of the symbol table
|
||||
// because that could affect the size of the symbol table due to VBR encoding.
|
||||
// We now have to account for this by adjusting the offset by the size of the
|
||||
// We now have to account for this by adjusting the offset by the size of the
|
||||
// symbol table and its header.
|
||||
unsigned fileOffset =
|
||||
unsigned fileOffset =
|
||||
SI->second + // offset in symbol-table-less file
|
||||
firstFileOffset; // add offset to first "real" file in archive
|
||||
|
||||
|
@ -417,10 +417,10 @@ Archive::findModuleDefiningSymbol(const std::string& symbol) {
|
|||
ArchiveMember* mbr = parseMemberHeader(modptr, base + mapfile->size());
|
||||
|
||||
// Now, load the bytecode module to get the ModuleProvider
|
||||
std::string FullMemberName = archPath.toString() + "(" +
|
||||
std::string FullMemberName = archPath.toString() + "(" +
|
||||
mbr->getPath().toString() + ")";
|
||||
ModuleProvider* mp = getBytecodeBufferModuleProvider(
|
||||
(const unsigned char*) mbr->getData(), mbr->getSize(),
|
||||
(const unsigned char*) mbr->getData(), mbr->getSize(),
|
||||
FullMemberName, 0);
|
||||
|
||||
modules.insert(std::make_pair(fileOffset, std::make_pair(mp, mbr)));
|
||||
|
@ -428,7 +428,7 @@ Archive::findModuleDefiningSymbol(const std::string& symbol) {
|
|||
return mp;
|
||||
}
|
||||
|
||||
// Look up multiple symbols in the symbol table and return a set of
|
||||
// Look up multiple symbols in the symbol table and return a set of
|
||||
// ModuleProviders that define those symbols.
|
||||
void
|
||||
Archive::findModulesDefiningSymbols(std::set<std::string>& symbols,
|
||||
|
@ -454,16 +454,16 @@ Archive::findModulesDefiningSymbols(std::set<std::string>& symbols,
|
|||
|
||||
// If it contains symbols
|
||||
if (mbr->isBytecode() || mbr->isCompressedBytecode()) {
|
||||
// Get the symbols
|
||||
// Get the symbols
|
||||
std::vector<std::string> symbols;
|
||||
std::string FullMemberName = archPath.toString() + "(" +
|
||||
std::string FullMemberName = archPath.toString() + "(" +
|
||||
mbr->getPath().toString() + ")";
|
||||
ModuleProvider* MP = GetBytecodeSymbols((const unsigned char*)At,
|
||||
mbr->getSize(), FullMemberName, symbols);
|
||||
|
||||
if (MP) {
|
||||
// Insert the module's symbols into the symbol table
|
||||
for (std::vector<std::string>::iterator I = symbols.begin(),
|
||||
for (std::vector<std::string>::iterator I = symbols.begin(),
|
||||
E=symbols.end(); I != E; ++I ) {
|
||||
symTab.insert(std::make_pair(*I, offset));
|
||||
}
|
||||
|
@ -483,10 +483,10 @@ Archive::findModulesDefiningSymbols(std::set<std::string>& symbols,
|
|||
}
|
||||
}
|
||||
|
||||
// At this point we have a valid symbol table (one way or another) so we
|
||||
// At this point we have a valid symbol table (one way or another) so we
|
||||
// just use it to quickly find the symbols requested.
|
||||
|
||||
for (std::set<std::string>::iterator I=symbols.begin(),
|
||||
for (std::set<std::string>::iterator I=symbols.begin(),
|
||||
E=symbols.end(); I != E;) {
|
||||
// See if this symbol exists
|
||||
ModuleProvider* mp = findModuleDefiningSymbol(*I);
|
||||
|
@ -495,7 +495,7 @@ Archive::findModulesDefiningSymbols(std::set<std::string>& symbols,
|
|||
// duplicates wil be ignored
|
||||
result.insert(mp);
|
||||
|
||||
// Remove the symbol now that its been resolved, being careful to
|
||||
// Remove the symbol now that its been resolved, being careful to
|
||||
// post-increment the iterator.
|
||||
symbols.erase(I++);
|
||||
} else {
|
||||
|
@ -509,13 +509,13 @@ Archive::isBytecodeArchive()
|
|||
{
|
||||
//Make sure the symTab has been loaded...
|
||||
//in most cases this should have been done
|
||||
//when the archive was constructed, but still,
|
||||
//when the archive was constructed, but still,
|
||||
//this is just in case.
|
||||
if ( !symTab.size() )
|
||||
loadSymbolTable();
|
||||
|
||||
//Now that we know it's been loaded, return true
|
||||
//if it has a size
|
||||
//if it has a size
|
||||
if ( symTab.size() ) return true;
|
||||
|
||||
//We still can't be sure it isn't a bytecode archive
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//===-- ArchiveWriter.cpp - Write LLVM archive files ----------------------===//
|
||||
//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file was developed by Reid Spencer and is distributed under the
|
||||
// This file was developed by Reid Spencer and is distributed under the
|
||||
// University of Illinois Open Source License. See LICENSE.TXT for details.
|
||||
//
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Builds up an LLVM archive file (.a) containing LLVM bytecode.
|
||||
|
@ -30,7 +30,7 @@ inline void writeInteger(unsigned num, std::ofstream& ARFile) {
|
|||
ARFile << (unsigned char)num;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Nope, we are bigger than a character, output the next 7 bits and set the
|
||||
// high bit to say that there is more coming...
|
||||
ARFile << (unsigned char)(0x80 | ((unsigned char)num & 0x7F));
|
||||
|
@ -44,9 +44,9 @@ inline unsigned numVbrBytes(unsigned num) {
|
|||
|
||||
// Note that the following nested ifs are somewhat equivalent to a binary
|
||||
// search. We split it in half by comparing against 2^14 first. This allows
|
||||
// most reasonable values to be done in 2 comparisons instead of 1 for
|
||||
// most reasonable values to be done in 2 comparisons instead of 1 for
|
||||
// small ones and four for large ones. We expect this to access file offsets
|
||||
// in the 2^10 to 2^24 range and symbol lengths in the 2^0 to 2^8 range,
|
||||
// in the 2^10 to 2^24 range and symbol lengths in the 2^0 to 2^8 range,
|
||||
// so this approach is reasonable.
|
||||
if (num < 1<<14)
|
||||
if (num < 1<<7)
|
||||
|
@ -62,17 +62,17 @@ inline unsigned numVbrBytes(unsigned num) {
|
|||
}
|
||||
|
||||
// Create an empty archive.
|
||||
Archive*
|
||||
Archive*
|
||||
Archive::CreateEmpty(const sys::Path& FilePath ) {
|
||||
Archive* result = new Archive(FilePath,false);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Fill the ArchiveMemberHeader with the information from a member. If
|
||||
// Fill the ArchiveMemberHeader with the information from a member. If
|
||||
// TruncateNames is true, names are flattened to 15 chars or less. The sz field
|
||||
// is provided here instead of coming from the mbr because the member might be
|
||||
// stored compressed and the compressed size is not the ArchiveMember's size.
|
||||
// Furthermore compressed files have negative size fields to identify them as
|
||||
// is provided here instead of coming from the mbr because the member might be
|
||||
// stored compressed and the compressed size is not the ArchiveMember's size.
|
||||
// Furthermore compressed files have negative size fields to identify them as
|
||||
// compressed.
|
||||
bool
|
||||
Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr,
|
||||
|
@ -119,7 +119,7 @@ Archive::fillHeader(const ArchiveMember &mbr, ArchiveMemberHeader& hdr,
|
|||
nm += slashpos + 1;
|
||||
len -= slashpos +1;
|
||||
}
|
||||
if (len > 15)
|
||||
if (len > 15)
|
||||
len = 15;
|
||||
memcpy(hdr.name,nm,len);
|
||||
hdr.name[len] = '/';
|
||||
|
@ -190,7 +190,7 @@ Archive::writeMember(
|
|||
std::ofstream& ARFile,
|
||||
bool CreateSymbolTable,
|
||||
bool TruncateNames,
|
||||
bool ShouldCompress
|
||||
bool ShouldCompress
|
||||
) {
|
||||
|
||||
unsigned filepos = ARFile.tellp();
|
||||
|
@ -205,45 +205,45 @@ Archive::writeMember(
|
|||
mFile = new sys::MappedFile(member.getPath());
|
||||
data = (const char*) mFile->map();
|
||||
fSize = mFile->size();
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we have the data in memory, update the
|
||||
// Now that we have the data in memory, update the
|
||||
// symbol table if its a bytecode file.
|
||||
if (CreateSymbolTable &&
|
||||
if (CreateSymbolTable &&
|
||||
(member.isBytecode() || member.isCompressedBytecode())) {
|
||||
std::vector<std::string> symbols;
|
||||
std::string FullMemberName = archPath.toString() + "(" +
|
||||
member.getPath().toString()
|
||||
std::string FullMemberName = archPath.toString() + "(" +
|
||||
member.getPath().toString()
|
||||
+ ")";
|
||||
ModuleProvider* MP = GetBytecodeSymbols(
|
||||
(const unsigned char*)data,fSize,FullMemberName, symbols);
|
||||
|
||||
// If the bytecode parsed successfully
|
||||
if ( MP ) {
|
||||
for (std::vector<std::string>::iterator SI = symbols.begin(),
|
||||
for (std::vector<std::string>::iterator SI = symbols.begin(),
|
||||
SE = symbols.end(); SI != SE; ++SI) {
|
||||
|
||||
std::pair<SymTabType::iterator,bool> Res =
|
||||
std::pair<SymTabType::iterator,bool> Res =
|
||||
symTab.insert(std::make_pair(*SI,filepos));
|
||||
|
||||
if (Res.second) {
|
||||
symTabSize += SI->length() +
|
||||
numVbrBytes(SI->length()) +
|
||||
symTabSize += SI->length() +
|
||||
numVbrBytes(SI->length()) +
|
||||
numVbrBytes(filepos);
|
||||
}
|
||||
}
|
||||
// We don't need this module any more.
|
||||
delete MP;
|
||||
} else {
|
||||
throw std::string("Can't parse bytecode member: ") +
|
||||
throw std::string("Can't parse bytecode member: ") +
|
||||
member.getPath().toString();
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if we actually should compress this member
|
||||
bool willCompress =
|
||||
(ShouldCompress &&
|
||||
!member.isCompressed() &&
|
||||
bool willCompress =
|
||||
(ShouldCompress &&
|
||||
!member.isCompressed() &&
|
||||
!member.isCompressedBytecode() &&
|
||||
!member.isLLVMSymbolTable() &&
|
||||
!member.isSVR4SymbolTable() &&
|
||||
|
@ -266,7 +266,7 @@ Archive::writeMember(
|
|||
fSize = Compressor::compressToNewBuffer(data,fSize,output);
|
||||
data = output;
|
||||
if (member.isBytecode())
|
||||
hdrSize = -fSize-4;
|
||||
hdrSize = -fSize-4;
|
||||
else
|
||||
hdrSize = -fSize;
|
||||
} else {
|
||||
|
@ -361,15 +361,15 @@ Archive::writeSymbolTable(std::ofstream& ARFile) {
|
|||
}
|
||||
|
||||
// Write the entire archive to the file specified when the archive was created.
|
||||
// This writes to a temporary file first. Options are for creating a symbol
|
||||
// table, flattening the file names (no directories, 15 chars max) and
|
||||
// This writes to a temporary file first. Options are for creating a symbol
|
||||
// table, flattening the file names (no directories, 15 chars max) and
|
||||
// compressing each archive member.
|
||||
void
|
||||
Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress){
|
||||
|
||||
|
||||
// Make sure they haven't opened up the file, not loaded it,
|
||||
// but are now trying to write it which would wipe out the file.
|
||||
assert(!(members.empty() && mapfile->size() > 8) &&
|
||||
assert(!(members.empty() && mapfile->size() > 8) &&
|
||||
"Can't write an archive not opened for writing");
|
||||
|
||||
// Create a temporary file to store the archive in
|
||||
|
@ -385,7 +385,7 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress){
|
|||
std::ios::openmode io_mode = std::ios::out | std::ios::trunc |
|
||||
std::ios::binary;
|
||||
std::ofstream ArchiveFile(TmpArchive.c_str(), io_mode);
|
||||
|
||||
|
||||
// Check for errors opening or creating archive file.
|
||||
if ( !ArchiveFile.is_open() || ArchiveFile.bad() ) {
|
||||
throw std::string("Error opening archive file: ") + archPath.toString();
|
||||
|
@ -444,7 +444,7 @@ Archive::writeToDisk(bool CreateSymbolTable, bool TruncateNames, bool Compress){
|
|||
|
||||
// Copy the temporary file contents being sure to skip the file's magic
|
||||
// number.
|
||||
FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
|
||||
FinalFile.write(base + sizeof(ARFILE_MAGIC)-1,
|
||||
arch.size()-sizeof(ARFILE_MAGIC)+1);
|
||||
|
||||
// Close up shop
|
||||
|
|
Loading…
Reference in New Issue