diff options
author | Ben Gamari <ben@smart-cactus.org> | 2019-07-29 19:34:57 -0400 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2019-10-07 12:01:46 -0400 |
commit | b2577081528fe36facf5153bed256fe838a74ae6 (patch) | |
tree | c0ce42d462656bc3dae6543c5239a8e56a5e2217 /compiler/main/SysTools.hs | |
parent | 825c108bd26f20accf1eaef2ba652a2ee12924bb (diff) | |
download | haskell-b2577081528fe36facf5153bed256fe838a74ae6.tar.gz |
Refactor, document, and optimize LLVM configuration loading
As described in the new Note [LLVM Configuration] in SysTools, we now
load llvm-targets and llvm-passes lazily to avoid the overhead of doing
so when -fllvm isn't used (also known as "the common case").
Noticed in #17003.
Metric Decrease:
T12234
T12150
Diffstat (limited to 'compiler/main/SysTools.hs')
-rw-r--r-- | compiler/main/SysTools.hs | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/compiler/main/SysTools.hs b/compiler/main/SysTools.hs index fa339bbb87..b3312b0dae 100644 --- a/compiler/main/SysTools.hs +++ b/compiler/main/SysTools.hs @@ -13,7 +13,7 @@ module SysTools ( -- * Initialisation initSysTools, - initLlvmConfig, + lazyInitLlvmConfig, -- * Interface to system tools module SysTools.Tasks, @@ -52,6 +52,7 @@ import DynFlags import Control.Monad.Trans.Except (runExceptT) import System.FilePath import System.IO +import System.IO.Unsafe (unsafeInterleaveIO) import SysTools.ExtraObj import SysTools.Info import SysTools.Tasks @@ -110,13 +111,34 @@ stuff. ************************************************************************ -} -initLlvmConfig :: String +-- Note [LLVM configuration] +-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-- The `llvm-targets` and `llvm-passes` files are shipped with GHC and contain +-- information needed by the LLVM backend to invoke `llc` and `opt`. +-- Specifically: +-- +-- * llvm-targets maps autoconf host triples to the corresponding LLVM +-- `data-layout` declarations. This information is extracted from clang using +-- the script in utils/llvm-targets/gen-data-layout.sh and should be updated +-- whenever we target a new version of LLVM. +-- +-- * llvm-passes maps GHC optimization levels to sets of LLVM optimization +-- flags that GHC should pass to `opt`. +-- +-- This information is contained in files rather the GHC source to allow users +-- to add new targets to GHC without having to recompile the compiler. +-- +-- Since this information is only needed by the LLVM backend we load it lazily +-- with unsafeInterleaveIO. Consequently it is important that we lazily pattern +-- match on LlvmConfig until we actually need its contents. + +lazyInitLlvmConfig :: String -> IO LlvmConfig -initLlvmConfig top_dir - = do +lazyInitLlvmConfig top_dir + = unsafeInterleaveIO $ do -- see Note [LLVM configuration] targets <- readAndParse "llvm-targets" mkLlvmTarget passes <- readAndParse "llvm-passes" id - return (targets, passes) + return $ LlvmConfig { llvmTargets = targets, llvmPasses = passes } where readAndParse name builder = do let llvmConfigFile = top_dir </> name |