ghc-9.12.1: The GHC API
Safe HaskellNone
LanguageGHC2021

GHC.CmmToAsm.CFG

Synopsis

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 

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

data EdgeInfo Source #

Information about edges

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

newtype EdgeWeight Source #

Constructors

EdgeWeight 

Instances

Instances details
Outputable EdgeWeight Source # 
Instance details

Defined in GHC.CmmToAsm.CFG

Methods

ppr :: EdgeWeight -> SDoc Source #

Enum EdgeWeight Source # 
Instance details

Defined in GHC.CmmToAsm.CFG

Num EdgeWeight Source # 
Instance details

Defined in GHC.CmmToAsm.CFG

Fractional EdgeWeight Source # 
Instance details

Defined in GHC.CmmToAsm.CFG

Real EdgeWeight Source # 
Instance details

Defined in GHC.CmmToAsm.CFG

Eq EdgeWeight Source # 
Instance details

Defined in GHC.CmmToAsm.CFG

Ord EdgeWeight Source # 
Instance details

Defined in GHC.CmmToAsm.CFG

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

AsmCodeGen 

Instances

Instances details
Eq TransitionSource Source # 
Instance details

Defined in GHC.CmmToAsm.CFG

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

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.

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)

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.

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.

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

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

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.

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.