Generate tail call opcode

后端 未结 3 1294
野的像风
野的像风 2020-11-28 12:04

Out of curiosity I was trying to generate a tail call opcode using C#. Fibinacci is an easy one, so my c# example looks like this:

    private static void M         


        
3条回答
  •  我在风中等你
    2020-11-28 12:34

    C# compiler does not give you any guarantees about tail-call optimizations because C# programs usually use loops and so they do not rely on the tail-call optimizations. So, in C#, this is simply a JIT optimization that may or may not happen (and you cannot rely on it).

    F# compiler is designed to handle functional code that uses recursion and so it does give you certain guarantees about tail-calls. This is done in two ways:

    • if you write a recursive function that calls itself (like your fib) the compiler turns it into a function that uses loop in the body (this is a simple optimization and the produced code is faster than using a tail-call)

    • if you use a recursive call in a more complex position (when using continuation passing style where function is passed as an argument), then the compiler generates a tail-call instruction that tells the JIT that it must use a tail call.

    As an example of the second case, compile the following simple F# function (F# does not do this in Debug mode to simplify debugging, so you may need Release mode or add --tailcalls+):

    let foo a cont = cont (a + 1)
    

    The function simply calls the function cont with the first argument incremented by one. In continuation passing style, you have a long sequence of such calls, so the optimization is crucial (you simply cannot use this style without some handling of tail calls). The generates IL code looks like this:

    IL_0000: ldarg.1
    IL_0001: ldarg.0
    IL_0002: ldc.i4.1
    IL_0003: add
    IL_0004: tail.                          // Here is the 'tail' opcode!
    IL_0006: callvirt instance !1 
      class [FSharp.Core] Microsoft.FSharp.Core.FSharpFunc`2::Invoke(!0)
    IL_000b: ret
    

提交回复
热议问题