[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

Devang Patel dpatel at apple.com
Mon Mar 10 11:39:38 PDT 2008


On Mar 7, 2008, at 5:30 PM, Devang Patel wrote:

>
> On Mar 7, 2008, at 5:19 PM, Chris Lattner wrote:
>
>> 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.
>
> ok

done

>
>
>>> =
>>> =
>>> =
>>> ====================================================================
>>> --- 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.
>
> You're not mistaken. I expect simplification pass to merge the block
> easily, but did not realize that extra br and one additional block can
> have significant impact on inlining cost. I'll restore this.

done

>
>
>> 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)'.
>
> ok

done

>
>
>> 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.
>
> I already noticed that :) I'll restore natural order.

done

>
>
>>
>>
>>>
>>> +          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.
>
> ok

done
>
>
>>> -      // 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();
>
> good idea!

done

>
> -
> Devang
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits

-
Devang






More information about the llvm-commits mailing list