summaryrefslogtreecommitdiff
path: root/lib/Transforms/IPO
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-01-17 01:17:03 +0000
committerChris Lattner <sabre@nondot.org>2008-01-17 01:17:03 +0000
commitab04e13a1f017c2b0a82344b4c083d92139ee2cc (patch)
tree2cf96957333606d277053e4ad193fab92eca4d19 /lib/Transforms/IPO
parent644340a9bdc663762a58784e0b86c87aeeb41116 (diff)
downloadllvm-ab04e13a1f017c2b0a82344b4c083d92139ee2cc.tar.gz
llvm-ab04e13a1f017c2b0a82344b4c083d92139ee2cc.tar.bz2
llvm-ab04e13a1f017c2b0a82344b4c083d92139ee2cc.tar.xz
Fix arg promotion to propagate the correct attrs on the calls to
promoted functions. This is important for varargs calls in particular. Thanks to duncan for providing a great testcase. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@46108 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/IPO')
-rw-r--r--lib/Transforms/IPO/ArgumentPromotion.cpp39
1 files changed, 25 insertions, 14 deletions
diff --git a/lib/Transforms/IPO/ArgumentPromotion.cpp b/lib/Transforms/IPO/ArgumentPromotion.cpp
index 073d752af0..3ac1c7bb2b 100644
--- a/lib/Transforms/IPO/ArgumentPromotion.cpp
+++ b/lib/Transforms/IPO/ArgumentPromotion.cpp
@@ -404,9 +404,9 @@ Function *ArgPromotion::DoPromotion(Function *F,
ParamAttrsVector ParamAttrsVec;
const ParamAttrsList *PAL = F->getParamAttrs();
- unsigned index = 1;
+ unsigned ArgIndex = 1;
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
- ++I, ++index) {
+ ++I, ++ArgIndex) {
if (ByValArgsToTransform.count(I)) {
// Just add all the struct element types.
const Type *AgTy = cast<PointerType>(I->getType())->getElementType();
@@ -416,7 +416,7 @@ Function *ArgPromotion::DoPromotion(Function *F,
++NumByValArgsPromoted;
} else if (!ArgsToPromote.count(I)) {
Params.push_back(I->getType());
- if (unsigned attrs = PAL ? PAL->getParamAttrs(index) : 0)
+ if (unsigned attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), attrs));
} else if (I->use_empty()) {
++NumArgumentsDead;
@@ -454,10 +454,6 @@ Function *ArgPromotion::DoPromotion(Function *F,
const Type *RetTy = FTy->getReturnType();
- // Recompute the parameter attributes list based on the new arguments for
- // the function.
- PAL = ParamAttrsList::get(ParamAttrsVec);
-
// Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
// have zero fixed arguments.
bool ExtraArgHack = false;
@@ -472,7 +468,12 @@ Function *ArgPromotion::DoPromotion(Function *F,
// Create the new function body and insert it into the module...
Function *NF = new Function(NFTy, F->getLinkage(), F->getName());
NF->setCallingConv(F->getCallingConv());
- NF->setParamAttrs(PAL);
+
+ // Recompute the parameter attributes list based on the new arguments for
+ // the function.
+ NF->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
+ ParamAttrsVec.clear(); PAL = 0;
+
if (F->hasCollector())
NF->setCollector(F->getCollector());
F->getParent()->getFunctionList().insert(F, NF);
@@ -484,18 +485,24 @@ Function *ArgPromotion::DoPromotion(Function *F,
// Loop over all of the callers of the function, transforming the call sites
// to pass in the loaded pointers.
//
- std::vector<Value*> Args;
+ SmallVector<Value*, 16> Args;
while (!F->use_empty()) {
CallSite CS = CallSite::get(F->use_back());
Instruction *Call = CS.getInstruction();
-
+ PAL = CS.getParamAttrs();
+
// Loop over the operands, inserting GEP and loads in the caller as
// appropriate.
CallSite::arg_iterator AI = CS.arg_begin();
+ ArgIndex = 1;
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
- I != E; ++I, ++AI)
+ I != E; ++I, ++AI, ++ArgIndex)
if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) {
Args.push_back(*AI); // Unmodified argument
+
+ if (unsigned Attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
+ ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
+
} else if (ByValArgsToTransform.count(I)) {
// Emit a GEP and load for each element of the struct.
const Type *AgTy = cast<PointerType>(I->getType())->getElementType();
@@ -530,23 +537,27 @@ Function *ArgPromotion::DoPromotion(Function *F,
Args.push_back(Constant::getNullValue(Type::Int32Ty));
// Push any varargs arguments on the list
- for (; AI != CS.arg_end(); ++AI)
+ for (; AI != CS.arg_end(); ++AI, ++ArgIndex) {
Args.push_back(*AI);
+ if (unsigned Attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
+ ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
+ }
Instruction *New;
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
Args.begin(), Args.end(), "", Call);
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
- cast<InvokeInst>(New)->setParamAttrs(PAL);
+ cast<InvokeInst>(New)->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
} else {
New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
- cast<CallInst>(New)->setParamAttrs(PAL);
+ cast<CallInst>(New)->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
if (cast<CallInst>(Call)->isTailCall())
cast<CallInst>(New)->setTailCall();
}
Args.clear();
+ ParamAttrsVec.clear();
// Update the alias analysis implementation to know that we are replacing
// the old call with a new one.