Skip to content

Commit 5630c4f

Browse files
committed
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. llvm-svn: 46108
1 parent 15051b4 commit 5630c4f

File tree

2 files changed

+50
-14
lines changed

2 files changed

+50
-14
lines changed

llvm/lib/Transforms/IPO/ArgumentPromotion.cpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,9 @@ Function *ArgPromotion::DoPromotion(Function *F,
404404
ParamAttrsVector ParamAttrsVec;
405405
const ParamAttrsList *PAL = F->getParamAttrs();
406406

407-
unsigned index = 1;
407+
unsigned ArgIndex = 1;
408408
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
409-
++I, ++index) {
409+
++I, ++ArgIndex) {
410410
if (ByValArgsToTransform.count(I)) {
411411
// Just add all the struct element types.
412412
const Type *AgTy = cast<PointerType>(I->getType())->getElementType();
@@ -416,7 +416,7 @@ Function *ArgPromotion::DoPromotion(Function *F,
416416
++NumByValArgsPromoted;
417417
} else if (!ArgsToPromote.count(I)) {
418418
Params.push_back(I->getType());
419-
if (unsigned attrs = PAL ? PAL->getParamAttrs(index) : 0)
419+
if (unsigned attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
420420
ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), attrs));
421421
} else if (I->use_empty()) {
422422
++NumArgumentsDead;
@@ -454,10 +454,6 @@ Function *ArgPromotion::DoPromotion(Function *F,
454454

455455
const Type *RetTy = FTy->getReturnType();
456456

457-
// Recompute the parameter attributes list based on the new arguments for
458-
// the function.
459-
PAL = ParamAttrsList::get(ParamAttrsVec);
460-
461457
// Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
462458
// have zero fixed arguments.
463459
bool ExtraArgHack = false;
@@ -472,7 +468,12 @@ Function *ArgPromotion::DoPromotion(Function *F,
472468
// Create the new function body and insert it into the module...
473469
Function *NF = new Function(NFTy, F->getLinkage(), F->getName());
474470
NF->setCallingConv(F->getCallingConv());
475-
NF->setParamAttrs(PAL);
471+
472+
// Recompute the parameter attributes list based on the new arguments for
473+
// the function.
474+
NF->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
475+
ParamAttrsVec.clear(); PAL = 0;
476+
476477
if (F->hasCollector())
477478
NF->setCollector(F->getCollector());
478479
F->getParent()->getFunctionList().insert(F, NF);
@@ -484,18 +485,24 @@ Function *ArgPromotion::DoPromotion(Function *F,
484485
// Loop over all of the callers of the function, transforming the call sites
485486
// to pass in the loaded pointers.
486487
//
487-
std::vector<Value*> Args;
488+
SmallVector<Value*, 16> Args;
488489
while (!F->use_empty()) {
489490
CallSite CS = CallSite::get(F->use_back());
490491
Instruction *Call = CS.getInstruction();
491-
492+
PAL = CS.getParamAttrs();
493+
492494
// Loop over the operands, inserting GEP and loads in the caller as
493495
// appropriate.
494496
CallSite::arg_iterator AI = CS.arg_begin();
497+
ArgIndex = 1;
495498
for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
496-
I != E; ++I, ++AI)
499+
I != E; ++I, ++AI, ++ArgIndex)
497500
if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) {
498501
Args.push_back(*AI); // Unmodified argument
502+
503+
if (unsigned Attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
504+
ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
505+
499506
} else if (ByValArgsToTransform.count(I)) {
500507
// Emit a GEP and load for each element of the struct.
501508
const Type *AgTy = cast<PointerType>(I->getType())->getElementType();
@@ -530,23 +537,27 @@ Function *ArgPromotion::DoPromotion(Function *F,
530537
Args.push_back(Constant::getNullValue(Type::Int32Ty));
531538

532539
// Push any varargs arguments on the list
533-
for (; AI != CS.arg_end(); ++AI)
540+
for (; AI != CS.arg_end(); ++AI, ++ArgIndex) {
534541
Args.push_back(*AI);
542+
if (unsigned Attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
543+
ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
544+
}
535545

536546
Instruction *New;
537547
if (InvokeInst *II = dyn_cast<InvokeInst>(Call)) {
538548
New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
539549
Args.begin(), Args.end(), "", Call);
540550
cast<InvokeInst>(New)->setCallingConv(CS.getCallingConv());
541-
cast<InvokeInst>(New)->setParamAttrs(PAL);
551+
cast<InvokeInst>(New)->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
542552
} else {
543553
New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
544554
cast<CallInst>(New)->setCallingConv(CS.getCallingConv());
545-
cast<CallInst>(New)->setParamAttrs(PAL);
555+
cast<CallInst>(New)->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
546556
if (cast<CallInst>(Call)->isTailCall())
547557
cast<CallInst>(New)->setTailCall();
548558
}
549559
Args.clear();
560+
ParamAttrsVec.clear();
550561

551562
// Update the alias analysis implementation to know that we are replacing
552563
// the old call with a new one.
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; RUN: llvm-as < %s | opt -argpromotion | llvm-dis | grep zeroext
2+
3+
%struct.ss = type { i32, i64 }
4+
5+
define internal void @f(%struct.ss* byval %b, i32* byval %X, i32 %i) nounwind {
6+
entry:
7+
%tmp = getelementptr %struct.ss* %b, i32 0, i32 0
8+
%tmp1 = load i32* %tmp, align 4
9+
%tmp2 = add i32 %tmp1, 1
10+
store i32 %tmp2, i32* %tmp, align 4
11+
12+
store i32 0, i32* %X
13+
ret void
14+
}
15+
16+
define i32 @test(i32* %X) {
17+
entry:
18+
%S = alloca %struct.ss ; <%struct.ss*> [#uses=4]
19+
%tmp1 = getelementptr %struct.ss* %S, i32 0, i32 0 ; <i32*> [#uses=1]
20+
store i32 1, i32* %tmp1, align 8
21+
%tmp4 = getelementptr %struct.ss* %S, i32 0, i32 1 ; <i64*> [#uses=1]
22+
store i64 2, i64* %tmp4, align 4
23+
call void @f( %struct.ss* byval %S, i32* byval %X, i32 zeroext 0)
24+
ret i32 0
25+
}

0 commit comments

Comments
 (0)