[GHC] #9387: LLVM backend: redundant code for functions calling themselves

GHC ghc-devs at haskell.org
Wed Jul 30 17:39:09 UTC 2014


#9387: LLVM backend: redundant code for functions calling themselves
-------------------------------------+-------------------------------------
              Reporter:  jmoy        |            Owner:
                  Type:  feature     |           Status:  new
  request                            |        Milestone:
              Priority:  normal      |          Version:  7.6.3
             Component:  Compiler    |         Keywords:
  (LLVM)                             |     Architecture:  x86_64 (amd64)
            Resolution:              |       Difficulty:  Unknown
      Operating System:  Linux       |       Blocked By:
       Type of failure:              |  Related Tickets:
  None/Unknown                       |
             Test Case:              |
              Blocking:              |
Differential Revisions:              |
-------------------------------------+-------------------------------------
Description changed by jmoy:

Old description:

> It seems that the LLVM backed does not recognize when a function calls
> itself. As a result it generates redundant load and store instructions.
>
> I am compiling the following simple recursive Fibonacci function
>
> {{{
> fib::Int->Int
> fib n
>   = loop n 0 1
>   where
>     loop !n !a !b
>       = if n==1 then
>           a
>         else
>           loop (n-1) b (a+b)
> }}}
>
> I am attaching the files produced by
>
> {{{
> ghc -c -O3 -fllvm -ddump-stg -ddump-cmm -ddump-llvm -ddump-to-file Fib.hs
> }}}
>
> I rename the generated LLVM file with a `.ll` extension and run `llc -O3`
> on it to generate the attached `.s` file (LLVM version 3.4.2).
>
> The actual work gets done in `Fib_zdwloop_info`. It begins as:
>
> {{{
> Fib_zdwloop_info:                       # @Fib_zdwloop_info
> # BB#0:                                 # %css
>         pushq   %rax
>         movq    %r13, (%rsp)
>         movq    %rbp, -8(%rsp)
>         movq    %r12, -16(%rsp)
>         movq    %rbx, -24(%rsp)
>         movq    %r14, -32(%rsp)
>         movq    %rsi, -40(%rsp)
>         movq    %rdi, -48(%rsp)
>         movq    %r8, -56(%rsp)
>         movq    %r9, -64(%rsp)
>         movq    %r15, -72(%rsp)
>         movss   %xmm1, -76(%rsp)
>         movss   %xmm2, -80(%rsp)
>         movss   %xmm3, -84(%rsp)
>         movss   %xmm4, -88(%rsp)
>         movsd   %xmm5, -96(%rsp)
>         movsd   %xmm6, -104(%rsp)
> }}}
>
> Later on when the function makes a recursive call to itself the code
> generated is
>
> {{{
>         movq    -8(%rsp), %rbp
>         movq    -16(%rsp), %r12
>         movq    -24(%rsp), %rbx
>         movq    -32(%rsp), %r14
>         movq    -40(%rsp), %rsi
>         movq    -72(%rsp), %r15
>         popq    %rax
>         jmp     Fib_zdwloop_info        # TAILCALL
> }}}
>
> Given that the values are being loaded from the stack to the registers in
> the second excerpt, it is redundant to re-store the same values into the
> stack at the entry of the function.
>
> It seems to me that this is happening because LLVM uses a general
> function call instruction to translate a function calling itself. I was
> wondering if it is possible to recognize this special case in the LLVM
> backed or earlier so that instead of a function call we can translate
> this as the LLVM level as a jump to some point after the function entry.

New description:

 It seems that the LLVM backed does not recognize when a function calls
 itself. As a result it generates redundant load and store instructions.

 I am compiling the following simple recursive Fibonacci function

 {{{
 fib::Int->Int
 fib n
   = loop n 0 1
   where
     loop !n !a !b
       = if n==1 then
           a
         else
           loop (n-1) b (a+b)
 }}}

 I am attaching the files produced by

 {{{
 ghc -c -O3 -fllvm -ddump-stg -ddump-cmm -ddump-llvm -ddump-to-file Fib.hs
 }}}

 I rename the generated LLVM file with a `.ll` extension and run `llc -O3`
 on it to generate the attached `.s` file (LLVM version 3.4.2).

 The actual work gets done in `Fib_zdwloop_info`. It begins as:

 {{{
 Fib_zdwloop_info:                       # @Fib_zdwloop_info
 # BB#0:                                 # %css
         pushq   %rax
         movq    %r13, (%rsp)
         movq    %rbp, -8(%rsp)
         movq    %r12, -16(%rsp)
         movq    %rbx, -24(%rsp)
         movq    %r14, -32(%rsp)
         movq    %rsi, -40(%rsp)
         movq    %rdi, -48(%rsp)
         movq    %r8, -56(%rsp)
         movq    %r9, -64(%rsp)
         movq    %r15, -72(%rsp)
         movss   %xmm1, -76(%rsp)
         movss   %xmm2, -80(%rsp)
         movss   %xmm3, -84(%rsp)
         movss   %xmm4, -88(%rsp)
         movsd   %xmm5, -96(%rsp)
         movsd   %xmm6, -104(%rsp)
 }}}

 Later on when the function makes a recursive call to itself the code
 generated is

 {{{
         movq    -8(%rsp), %rbp
         movq    -16(%rsp), %r12
         movq    -24(%rsp), %rbx
         movq    -32(%rsp), %r14
         movq    -40(%rsp), %rsi
         movq    -72(%rsp), %r15
         popq    %rax
         jmp     Fib_zdwloop_info        # TAILCALL
 }}}

 Given that the values are being loaded from the stack to the registers in
 the second excerpt, it is redundant to re-store the same values into the
 stack at the entry of the function.

 It seems to me that this is happening because LLVM uses a general function
 call instruction to translate a function calling itself. I was wondering
 if it is possible to recognize this special case in the LLVM backed or
 earlier so that instead of a function call we can translate this at the
 LLVM level as a jump to some point after the function entry.

--

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9387#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list