[GHC] #8855: LLVM backend needs to use `-globalopt` explicitly

GHC ghc-devs at haskell.org
Fri Mar 7 15:31:47 UTC 2014


#8855: LLVM backend needs to use `-globalopt` explicitly
-------------------------------------+------------------------------------
        Reporter:  bgamari           |            Owner:
            Type:  bug               |           Status:  patch
        Priority:  normal            |        Milestone:  7.8.1
       Component:  Compiler          |          Version:  7.8.1-rc1
      Resolution:                    |         Keywords:
Operating System:  Unknown/Multiple  |     Architecture:  Unknown/Multiple
 Type of failure:  None/Unknown      |       Difficulty:  Unknown
       Test Case:                    |       Blocked By:
        Blocking:                    |  Related Tickets:
-------------------------------------+------------------------------------

Comment (by scpmw):

 The issue here is that GHC code somewhat randomly refuses to compile with
 LLVM 3.4, with an error along the lines of:

 {{{
     LLVM ERROR: .LnewCAF$alias: Target doesn't support aliases to
 declarations
 }}}

 These `$alias` definitions are forward references used by the LLVM backend
 where it can not derive the exact type of a symbol yet due to it either
 being a global symbol. That can happen because either the symbol is
 external, or because it is part of another `CmmGroup` (which we can't see
 due to streaming).

 In either case we rely on these aliases getting eliminated by the
 `-globalopt` optimisation pass, much in the same way we are relying on
 `-mem2reg` to remove `alloca`s. This is the reason we already pass
 `-globalopt` explicitly for `-O0`. For `-O1` and `-O2` the `-globalopt`
 pass is always active, so we don't run it twice.

 What seems to happen here that in spite of the `-globalopt` pass getting
 run, a few `$alias$` definitions survive:

 {{{
 $ llvm-3.4-build/bin/opt bgamari/History.ll -O1 -S -o - | grep \$alias
 @"base_GHCziChar_chr2_info$alias" = alias private i8*
 @base_GHCziChar_chr2_info
 }}}

 Especially note that we only find a definition, but no usage site. So it
 might simply be dead code detection not doing its job to completion.
 Notably, this behaviour doesn't happen for any of the previous LLVM
 versions:

 {{{
 $ llvm-3.3-build/bin/opt bgamari/History.ll -O1 -S -o - | grep \$alias
 $ llvm-3.2-build/bin/opt bgamari/History.ll -O1 -S -o - | grep \$alias
 $ llvm-3.1-build/bin/opt bgamari/History.ll -O1 -S -o - | grep \$alias
 $ llvm-3.0-build/bin/opt bgamari/History.ll -O1 -S -o - | grep \$alias
 $ llvm-2.9-build/bin/opt bgamari/History.ll -O1 -S -o - | grep \$alias
 $ llvm-2.8-build/bin/opt bgamari/History.ll -O1 -S -o - | grep \$alias
 $ llvm-2.7-build/bin/opt bgamari/History.ll -O1 -S -o - | grep \$alias
 }}}

 And it vanishes for both `-O1 -globalopt` as well as `-O2` for LLVM 3.4:

 {{{
 $ llvm-3.4-build/bin/opt bgamari/History.ll -O1 -globalopt -S -o - | grep
 \$alias
 $ llvm-3.4-build/bin/opt bgamari/History.ll -O2 -S -o - | grep \$alias
 }}}

 Bottom line is that `-O1 -globalopt` is positively needed for LLVM 3.4. On
 the other hand, it's up for discussion whether we want it

 1. for `-O2`. I would vote no, it probably does multiple passes already,
 at which point we should *really* except all remainders to be gone.
 2. for other LLVM versions. Unsure about that one. It only started
 happening very recently, and that a lone definition survives with `-O1`
 smells like a bug. On the other hand, without having any numbers I would
 estimate that `-globalopt` is one of the cheaper optimization passes.

 In the end, I would favour doing:
 {{{
         llvmOpts = ["-mem2reg -globalopt"
                    , if ver >= 34 then "-O1 -globalopt" else "-O1"
                    -- LLVM 3.4 -O1 doesn't eliminate aliases reliably
                    , "-O2"]
 }}}

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


More information about the ghc-tickets mailing list