[GHC] #8321: improve basic block layout on LLVM backend by predicting stack/heap checks

GHC ghc-devs at haskell.org
Tue Sep 17 20:53:36 CEST 2013


#8321: improve basic block layout on LLVM backend by predicting stack/heap checks
------------------------------------+-------------------------------------
       Reporter:  rwbarton          |             Owner:
           Type:  feature request   |            Status:  new
       Priority:  normal            |         Milestone:  7.10.1
      Component:  Compiler (LLVM)   |           Version:  7.7
       Keywords:                    |  Operating System:  Unknown/Multiple
   Architecture:  Unknown/Multiple  |   Type of failure:  None/Unknown
     Difficulty:  Unknown           |         Test Case:
     Blocked By:                    |          Blocking:
Related Tickets:                    |
------------------------------------+-------------------------------------
 Currently we don't give the LLVM optimizer any information about which
 branch of an `if` is likely to be taken. As a result, the optimizer is
 likely to produce a basic block layout which is not optimal. Improving the
 layout can improve performance through better instruction cache usage and
 better branch prediction by the hardware.

 We can control LLVM's idea of what is likely with the `llvm.expect`
 intrinsic function. Some obvious branches which we can predict accurately
 are the stack and heap checks that appear near the entry of many
 functions.

 Here's a small example of some Cmm code and the output of the LLVM
 optimizer/compiler.

 {{{
  block_c2Lc_entry() //  [R1, R2]
          { info_tbl: [(c2Lc,
                        label: block_c2Lc_info
                        rep:StackRep [])]
            stack_info: arg_space: 0 updfr_space: Nothing
          }
      {offset
        c2Lc:
            Hp = Hp + 24;
            if (Hp > HpLim) goto c2Lm; else goto c2Ll;
        c2Lm:
            HpAlloc = 24;
            R2 = R2;
            R1 = R1;
            call stg_gc_pp(R2, R1) args: 8, res: 8, upd: 24;
        c2Ll:
            I64[Hp - 16] = :_con_info;
            P64[Hp - 8] = R1;
            P64[Hp] = R2;
            R1 = Hp - 14;
            Sp = Sp + 8;
            call (P64[Sp])(R1) args: 24, res: 0, upd: 24;
      }
  }]
 }}}

 {{{

 00000000000002b8 <c2Lc_info>:
  2b8:   4c 89 e0                mov    %r12,%rax
  2bb:   4c 8d 60 18             lea    0x18(%rax),%r12
  2bf:   4d 3b a5 18 01 00 00    cmp    0x118(%r13),%r12
  2c6:   76 10                   jbe    2d8 <c2Lc_info+0x20>
  2c8:   49 c7 85 48 01 00 00    movq   $0x18,0x148(%r13)
  2cf:   18 00 00 00
  2d3:   e9 00 00 00 00          jmpq   2d8 <c2Lc_info+0x20>
                         2d4: R_X86_64_PC32
 stg_gc_pp+0xfffffffffffffffc
  2d8:   48 c7 40 08 00 00 00    movq   $0x0,0x8(%rax)
  2df:   00
                         2dc: R_X86_64_32S
 ghczmprim_GHCziTypes_ZC_con_info
  2e0:   48 89 58 10             mov    %rbx,0x10(%rax)
  2e4:   4c 89 70 18             mov    %r14,0x18(%rax)
  2e8:   48 8b 45 08             mov    0x8(%rbp),%rax
  2ec:   48 83 c5 08             add    $0x8,%rbp
  2f0:   49 8d 5c 24 f2          lea    -0xe(%r12),%rbx
  2f5:   ff e0                   jmpq   *%rax
  2f7:   90                      nop
 }}}

 It would likely be better to invert the branch at `2c6` to a `ja`, so that
 the common case is adjacent to the function entry, and when `llvm.expect`
 is used on the condition in the branch, the LLVM optimizer does produce
 this alternate layout.

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



More information about the ghc-tickets mailing list