llvm.org GIT mirror llvm / ab04e13
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 Chris Lattner 11 years ago
2 changed file(s) with 50 addition(s) and 14 deletion(s). Raw diff Collapse all Expand all
403403 ParamAttrsVector ParamAttrsVec;
404404 const ParamAttrsList *PAL = F->getParamAttrs();
405405
406 unsigned index = 1;
406 unsigned ArgIndex = 1;
407407 for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
408 ++I, ++index) {
408 ++I, ++ArgIndex) {
409409 if (ByValArgsToTransform.count(I)) {
410410 // Just add all the struct element types.
411411 const Type *AgTy = cast(I->getType())->getElementType();
415415 ++NumByValArgsPromoted;
416416 } else if (!ArgsToPromote.count(I)) {
417417 Params.push_back(I->getType());
418 if (unsigned attrs = PAL ? PAL->getParamAttrs(index) : 0)
418 if (unsigned attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
419419 ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), attrs));
420420 } else if (I->use_empty()) {
421421 ++NumArgumentsDead;
453453
454454 const Type *RetTy = FTy->getReturnType();
455455
456 // Recompute the parameter attributes list based on the new arguments for
457 // the function.
458 PAL = ParamAttrsList::get(ParamAttrsVec);
459
460456 // Work around LLVM bug PR56: the CWriter cannot emit varargs functions which
461457 // have zero fixed arguments.
462458 bool ExtraArgHack = false;
471467 // Create the new function body and insert it into the module...
472468 Function *NF = new Function(NFTy, F->getLinkage(), F->getName());
473469 NF->setCallingConv(F->getCallingConv());
474 NF->setParamAttrs(PAL);
470
471 // Recompute the parameter attributes list based on the new arguments for
472 // the function.
473 NF->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
474 ParamAttrsVec.clear(); PAL = 0;
475
475476 if (F->hasCollector())
476477 NF->setCollector(F->getCollector());
477478 F->getParent()->getFunctionList().insert(F, NF);
483484 // Loop over all of the callers of the function, transforming the call sites
484485 // to pass in the loaded pointers.
485486 //
486 std::vector> Args;
487 SmallVector> Args;
487488 while (!F->use_empty()) {
488489 CallSite CS = CallSite::get(F->use_back());
489490 Instruction *Call = CS.getInstruction();
490
491 PAL = CS.getParamAttrs();
492
491493 // Loop over the operands, inserting GEP and loads in the caller as
492494 // appropriate.
493495 CallSite::arg_iterator AI = CS.arg_begin();
496 ArgIndex = 1;
494497 for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
495 I != E; ++I, ++AI)
498 I != E; ++I, ++AI, ++ArgIndex)
496499 if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) {
497500 Args.push_back(*AI); // Unmodified argument
501
502 if (unsigned Attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
503 ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
504
498505 } else if (ByValArgsToTransform.count(I)) {
499506 // Emit a GEP and load for each element of the struct.
500507 const Type *AgTy = cast(I->getType())->getElementType();
529536 Args.push_back(Constant::getNullValue(Type::Int32Ty));
530537
531538 // Push any varargs arguments on the list
532 for (; AI != CS.arg_end(); ++AI)
539 for (; AI != CS.arg_end(); ++AI, ++ArgIndex) {
533540 Args.push_back(*AI);
541 if (unsigned Attrs = PAL ? PAL->getParamAttrs(ArgIndex) : 0)
542 ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Args.size(), Attrs));
543 }
534544
535545 Instruction *New;
536546 if (InvokeInst *II = dyn_cast(Call)) {
537547 New = new InvokeInst(NF, II->getNormalDest(), II->getUnwindDest(),
538548 Args.begin(), Args.end(), "", Call);
539549 cast(New)->setCallingConv(CS.getCallingConv());
540 cast(New)->setParamAttrs(PAL);
550 cast(New)->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
541551 } else {
542552 New = new CallInst(NF, Args.begin(), Args.end(), "", Call);
543553 cast(New)->setCallingConv(CS.getCallingConv());
544 cast(New)->setParamAttrs(PAL);
554 cast(New)->setParamAttrs(ParamAttrsList::get(ParamAttrsVec));
545555 if (cast(Call)->isTailCall())
546556 cast(New)->setTailCall();
547557 }
548558 Args.clear();
559 ParamAttrsVec.clear();
549560
550561 // Update the alias analysis implementation to know that we are replacing
551562 // the old call with a new one.
0 ; RUN: llvm-as < %s | opt -argpromotion | llvm-dis | grep zeroext
1
2 %struct.ss = type { i32, i64 }
3
4 define internal void @f(%struct.ss* byval %b, i32* byval %X, i32 %i) nounwind {
5 entry:
6 %tmp = getelementptr %struct.ss* %b, i32 0, i32 0
7 %tmp1 = load i32* %tmp, align 4
8 %tmp2 = add i32 %tmp1, 1
9 store i32 %tmp2, i32* %tmp, align 4
10
11 store i32 0, i32* %X
12 ret void
13 }
14
15 define i32 @test(i32* %X) {
16 entry:
17 %S = alloca %struct.ss ; <%struct.ss*> [#uses=4]
18 %tmp1 = getelementptr %struct.ss* %S, i32 0, i32 0 ; [#uses=1]
19 store i32 1, i32* %tmp1, align 8
20 %tmp4 = getelementptr %struct.ss* %S, i32 0, i32 1 ; [#uses=1]
21 store i64 2, i64* %tmp4, align 4
22 call void @f( %struct.ss* byval %S, i32* byval %X, i32 zeroext 0)
23 ret i32 0
24 }