Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
GHC
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Iterations
Merge Requests
0
Merge Requests
0
Requirements
Requirements
List
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Operations
Operations
Incidents
Environments
Packages & Registries
Packages & Registries
Package Registry
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issue
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
jberryman
GHC
Commits
ceffd7fe
Commit
ceffd7fe
authored
Sep 12, 2018
by
Ben Gamari
🐢
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "An overhaul of the SRT representation"
This reverts commit
eb8e692c
.
parent
dee22948
Changes
23
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
540 additions
and
825 deletions
+540
-825
compiler/cmm/CLabel.hs
compiler/cmm/CLabel.hs
+29
-28
compiler/cmm/Cmm.hs
compiler/cmm/Cmm.hs
+13
-1
compiler/cmm/CmmBuildInfoTables.hs
compiler/cmm/CmmBuildInfoTables.hs
+296
-617
compiler/cmm/CmmInfo.hs
compiler/cmm/CmmInfo.hs
+5
-4
compiler/cmm/CmmParse.y
compiler/cmm/CmmParse.y
+6
-6
compiler/cmm/CmmPipeline.hs
compiler/cmm/CmmPipeline.hs
+10
-11
compiler/cmm/Hoopl/Dataflow.hs
compiler/cmm/Hoopl/Dataflow.hs
+0
-6
compiler/cmm/PprCmm.hs
compiler/cmm/PprCmm.hs
+1
-1
compiler/cmm/PprCmmDecl.hs
compiler/cmm/PprCmmDecl.hs
+10
-7
compiler/codeGen/StgCmmClosure.hs
compiler/codeGen/StgCmmClosure.hs
+5
-5
compiler/main/HscMain.hs
compiler/main/HscMain.hs
+13
-7
compiler/stgSyn/CoreToStg.hs
compiler/stgSyn/CoreToStg.hs
+9
-0
includes/rts/storage/ClosureMacros.h
includes/rts/storage/ClosureMacros.h
+1
-1
includes/rts/storage/InfoTables.h
includes/rts/storage/InfoTables.h
+38
-15
includes/stg/MiscClosures.h
includes/stg/MiscClosures.h
+0
-16
libraries/ghc-heap/GHC/Exts/Heap/InfoTable.hsc
libraries/ghc-heap/GHC/Exts/Heap/InfoTable.hsc
+0
-8
libraries/ghc-heap/GHC/Exts/Heap/InfoTableProf.hsc
libraries/ghc-heap/GHC/Exts/Heap/InfoTableProf.hsc
+0
-8
rts/RtsAPI.c
rts/RtsAPI.c
+1
-1
rts/RtsSymbols.c
rts/RtsSymbols.c
+0
-16
rts/StgMiscClosures.cmm
rts/StgMiscClosures.cmm
+1
-54
rts/sm/Evac.c
rts/sm/Evac.c
+2
-2
rts/sm/Scav.c
rts/sm/Scav.c
+99
-10
testsuite/tests/regalloc/regalloc_unit_tests.hs
testsuite/tests/regalloc/regalloc_unit_tests.hs
+1
-1
No files found.
compiler/cmm/CLabel.hs
View file @
ceffd7fe
...
...
@@ -14,11 +14,12 @@ module CLabel (
pprDebugCLabel
,
mkClosureLabel
,
mkSRTLabel
,
mk
Top
SRTLabel
,
mkInfoTableLabel
,
mkEntryLabel
,
mkRednCountsLabel
,
mkConInfoTableLabel
,
mkLargeSRTLabel
,
mkApEntryLabel
,
mkApInfoTableLabel
,
mkClosureTableLabel
,
...
...
@@ -53,7 +54,6 @@ module CLabel (
mkSMAP_DIRTY_infoLabel
,
mkBadAlignmentLabel
,
mkArrWords_infoLabel
,
mkSRTInfoLabel
,
mkTopTickyCtrLabel
,
mkCAFBlackHoleInfoTableLabel
,
...
...
@@ -250,7 +250,10 @@ data CLabel
|
HpcTicksLabel
Module
-- | Static reference table
|
SRTLabel
|
SRTLabel
!
Unique
-- | Label of an StgLargeSRT
|
LargeSRTLabel
{-# UNPACK #-}
!
Unique
-- | A bitmap (function or case return)
...
...
@@ -300,6 +303,8 @@ instance Ord CLabel where
compare
a1
a2
compare
(
SRTLabel
u1
)
(
SRTLabel
u2
)
=
nonDetCmpUnique
u1
u2
compare
(
LargeSRTLabel
u1
)
(
LargeSRTLabel
u2
)
=
nonDetCmpUnique
u1
u2
compare
(
LargeBitmapLabel
u1
)
(
LargeBitmapLabel
u2
)
=
nonDetCmpUnique
u1
u2
compare
IdLabel
{}
_
=
LT
...
...
@@ -332,6 +337,8 @@ instance Ord CLabel where
compare
_
HpcTicksLabel
{}
=
GT
compare
SRTLabel
{}
_
=
LT
compare
_
SRTLabel
{}
=
GT
compare
LargeSRTLabel
{}
_
=
LT
compare
_
LargeSRTLabel
{}
=
GT
-- | Record where a foreign label is stored.
data
ForeignLabelSource
...
...
@@ -380,6 +387,9 @@ pprDebugCLabel lbl
data
IdLabelInfo
=
Closure
-- ^ Label for closure
|
SRT
-- ^ Static reference table (TODO: could be removed
-- with the old code generator, but might be needed
-- when we implement the New SRT Plan)
|
InfoTable
-- ^ Info tables for closures; always read-only
|
Entry
-- ^ Entry point
|
Slow
-- ^ Slow entry point
...
...
@@ -449,8 +459,8 @@ data DynamicLinkerLabelInfo
-- Constructing IdLabels
-- These are always local:
mkSRTLabel
::
Unique
->
CLabel
mkSRTLabel
u
=
SRTLabel
u
mk
Top
SRTLabel
::
Unique
->
CLabel
mk
Top
SRTLabel
u
=
SRTLabel
u
mkRednCountsLabel
::
Name
->
CLabel
mkRednCountsLabel
name
=
...
...
@@ -508,29 +518,6 @@ mkSMAP_FROZEN_DIRTY_infoLabel = CmmLabel rtsUnitId (fsLit "stg_SMALL_MUT_ARR_P
mkSMAP_DIRTY_infoLabel
=
CmmLabel
rtsUnitId
(
fsLit
"stg_SMALL_MUT_ARR_PTRS_DIRTY"
)
CmmInfo
mkBadAlignmentLabel
=
CmmLabel
rtsUnitId
(
fsLit
"stg_badAlignment"
)
CmmEntry
mkSRTInfoLabel
::
Int
->
CLabel
mkSRTInfoLabel
n
=
CmmLabel
rtsUnitId
lbl
CmmInfo
where
lbl
=
case
n
of
1
->
fsLit
"stg_SRT_1"
2
->
fsLit
"stg_SRT_2"
3
->
fsLit
"stg_SRT_3"
4
->
fsLit
"stg_SRT_4"
5
->
fsLit
"stg_SRT_5"
6
->
fsLit
"stg_SRT_6"
7
->
fsLit
"stg_SRT_7"
8
->
fsLit
"stg_SRT_8"
9
->
fsLit
"stg_SRT_9"
10
->
fsLit
"stg_SRT_10"
11
->
fsLit
"stg_SRT_11"
12
->
fsLit
"stg_SRT_12"
13
->
fsLit
"stg_SRT_13"
14
->
fsLit
"stg_SRT_14"
15
->
fsLit
"stg_SRT_15"
16
->
fsLit
"stg_SRT_16"
_
->
panic
"mkSRTInfoLabel"
-----
mkCmmInfoLabel
,
mkCmmEntryLabel
,
mkCmmRetInfoLabel
,
mkCmmRetLabel
,
mkCmmCodeLabel
,
mkCmmDataLabel
,
mkCmmClosureLabel
...
...
@@ -615,6 +602,9 @@ isSomeRODataLabel (IdLabel _ _ ConInfoTable) = True
isSomeRODataLabel
(
IdLabel
_
_
InfoTable
)
=
True
isSomeRODataLabel
(
IdLabel
_
_
LocalInfoTable
)
=
True
isSomeRODataLabel
(
IdLabel
_
_
BlockInfoTable
)
=
True
-- static reference tables defined in haskell (.hs)
isSomeRODataLabel
(
IdLabel
_
_
SRT
)
=
True
isSomeRODataLabel
(
SRTLabel
_
)
=
True
-- info table defined in cmm (.cmm)
isSomeRODataLabel
(
CmmLabel
_
_
CmmInfo
)
=
True
isSomeRODataLabel
_lbl
=
False
...
...
@@ -626,7 +616,9 @@ foreignLabelStdcallInfo _lbl = Nothing
-- Constructing Large*Labels
mkLargeSRTLabel
::
Unique
->
CLabel
mkBitmapLabel
::
Unique
->
CLabel
mkLargeSRTLabel
uniq
=
LargeSRTLabel
uniq
mkBitmapLabel
uniq
=
LargeBitmapLabel
uniq
-- Constructing Cost Center Labels
...
...
@@ -684,6 +676,8 @@ mkAsmTempDieLabel l = mkAsmTempDerivedLabel l (fsLit "_die")
-- Convert between different kinds of label
toClosureLbl
::
CLabel
->
CLabel
toClosureLbl
(
IdLabel
n
_
BlockInfoTable
)
=
pprPanic
"toClosureLbl: BlockInfoTable"
(
ppr
n
)
toClosureLbl
(
IdLabel
n
c
_
)
=
IdLabel
n
c
Closure
toClosureLbl
(
CmmLabel
m
str
_
)
=
CmmLabel
m
str
CmmClosure
toClosureLbl
l
=
pprPanic
"toClosureLbl"
(
ppr
l
)
...
...
@@ -752,6 +746,7 @@ needsCDecl :: CLabel -> Bool
-- don't bother declaring Bitmap labels, we always make sure
-- they are defined before use.
needsCDecl
(
SRTLabel
_
)
=
True
needsCDecl
(
LargeSRTLabel
_
)
=
False
needsCDecl
(
LargeBitmapLabel
_
)
=
False
needsCDecl
(
IdLabel
_
_
_
)
=
True
needsCDecl
(
LocalBlockLabel
_
)
=
True
...
...
@@ -898,10 +893,12 @@ externallyVisibleCLabel (DynamicLinkerLabel _ _) = False
externallyVisibleCLabel
(
HpcTicksLabel
_
)
=
True
externallyVisibleCLabel
(
LargeBitmapLabel
_
)
=
False
externallyVisibleCLabel
(
SRTLabel
_
)
=
False
externallyVisibleCLabel
(
LargeSRTLabel
_
)
=
False
externallyVisibleCLabel
(
PicBaseLabel
{})
=
panic
"externallyVisibleCLabel PicBaseLabel"
externallyVisibleCLabel
(
DeadStripPreventer
{})
=
panic
"externallyVisibleCLabel DeadStripPreventer"
externallyVisibleIdLabel
::
IdLabelInfo
->
Bool
externallyVisibleIdLabel
SRT
=
False
externallyVisibleIdLabel
LocalInfoTable
=
False
externallyVisibleIdLabel
LocalEntry
=
False
externallyVisibleIdLabel
BlockInfoTable
=
False
...
...
@@ -957,6 +954,7 @@ labelType (DynamicLinkerLabel _ _) = DataLabel -- Is this right?
labelType
PicBaseLabel
=
DataLabel
labelType
(
DeadStripPreventer
_
)
=
DataLabel
labelType
(
HpcTicksLabel
_
)
=
DataLabel
labelType
(
LargeSRTLabel
_
)
=
DataLabel
labelType
(
LargeBitmapLabel
_
)
=
DataLabel
idInfoLabelType
::
IdLabelInfo
->
CLabelType
...
...
@@ -1045,6 +1043,7 @@ internal names. <type> is one of the following:
info Info table
srt Static reference table
srtd Static reference table descriptor
entry Entry code (function, closure)
slow Slow entry code (if any)
ret Direct return address
...
...
@@ -1183,6 +1182,7 @@ pprCLbl (StringLitLabel u)
pprCLbl
(
SRTLabel
u
)
=
pprUniqueAlways
u
<>
pp_cSEP
<>
text
"srt"
pprCLbl
(
LargeSRTLabel
u
)
=
pprUniqueAlways
u
<>
pp_cSEP
<>
text
"srtd"
pprCLbl
(
LargeBitmapLabel
u
)
=
text
"b"
<>
pprUniqueAlways
u
<>
pp_cSEP
<>
text
"btm"
-- Some bitsmaps for tuple constructors have a numeric tag (e.g. '7')
-- until that gets resolved we'll just force them to start
...
...
@@ -1275,6 +1275,7 @@ ppIdFlavor :: IdLabelInfo -> SDoc
ppIdFlavor
x
=
pp_cSEP
<>
(
case
x
of
Closure
->
text
"closure"
SRT
->
text
"srt"
InfoTable
->
text
"info"
LocalInfoTable
->
text
"info"
Entry
->
text
"entry"
...
...
compiler/cmm/Cmm.hs
View file @
ceffd7fe
...
...
@@ -18,6 +18,7 @@ module Cmm (
-- * Info Tables
CmmTopInfo
(
..
),
CmmStackInfo
(
..
),
CmmInfoTable
(
..
),
topInfoTable
,
ClosureTypeInfo
(
..
),
C_SRT
(
..
),
needsSRT
,
ProfilingInfo
(
..
),
ConstrDescription
,
-- * Statements, expressions and types
...
...
@@ -137,13 +138,24 @@ data CmmInfoTable
cit_lbl
::
CLabel
,
-- Info table label
cit_rep
::
SMRep
,
cit_prof
::
ProfilingInfo
,
cit_srt
::
Maybe
CLabel
-- empty, or a closure address
cit_srt
::
C_SRT
}
data
ProfilingInfo
=
NoProfilingInfo
|
ProfilingInfo
[
Word8
]
[
Word8
]
-- closure_type, closure_desc
-- C_SRT is what StgSyn.SRT gets translated to...
-- we add a label for the table, and expect only the 'offset/length' form
data
C_SRT
=
NoC_SRT
|
C_SRT
!
CLabel
!
WordOff
!
StgHalfWord
{-bitmap or escape-}
deriving
(
Eq
)
needsSRT
::
C_SRT
->
Bool
needsSRT
NoC_SRT
=
False
needsSRT
(
C_SRT
_
_
_
)
=
True
-----------------------------------------------------------------------------
-- Static Data
-----------------------------------------------------------------------------
...
...
compiler/cmm/CmmBuildInfoTables.hs
View file @
ceffd7fe
{-# LANGUAGE GADTs, BangPatterns, RecordWildCards,
GeneralizedNewtypeDeriving, NondecreasingIndentation #-}
{-# LANGUAGE BangPatterns, GADTs #-}
module
CmmBuildInfoTables
(
CAFSet
,
CAFEnv
,
cafAnal
,
doSRTs
,
ModuleSRTInfo
,
emptySRT
)
where
,
doSRTs
,
TopSRT
,
emptySRT
,
isEmptySRT
,
srtToData
)
where
import
GhcPrelude
hiding
(
succ
)
import
BlockId
import
Hoopl.Block
import
Hoopl.Graph
import
Hoopl.Label
import
Hoopl.Collections
import
Hoopl.Dataflow
import
Module
import
Digraph
import
Bitmap
import
CLabel
import
PprCmmDecl
()
import
Cmm
import
CmmUtils
import
CmmInfo
import
Data.List
import
DynFlags
import
Maybes
import
Outputable
import
SMRep
import
UniqSupply
import
CostCentre
import
StgCmmHeap
import
Util
import
PprCmm
()
import
Data.Map
(
Map
)
import
qualified
Data.Map
as
Map
import
Data.Set
(
Set
)
import
qualified
Data.Set
as
Set
import
Data.Tuple
import
Control.Monad
import
Control.Monad.Trans.State
import
Control.Monad.Trans.Class
foldSet
::
(
a
->
b
->
b
)
->
b
->
Set
a
->
b
foldSet
=
Set
.
foldr
{- Note [SRTs]
-----------------------------------------------------------------------
-- SRTs
SRTs are the mechanism by which the garbage collector can determine
the live CAFs in the program.
Representation
^^^^^^^^^^^^^^
+------+
| info |
| | +-----+---+---+---+
| -------->|SRT_2| | | | | 0 |
|------| +-----+-|-+-|-+---+
| | | |
| code | | |
| | v v
An SRT is simply an object in the program's data segment. It has the
same representation as a static constructor. There are 16
pre-compiled SRT info tables: stg_SRT_1_info, .. stg_SRT_16_info,
representing SRT objects with 1-16 pointers, respectively.
The entries of an SRT object point to static closures, which are either
- FUN_STATIC, THUNK_STATIC or CONSTR
- Another SRT (actually just a CONSTR)
The final field of the SRT is the static link field, used by the
garbage collector to chain together static closures that it visits and
to determine whether a static closure has been visited or not. (see
Note [STATIC_LINK fields])
By traversing the transitive closure of an SRT, the GC will reach all
of the CAFs that are reachable from the code associated with this SRT.
If we need to create an SRT with more than 16 entries, we build a
chain of SRT objects with all but the last having 16 entries.
+-----+---+- -+---+---+
|SRT16| | | | | | 0 |
+-----+-|-+- -+-|-+---+
| |
v v
+----+---+---+---+
|SRT2| | | | | 0 |
+----+-|-+-|-+---+
| |
| |
v v
Referring to an SRT from the info table
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The following things have SRTs:
- Static functions (FUN)
- Static thunks (THUNK), ie. CAFs
- Continuations (RET_SMALL, etc.)
In each case, the info table points to the SRT.
- info->srt is zero if there's no SRT, otherwise:
- info->srt == 1 and info->f.srt_offset points to the SRT
(but see TODO below, we can improve this)
e.g. for a FUN with an SRT:
StgFunInfoTable +------+
info->f.srt_offset | ------------> offset to SRT object
StgStdInfoTable +------+
info->layout.ptrs | ... |
info->layout.nptrs | ... |
info->srt | 1 |
info->type | ... |
|------|
EXAMPLE
^^^^^^^
{- EXAMPLE
f = \x. ... g ...
where
...
...
@@ -139,218 +62,28 @@ CmmDecls. e.g. for f_entry, we might end up with
where f1_ret is a return point, and f2_proc is a proc-point. We have
a CAFSet for each of these CmmDecls, let's suppose they are
[ f_entry{g_
info}, f1_ret{g_info
}, f2_proc{} ]
[ g_entry{h_
info
, c1_closure} ]
[ f_entry{g_
closure}, f1_ret{g_closure
}, f2_proc{} ]
[ g_entry{h_
closure
, c1_closure} ]
[ h_entry{c2_closure} ]
Next, we make an SRT for each of these functions:
f_srt : [g_info]
g_srt : [h_info, c1_closure]
h_srt : [c2_closure]
Now, for g_info and h_info, we want to refer to the SRTs for g and h
respectively, which we'll label g_srt and h_srt:
f_srt : [g_srt]
g_srt : [h_srt, c1_closure]
h_srt : [c2_closure]
Now, when an SRT has a single entry, we don't actually generate an SRT
closure for it, instead we just replace references to it with its
single element. So, since h_srt == c2_closure, we have
f_srt : [g_srt]
g_srt : [c2_closure, c1_closure]
h_srt : [c2_closure]
and the only SRT closure we generate is
g_srt = SRT_2 [c2_closure, c1_closure]
Optimisations
^^^^^^^^^^^^^
To reduce the code size overhead and the cost of traversing SRTs in
the GC, we want to simplify SRTs where possible. We therefore apply
the following optimisations. Each has a [keyword]; search for the
keyword in the code below to see where the optimisation is
implemented.
1. [Shortcut] we never create an SRT with a single entry, instead
we replace all references to the singleton SRT with a reference
to its element. This includes references from info tables.
i.e. instead of
+------+
| info |
| | +-----+---+---+
| -------->|SRT_1| | | 0 |
|------| +-----+-|-+---+
| | |
| code | |
| | v
closure
we can point directly to the closure:
+------+
| info |
| |
| -------->closure
|------|
| |
| code |
| |
The exception to this is when we're doing dynamic linking. In that
case, if the closure is not locally defined then we can't point to
it directly from the info table, because this is the text section
which cannot contain runtime relocations. In this case we skip this
optimisation and generate the singleton SRT, becase SRTs are in the
data section and *can* have relocatable references.
2. [FUN] If an SRT refers to a top-level function (a FUN_STATIC), then
we can shortcut the reference to point directly to the function's
SRT instead.
i.e. instead of
+---+---+---
|SRT| | |
+---+-|-+---
|
v
+---+---+
| | | 0 |
+-|-+---+
|
| +------+
| | info |
| | | +-----+---+---+
| | -------->|SRT_1| | | 0 |
`----->|------| +-----+-|-+---+
| | |
| code | |
| | v
closure
we can generate
+---+---+---
|SRT| | |
+---+-|-+---
`----------------------,
|
+---+---+ |
| | | 0 | |
+-|-+---+ |
| |
| +------+ |
| | info | v
| | | +-----+---+---+
| | -------->|SRT_1| | | 0 |
`----->|------| +-----+-|-+---+
| | |
| code | |
| | v
closure
This is quicker for the garbage collector to traverse, and avoids
setting the static link field on the function's closure.
Of course we can only do this if we know what the function's SRT
is. Due to [Shortcut] the function's SRT can be an arbitrary
closure, so this optimisation only applies within a module.
Note: we can *not* do this optimisation for top-level thunks
(CAFs), because we want the SRT to point directly to the
CAF. Otherwise the SRT would keep the CAF's static references alive
even after the CAF had been evaluated!
3. [Common] Identical SRTs can be commoned up.
4. [Filter] If an SRT A refers to an SRT B and a closure C, and B also
refers to C (perhaps transitively), then we can omit the reference
to C from A.
As an alternative to [FUN]: we could merge the FUN's SRT with the FUN
object itself.
TODO: make info->srt be an offset to the SRT, or zero if none (save
one word per info table that has an SRT)
Note that there are many other optimisations that we could do, but
aren't implemented. In general, we could omit any reference from an
SRT if everything reachable from it is also reachable from the other
fields in the SRT. Our [Filter] optimisation is a special case of
this.
Another opportunity we don't exploit is this:
A = {X,Y,Z}
B = {Y,Z}
C = {X,B}
Here we could use C = {A} and therefore [Shortcut] C = A.
-}
-- ---------------------------------------------------------------------
-- Label types
Now, note that we cannot use g_closure and h_closure in an SRT,
because there are no static closures corresponding to these functions.
So we have to flatten out the structure, replacing g_closure and
h_closure with their contents:
-- Labels that come from cafAnal can be:
-- - _closure labels for static functions or CAFs
-- - _info labels for dynamic functions, thunks, or continuations
-- - _entry labels for functions or thunks
--
-- Meanwhile the labels on top-level blocks are _entry labels.
--
-- To put everything in the same namespace we convert all labels to
-- closure labels using toClosureLbl. Note that some of these
-- labels will not actually exist; that's ok because we're going to
-- map them to SRTEntry later, which ranges over labels that do exist.
--
newtype
CAFLabel
=
CAFLabel
CLabel
deriving
(
Eq
,
Ord
,
Outputable
)
type
CAFSet
=
Set
CAFLabel
type
CAFEnv
=
LabelMap
CAFSet
mkCAFLabel
::
CLabel
->
CAFLabel
mkCAFLabel
lbl
=
CAFLabel
(
toClosureLbl
lbl
)
[ f_entry{c2_closure, c1_closure}, f1_ret{c2_closure,c1_closure}, f2_proc{} ]
[ g_entry{c2_closure, c1_closure} ]
[ h_entry{c2_closure} ]
-- This is a label that we can put in an SRT. It *must* be a closure label,
-- pointing to either a FUN_STATIC, THUNK_STATIC, or CONSTR.
newtype
SRTEntry
=
SRTEntry
CLabel
deriving
(
Eq
,
Ord
,
Outputable
)
This is what flattenCAFSets is doing.
-- ---------------------------------------------------------------------
-- CAF analysis
-}
-- |
-- For each code block:
-- - collect the references reachable from this code block to FUN,
-- THUNK or RET labels for which hasCAF == True
--
-- This gives us a `CAFEnv`: a mapping from code block to sets of labels
--
cafAnal
::
LabelSet
-- The blocks representing continuations, ie. those
-- that will get RET info tables. These labels will
-- get their own SRTs, so we don't aggregate CAFs from
-- references to these labels, we just use the label.
->
CLabel
-- The top label of the proc
->
CmmGraph
->
CAFEnv
cafAnal
contLbls
topLbl
cmmGraph
=
analyzeCmmBwd
cafLattice
(
cafTransfers
contLbls
(
g_entry
cmmGraph
)
topLbl
)
cmmGraph
mapEmpty
-----------------------------------------------------------------------
-- Finding the CAFs used by a procedure
type
CAFSet
=
Set
CLabel
type
CAFEnv
=
LabelMap
CAFSet
cafLattice
::
DataflowLattice
CAFSet
cafLattice
=
DataflowLattice
Set
.
empty
add
...
...
@@ -359,329 +92,279 @@ cafLattice = DataflowLattice Set.empty add
let
!
new'
=
old
`
Set
.
union
`
new
in
changedIf
(
Set
.
size
new'
>
Set
.
size
old
)
new'
cafTransfers
::
LabelSet
->
Label
->
CLabel
->
TransferFun
CAFSet
cafTransfers
contLbls
entry
topLbl
(
BlockCC
eNode
middle
xNode
)
fBase
=
let
joined
=
cafsInNode
xNode
$!
live'
cafTransfers
::
TransferFun
CAFSet
cafTransfers
(
BlockCC
eNode
middle
xNode
)
fBase
=
let
joined
=
cafsInNode
xNode
$!
joinOutFacts
cafLattice
xNode
fBase
!
result
=
foldNodesBwdOO
cafsInNode
middle
joined
in
mapSingleton
(
entryLabel
eNode
)
result
facts
=
mapMaybe
successorFact
(
successors
xNode
)
live'
=
joinFacts
cafLattice
facts
successorFact
s
-- If this is a loop back to the entry, we can refer to the
-- entry label.
|
s
==
entry
=
Just
(
add
topLbl
Set
.
empty
)
-- If this is a continuation, we want to refer to the
-- SRT for the continuation's info table
|
s
`
setMember
`
contLbls
=
Just
(
Set
.
singleton
(
mkCAFLabel
(
infoTblLbl
s
)))
-- Otherwise, takes the CAF references from the destination
|
otherwise
=
lookupFact
s
fBase
cafsInNode
::
CmmNode
e
x
->
CAFSet
->
CAFSet
cafsInNode
node
set
=
foldExpDeep
addCaf
node
set
cafsInNode
::
CmmNode
e
x
->
CAFSet
->
CAFSet
cafsInNode
node
set
=
foldExpDeep
addCaf
node
set
where
addCaf
expr
!
set
=
case
expr
of
CmmLit
(
CmmLabel
c
)
->
add
c
set
CmmLit
(
CmmLabelOff
c
_
)
->
add
c
set
CmmLit
(
CmmLabelDiffOff
c1
c2
_
_
)
->
add
c1
$!
add
c2
set
_
->
set
add
l
s
|
hasCAF
l
=
Set
.
insert
(
mkCAFLabe
l
l
)
s
add
l
s
|
hasCAF
l
=
Set
.
insert
(
toClosureLb
l
l
)
s
|
otherwise
=
s
in
mapSingleton
(
entryLabel
eNode
)
result
-- | An analysis to find live CAFs.
cafAnal
::
CmmGraph
->
CAFEnv
cafAnal
cmmGraph
=
analyzeCmmBwd
cafLattice
cafTransfers
cmmGraph
mapEmpty
-----------------------------------------------------------------------
-- Building the SRTs
-- -----------------------------------------------------------------------------
-- ModuleSRTInfo
data
ModuleSRTInfo
=
ModuleSRTInfo
{
thisModule
::
Module
-- ^ Current module being compiled. Required for calling labelDynamic.
,
dedupSRTs
::
Map
(
Set
SRTEntry
)
SRTEntry
-- ^ previous SRTs we've emitted, so we can de-duplicate.
-- Used to implement the [Common] optimisation.
,
flatSRTs
::
Map
SRTEntry
(
Set
SRTEntry
)
-- ^ The reverse mapping, so that we can remove redundant
-- entries. e.g. if we have an SRT [a,b,c], and we know that b
-- points to [c,d], we can omit c and emit [a,b].
-- Used to implement the [Filter] optimisation.