
#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