#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringExtras.h"
-#include <iostream>
+#include "llvm/Support/Compiler.h"
#include <set>
using namespace llvm;
-namespace {
- Statistic<> NumArgumentsPromoted("argpromotion",
- "Number of pointer arguments promoted");
- Statistic<> NumAggregatesPromoted("argpromotion",
- "Number of aggregate arguments promoted");
- Statistic<> NumArgumentsDead("argpromotion",
- "Number of dead pointer args eliminated");
+STATISTIC(NumArgumentsPromoted , "Number of pointer arguments promoted");
+STATISTIC(NumAggregatesPromoted, "Number of aggregate arguments promoted");
+STATISTIC(NumArgumentsDead , "Number of dead pointer args eliminated");
+namespace {
/// ArgPromotion - The 'by reference' to 'by value' argument promotion pass.
///
- struct ArgPromotion : public CallGraphSCCPass {
+ struct VISIBILITY_HIDDEN ArgPromotion : public CallGraphSCCPass {
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequired<AliasAnalysis>();
AU.addRequired<TargetData>();
"Promote 'by reference' arguments to scalars");
}
-ModulePass *llvm::createArgumentPromotionPass() {
+Pass *llvm::createArgumentPromotionPass() {
return new ArgPromotion();
}
static bool AllCalleesPassInValidPointerForArgument(Argument *Arg) {
Function *Callee = Arg->getParent();
- unsigned ArgNo = std::distance(Callee->arg_begin(), Function::arg_iterator(Arg));
+ unsigned ArgNo = std::distance(Callee->arg_begin(),
+ Function::arg_iterator(Arg));
// Look at all call sites of the function. At this pointer we know we only
// have direct callees.
return true;
}
-/// AccessOccursOnPath - Returns true if and only if a load or GEP instruction
-/// on Pointer occurs in Path, or in every control-flow path that succeeds it.
-bool AccessOccursOnPath(Argument* Arg) {
- std::vector<BasicBlock*> Worklist;
- Worklist.push_back(Arg->getParent()->begin());
-
- std::set<BasicBlock*> Visited;
-
- while (!Worklist.empty()) {
- BasicBlock* BB = Worklist.back();
- Worklist.pop_back();
- Visited.insert(BB);
-
- bool ContainsAccess = false;
- for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I)
- if (isa<LoadInst>(I) || isa<GetElementPtrInst>(I)) {
- ContainsAccess = true;
- break;
- }
-
- if (ContainsAccess) continue;
-
- TerminatorInst* TI = BB->getTerminator();
- if (isa<BranchInst>(TI) || isa<SwitchInst>(TI)) {
- for (unsigned i = 0; i < TI->getNumSuccessors(); ++i)
- if (!Visited.count(TI->getSuccessor(i)))
- Worklist.push_back(TI->getSuccessor(i));
- } else {
- return false;
- }
- }
-
- return true;
-}
/// isSafeToPromoteArgument - As you might guess from the name of this method,
/// it checks to see if it is both safe and useful to promote the argument.
if (std::find(GEPIndices.begin(), GEPIndices.end(), Operands) ==
GEPIndices.end()) {
if (GEPIndices.size() == 3) {
- DEBUG(std::cerr << "argpromotion disable promoting argument '"
- << Arg->getName() << "' because it would require adding more "
- << "than 3 arguments to the function.\n");
+ DOUT << "argpromotion disable promoting argument '"
+ << Arg->getName() << "' because it would require adding more "
+ << "than 3 arguments to the function.\n";
// We limit aggregate promotion to only promoting up to three elements
// of the aggregate.
return false;
// of the pointer in the entry block of the function) or if we can prove that
// all pointers passed in are always to legal locations (for example, no null
// pointers are passed in, no pointers to free'd memory, etc).
- if (!AccessOccursOnPath(Arg) && !AllCalleesPassInValidPointerForArgument(Arg))
+ if (!HasLoadInEntryBlock && !AllCalleesPassInValidPointerForArgument(Arg))
return false; // Cannot prove that this is safe!!
// Okay, now we know that the argument is only used by load instructions and
// it is safe to unconditionally load the pointer. Use alias analysis to
// check to see if the pointer is guaranteed to not be modified from entry of
// the function to each of the load instructions.
- Function &F = *Arg->getParent();
// Because there could be several/many load instructions, remember which
// blocks we know to be transparent to the load.
unsigned idx = 0;
for (; idx < LHS.size() && idx < RHS.size(); ++idx) {
if (LHS[idx] != RHS[idx]) {
- return cast<ConstantInt>(LHS[idx])->getRawValue() <
- cast<ConstantInt>(RHS[idx])->getRawValue();
+ return cast<ConstantInt>(LHS[idx])->getZExtValue() <
+ cast<ConstantInt>(RHS[idx])->getZExtValue();
}
}
// Add a parameter to the function for each element passed in.
for (ScalarizeTable::iterator SI = ArgIndices.begin(),
E = ArgIndices.end(); SI != E; ++SI)
- Params.push_back(GetElementPtrInst::getIndexedType(I->getType(), *SI));
+ Params.push_back(GetElementPtrInst::getIndexedType(I->getType(),
+ &(*SI)[0],
+ SI->size()));
if (ArgIndices.size() == 1 && ArgIndices.begin()->empty())
++NumArgumentsPromoted;
bool ExtraArgHack = false;
if (Params.empty() && FTy->isVarArg()) {
ExtraArgHack = true;
- Params.push_back(Type::IntTy);
+ Params.push_back(Type::Int32Ty);
}
FunctionType *NFTy = FunctionType::get(RetTy, Params, FTy->isVarArg());
Value *V = *AI;
LoadInst *OrigLoad = OriginalLoads[*SI];
if (!SI->empty()) {
- V = new GetElementPtrInst(V, *SI, V->getName()+".idx", Call);
+ V = new GetElementPtrInst(V, &(*SI)[0], SI->size(),
+ V->getName()+".idx", Call);
AA.copyValue(OrigLoad->getOperand(0), V);
}
Args.push_back(new LoadInst(V, V->getName()+".val", Call));
}
if (ExtraArgHack)
- Args.push_back(Constant::getNullValue(Type::IntTy));
+ Args.push_back(Constant::getNullValue(Type::Int32Ty));
// Push any varargs arguments on the list
for (; AI != CS.arg_end(); ++AI)
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
- Args, "", Call);
+ &Args[0], Args.size(), "", Call);
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
} else {
- New = new CallInst(NF, Args, "", Call);
+ New = new CallInst(NF, &Args[0], Args.size(), "", Call);
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
if (cast<CallInst>(Call)->isTailCall())
cast<CallInst>(New)->setTailCall();
if (!Call->use_empty()) {
Call->replaceAllUsesWith(New);
- std::string Name = Call->getName();
- Call->setName("");
- New->setName(Name);
+ New->takeName(Call);
}
// Finally, remove the old call from the program, reducing the use-count of
// Loop over the argument list, transfering uses of the old arguments over to
// the new arguments, also transfering over the names as well.
//
- for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(), I2 = NF->arg_begin();
- I != E; ++I)
+ for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(),
+ I2 = NF->arg_begin(); I != E; ++I)
if (!ArgsToPromote.count(I)) {
// If this is an unmodified argument, move the name and users over to the
// new version.
I->replaceAllUsesWith(I2);
- I2->setName(I->getName());
+ I2->takeName(I);
AA.replaceWithNewValue(I, I2);
++I2;
} else if (I->use_empty()) {
LI->replaceAllUsesWith(I2);
AA.replaceWithNewValue(LI, I2);
LI->getParent()->getInstList().erase(LI);
- DEBUG(std::cerr << "*** Promoted load of argument '" << I->getName()
- << "' in function '" << F->getName() << "'\n");
+ DOUT << "*** Promoted load of argument '" << I->getName()
+ << "' in function '" << F->getName() << "'\n";
} else {
GetElementPtrInst *GEP = cast<GetElementPtrInst>(I->use_back());
std::vector<Value*> Operands(GEP->op_begin()+1, GEP->op_end());
- unsigned ArgNo = 0;
Function::arg_iterator TheArg = I2;
for (ScalarizeTable::iterator It = ArgIndices.begin();
*It != Operands; ++It, ++TheArg) {
std::string NewName = I->getName();
for (unsigned i = 0, e = Operands.size(); i != e; ++i)
if (ConstantInt *CI = dyn_cast<ConstantInt>(Operands[i]))
- NewName += "."+itostr((int64_t)CI->getRawValue());
+ NewName += "." + CI->getValue().toString(10);
else
NewName += ".x";
TheArg->setName(NewName+".val");
- DEBUG(std::cerr << "*** Promoted agg argument '" << TheArg->getName()
- << "' of function '" << F->getName() << "'\n");
+ DOUT << "*** Promoted agg argument '" << TheArg->getName()
+ << "' of function '" << F->getName() << "'\n";
// All of the uses must be load instructions. Replace them all with
// the argument specified by ArgNo.
// Notify the alias analysis implementation that we inserted a new argument.
if (ExtraArgHack)
- AA.copyValue(Constant::getNullValue(Type::IntTy), NF->arg_begin());
+ AA.copyValue(Constant::getNullValue(Type::Int32Ty), NF->arg_begin());
// Tell the alias analysis that the old function is about to disappear.