aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2007-09-17 10:26:40 +0000
committerDuncan Sands <baldrick@free.fr>2007-09-17 10:26:40 +0000
commitcdb6d929d0d2d2399a66bc7eb391934a10a752ed (patch)
tree40676f5f65ef34ccee1fc08f7f37321ba69f60dd /lib
parent53f0bc1b2526e1b8356536c5ec3aa107a3f237eb (diff)
downloadexternal_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')
-rw-r--r--lib/Transforms/Scalar/InstructionCombining.cpp285
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.