diff options
author | Duncan Sands <baldrick@free.fr> | 2007-09-17 10:26:40 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2007-09-17 10:26:40 +0000 |
commit | cdb6d929d0d2d2399a66bc7eb391934a10a752ed (patch) | |
tree | 40676f5f65ef34ccee1fc08f7f37321ba69f60dd /lib/Transforms | |
parent | 53f0bc1b2526e1b8356536c5ec3aa107a3f237eb (diff) | |
download | external_llvm-cdb6d929d0d2d2399a66bc7eb391934a10a752ed.zip external_llvm-cdb6d929d0d2d2399a66bc7eb391934a10a752ed.tar.gz external_llvm-cdb6d929d0d2d2399a66bc7eb391934a10a752ed.tar.bz2 |
Factor the trampoline transformation into a subroutine.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@42021 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/Scalar/InstructionCombining.cpp | 285 |
1 files changed, 148 insertions, 137 deletions
diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index ab6262b..787a3d5 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -235,6 +235,7 @@ namespace { private: Instruction *visitCallSite(CallSite CS); bool transformConstExprCastCall(CallSite CS); + Instruction *transformCallThroughTrampoline(CallSite CS); public: // InsertNewInstBefore - insert an instruction New before instruction Old @@ -7834,6 +7835,11 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) { return EraseInstFromFunction(*CS.getInstruction()); } + if (BitCastInst *BC = dyn_cast<BitCastInst>(Callee)) + if (IntrinsicInst *In = dyn_cast<IntrinsicInst>(BC->getOperand(0))) + if (In->getIntrinsicID() == Intrinsic::init_trampoline) + return transformCallThroughTrampoline(CS); + const PointerType *PTy = cast<PointerType>(Callee->getType()); const FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); if (FTy->isVarArg()) { @@ -7852,143 +7858,6 @@ Instruction *InstCombiner::visitCallSite(CallSite CS) { } } - 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 = 0; - - 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; } @@ -8191,6 +8060,148 @@ bool InstCombiner::transformConstExprCastCall(CallSite CS) { return true; } +// transformCallThroughTrampoline - Turn a call to a function created by the +// init_trampoline intrinsic into a direct call to the underlying function. +// +Instruction *InstCombiner::transformCallThroughTrampoline(CallSite CS) { + Value *Callee = CS.getCalledValue(); + const PointerType *PTy = cast<PointerType>(Callee->getType()); + const FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); + + IntrinsicInst *Tramp = + cast<IntrinsicInst>(cast<BitCastInst>(Callee)->getOperand(0)); + + Function *NestF = + cast<Function>(IntrinsicInst::StripPointerCasts(Tramp->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 = 0; + + // 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) { + Instruction *Caller = CS.getInstruction(); + 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 = Tramp->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); + return CS.getInstruction(); +} + /// FoldPHIArgBinOpIntoPHI - If we have something like phi [add (a,b), add(c,d)] /// and if a/b/c/d and the add's all have a single use, turn this into two phi's /// and a single binop. |