ghc-9.6.3: The GHC API

Safe Haskell | Safe-Inferred
Language | Haskell2010

GHC.CmmToAsm.CFG

Synopsis

- type CFG = EdgeInfoMap EdgeInfo
- data CfgEdge = CfgEdge {
  - edgeFrom :: !BlockId
  - edgeTo :: !BlockId
  - edgeInfo :: !EdgeInfo
  }
- data EdgeInfo = EdgeInfo {
  - transitionSource :: !TransitionSource
  - edgeWeight :: !EdgeWeight
  }
- newtype EdgeWeight = EdgeWeight {
  - weightToDouble :: Double
  }
- data TransitionSource
  - = CmmSource {
    - trans_cmmNode :: CmmNode O C
    - trans_info :: BranchInfo
    }
  - | AsmCodeGen
- addWeightEdge :: BlockId -> BlockId -> EdgeWeight -> CFG -> CFG
- addEdge :: BlockId -> BlockId -> EdgeInfo -> CFG -> CFG
- delEdge :: BlockId -> BlockId -> CFG -> CFG
- addNodesBetween :: Weights -> CFG -> [(BlockId, BlockId, BlockId)] -> CFG
- shortcutWeightMap :: LabelMap (Maybe BlockId) -> CFG -> CFG
- reverseEdges :: CFG -> CFG
- filterEdges :: (BlockId -> BlockId -> EdgeInfo -> Bool) -> CFG -> CFG
- addImmediateSuccessor :: Weights -> BlockId -> BlockId -> CFG -> CFG
- mkWeightInfo :: EdgeWeight -> EdgeInfo
- adjustEdgeWeight :: CFG -> (EdgeWeight -> EdgeWeight) -> BlockId -> BlockId -> CFG
- setEdgeWeight :: CFG -> EdgeWeight -> BlockId -> BlockId -> CFG
- infoEdgeList :: CFG -> [CfgEdge]
- edgeList :: CFG -> [Edge]
- getSuccessorEdges :: HasDebugCallStack => CFG -> BlockId -> [(BlockId, EdgeInfo)]
- getSuccessors :: HasDebugCallStack => CFG -> BlockId -> [BlockId]
- getSuccEdgesSorted :: CFG -> BlockId -> [(BlockId, EdgeInfo)]
- getEdgeInfo :: BlockId -> BlockId -> CFG -> Maybe EdgeInfo
- getCfgNodes :: CFG -> [BlockId]
- hasNode :: CFG -> BlockId -> Bool
- loopMembers :: HasDebugCallStack => CFG -> LabelMap Bool
- loopLevels :: CFG -> BlockId -> LabelMap Int
- loopInfo :: HasDebugCallStack => CFG -> BlockId -> LoopInfo
- getCfg :: Platform -> Weights -> CmmGraph -> CFG
- getCfgProc :: Platform -> Weights -> RawCmmDecl -> CFG
- pprEdgeWeights :: CFG -> SDoc
- sanityCheckCfg :: CFG -> LabelSet -> SDoc -> Bool
- optimizeCFG :: Bool -> Weights -> RawCmmDecl -> CFG -> CFG
- mkGlobalWeights :: HasDebugCallStack => BlockId -> CFG -> (LabelMap Double, LabelMap (LabelMap Double))

# Documentation

type CFG = EdgeInfoMap EdgeInfo Source #

A control flow graph where edges have been annotated with a weight. Implemented as IntMap (IntMap <edgeData>) We must uphold the invariant that for each edge A -> B we must have: A entry B in the outer map. A entry B in the map we get when looking up A. Maintaining this invariant is useful as any failed lookup now indicates an actual error in code which might go unnoticed for a while otherwise.

data CfgEdge Source #

Constructors

CfgEdge |

Fields

- edgeFrom :: !BlockId
- edgeTo :: !BlockId
- edgeInfo :: !EdgeInfo

#### Instances

Instances details

Outputable CfgEdge Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods ppr :: CfgEdge -> SDoc Source #
Eq CfgEdge Source # | Careful! Since we assume there is at most one edge from A to B the Eq instance does not consider weight.
Instance details Defined in GHC.CmmToAsm.CFG Methods (==) :: CfgEdge -> CfgEdge -> Bool # (/=) :: CfgEdge -> CfgEdge -> Bool #
Ord CfgEdge Source # | Edges are sorted ascending pointwise by weight, source and destination
Instance details Defined in GHC.CmmToAsm.CFG Methods compare :: CfgEdge -> CfgEdge -> Ordering # (<) :: CfgEdge -> CfgEdge -> Bool # (<=) :: CfgEdge -> CfgEdge -> Bool # (>) :: CfgEdge -> CfgEdge -> Bool # (>=) :: CfgEdge -> CfgEdge -> Bool # max :: CfgEdge -> CfgEdge -> CfgEdge # min :: CfgEdge -> CfgEdge -> CfgEdge #

data EdgeInfo Source #

Information about edges

Constructors

EdgeInfo |

Fields

- transitionSource :: !TransitionSource
- edgeWeight :: !EdgeWeight

#### Instances

Instances details

Outputable EdgeInfo Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods ppr :: EdgeInfo -> SDoc Source #
Eq EdgeInfo Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods (==) :: EdgeInfo -> EdgeInfo -> Bool # (/=) :: EdgeInfo -> EdgeInfo -> Bool #

newtype EdgeWeight Source #

Constructors

EdgeWeight |

Fields

- weightToDouble :: Double

#### Instances

Instances details

Enum EdgeWeight Source # |

Instance details

Defined in GHC.CmmToAsm.CFG

Methods

succ :: EdgeWeight -> EdgeWeight Source #

pred :: EdgeWeight -> EdgeWeight Source #

toEnum :: Int -> EdgeWeight Source #

fromEnum :: EdgeWeight -> Int Source #

enumFrom :: EdgeWeight -> [EdgeWeight] Source #

enumFromThen :: EdgeWeight -> EdgeWeight -> [EdgeWeight] Source #

enumFromTo :: EdgeWeight -> EdgeWeight -> [EdgeWeight] Source #

enumFromThenTo :: EdgeWeight -> EdgeWeight -> EdgeWeight -> [EdgeWeight] Source #

Num EdgeWeight Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods (+) :: EdgeWeight -> EdgeWeight -> EdgeWeight Source # (-) :: EdgeWeight -> EdgeWeight -> EdgeWeight Source # (*) :: EdgeWeight -> EdgeWeight -> EdgeWeight Source # negate :: EdgeWeight -> EdgeWeight Source # abs :: EdgeWeight -> EdgeWeight Source # signum :: EdgeWeight -> EdgeWeight Source # fromInteger :: Integer -> EdgeWeight Source #
Fractional EdgeWeight Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods (/) :: EdgeWeight -> EdgeWeight -> EdgeWeight Source # recip :: EdgeWeight -> EdgeWeight Source # fromRational :: Rational -> EdgeWeight Source #
Real EdgeWeight Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods toRational :: EdgeWeight -> Rational Source #
Outputable EdgeWeight Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods ppr :: EdgeWeight -> SDoc Source #
Eq EdgeWeight Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods (==) :: EdgeWeight -> EdgeWeight -> Bool # (/=) :: EdgeWeight -> EdgeWeight -> Bool #
Ord EdgeWeight Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods compare :: EdgeWeight -> EdgeWeight -> Ordering # (<) :: EdgeWeight -> EdgeWeight -> Bool # (<=) :: EdgeWeight -> EdgeWeight -> Bool # (>) :: EdgeWeight -> EdgeWeight -> Bool # (>=) :: EdgeWeight -> EdgeWeight -> Bool # max :: EdgeWeight -> EdgeWeight -> EdgeWeight # min :: EdgeWeight -> EdgeWeight -> EdgeWeight #

data TransitionSource Source #

Can we trace back a edge to a specific Cmm Node or has it been introduced during assembly codegen. We use this to maintain some information which would otherwise be lost during the Cmm <-> asm transition. See also Note [Inverting conditions]

Constructors

CmmSource |

Fields

- trans_cmmNode :: CmmNode O C
- trans_info :: BranchInfo

AsmCodeGen |

#### Instances

Instances details

Eq TransitionSource Source # |
Instance details Defined in GHC.CmmToAsm.CFG Methods (==) :: TransitionSource -> TransitionSource -> Bool # (/=) :: TransitionSource -> TransitionSource -> Bool #

addWeightEdge :: BlockId -> BlockId -> EdgeWeight -> CFG -> CFG Source #

Adds a edge with the given weight to the cfg If there already existed an edge it is overwritten. `addWeightEdge from to weight cfg`

addEdge :: BlockId -> BlockId -> EdgeInfo -> CFG -> CFG Source #

Adds a new edge, overwrites existing edges if present

delEdge :: BlockId -> BlockId -> CFG -> CFG Source #

addNodesBetween :: Weights -> CFG -> [(BlockId, BlockId, BlockId)] -> CFG Source #

Insert a block in the control flow between two other blocks. We pass a list of tuples (A,B,C) where * A -> C: Old edge * A -> B -> C : New Arc, where B is the new block. It's possible that a block has two jumps to the same block in the assembly code. However we still only store a single edge for these cases. We assign the old edge info to the edge A -> B and assign B -> C the weight of an unconditional jump.

shortcutWeightMap :: LabelMap (Maybe BlockId) -> CFG -> CFG Source #

reverseEdges :: CFG -> CFG Source #

filterEdges :: (BlockId -> BlockId -> EdgeInfo -> Bool) -> CFG -> CFG Source #

Filter the CFG with a custom function f. Parameters are `f from to edgeInfo`

addImmediateSuccessor :: Weights -> BlockId -> BlockId -> CFG -> CFG Source #

Sometimes we insert a block which should unconditionally be executed after a given block. This function updates the CFG for these cases. So we get A -> B => A -> A' -> B -> C => -> C

mkWeightInfo :: EdgeWeight -> EdgeInfo Source #

Convenience function, generate edge info based on weight not originating from cmm.

adjustEdgeWeight :: CFG -> (EdgeWeight -> EdgeWeight) -> BlockId -> BlockId -> CFG Source #

Adjust the weight between the blocks using the given function. If there is no such edge returns the original map.

setEdgeWeight :: CFG -> EdgeWeight -> BlockId -> BlockId -> CFG Source #

Set the weight between the blocks to the given weight. If there is no such edge returns the original map.

infoEdgeList :: CFG -> [CfgEdge] Source #

Returns a unordered list of all edges with info

edgeList :: CFG -> [Edge] Source #

Returns a unordered list of all edges without weights

getSuccessorEdges :: HasDebugCallStack => CFG -> BlockId -> [(BlockId, EdgeInfo)] Source #

Get successors of a given node with edge weights.

getSuccessors :: HasDebugCallStack => CFG -> BlockId -> [BlockId] Source #

Get successors of a given node without edge weights.

getSuccEdgesSorted :: CFG -> BlockId -> [(BlockId, EdgeInfo)] Source #

Destinations from bid ordered by weight (descending)

getEdgeInfo :: BlockId -> BlockId -> CFG -> Maybe EdgeInfo Source #

getCfgNodes :: CFG -> [BlockId] Source #

hasNode :: CFG -> BlockId -> Bool Source #

Is this block part of this graph?

loopMembers :: HasDebugCallStack => CFG -> LabelMap Bool Source #

Determine loop membership of blocks based on SCC analysis This is faster but only gives yes/no answers.

loopLevels :: CFG -> BlockId -> LabelMap Int Source #

loopInfo :: HasDebugCallStack => CFG -> BlockId -> LoopInfo Source #

Determine loop membership of blocks based on Dominator analysis. This is slower but gives loop levels instead of just loop membership. However it only detects natural loops. Irreducible control flow is not recognized even if it loops. But that is rare enough that we don't have to care about that special case.

getCfg :: Platform -> Weights -> CmmGraph -> CFG Source #

getCfgProc :: Platform -> Weights -> RawCmmDecl -> CFG Source #

Generate weights for a Cmm proc based on some simple heuristics.

pprEdgeWeights :: CFG -> SDoc Source #

sanityCheckCfg :: CFG -> LabelSet -> SDoc -> Bool Source #

Check if the nodes in the cfg and the set of blocks are the same. In a case of a mismatch we panic and show the difference.

optimizeCFG :: Bool -> Weights -> RawCmmDecl -> CFG -> CFG Source #

mkGlobalWeights :: HasDebugCallStack => BlockId -> CFG -> (LabelMap Double, LabelMap (LabelMap Double)) Source #

We take in a CFG which has on its edges weights which are relative only to other edges originating from the same node.

We return a CFG for which each edge represents a GLOBAL weight. This means edge weights are comparable across the whole graph.

For irreducible control flow results might be imprecise, otherwise they are reliable.

The algorithm is based on the Paper "Static Branch Prediction and Program Profile Analysis" by Y Wu, JR Larus The only big change is that we go over the nodes in the body of loops in reverse post order. Which is required for diamond control flow to work probably.

We also apply a few prediction heuristics (based on the same paper)

The returned result represents frequences. For blocks it's the expected number of executions and for edges is the number of traversals.