llvm.org GIT mirror llvm / 10603e0
Teach argpromote to ruthlessly hack small byval structs when it can get away with it, which exposes opportunities to eliminate the memory objects entirely. For example, we now compile byval.ll to: define internal void @f1(i32 %b.0, i64 %b.1) { entry: %tmp2 = add i32 %b.0, 1 ; <i32> [#uses=0] ret void } define i32 @main() nounwind { entry: call void @f1( i32 1, i64 2 ) ret i32 0 } This seems like it would trigger a lot for code that passes around small structs (e.g. SDOperand's or _Complex)... git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45886 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 11 years ago
2 changed file(s) with 177 addition(s) and 73 deletion(s). Raw diff Collapse all Expand all
5050
5151 STATISTIC(NumArgumentsPromoted , "Number of pointer arguments promoted");
5252 STATISTIC(NumAggregatesPromoted, "Number of aggregate arguments promoted");
53 STATISTIC(NumByValArgsPromoted , "Number of byval arguments promoted");
5354 STATISTIC(NumArgumentsDead , "Number of dead pointer args eliminated");
5455
5556 namespace {
7071 bool PromoteArguments(CallGraphNode *CGN);
7172 bool isSafeToPromoteArgument(Argument *Arg, bool isByVal) const;
7273 Function *DoPromotion(Function *F,
73 SmallPtrSet &ArgsToPromote);
74 SmallPtrSet &ArgsToPromote,
75 SmallPtrSet &ByValArgsToTransform);
7476 };
7577
7678 char ArgPromotion::ID = 0;
133135 // Check to see which arguments are promotable. If an argument is promotable,
134136 // add it to ArgsToPromote.
135137 SmallPtrSet ArgsToPromote;
138 SmallPtrSet ByValArgsToTransform;
136139 for (unsigned i = 0; i != PointerArgs.size(); ++i) {
137 bool isByVal = F->paramHasAttr(PointerArgs[i].second, ParamAttr::ByVal);
138 if (isSafeToPromoteArgument(PointerArgs[i].first, isByVal))
139 ArgsToPromote.insert(PointerArgs[i].first);
140 bool isByVal = F->paramHasAttr(PointerArgs[i].second+1, ParamAttr::ByVal);
141
142 // If this is a byval argument, and if the aggregate type is small, just
143 // pass the elements, which is always safe.
144 Argument *PtrArg = PointerArgs[i].first;
145 if (isByVal) {
146 const Type *AgTy = cast(PtrArg->getType())->getElementType();
147 if (const StructType *STy = dyn_cast(AgTy))
148 if (STy->getNumElements() <= 3) {
149 // If all the elements are first class types, we can promote it.
150 bool AllSimple = true;
151 for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
152 if (!STy->getElementType(i)->isFirstClassType()) {
153 AllSimple = false;
154 break;
155 }
156
157 // Safe to transform, don't even bother trying to "promote" it.
158 // Passing the elements as a scalar will allow scalarrepl to hack on
159 // the new alloca we introduce.
160 if (AllSimple) {
161 ByValArgsToTransform.insert(PtrArg);
162 continue;
163 }
164 }
165 }
166
167 // Otherwise, see if we can promote the pointer to its value.
168 if (isSafeToPromoteArgument(PtrArg, isByVal))
169 ArgsToPromote.insert(PtrArg);
140170 }
141171
142172 // No promotable pointer arguments.
143 if (ArgsToPromote.empty()) return false;
144
145 Function *NewF = DoPromotion(F, ArgsToPromote);
173 if (ArgsToPromote.empty() && ByValArgsToTransform.empty()) return false;
174
175 Function *NewF = DoPromotion(F, ArgsToPromote, ByValArgsToTransform);
146176
147177 // Update the call graph to know that the function has been transformed.
148178 getAnalysis().changeFunction(F, NewF);
343373 /// arguments, and returns the new function. At this point, we know that it's
344374 /// safe to do so.
345375 Function *ArgPromotion::DoPromotion(Function *F,
346 SmallPtrSet &ArgsToPromote) {
376 SmallPtrSet &ArgsToPromote,
377 SmallPtrSet &ByValArgsToTransform) {
347378
348379 // Start by computing a new prototype for the function, which is the same as
349380 // the old function, but has modified arguments.
374405
375406 unsigned index = 1;
376407 for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E;
377 ++I, ++index)
378 if (!ArgsToPromote.count(I)) {
408 ++I, ++index) {
409 if (ByValArgsToTransform.count(I)) {
410 // Just add all the struct element types.
411 const Type *AgTy = cast(I->getType())->getElementType();
412 const StructType *STy = cast(AgTy);
413 for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i)
414 Params.push_back(STy->getElementType(i));
415 ++NumByValArgsPromoted;
416 } else if (!ArgsToPromote.count(I)) {
379417 Params.push_back(I->getType());
380 if (PAL) {
381 unsigned attrs = PAL->getParamAttrs(index);
382 if (attrs)
383 ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(),
384 attrs));
385 }
418 if (unsigned attrs = PAL ? PAL->getParamAttrs(index) : 0)
419 ParamAttrsVec.push_back(ParamAttrsWithIndex::get(Params.size(), attrs));
386420 } else if (I->use_empty()) {
387421 ++NumArgumentsDead;
388422 } else {
415449 else
416450 ++NumAggregatesPromoted;
417451 }
452 }
418453
419454 const Type *RetTy = FTy->getReturnType();
420455
461496 CallSite::arg_iterator AI = CS.arg_begin();
462497 for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end();
463498 I != E; ++I, ++AI)
464 if (!ArgsToPromote.count(I))
499 if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) {
465500 Args.push_back(*AI); // Unmodified argument
466 else if (!I->use_empty()) {
501 } else if (ByValArgsToTransform.count(I)) {
502 // Emit a GEP and load for each element of the struct.
503 const Type *AgTy = cast(I->getType())->getElementType();
504 const StructType *STy = cast(AgTy);
505 Value *Idxs[2] = { ConstantInt::get(Type::Int32Ty, 0), 0 };
506 for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
507 Idxs[1] = ConstantInt::get(Type::Int32Ty, i);
508 Value *Idx = new GetElementPtrInst(*AI, Idxs, Idxs+2,
509 (*AI)->getName()+"."+utostr(i),
510 Call);
511 // TODO: Tell AA about the new values?
512 Args.push_back(new LoadInst(Idx, Idx->getName()+".val", Call));
513 }
514 } else if (!I->use_empty()) {
467515 // Non-dead argument: insert GEPs and loads as appropriate.
468516 ScalarizeTable &ArgIndices = ScalarizedElements[I];
469517 for (ScalarizeTable::iterator SI = ArgIndices.begin(),
525573 // the new arguments, also transfering over the names as well.
526574 //
527575 for (Function::arg_iterator I = F->arg_begin(), E = F->arg_end(),
528 I2 = NF->arg_begin(); I != E; ++I)
529 if (!ArgsToPromote.count(I)) {
576 I2 = NF->arg_begin(); I != E; ++I) {
577 if (!ArgsToPromote.count(I) && !ByValArgsToTransform.count(I)) {
530578 // If this is an unmodified argument, move the name and users over to the
531579 // new version.
532580 I->replaceAllUsesWith(I2);
533581 I2->takeName(I);
534582 AA.replaceWithNewValue(I, I2);
535583 ++I2;
536 } else if (I->use_empty()) {
584 continue;
585 }
586
587 if (ByValArgsToTransform.count(I)) {
588 // In the callee, we create an alloca, and store each of the new incoming
589 // arguments into the alloca.
590 Instruction *InsertPt = NF->begin()->begin();
591
592 // Just add all the struct element types.
593 const Type *AgTy = cast(I->getType())->getElementType();
594 Value *TheAlloca = new AllocaInst(AgTy, 0, "", InsertPt);
595 const StructType *STy = cast(AgTy);
596 Value *Idxs[2] = { ConstantInt::get(Type::Int32Ty, 0), 0 };
597
598 for (unsigned i = 0, e = STy->getNumElements(); i != e; ++i) {
599 Idxs[1] = ConstantInt::get(Type::Int32Ty, i);
600 Value *Idx = new GetElementPtrInst(TheAlloca, Idxs, Idxs+2,
601 TheAlloca->getName()+"."+utostr(i),
602 InsertPt);
603 I2->setName(I->getName()+"."+utostr(i));
604 new StoreInst(I2++, Idx, InsertPt);
605 }
606
607 // Anything that used the arg should now use the alloca.
608 I->replaceAllUsesWith(TheAlloca);
609 TheAlloca->takeName(I);
610 AA.replaceWithNewValue(I, TheAlloca);
611 continue;
612 }
613
614 if (I->use_empty()) {
537615 AA.deleteValue(I);
538 } else {
539 // Otherwise, if we promoted this argument, then all users are load
540 // instructions, and all loads should be using the new argument that we
541 // added.
542 ScalarizeTable &ArgIndices = ScalarizedElements[I];
543
544 while (!I->use_empty()) {
545 if (LoadInst *LI = dyn_cast(I->use_back())) {
546 assert(ArgIndices.begin()->empty() &&
547 "Load element should sort to front!");
548 I2->setName(I->getName()+".val");
549 LI->replaceAllUsesWith(I2);
550 AA.replaceWithNewValue(LI, I2);
551 LI->eraseFromParent();
552 DOUT << "*** Promoted load of argument '" << I->getName()
553 << "' in function '" << F->getName() << "'\n";
554 } else {
555 GetElementPtrInst *GEP = cast(I->use_back());
556 std::vector Operands(GEP->op_begin()+1, GEP->op_end());
557
558 Function::arg_iterator TheArg = I2;
559 for (ScalarizeTable::iterator It = ArgIndices.begin();
560 *It != Operands; ++It, ++TheArg) {
561 assert(It != ArgIndices.end() && "GEP not handled??");
562 }
563
564 std::string NewName = I->getName();
565 for (unsigned i = 0, e = Operands.size(); i != e; ++i)
566 if (ConstantInt *CI = dyn_cast(Operands[i]))
567 NewName += "." + CI->getValue().toStringUnsigned(10);
568 else
569 NewName += ".x";
570 TheArg->setName(NewName+".val");
571
572 DOUT << "*** Promoted agg argument '" << TheArg->getName()
573 << "' of function '" << F->getName() << "'\n";
574
575 // All of the uses must be load instructions. Replace them all with
576 // the argument specified by ArgNo.
577 while (!GEP->use_empty()) {
578 LoadInst *L = cast(GEP->use_back());
579 L->replaceAllUsesWith(TheArg);
580 AA.replaceWithNewValue(L, TheArg);
581 L->eraseFromParent();
582 }
583 AA.deleteValue(GEP);
584 GEP->eraseFromParent();
616 continue;
617 }
618
619 // Otherwise, if we promoted this argument, then all users are load
620 // instructions, and all loads should be using the new argument that we
621 // added.
622 ScalarizeTable &ArgIndices = ScalarizedElements[I];
623
624 while (!I->use_empty()) {
625 if (LoadInst *LI = dyn_cast(I->use_back())) {
626 assert(ArgIndices.begin()->empty() &&
627 "Load element should sort to front!");
628 I2->setName(I->getName()+".val");
629 LI->replaceAllUsesWith(I2);
630 AA.replaceWithNewValue(LI, I2);
631 LI->eraseFromParent();
632 DOUT << "*** Promoted load of argument '" << I->getName()
633 << "' in function '" << F->getName() << "'\n";
634 } else {
635 GetElementPtrInst *GEP = cast(I->use_back());
636 std::vector Operands(GEP->op_begin()+1, GEP->op_end());
637
638 Function::arg_iterator TheArg = I2;
639 for (ScalarizeTable::iterator It = ArgIndices.begin();
640 *It != Operands; ++It, ++TheArg) {
641 assert(It != ArgIndices.end() && "GEP not handled??");
585642 }
643
644 std::string NewName = I->getName();
645 for (unsigned i = 0, e = Operands.size(); i != e; ++i)
646 if (ConstantInt *CI = dyn_cast(Operands[i]))
647 NewName += "." + CI->getValue().toStringUnsigned(10);
648 else
649 NewName += ".x";
650 TheArg->setName(NewName+".val");
651
652 DOUT << "*** Promoted agg argument '" << TheArg->getName()
653 << "' of function '" << F->getName() << "'\n";
654
655 // All of the uses must be load instructions. Replace them all with
656 // the argument specified by ArgNo.
657 while (!GEP->use_empty()) {
658 LoadInst *L = cast(GEP->use_back());
659 L->replaceAllUsesWith(TheArg);
660 AA.replaceWithNewValue(L, TheArg);
661 L->eraseFromParent();
662 }
663 AA.deleteValue(GEP);
664 GEP->eraseFromParent();
586665 }
587
588 // Increment I2 past all of the arguments added for this promoted pointer.
589 for (unsigned i = 0, e = ArgIndices.size(); i != e; ++i)
590 ++I2;
591 }
666 }
667
668 // Increment I2 past all of the arguments added for this promoted pointer.
669 for (unsigned i = 0, e = ArgIndices.size(); i != e; ++i)
670 ++I2;
671 }
592672
593673 // Notify the alias analysis implementation that we inserted a new argument.
594674 if (ExtraArgHack)
0 ; RUN: llvm-as < %s | opt -argpromotion -scalarrepl | llvm-dis | not grep load
1 ; Argpromote + scalarrepl should change this to passing the two integers by value.
2
3 %struct.ss = type { i32, i64 }
4
5 define internal void @f(%struct.ss* byval %b) nounwind {
6 entry:
7 %tmp = getelementptr %struct.ss* %b, i32 0, i32 0 ; [#uses=2]
8 %tmp1 = load i32* %tmp, align 4 ; [#uses=1]
9 %tmp2 = add i32 %tmp1, 1 ; [#uses=1]
10 store i32 %tmp2, i32* %tmp, align 4
11 ret void
12 }
13
14 define i32 @main() nounwind {
15 entry:
16 %S = alloca %struct.ss ; <%struct.ss*> [#uses=4]
17 %tmp1 = getelementptr %struct.ss* %S, i32 0, i32 0 ; [#uses=1]
18 store i32 1, i32* %tmp1, align 8
19 %tmp4 = getelementptr %struct.ss* %S, i32 0, i32 1 ; [#uses=1]
20 store i64 2, i64* %tmp4, align 4
21 call void @f( %struct.ss* byval %S ) nounwind
22 ret i32 0
23 }