Currently LLVM has two intrinsics for supporting trampolines, aka pointers to nested functions: init_trampoline and adjust_trampoline. In essence, init_trampoline fills a block of memory with executable code, and adjust_trampoline returns a suitable function pointer for calling that code. These patches fold adjust_trampoline into init_trampoline, leaving init_trampoline as the only intrinsic (it now returns the function pointer adjust_trampoline used to return). This requires modifying gcc's nested function lowering pass, which currently stores the executable code in the "frame" used to pass the variables of a parent function to its children, and calls adjust_trampoline whenever it needs the function pointer (the call may occur in a child function, far from the point at which init_trampoline was called). After these patches, the function pointer is stored in the frame instead, with the code being written to a temporary variable on the parent's stack. This means that the adjust_trampoline call happens immediately after the init_trampoline call, so they might as well be combined into one intrinsic. The cost of organizing things this way is that space for one extra function pointer per trampoline is allocated on the stack.
My motive for doing this was not to simplify LLVM (which is a nice benefit), but to make it easier to do the optimization in the attached patch tramp_opt.diff This teaches instcombine how to turn a call to the function pointer returned by init_trampoline into a direct call to the nested function. This matters because calling a function via a trampoline is amazingly expensive (presumably due to icache flushing - remember that code on the stack gets executed). Since usually a pointer to a nested function is taken in order to pass it to some other function, this optimization is only going to happen if that other function is inlined, so that the init_trampoline and the call to the nested function pointer occur in the same function. It is easy to construct testcases for which this works, but sadly I was unable to get the optimization to occur even once in a trampoline heavy real-world program without jacking-up the inlining limit hugely (to 100000; 10000 wasn't enough). Still, I'm hoping that it may sometimes be useful. Ciao, Duncan.
Index: llvm.master/include/llvm/CodeGen/SelectionDAGNodes.h =================================================================== --- llvm.master.orig/include/llvm/CodeGen/SelectionDAGNodes.h 2007-09-06 19:25:40.000000000 +0200 +++ llvm.master/include/llvm/CodeGen/SelectionDAGNodes.h 2007-09-06 19:26:34.000000000 +0200 @@ -540,16 +540,13 @@ // produces a token chain as output. DEBUG_LOC, - // ADJUST_TRAMP - This corresponds to the adjust_trampoline intrinsic. - // It takes a value as input and returns a value as output. - ADJUST_TRAMP, - // TRAMPOLINE - This corresponds to the init_trampoline intrinsic. // It takes as input a token chain, the pointer to the trampoline, // the pointer to the nested function, the pointer to pass for the // 'nest' parameter, a SRCVALUE for the trampoline and another for // the nested function (allowing targets to access the original - // Function*). It produces a token chain as output. + // Function*). It produces the result of the intrinsic and a token + // chain as output. TRAMPOLINE, // BUILTIN_OP_END - This must be the last enum value in this list. Index: llvm.master/include/llvm/Intrinsics.td =================================================================== --- llvm.master.orig/include/llvm/Intrinsics.td 2007-09-06 19:25:40.000000000 +0200 +++ llvm.master/include/llvm/Intrinsics.td 2007-09-06 19:26:34.000000000 +0200 @@ -239,11 +239,9 @@ //===------------------------ Trampoline Intrinsics -----------------------===// // -def int_init_trampoline : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty, - llvm_ptr_ty], []>, - GCCBuiltin<"__builtin_init_trampoline">; -def int_adjust_trampoline : Intrinsic<[llvm_ptr_ty, llvm_ptr_ty], [IntrNoMem]>, - GCCBuiltin<"__builtin_adjust_trampoline">; +def int_init_trampoline : Intrinsic<[llvm_ptr_ty, llvm_ptr_ty, llvm_ptr_ty, + llvm_ptr_ty], []>, + GCCBuiltin<"__builtin_init_trampoline">; //===----------------------------------------------------------------------===// // Target-specific intrinsics Index: llvm.master/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- llvm.master.orig/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp 2007-09-06 19:25:40.000000000 +0200 +++ llvm.master/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp 2007-09-06 19:26:34.000000000 +0200 @@ -3347,21 +3347,6 @@ } break; } - case ISD::ADJUST_TRAMP: { - Tmp1 = LegalizeOp(Node->getOperand(0)); - switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { - default: assert(0 && "This action is not supported yet!"); - case TargetLowering::Custom: - Result = DAG.UpdateNodeOperands(Result, Tmp1); - Result = TLI.LowerOperation(Result, DAG); - if (Result.Val) break; - // FALL THROUGH - case TargetLowering::Expand: - Result = Tmp1; - break; - } - break; - } case ISD::TRAMPOLINE: { SDOperand Ops[6]; for (unsigned i = 0; i != 6; ++i) @@ -3370,7 +3355,14 @@ // The only option for this node is to custom lower it. Result = TLI.LowerOperation(Result, DAG); assert(Result.Val && "Should always custom lower!"); - break; + + // Since trampoline produces two values, make sure to remember that we + // legalized both of them. + Tmp1 = LegalizeOp(Result.getValue(1)); + Result = LegalizeOp(Result); + AddLegalizedOperand(SDOperand(Node, 0), Result); + AddLegalizedOperand(SDOperand(Node, 1), Tmp1); + return Op.ResNo ? Tmp1 : Result; } } Index: llvm.master/lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- llvm.master.orig/lib/CodeGen/SelectionDAG/SelectionDAG.cpp 2007-09-06 19:25:40.000000000 +0200 +++ llvm.master/lib/CodeGen/SelectionDAG/SelectionDAG.cpp 2007-09-06 19:26:34.000000000 +0200 @@ -3643,8 +3643,7 @@ case ISD::DEBUG_LOC: return "debug_loc"; // Trampolines - case ISD::ADJUST_TRAMP: return "adjust_tramp"; - case ISD::TRAMPOLINE: return "trampoline"; + case ISD::TRAMPOLINE: return "trampoline"; case ISD::CONDCODE: switch (cast<CondCodeSDNode>(this)->get()) { Index: llvm.master/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- llvm.master.orig/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp 2007-09-06 19:25:40.000000000 +0200 +++ llvm.master/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp 2007-09-06 19:26:34.000000000 +0200 @@ -2873,12 +2873,6 @@ // Discard annotate attributes return 0; - case Intrinsic::adjust_trampoline: { - SDOperand Arg = getValue(I.getOperand(1)); - setValue(&I, DAG.getNode(ISD::ADJUST_TRAMP, TLI.getPointerTy(), Arg)); - return 0; - } - case Intrinsic::init_trampoline: { const Function *F = cast<Function>(IntrinsicInst::StripPointerCasts(I.getOperand(2))); @@ -2891,7 +2885,13 @@ Ops[4] = DAG.getSrcValue(I.getOperand(1)); Ops[5] = DAG.getSrcValue(F); - DAG.setRoot(DAG.getNode(ISD::TRAMPOLINE, MVT::Other, Ops, 6)); + SDOperand Tmp = DAG.getNode(ISD::TRAMPOLINE, + DAG.getNodeValueTypes(TLI.getPointerTy(), + MVT::Other), 2, + Ops, 6); + + setValue(&I, Tmp); + DAG.setRoot(Tmp.getValue(1)); return 0; } } Index: llvm.master/lib/Target/ARM/ARMISelLowering.cpp =================================================================== --- llvm.master.orig/lib/Target/ARM/ARMISelLowering.cpp 2007-09-06 19:25:39.000000000 +0200 +++ llvm.master/lib/Target/ARM/ARMISelLowering.cpp 2007-09-06 19:26:35.000000000 +0200 @@ -191,11 +191,6 @@ setOperationAction(ISD::MEMCPY , MVT::Other, Custom); setOperationAction(ISD::MEMMOVE , MVT::Other, Expand); - if (Subtarget->isThumb()) - setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Custom); - else - setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand); - // Use the default implementation. setOperationAction(ISD::VASTART , MVT::Other, Expand); setOperationAction(ISD::VAARG , MVT::Other, Expand); @@ -1418,14 +1413,6 @@ return Chain; } -SDOperand ARMTargetLowering::LowerADJUST_TRAMP(SDOperand Op, - SelectionDAG &DAG) { - // Thumb trampolines should be entered in thumb mode, so set the bottom bit - // of the address. - return DAG.getNode(ISD::OR, MVT::i32, Op.getOperand(0), - DAG.getConstant(1, MVT::i32)); -} - SDOperand ARMTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { default: assert(0 && "Don't know how to custom lower this!"); abort(); @@ -1457,7 +1444,6 @@ case ISD::FRAMEADDR: break; case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG); case ISD::MEMCPY: return LowerMEMCPY(Op, DAG); - case ISD::ADJUST_TRAMP: return LowerADJUST_TRAMP(Op, DAG); } return SDOperand(); } Index: llvm.master/lib/Target/ARM/ARMISelLowering.h =================================================================== --- llvm.master.orig/lib/Target/ARM/ARMISelLowering.h 2007-09-06 19:25:39.000000000 +0200 +++ llvm.master/lib/Target/ARM/ARMISelLowering.h 2007-09-06 19:26:35.000000000 +0200 @@ -138,7 +138,6 @@ SDOperand LowerFORMAL_ARGUMENTS(SDOperand Op, SelectionDAG &DAG); SDOperand LowerBR_JT(SDOperand Op, SelectionDAG &DAG); SDOperand LowerMEMCPY(SDOperand Op, SelectionDAG &DAG); - SDOperand LowerADJUST_TRAMP(SDOperand Op, SelectionDAG &DAG); }; } Index: llvm.master/lib/Target/Alpha/AlphaISelLowering.cpp =================================================================== --- llvm.master.orig/lib/Target/Alpha/AlphaISelLowering.cpp 2007-09-06 19:25:40.000000000 +0200 +++ llvm.master/lib/Target/Alpha/AlphaISelLowering.cpp 2007-09-06 19:26:35.000000000 +0200 @@ -124,9 +124,6 @@ setOperationAction(ISD::ExternalSymbol, MVT::i64, Custom); setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom); - setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand); - setOperationAction(ISD::ADJUST_TRAMP, MVT::i64, Expand); - setOperationAction(ISD::VASTART, MVT::Other, Custom); setOperationAction(ISD::VAEND, MVT::Other, Expand); setOperationAction(ISD::VACOPY, MVT::Other, Custom); Index: llvm.master/lib/Target/IA64/IA64ISelLowering.cpp =================================================================== --- llvm.master.orig/lib/Target/IA64/IA64ISelLowering.cpp 2007-09-06 19:25:39.000000000 +0200 +++ llvm.master/lib/Target/IA64/IA64ISelLowering.cpp 2007-09-06 19:26:35.000000000 +0200 @@ -97,8 +97,6 @@ setOperationAction(ISD::ROTR , MVT::i64 , Expand); setOperationAction(ISD::BSWAP, MVT::i64 , Expand); // mux @rev - setOperationAction(ISD::ADJUST_TRAMP, MVT::i64, Expand); - // VASTART needs to be custom lowered to use the VarArgsFrameIndex setOperationAction(ISD::VAARG , MVT::Other, Custom); setOperationAction(ISD::VASTART , MVT::Other, Custom); Index: llvm.master/lib/Target/Mips/MipsISelLowering.cpp =================================================================== --- llvm.master.orig/lib/Target/Mips/MipsISelLowering.cpp 2007-09-06 19:25:39.000000000 +0200 +++ llvm.master/lib/Target/Mips/MipsISelLowering.cpp 2007-09-06 19:26:35.000000000 +0200 @@ -105,8 +105,6 @@ setOperationAction(ISD::STACKSAVE, MVT::Other, Expand); setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand); - setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand); - setStackPointerRegisterToSaveRestore(Mips::SP); computeRegisterProperties(); } Index: llvm.master/lib/Target/PowerPC/PPCISelLowering.cpp =================================================================== --- llvm.master.orig/lib/Target/PowerPC/PPCISelLowering.cpp 2007-09-06 19:25:40.000000000 +0200 +++ llvm.master/lib/Target/PowerPC/PPCISelLowering.cpp 2007-09-06 19:26:35.000000000 +0200 @@ -170,9 +170,6 @@ // RET must be custom lowered, to meet ABI requirements setOperationAction(ISD::RET , MVT::Other, Custom); - setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand); - setOperationAction(ISD::ADJUST_TRAMP, MVT::i64, Expand); - // VASTART needs to be custom lowered to use the VarArgsFrameIndex setOperationAction(ISD::VASTART , MVT::Other, Custom); Index: llvm.master/lib/Target/Sparc/SparcISelDAGToDAG.cpp =================================================================== --- llvm.master.orig/lib/Target/Sparc/SparcISelDAGToDAG.cpp 2007-09-06 19:25:39.000000000 +0200 +++ llvm.master/lib/Target/Sparc/SparcISelDAGToDAG.cpp 2007-09-06 19:26:35.000000000 +0200 @@ -216,8 +216,6 @@ // RET must be custom lowered, to meet ABI requirements setOperationAction(ISD::RET , MVT::Other, Custom); - setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand); - // VASTART needs to be custom lowered to use the VarArgsFrameIndex. setOperationAction(ISD::VASTART , MVT::Other, Custom); // VAARG needs to be lowered to not do unaligned accesses for doubles. Index: llvm.master/lib/Target/X86/X86ISelLowering.cpp =================================================================== --- llvm.master.orig/lib/Target/X86/X86ISelLowering.cpp 2007-09-06 19:25:40.000000000 +0200 +++ llvm.master/lib/Target/X86/X86ISelLowering.cpp 2007-09-06 19:26:35.000000000 +0200 @@ -246,9 +246,7 @@ } setOperationAction(ISD::FRAME_TO_ARGS_OFFSET, MVT::i32, Custom); - setOperationAction(ISD::ADJUST_TRAMP, MVT::i32, Expand); - setOperationAction(ISD::ADJUST_TRAMP, MVT::i64, Expand); - setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom); + setOperationAction(ISD::TRAMPOLINE, MVT::Other, Custom); // VASTART needs to be custom lowered to use the VarArgsFrameIndex setOperationAction(ISD::VASTART , MVT::Other, Custom); @@ -4405,7 +4403,9 @@ OutChains[3] = DAG.getStore(Root, Disp, Addr, TrmpSV->getValue(), TrmpSV->getOffset() + 6, false, 1); - return DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains, 4); + SDOperand Ops[] = + { Trmp, DAG.getNode(ISD::TokenFactor, MVT::Other, OutChains, 4) }; + return DAG.getNode(ISD::MERGE_VALUES, Op.Val->getVTList(), Ops, 2); } } Index: llvm.master/docs/LangRef.html =================================================================== --- llvm.master.orig/docs/LangRef.html 2007-09-06 19:25:39.000000000 +0200 +++ llvm.master/docs/LangRef.html 2007-09-06 19:26:35.000000000 +0200 @@ -200,10 +200,9 @@ <li><a href="#int_memory_barrier">'<tt>llvm.memory.barrier</tt>' Intrinsic</a></li> </ol> </li> - <li><a href="#int_trampoline">Trampoline Intrinsics</a> + <li><a href="#int_trampoline">Trampoline Intrinsic</a> <ol> <li><a href="#int_it">'<tt>llvm.init.trampoline</tt>' Intrinsic</a></li> - <li><a href="#int_at">'<tt>llvm.adjust.trampoline</tt>' Intrinsic</a></li> </ol> </li> <li><a href="#int_general">General intrinsics</a> @@ -5143,12 +5142,12 @@ <!-- ======================================================================= --> <div class="doc_subsection"> - <a name="int_trampoline">Trampoline Intrinsics</a> + <a name="int_trampoline">Trampoline Intrinsic</a> </div> <div class="doc_text"> <p> - These intrinsics make it possible to excise one parameter, marked with + This intrinsic makes it possible to excise one parameter, marked with the <tt>nest</tt> attribute, from a function. The result is a callable function pointer lacking the nest parameter - the caller does not need to provide a value for it. Instead, the value to use is stored in @@ -5162,11 +5161,10 @@ <tt>i32 f(i8* nest %c, i32 %x, i32 %y)</tt> then the resulting function pointer has signature <tt>i32 (i32, i32)*</tt>. It can be created as follows: <pre> - %tramp1 = alloca [10 x i8], align 4 ; size and alignment only correct for X86 - %tramp = getelementptr [10 x i8]* %tramp1, i32 0, i32 0 - call void @llvm.init.trampoline( i8* %tramp, i8* bitcast (i32 (i8* nest , i32, i32)* @f to i8*), i8* %nval ) - %adj = call i8* @llvm.adjust.trampoline( i8* %tramp ) - %fp = bitcast i8* %adj to i32 (i32, i32)* + %tramp = alloca [10 x i8], align 4 ; size and alignment only correct for X86 + %tramp1 = getelementptr [10 x i8]* %tramp, i32 0, i32 0 + %p = call i8* @llvm.init.trampoline( i8* %tramp1, i8* bitcast (i32 (i8* nest , i32, i32)* @f to i8*), i8* %nval ) + %fp = bitcast i8* %p to i32 (i32, i32)* </pre> The call <tt>%val = call i32 %fp( i32 %x, i32 %y )</tt> is then equivalent to <tt>%val = call i32 %f( i8* %nval, i32 %x, i32 %y )</tt>. @@ -5180,11 +5178,12 @@ <div class="doc_text"> <h5>Syntax:</h5> <pre> -declare void @llvm.init.trampoline(i8* <tramp>, i8* <func>, i8* <nval>) +declare i8* @llvm.init.trampoline(i8* <tramp>, i8* <func>, i8* <nval>) </pre> <h5>Overview:</h5> <p> - This initializes the memory pointed to by <tt>tramp</tt> as a trampoline. + This fills the memory pointed to by <tt>tramp</tt> with code + and returns a function pointer suitable for executing it. </p> <h5>Arguments:</h5> <p> @@ -5199,42 +5198,18 @@ <h5>Semantics:</h5> <p> The block of memory pointed to by <tt>tramp</tt> is filled with target - dependent code, turning it into a function. - The new function's signature is the same as that of <tt>func</tt> with - any arguments marked with the <tt>nest</tt> attribute removed. At most - one such <tt>nest</tt> argument is allowed, and it must be of pointer - type. Calling the new function is equivalent to calling <tt>func</tt> - with the same argument list, but with <tt>nval</tt> used for the missing - <tt>nest</tt> argument. -</p> -</div> - -<!-- _______________________________________________________________________ --> -<div class="doc_subsubsection"> - <a name="int_at">'<tt>llvm.adjust.trampoline</tt>' Intrinsic</a> -</div> -<div class="doc_text"> -<h5>Syntax:</h5> -<pre> -declare i8* @llvm.adjust.trampoline(i8* <tramp>) -</pre> -<h5>Overview:</h5> -<p> - This intrinsic returns a function pointer suitable for executing - the trampoline code pointed to by <tt>tramp</tt>. -</p> -<h5>Arguments:</h5> -<p> - The <tt>llvm.adjust.trampoline</tt> takes one argument, a pointer to a - trampoline initialized by the - <a href="#int_it">'<tt>llvm.init.trampoline</tt>' intrinsic</a>. -</p> -<h5>Semantics:</h5> -<p> - A function pointer that can be used to execute the trampoline code in - <tt>tramp</tt> is returned. The returned value should be bitcast to an + dependent code, turning it into a function. A pointer to this function is + returned, but needs to be bitcast to an <a href="#int_trampoline">appropriate function pointer type</a> - before being called. + before being called. The new function's signature is the same as that of + <tt>func</tt> with any arguments marked with the <tt>nest</tt> attribute + removed. At most one such <tt>nest</tt> argument is allowed, and it must be + of pointer type. Calling the new function is equivalent to calling + <tt>func</tt> with the same argument list, but with <tt>nval</tt> used for the + missing <tt>nest</tt> argument. If, after calling + <tt>llvm.init.trampoline</tt>, the memory pointed to by <tt>tramp</tt> is + modified, then the effect of any later call to the returned function pointer is + undefined. </p> </div>
Index: gcc.llvm.master/gcc/builtins.c =================================================================== --- gcc.llvm.master.orig/gcc/builtins.c 2007-09-06 11:16:22.000000000 +0200 +++ gcc.llvm.master/gcc/builtins.c 2007-09-06 11:23:08.000000000 +0200 @@ -4986,25 +4986,13 @@ trampolines_created = 1; INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain); - return const0_rtx; -} - -static rtx -expand_builtin_adjust_trampoline (tree arglist) -{ - rtx tramp; - - if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) - return NULL_RTX; - - tramp = expand_expr (TREE_VALUE (arglist), NULL_RTX, VOIDmode, 0); - tramp = round_trampoline_addr (tramp); #ifdef TRAMPOLINE_ADJUST_ADDRESS - TRAMPOLINE_ADJUST_ADDRESS (tramp); + TRAMPOLINE_ADJUST_ADDRESS (r_tramp); #endif - return tramp; + return r_tramp; } +/* LLVM local end */ /* Expand a call to the built-in signbit, signbitf or signbitl function. Return NULL_RTX if a normal call should be emitted rather than expanding @@ -5784,8 +5772,7 @@ case BUILT_IN_INIT_TRAMPOLINE: return expand_builtin_init_trampoline (arglist); - case BUILT_IN_ADJUST_TRAMPOLINE: - return expand_builtin_adjust_trampoline (arglist); + /* LLVM local deleted 2 lines */ case BUILT_IN_FORK: case BUILT_IN_EXECL: Index: gcc.llvm.master/gcc/builtins.def =================================================================== --- gcc.llvm.master.orig/gcc/builtins.def 2007-09-06 11:16:22.000000000 +0200 +++ gcc.llvm.master/gcc/builtins.def 2007-09-06 11:23:08.000000000 +0200 @@ -635,7 +635,7 @@ /* Implementing nested functions. */ DEF_BUILTIN_STUB (BUILT_IN_INIT_TRAMPOLINE, "__builtin_init_trampoline") -DEF_BUILTIN_STUB (BUILT_IN_ADJUST_TRAMPOLINE, "__builtin_adjust_trampoline") +/* LLVM local deleted 1 line */ DEF_BUILTIN_STUB (BUILT_IN_NONLOCAL_GOTO, "__builtin_nonlocal_goto") /* Implementing variable sized local variables. */ Index: gcc.llvm.master/gcc/llvm-convert.cpp =================================================================== --- gcc.llvm.master.orig/gcc/llvm-convert.cpp 2007-09-06 11:23:08.000000000 +0200 +++ gcc.llvm.master/gcc/llvm-convert.cpp 2007-09-06 11:28:05.000000000 +0200 @@ -4342,9 +4342,7 @@ case BUILT_IN_FROB_RETURN_ADDR: return EmitBuiltinFrobReturnAddr(exp, Result); case BUILT_IN_INIT_TRAMPOLINE: - return EmitBuiltinInitTrampoline(exp); - case BUILT_IN_ADJUST_TRAMPOLINE: - return EmitBuiltinAdjustTrampoline(exp, Result); + return EmitBuiltinInitTrampoline(exp, Result); // Builtins used by the exception handling runtime. case BUILT_IN_DWARF_CFA: @@ -5004,7 +5002,7 @@ return true; } -bool TreeToLLVM::EmitBuiltinInitTrampoline(tree exp) { +bool TreeToLLVM::EmitBuiltinInitTrampoline(tree exp, Value *&Result) { tree arglist = TREE_OPERAND(exp, 1); if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) @@ -5025,22 +5023,7 @@ Function *Intr = Intrinsic::getDeclaration(TheModule, Intrinsic::init_trampoline); - Builder.CreateCall(Intr, Ops, Ops+3); - return true; -} - -bool TreeToLLVM::EmitBuiltinAdjustTrampoline(tree exp, Value *&Result) { - tree arglist = TREE_OPERAND(exp, 1); - if (!validate_arglist(arglist, POINTER_TYPE, VOID_TYPE)) - return false; - - Value *Tramp = Emit(TREE_VALUE(arglist), 0); - Tramp = CastToType(Instruction::BitCast, Tramp, - PointerType::get(Type::Int8Ty)); - - Function *Intr = Intrinsic::getDeclaration(TheModule, - Intrinsic::adjust_trampoline); - Result = Builder.CreateCall(Intr, Tramp, "adj"); + Result = Builder.CreateCall(Intr, Ops, Ops+3, "tramp"); return true; } Index: gcc.llvm.master/gcc/llvm-internal.h =================================================================== --- gcc.llvm.master.orig/gcc/llvm-internal.h 2007-09-06 11:16:22.000000000 +0200 +++ gcc.llvm.master/gcc/llvm-internal.h 2007-09-06 11:23:08.000000000 +0200 @@ -582,8 +582,7 @@ bool EmitBuiltinEHReturn(tree_node *exp, Value *&Result); bool EmitBuiltinInitDwarfRegSizes(tree_node *exp, Value *&Result); bool EmitBuiltinUnwindInit(tree_node *exp, Value *&Result); - bool EmitBuiltinInitTrampoline(tree_node *exp); - bool EmitBuiltinAdjustTrampoline(tree_node *exp, Value *&Result); + bool EmitBuiltinInitTrampoline(tree_node *exp, Value *&Result); // Complex Math Expressions. void EmitLoadFromComplex(Value *&Real, Value *&Imag, Value *SrcComplex, Index: gcc.llvm.master/gcc/tree-nested.c =================================================================== --- gcc.llvm.master.orig/gcc/tree-nested.c 2007-09-06 11:23:07.000000000 +0200 +++ gcc.llvm.master/gcc/tree-nested.c 2007-09-06 11:23:08.000000000 +0200 @@ -399,16 +399,20 @@ /* Build or return the type used to represent a nested function trampoline. */ -static GTY(()) tree trampoline_type; +/* LLVM local */ +static GTY(()) tree trampoline_storage_type; static tree -get_trampoline_type (void) +/* LLVM local */ +get_trampoline_storage_type (void) { tree record, t; unsigned align, size; - if (trampoline_type) - return trampoline_type; + /* LLVM local begin */ + if (trampoline_storage_type) + return trampoline_storage_type; + /* LLVM local end */ align = TRAMPOLINE_ALIGNMENT; size = TRAMPOLINE_SIZE; @@ -464,8 +468,9 @@ { field = make_node (FIELD_DECL); DECL_NAME (field) = DECL_NAME (decl); - TREE_TYPE (field) = get_trampoline_type (); - TREE_ADDRESSABLE (field) = 1; + /* LLVM local begin */ + TREE_TYPE (field) = TYPE_POINTER_TO (TREE_TYPE (decl)); + /* LLVM local end */ insert_field_into_struct (get_frame_type (info), field); @@ -1286,17 +1291,14 @@ { struct walk_stmt_info *wi = data; struct nesting_info *info = wi->info, *i; - tree t = *tp, decl, target_context, x, arg; + /* LLVM local */ + tree t = *tp, decl, target_context, x; *walk_subtrees = 0; switch (TREE_CODE (t)) { case ADDR_EXPR: - /* Build - T.1 = &CHAIN->tramp; - T.2 = __builtin_adjust_trampoline (T.1); - T.3 = (func_type)T.2; - */ + /* LLVM local deleted 5 lines */ decl = TREE_OPERAND (t, 0); if (TREE_CODE (decl) != FUNCTION_DECL) @@ -1316,22 +1318,12 @@ we need to insert the trampoline. */ for (i = info; i->context != target_context; i = i->outer) continue; - x = lookup_tramp_for_decl (i, decl, INSERT); + /* LLVM local begin */ - /* Compute the address of the field holding the trampoline. */ + /* Lookup the trampoline. */ + x = lookup_tramp_for_decl (i, decl, INSERT); x = get_frame_field (info, target_context, x, &wi->tsi); - x = build_addr (x); - x = tsi_gimplify_val (info, x, &wi->tsi); - arg = tree_cons (NULL, x, NULL); - - /* Do machine-specific ugliness. Normally this will involve - computing extra alignment, but it can really be anything. */ - x = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE]; - x = build_function_call_expr (x, arg); - x = init_tmp_var (info, x, &wi->tsi); - - /* Cast back to the proper function type. */ - x = build1 (NOP_EXPR, TREE_TYPE (t), x); + /* LLVM local end */ x = init_tmp_var (info, x, &wi->tsi); *tp = x; @@ -1483,7 +1475,8 @@ struct nesting_info *i; for (i = root->inner; i ; i = i->next) { - tree arg, x, field; + /* LLVM local */ + tree arg, x, y, field; field = lookup_tramp_for_decl (root, i->context, NO_INSERT); if (!field) @@ -1498,13 +1491,27 @@ x = build_addr (i->context); arg = tree_cons (NULL, x, arg); - x = build (COMPONENT_REF, TREE_TYPE (field), - root->frame_decl, field, NULL_TREE); - x = build_addr (x); + /* LLVM local begin */ + /* Create a local variable to hold the trampoline code. */ + y = create_tmp_var_for (root, get_trampoline_storage_type(), + "TRAMP"); + x = build_addr (y); arg = tree_cons (NULL, x, arg); x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE]; x = build_function_call_expr (x, arg); + y = create_tmp_var_for (root, TREE_TYPE(x), NULL); + x = build2 (MODIFY_EXPR, TREE_TYPE (x), y, x); + append_to_statement_list (x, &stmt_list); + + /* Cast back to the proper function type. */ + y = build1 (NOP_EXPR, TREE_TYPE (field), y); + + /* Initialize the trampoline. */ + x = build3 (COMPONENT_REF, TREE_TYPE (field), + root->frame_decl, field, NULL_TREE); + x = build2 (MODIFY_EXPR, TREE_TYPE (field), x, y); + /* LLVM local end */ append_to_statement_list (x, &stmt_list); } Index: gcc.llvm.master/gcc/tree.c =================================================================== --- gcc.llvm.master.orig/gcc/tree.c 2007-09-06 11:23:06.000000000 +0200 +++ gcc.llvm.master/gcc/tree.c 2007-09-06 11:23:08.000000000 +0200 @@ -6029,17 +6029,12 @@ tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); - ftype = build_function_type (void_type_node, tmp); + /* LLVM local begin */ + ftype = build_function_type (ptr_type_node, tmp); local_define_builtin ("__builtin_init_trampoline", ftype, BUILT_IN_INIT_TRAMPOLINE, "__builtin_init_trampoline", ECF_NOTHROW); - - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - ftype = build_function_type (ptr_type_node, tmp); - local_define_builtin ("__builtin_adjust_trampoline", ftype, - BUILT_IN_ADJUST_TRAMPOLINE, - "__builtin_adjust_trampoline", - ECF_CONST | ECF_NOTHROW); + /* LLVM local end */ tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
Index: gcc-4.2.llvm/gcc/builtins.c =================================================================== --- gcc-4.2.llvm.orig/gcc/builtins.c 2007-08-12 17:16:59.000000000 +0200 +++ gcc-4.2.llvm/gcc/builtins.c 2007-09-08 23:26:53.000000000 +0200 @@ -5281,25 +5281,14 @@ trampolines_created = 1; INITIALIZE_TRAMPOLINE (r_tramp, r_func, r_chain); - return const0_rtx; -} - -static rtx -expand_builtin_adjust_trampoline (tree arglist) -{ - rtx tramp; - - if (!validate_arglist (arglist, POINTER_TYPE, VOID_TYPE)) - return NULL_RTX; - - tramp = expand_normal (TREE_VALUE (arglist)); - tramp = round_trampoline_addr (tramp); +/* LLVM local begin */ #ifdef TRAMPOLINE_ADJUST_ADDRESS - TRAMPOLINE_ADJUST_ADDRESS (tramp); + TRAMPOLINE_ADJUST_ADDRESS (r_tramp); #endif - return tramp; + return r_tramp; } +/* LLVM local end */ /* Expand a call to the built-in signbit, signbitf or signbitl function. Return NULL_RTX if a normal call should be emitted rather than expanding @@ -6285,8 +6274,7 @@ case BUILT_IN_INIT_TRAMPOLINE: return expand_builtin_init_trampoline (arglist); - case BUILT_IN_ADJUST_TRAMPOLINE: - return expand_builtin_adjust_trampoline (arglist); + /* LLVM local deleted 2 lines */ case BUILT_IN_FORK: case BUILT_IN_EXECL: Index: gcc-4.2.llvm/gcc/builtins.def =================================================================== --- gcc-4.2.llvm.orig/gcc/builtins.def 2007-07-17 16:42:19.000000000 +0200 +++ gcc-4.2.llvm/gcc/builtins.def 2007-09-08 23:26:53.000000000 +0200 @@ -691,7 +691,7 @@ /* Implementing nested functions. */ DEF_BUILTIN_STUB (BUILT_IN_INIT_TRAMPOLINE, "__builtin_init_trampoline") -DEF_BUILTIN_STUB (BUILT_IN_ADJUST_TRAMPOLINE, "__builtin_adjust_trampoline") +/* LLVM local deleted 1 line */ DEF_BUILTIN_STUB (BUILT_IN_NONLOCAL_GOTO, "__builtin_nonlocal_goto") /* Implementing __builtin_setjmp. */ Index: gcc-4.2.llvm/gcc/llvm-convert.cpp =================================================================== --- gcc-4.2.llvm.orig/gcc/llvm-convert.cpp 2007-09-08 23:18:10.000000000 +0200 +++ gcc-4.2.llvm/gcc/llvm-convert.cpp 2007-09-08 23:26:53.000000000 +0200 @@ -3845,9 +3845,7 @@ case BUILT_IN_FROB_RETURN_ADDR: return EmitBuiltinFrobReturnAddr(exp, Result); case BUILT_IN_INIT_TRAMPOLINE: - return EmitBuiltinInitTrampoline(exp); - case BUILT_IN_ADJUST_TRAMPOLINE: - return EmitBuiltinAdjustTrampoline(exp, Result); + return EmitBuiltinInitTrampoline(exp, Result); // Builtins used by the exception handling runtime. case BUILT_IN_DWARF_CFA: @@ -4513,7 +4511,7 @@ return true; } -bool TreeToLLVM::EmitBuiltinInitTrampoline(tree exp) { +bool TreeToLLVM::EmitBuiltinInitTrampoline(tree exp, Value *&Result) { tree arglist = TREE_OPERAND(exp, 1); if (!validate_arglist (arglist, POINTER_TYPE, POINTER_TYPE, POINTER_TYPE, VOID_TYPE)) @@ -4534,22 +4532,7 @@ Function *Intr = Intrinsic::getDeclaration(TheModule, Intrinsic::init_trampoline); - Builder.CreateCall(Intr, Ops, Ops+3); - return true; -} - -bool TreeToLLVM::EmitBuiltinAdjustTrampoline(tree exp, Value *&Result) { - tree arglist = TREE_OPERAND(exp, 1); - if (!validate_arglist(arglist, POINTER_TYPE, VOID_TYPE)) - return false; - - Value *Tramp = Emit(TREE_VALUE(arglist), 0); - Tramp = CastToType(Instruction::BitCast, Tramp, - PointerType::get(Type::Int8Ty)); - - Function *Intr = Intrinsic::getDeclaration(TheModule, - Intrinsic::adjust_trampoline); - Result = Builder.CreateCall(Intr, Tramp, "adj"); + Result = Builder.CreateCall(Intr, Ops, Ops+3, "tramp"); return true; } Index: gcc-4.2.llvm/gcc/llvm-internal.h =================================================================== --- gcc-4.2.llvm.orig/gcc/llvm-internal.h 2007-09-08 23:18:10.000000000 +0200 +++ gcc-4.2.llvm/gcc/llvm-internal.h 2007-09-08 23:26:53.000000000 +0200 @@ -527,8 +527,7 @@ bool EmitBuiltinEHReturn(tree_node *exp, Value *&Result); bool EmitBuiltinInitDwarfRegSizes(tree_node *exp, Value *&Result); bool EmitBuiltinUnwindInit(tree_node *exp, Value *&Result); - bool EmitBuiltinInitTrampoline(tree_node *exp); - bool EmitBuiltinAdjustTrampoline(tree_node *exp, Value *&Result); + bool EmitBuiltinInitTrampoline(tree_node *exp, Value *&Result); // Complex Math Expressions. void EmitLoadFromComplex(Value *&Real, Value *&Imag, Value *SrcComplex, Index: gcc-4.2.llvm/gcc/tree-nested.c =================================================================== --- gcc-4.2.llvm.orig/gcc/tree-nested.c 2007-07-27 15:27:04.000000000 +0200 +++ gcc-4.2.llvm/gcc/tree-nested.c 2007-09-08 23:26:53.000000000 +0200 @@ -425,16 +425,20 @@ /* Build or return the type used to represent a nested function trampoline. */ -static GTY(()) tree trampoline_type; +/* LLVM local */ +static GTY(()) tree trampoline_storage_type; static tree -get_trampoline_type (void) +/* LLVM local */ +get_trampoline_storage_type (void) { tree record, t; unsigned align, size; - if (trampoline_type) - return trampoline_type; + /* LLVM local begin */ + if (trampoline_storage_type) + return trampoline_storage_type; + /* LLVM local end */ align = TRAMPOLINE_ALIGNMENT; size = TRAMPOLINE_SIZE; @@ -490,8 +494,9 @@ { field = make_node (FIELD_DECL); DECL_NAME (field) = DECL_NAME (decl); - TREE_TYPE (field) = get_trampoline_type (); - TREE_ADDRESSABLE (field) = 1; + /* LLVM local begin */ + TREE_TYPE (field) = TYPE_POINTER_TO (TREE_TYPE (decl)); + /* LLVM local end */ insert_field_into_struct (get_frame_type (info), field); @@ -1618,17 +1623,14 @@ { struct walk_stmt_info *wi = (struct walk_stmt_info *) data; struct nesting_info *info = wi->info, *i; - tree t = *tp, decl, target_context, x, arg; + /* LLVM local */ + tree t = *tp, decl, target_context, x; *walk_subtrees = 0; switch (TREE_CODE (t)) { case ADDR_EXPR: - /* Build - T.1 = &CHAIN->tramp; - T.2 = __builtin_adjust_trampoline (T.1); - T.3 = (func_type)T.2; - */ + /* LLVM local deleted 5 lines */ decl = TREE_OPERAND (t, 0); if (TREE_CODE (decl) != FUNCTION_DECL) @@ -1648,22 +1650,12 @@ we need to insert the trampoline. */ for (i = info; i->context != target_context; i = i->outer) continue; - x = lookup_tramp_for_decl (i, decl, INSERT); + /* LLVM local begin */ - /* Compute the address of the field holding the trampoline. */ + /* Lookup the trampoline. */ + x = lookup_tramp_for_decl (i, decl, INSERT); x = get_frame_field (info, target_context, x, &wi->tsi); - x = build_addr (x, target_context); - x = tsi_gimplify_val (info, x, &wi->tsi); - arg = tree_cons (NULL, x, NULL); - - /* Do machine-specific ugliness. Normally this will involve - computing extra alignment, but it can really be anything. */ - x = implicit_built_in_decls[BUILT_IN_ADJUST_TRAMPOLINE]; - x = build_function_call_expr (x, arg); - x = init_tmp_var (info, x, &wi->tsi); - - /* Cast back to the proper function type. */ - x = build1 (NOP_EXPR, TREE_TYPE (t), x); + /* LLVM local end */ x = init_tmp_var (info, x, &wi->tsi); *tp = x; @@ -1858,7 +1850,8 @@ struct nesting_info *i; for (i = root->inner; i ; i = i->next) { - tree arg, x, field; + /* LLVM local */ + tree arg, x, y, field; field = lookup_tramp_for_decl (root, i->context, NO_INSERT); if (!field) @@ -1873,13 +1866,27 @@ x = build_addr (i->context, context); arg = tree_cons (NULL, x, arg); - x = build3 (COMPONENT_REF, TREE_TYPE (field), - root->frame_decl, field, NULL_TREE); - x = build_addr (x, context); + /* LLVM local begin */ + /* Create a local variable to hold the trampoline code. */ + y = create_tmp_var_for (root, get_trampoline_storage_type(), + "TRAMP"); + x = build_addr (y, context); arg = tree_cons (NULL, x, arg); x = implicit_built_in_decls[BUILT_IN_INIT_TRAMPOLINE]; x = build_function_call_expr (x, arg); + y = create_tmp_var_for (root, TREE_TYPE(x), NULL); + x = build2 (MODIFY_EXPR, TREE_TYPE (x), y, x); + append_to_statement_list (x, &stmt_list); + + /* Cast back to the proper function type. */ + y = build1 (NOP_EXPR, TREE_TYPE (field), y); + + /* Initialize the trampoline. */ + x = build3 (COMPONENT_REF, TREE_TYPE (field), + root->frame_decl, field, NULL_TREE); + x = build2 (MODIFY_EXPR, TREE_TYPE (field), x, y); + /* LLVM local end */ append_to_statement_list (x, &stmt_list); } Index: gcc-4.2.llvm/gcc/tree.c =================================================================== --- gcc-4.2.llvm.orig/gcc/tree.c 2007-08-12 17:16:58.000000000 +0200 +++ gcc-4.2.llvm/gcc/tree.c 2007-09-08 23:26:53.000000000 +0200 @@ -6772,17 +6772,12 @@ tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); tmp = tree_cons (NULL_TREE, ptr_type_node, tmp); - ftype = build_function_type (void_type_node, tmp); + /* LLVM local begin */ + ftype = build_function_type (ptr_type_node, tmp); local_define_builtin ("__builtin_init_trampoline", ftype, BUILT_IN_INIT_TRAMPOLINE, "__builtin_init_trampoline", ECF_NOTHROW); - - tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); - ftype = build_function_type (ptr_type_node, tmp); - local_define_builtin ("__builtin_adjust_trampoline", ftype, - BUILT_IN_ADJUST_TRAMPOLINE, - "__builtin_adjust_trampoline", - ECF_CONST | ECF_NOTHROW); + /* LLVM local end */ tmp = tree_cons (NULL_TREE, ptr_type_node, void_list_node); tmp = tree_cons (NULL_TREE, ptr_type_node, tmp);
Index: llvm.master/lib/Transforms/Scalar/InstructionCombining.cpp =================================================================== --- llvm.master.orig/lib/Transforms/Scalar/InstructionCombining.cpp 2007-09-06 19:25:38.000000000 +0200 +++ llvm.master/lib/Transforms/Scalar/InstructionCombining.cpp 2007-09-08 22:13:35.000000000 +0200 @@ -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" @@ -7855,6 +7856,142 @@ } } + 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 *NestPTy = cast<PointerType>(NestF->getType()); + const FunctionType *NestFTy = cast<FunctionType>(NestPTy->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@cs.uiuc.edu http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits