[llvm-commits] [llvm] r41844 - /llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp

Chris Lattner clattner at apple.com
Tue Sep 11 14:48:53 PDT 2007


On Sep 11, 2007, at 7:35 AM, Duncan Sands wrote:

> Author: baldrick
> Date: Tue Sep 11 09:35:41 2007
> New Revision: 41844
>
> URL: http://llvm.org/viewvc/llvm-project?rev=41844&view=rev
> Log:
> Turn calls to trampolines into calls to the underlying
> nested function.

Nice!  Can you please add a testcase?  Also, can you please move the  
body of the transformation out of visitCallSite, so that you end up  
with something like this:

   if (BitCastInst *BC = dyn_cast<BitCastInst>(Callee)) {
     if (IntrinsicInst *In = dyn_cast<IntrinsicInst>(BC->getOperand(0)))
       if (In->getIntrinsicID() == Intrinsic::init_trampoline)
         if (Instruction *I = HandleCallThroughInitTrampoline(...))
           return I;

in visitCallSite?

Thanks work, I think the single intrinsic approach is much cleaner! :)

-Chris


> Modified:
>     llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
>
> Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/ 
> Scalar/InstructionCombining.cpp?rev=41844&r1=41843&r2=41844&view=diff
>
> ====================================================================== 
> ========
> --- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp  
> (original)
> +++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Tue  
> Sep 11 09:35:41 2007
> @@ -39,6 +39,7 @@
>  #include "llvm/Pass.h"
>  #include "llvm/DerivedTypes.h"
>  #include "llvm/GlobalVariable.h"
> +#include "llvm/ParameterAttributes.h"
>  #include "llvm/Analysis/ConstantFolding.h"
>  #include "llvm/Target/TargetData.h"
>  #include "llvm/Transforms/Utils/BasicBlockUtils.h"
> @@ -7848,6 +7849,143 @@
>        }
>    }
>
> +  if (BitCastInst *BC = dyn_cast<BitCastInst>(Callee)) {
> +    IntrinsicInst *In = dyn_cast<IntrinsicInst>(BC->getOperand(0));
> +    if (In && In->getIntrinsicID() == Intrinsic::init_trampoline) {
> +      Function *NestF =
> +        cast<Function>(IntrinsicInst::StripPointerCasts(In- 
> >getOperand(2)));
> +      const PointerType *NestFPTy = cast<PointerType>(NestF- 
> >getType());
> +      const FunctionType *NestFTy =
> +        cast<FunctionType>(NestFPTy->getElementType());
> +
> +      if (const ParamAttrsList *NestAttrs = NestFTy->getParamAttrs 
> ()) {
> +        unsigned NestIdx = 1;
> +        const Type *NestTy = 0;
> +        uint16_t NestAttr;
> +
> +        Instruction *Caller = CS.getInstruction();
> +
> +        // Look for a parameter marked with the 'nest' attribute.
> +        for (FunctionType::param_iterator I = NestFTy->param_begin(),
> +             E = NestFTy->param_end(); I != E; ++NestIdx, ++I)
> +          if (NestAttrs->paramHasAttr(NestIdx, ParamAttr::Nest)) {
> +            // Record the parameter type and any other attributes.
> +            NestTy = *I;
> +            NestAttr = NestAttrs->getParamAttrs(NestIdx);
> +            break;
> +          }
> +
> +        if (NestTy) {
> +          std::vector<Value*> NewArgs;
> +          NewArgs.reserve(unsigned(CS.arg_end()-CS.arg_begin())+1);
> +
> +          // Insert the nest argument into the call argument list,  
> which may
> +          // mean appending it.
> +          {
> +            unsigned Idx = 1;
> +            CallSite::arg_iterator I = CS.arg_begin(), E =  
> CS.arg_end();
> +            do {
> +              if (Idx == NestIdx) {
> +                // Add the chain argument.
> +                Value *NestVal = In->getOperand(3);
> +                if (NestVal->getType() != NestTy)
> +                  NestVal = new BitCastInst(NestVal, NestTy,  
> "nest", Caller);
> +                NewArgs.push_back(NestVal);
> +              }
> +
> +              if (I == E)
> +                break;
> +
> +              // Add the original argument.
> +              NewArgs.push_back(*I);
> +
> +              ++Idx, ++I;
> +            } while (1);
> +          }
> +
> +          // The trampoline may have been bitcast to a bogus type  
> (FTy).
> +          // Handle this by synthesizing a new function type,  
> equal to FTy
> +          // with the chain parameter inserted.  Likewise for  
> attributes.
> +
> +          const ParamAttrsList *Attrs = FTy->getParamAttrs();
> +          std::vector<const Type*> NewTypes;
> +          ParamAttrsVector NewAttrs;
> +          NewTypes.reserve(FTy->getNumParams()+1);
> +
> +          // Add any function result attributes.
> +          uint16_t Attr = Attrs ? Attrs->getParamAttrs(0) : 0;
> +          if (Attr)
> +            NewAttrs.push_back (ParamAttrsWithIndex::get(0, Attr));
> +
> +          // Insert the chain's type into the list of parameter  
> types, which may
> +          // mean appending it.  Likewise for the chain's attributes.
> +          {
> +            unsigned Idx = 1;
> +            FunctionType::param_iterator I = FTy->param_begin(),
> +              E = FTy->param_end();
> +
> +            do {
> +              if (Idx == NestIdx) {
> +                // Add the chain's type and attributes.
> +                NewTypes.push_back(NestTy);
> +                NewAttrs.push_back(ParamAttrsWithIndex::get 
> (NestIdx, NestAttr));
> +              }
> +
> +              if (I == E)
> +                break;
> +
> +              // Add the original type and attributes.
> +              NewTypes.push_back(*I);
> +              Attr = Attrs ? Attrs->getParamAttrs(Idx) : 0;
> +              if (Attr)
> +                NewAttrs.push_back
> +                  (ParamAttrsWithIndex::get(Idx + (Idx >=  
> NestIdx), Attr));
> +
> +              ++Idx, ++I;
> +            } while (1);
> +          }
> +
> +          // Replace the trampoline call with a direct call.  Let  
> the generic
> +          // code sort out any function type mismatches.
> +          FunctionType *NewFTy =
> +            FunctionType::get(FTy->getReturnType(), NewTypes, FTy- 
> >isVarArg(),
> +                              ParamAttrsList::get(NewAttrs));
> +          Constant *NewCallee = NestF->getType() ==  
> PointerType::get(NewFTy) ?
> +            NestF : ConstantExpr::getBitCast(NestF,  
> PointerType::get(NewFTy));
> +
> +          Instruction *NewCaller;
> +          if (InvokeInst *II = dyn_cast<InvokeInst>(Caller)) {
> +            NewCaller = new InvokeInst(NewCallee, II->getNormalDest 
> (),
> +                                       II->getUnwindDest(),  
> NewArgs.begin(),
> +                                       NewArgs.end(), Caller- 
> >getName(),
> +                                       Caller);
> +            cast<InvokeInst>(NewCaller)->setCallingConv(II- 
> >getCallingConv());
> +          } else {
> +            NewCaller = new CallInst(NewCallee, NewArgs.begin(),  
> NewArgs.end(),
> +                                     Caller->getName(), Caller);
> +            if (cast<CallInst>(Caller)->isTailCall())
> +              cast<CallInst>(NewCaller)->setTailCall();
> +            cast<CallInst>(NewCaller)->
> +              setCallingConv(cast<CallInst>(Caller)->getCallingConv 
> ());
> +          }
> +          if (Caller->getType() != Type::VoidTy && !Caller- 
> >use_empty())
> +            Caller->replaceAllUsesWith(NewCaller);
> +          Caller->eraseFromParent();
> +          RemoveFromWorkList(Caller);
> +          return 0;
> +        }
> +      }
> +
> +      // Replace the trampoline call with a direct call.  Since  
> there is no
> +      // 'nest' parameter, there is no need to adjust the argument  
> list.  Let
> +      // the generic code sort out any function type mismatches.
> +      Constant *NewCallee = NestF->getType() == PTy ?
> +        NestF : ConstantExpr::getBitCast(NestF, PTy);
> +      CS.setCalledFunction(NewCallee);
> +      Changed = true;
> +    }
> +  }
> +
>    return Changed ? CS.getInstruction() : 0;
>  }
>
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits




More information about the llvm-commits mailing list