Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
b18b2c42 by Cheng Shao at 2026-01-17T06:03:44-05:00
llvm: fix split sections for llvm backend
This patch fixes split sections for llvm backend:
- Pass missing `--data-sections`/`--function-sections` flags to
llc/opt.
- Use `@llvm.compiler.used` instead of `@llvm.used` to avoid sections
being unnecessarily retained at link-time.
Fixes #26770.
-------------------------
Metric Decrease:
libdir
size_hello_artifact
size_hello_unicode
-------------------------
Co-authored-by: Codex
- - - - -
3 changed files:
- compiler/GHC/CmmToLlvm.hs
- compiler/GHC/CmmToLlvm/Base.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
Changes:
=====================================
compiler/GHC/CmmToLlvm.hs
=====================================
@@ -271,15 +271,23 @@ cmmUsedLlvmGens = do
-- used if we didn't provide these hints. This will generate a
-- definition of the form
--
- -- @llvm.used = appending global [42 x i8*] [i8* bitcast <var> to i8*, ...]
+ -- @llvm.compiler.used = appending global [42 x i8*] [i8* bitcast <var> to i8*, ...]
--
-- Which is the LLVM way of protecting them against getting removed.
+ --
+ -- We used to emit @llvm.used, but it's too strong and results in
+ -- SHF_GNU_RETAIN section flag in the object, which prevents linker
+ -- gc-sections from working properly for LLVM backend (#26770).
+ -- @llvm.compiler.used serves a similar purpose that protects the
+ -- variable from being dropped by llc/opt, but it allows linker
+ -- gc-sections to work. See
+ -- https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable
ivars <- getUsedVars
let cast x = LMBitc (LMStaticPointer (pVarLift x)) i8Ptr
ty = LMArray (length ivars) i8Ptr
usedArray = LMStaticArray (map cast ivars) ty
sectName = Just $ fsLit "llvm.metadata"
- lmUsedVar = LMGlobalVar (fsLit "llvm.used") ty Appending sectName Nothing Constant
+ lmUsedVar = LMGlobalVar (fsLit "llvm.compiler.used") ty Appending sectName Nothing Constant
lmUsed = LMGlobal lmUsedVar (Just usedArray)
if null ivars
then return ()
=====================================
compiler/GHC/CmmToLlvm/Base.hs
=====================================
@@ -286,7 +286,7 @@ data LlvmEnv = LlvmEnv
, envUniqMeta :: UniqFM Unique MetaId -- ^ Global metadata nodes
, envFunMap :: LlvmEnvMap -- ^ Global functions so far, with type
, envAliases :: UniqSet LMString -- ^ Globals that we had to alias, see [Llvm Forward References]
- , envUsedVars :: [LlvmVar] -- ^ Pointers to be added to llvm.used (see @cmmUsedLlvmGens@)
+ , envUsedVars :: [LlvmVar] -- ^ Pointers to be added to llvm.compiler.used (see @cmmUsedLlvmGens@)
-- the following get cleared for every function (see @withClearVars@)
, envVarMap :: LlvmEnvMap -- ^ Local variables so far, with type
=====================================
compiler/GHC/Driver/Pipeline/Execute.hs
=====================================
@@ -934,6 +934,14 @@ llvmOptions llvm_config llvm_version dflags =
[("-relocation-model=" ++ rmodel
,"-relocation-model=" ++ rmodel) | not (null rmodel)]
+ -- Both llc/opt need these flags for split sections
+ ++ [ ("--data-sections", "--data-sections")
+ | gopt Opt_SplitSections dflags
+ ]
+ ++ [ ("--function-sections", "--function-sections")
+ | gopt Opt_SplitSections dflags
+ ]
+
-- Additional llc flags
++ [("", "-mcpu=" ++ mcpu) | not (null mcpu)
, not (any (isInfixOf "-mcpu") (getOpts dflags opt_lc)) ]
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b18b2c42c32488ad6d3480a56a1fcd75...
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/b18b2c42c32488ad6d3480a56a1fcd75...
You're receiving this email because of your account on gitlab.haskell.org.