CFG

ghc-8.10.1: The GHC API

Safe Haskell | None
Language | Haskell2010

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
- delNode :: BlockId -> CFG -> CFG
- addNodesBetween :: CFG -> [(BlockId, BlockId, BlockId)] -> CFG
- shortcutWeightMap :: LabelMap (Maybe BlockId) -> CFG -> CFG
- reverseEdges :: CFG -> CFG
- filterEdges :: (BlockId -> BlockId -> EdgeInfo -> Bool) -> CFG -> CFG
- addImmediateSuccessor :: 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 :: CfgWeights -> CmmGraph -> CFG
- getCfgProc :: CfgWeights -> RawCmmDecl -> CFG
- pprEdgeWeights :: CFG -> SDoc
- sanityCheckCfg :: CFG -> LabelSet -> SDoc -> Bool
- optimizeCFG :: CfgWeights -> RawCmmDecl -> CFG -> CFG
- mkGlobalWeights :: HasDebugCallStack => BlockId -> CFG -> (LabelMap Double, LabelMap (LabelMap Double))

# Documentation

type CFG = EdgeInfoMap EdgeInfo #

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 #

Constructors

CfgEdge |
Fields edgeFrom :: !BlockId edgeTo :: !BlockId edgeInfo :: !EdgeInfo

#### Instances

Instances details

Eq CfgEdge # | 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 CFG Methods (==) :: CfgEdge -> CfgEdge -> Bool # (/=) :: CfgEdge -> CfgEdge -> Bool #
Ord CfgEdge # | Edges are sorted ascending pointwise by weight, source and destination
Instance details Defined in 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 #
Outputable CfgEdge # |
Instance details Defined in CFG Methods ppr :: CfgEdge -> SDoc # pprPrec :: Rational -> CfgEdge -> SDoc #

data EdgeInfo #

Information about edges

Constructors

EdgeInfo |
Fields transitionSource :: !TransitionSource edgeWeight :: !EdgeWeight

#### Instances

Instances details

Eq EdgeInfo # |
Instance details Defined in CFG Methods (==) :: EdgeInfo -> EdgeInfo -> Bool # (/=) :: EdgeInfo -> EdgeInfo -> Bool #
Outputable EdgeInfo # |
Instance details Defined in CFG Methods ppr :: EdgeInfo -> SDoc # pprPrec :: Rational -> EdgeInfo -> SDoc #

newtype EdgeWeight #

Constructors

EdgeWeight |
Fields weightToDouble :: Double

#### Instances

Instances details

Enum EdgeWeight # |
Instance details Defined in 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 #
Eq EdgeWeight # |
Instance details Defined in CFG Methods (==) :: EdgeWeight -> EdgeWeight -> Bool # (/=) :: EdgeWeight -> EdgeWeight -> Bool #
Fractional EdgeWeight # |
Instance details Defined in CFG Methods (/) :: EdgeWeight -> EdgeWeight -> EdgeWeight Source # recip :: EdgeWeight -> EdgeWeight Source # fromRational :: Rational -> EdgeWeight Source #
Num EdgeWeight # |
Instance details Defined in 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 #
Ord EdgeWeight # |
Instance details Defined in 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 #
Real EdgeWeight # |
Instance details Defined in CFG Methods toRational :: EdgeWeight -> Rational Source #
Outputable EdgeWeight # |
Instance details Defined in CFG Methods ppr :: EdgeWeight -> SDoc # pprPrec :: Rational -> EdgeWeight -> SDoc #

data TransitionSource #

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 Conditional Branches]

Constructors

CmmSource |
Fields trans_cmmNode :: CmmNode O C trans_info :: BranchInfo
AsmCodeGen |

#### Instances

Instances details

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

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

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 #

Adds a new edge, overwrites existing edges if present

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

delNode :: BlockId -> CFG -> CFG #

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

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 #

reverseEdges :: CFG -> CFG #

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

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

addImmediateSuccessor :: BlockId -> BlockId -> CFG -> CFG #

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 #

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

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

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 #

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

infoEdgeList :: CFG -> [CfgEdge] #

Returns a unordered list of all edges with info

edgeList :: CFG -> [Edge] #

Returns a unordered list of all edges without weights

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

Get successors of a given node with edge weights.

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

Get successors of a given node without edge weights.

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

Destinations from bid ordered by weight (descending)

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

getCfgNodes :: CFG -> [BlockId] #

hasNode :: CFG -> BlockId -> Bool #

Is this block part of this graph?

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

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

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

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

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 :: CfgWeights -> CmmGraph -> CFG #

getCfgProc :: CfgWeights -> RawCmmDecl -> CFG #

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

pprEdgeWeights :: CFG -> SDoc #

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

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

optimizeCFG :: CfgWeights -> RawCmmDecl -> CFG -> CFG #

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

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)