[LLVMdev] Tail call optimization thoughts

Arnold Schwaighofer arnold.schwaighofer at gmail.com
Thu Aug 9 12:23:08 PDT 2007


Implementing tail call opt could look like the following:

0.)a fast calling convention (maybe use the current  
CallingConv::Fast, or create a CallingConv::TailCall)
1.) lowering of formal arguments
   like for example x86_LowerCCCArguments in  stdcall mode
   we need to make sure that later mentioned CALL_CLOBBERED_REG is  
not used (remove it from available
   registers in callingconvention for argument passing?)
2.)lowering of the call:
   *if it can be shown that call really is tail call (next  
instruction is a return):
      -move the arguments to the correct position on the stack
      -create a REALTAILCALL SelDAG node holding
        tailcallee : if the tailcallee is dynamic, not a  
TargetGlobalAddress or the like,
        lower a move CALL_CLOBBERED_REG tailcallee instruction else  
attach a
        TargetGlobalAddress or the like
      -the size of the stack adjustment
      the realtailcall would be a no op operation that makes sure  
that epilogue is
      lowered before it (looks like a call), remember that we have a  
real tail call
      (like setBytesToPopOnReturn() , a setIsRealTailCall()) in the  
targetlowering())
   *else emit regular function call with same calling conventions
3.)lower of the return:
   *if we are dealing with a realtailcall (getIsRealTailCall)
       look for REALTAILCALL use its operands to
       emit a TC_RETURN node holding stacksize, tailcallee
       the tc_return node would again be a pseudoop
   *else lower normal return


When generating the epilog the two operands of the the tc_return  
machine instruction are used to emit code that adjust the  
stackpointer and jumps to the tailcallee (either label or register).  
Like it is done for EH_RETURN.

in X86RegisterInfo.cpp we would then have
TargetRegisterInfo::emitEpilogue() {
   ...
   if (RetOpcode== X86::TC_RETURN){
     if (isDynamicCallee(RetOpCode))
       add esp  {stack adjustment from tc_return}
       jmp {register operand of tc_return}
     } else
       add esp  {stack adjustment from tc_return}
       jmp {targetfunction operand}
     }
}

resulting code for dynamic function
	
   mov  ecx  esi  #load callee, say esi holds the address of the  
tailcalled
   epilogue
   #TAILCALL
   add esp 8  #caller has 2 more arg
   jmp ecx

if the targetfunction is known

   epilogue
   #TAILCALL
   add esp 8 #caller has 2 more arg
   jmp _targetfunction

Should also work for architectures other than x86.

any critique, comments welcome
regards arnold





More information about the llvm-dev mailing list