[llvm-commits] [llvm] r48020 - in /llvm/trunk: lib/Transforms/Utils/InlineFunction.cpp test/Transforms/SRETPromotion/2008-03-07-Inline-2.ll test/Transforms/SRETPromotion/2008-03-07-Inline.ll
Chris Lattner
clattner at apple.com
Fri Mar 7 17:19:49 PST 2008
On Mar 7, 2008, at 12:06 PM, Devang Patel wrote:
> URL: http://llvm.org/viewvc/llvm-project?rev=48020&view=rev
> Log:
> Update inliner to handle functions that return multiple values.
Nice.
> @@ -0,0 +1,46 @@
> +; RUN: llvm-as < %s | opt -inline -sretpromotion -disable-output
Again, your test should only be for the inliner, not both passes.
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp (original)
> +++ llvm/trunk/lib/Transforms/Utils/InlineFunction.cpp Fri Mar 7
> 14:06:16 2008
>
> // Handle all of the return instructions that we just cloned in,
> and eliminate
> // any users of the original call/invoke instruction.
> - if (Returns.size() > 1) {
> + if (!Returns.empty()) {
You are (apparently, I may be mistaken) dropping an important
optimization here. When a function only has a single return, we don't
want the inliner to turn:
...
call foo()
...
into:
...
somestuff
br label x
x:
...
This increases the apparent inlining cost of the resultant code and is
slow. Please don't lose this. The trick here is that you can't
insert a phi node into the middle of the block, even if it's a single
entry one. Not doing this optimization for multiple return calls
would be fine.
> // The PHI node should go at the front of the new basic block to
> merge all
> // possible incoming values.
> + SmallVector<PHINode *, 4> PHIs;
> if (!TheCall->use_empty()) {
> + const Type *RTy = CalledFunc->getReturnType();
> + if (const StructType *STy = dyn_cast<StructType>(RTy)) {
> + unsigned NumRetVals = STy->getNumElements();
> + // Create new phi nodes such that phi node number in the
> PHIs vector
> + // match corresponding return value operand number.
> + for (unsigned i = 0; i < NumRetVals; ++i) {
> + PHINode *PHI = new PHINode(STy->getElementType(i),
> + TheCall->getName(),
> AfterCallBB->begin());
I'd suggest naming these things 'TheCall->getName()+"."+utostr(i)'.
Also, you're inserting the phi nodes in backwards order (the block
will have rv3,rv2,rv1,rv0 in that order) which is not a functionality
issue but will make the ir be a bit strange looking.
>
> + PHIs.push_back(PHI);
> + }
> + // TheCall results are used by GetResult instructions.
> + while (!TheCall->use_empty()) {
> + GetResultInst *GR = cast<GetResultInst>(TheCall-
> >use_back());
> + GR->replaceAllUsesWith(PHIs[GR->getIndex()]);
> + GR->eraseFromParent();
Nice.
> + // Loop over all of the return instructions adding entries to
> the PHI node as
> // appropriate.
> + if (!PHIs.empty()) {
> + const Type *RTy = CalledFunc->getReturnType();
> + if (const StructType *STy = dyn_cast<StructType>(RTy)) {
I don't think you need to distinguish between the multiple return and
scalar return case here. Just loop over all the elements of Returns,
and then loop over all their operands.
> - // Add a branch to the merge point where the PHI node lives
> if it exists.
> + // Add a branch to the merge points and remove retrun
> instructions.
> + for (unsigned i = 0, e = Returns.size(); i != e; ++i) {
> + ReturnInst *RI = Returns[i];
> new BranchInst(AfterCallBB, RI);
> RI->getParent()->getInstList().erase(RI);
> }
How about RI->eraseFromParent();
-Chris
More information about the llvm-commits
mailing list