packages feed

canontra-0.1.0.0: src/Canontra/Analysis/CompactGraph.hs

{- |
Module      : Canontra.Analysis.CompactGraph
Description : Pure Haskell unboxed flat Vector representations for CFG and DFG.

Provides memory-compact, unboxed flat array representations for Control-Flow
Graph and Data-Flow Graph topologies using 'Data.Vector.Unboxed.Vector Word64',
reducing GC traversal overhead to near zero.
-}
module Canontra.Analysis.CompactGraph
  ( CompactCFG (..)
  , CompactDFG (..)
  , packCFGEdges
  , unpackCFGEdges
  , packDFGEdges
  , unpackDFGEdges
  , fromControlFlowGraph
  , fromDataFlowGraph
  ) where

import Control.DeepSeq (NFData)
import Data.Bits (shiftL, shiftR, (.&.), (.|.))
import qualified Data.Vector.Unboxed as U
import Data.Word (Word64)
import GHC.Generics (Generic)

import Canontra.Analysis.CFG (CFGEdge (..), ControlFlowGraph (..))
import Canontra.Analysis.DFG (DFGEdge (..), DataFlowGraph (..))

-- | Flat unboxed 64-bit representation of CFG: (FromBlockId << 32 | ToBlockId)
newtype CompactCFG = CompactCFG
  { unCompactCFG :: U.Vector Word64
  } deriving stock (Eq, Show, Generic)
  deriving newtype (NFData)

-- | Flat unboxed 64-bit representation of Def-Use: (DefNodeId << 32 | UseNodeId)
newtype CompactDFG = CompactDFG
  { unCompactDFG :: U.Vector Word64
  } deriving stock (Eq, Show, Generic)
  deriving newtype (NFData)

{-# INLINE packCFGEdges #-}
packCFGEdges :: [(Int, Int)] -> CompactCFG
packCFGEdges edges = CompactCFG $ U.fromList
  [ (fromIntegral from `shiftL` 32) .|. (fromIntegral to .&. 0xFFFFFFFF)
  | (from, to) <- edges
  ]

{-# INLINE unpackCFGEdges #-}
unpackCFGEdges :: CompactCFG -> [(Int, Int)]
unpackCFGEdges (CompactCFG vec) =
  [ (fromIntegral (w `shiftR` 32), fromIntegral (w .&. 0xFFFFFFFF))
  | w <- U.toList vec
  ]

{-# INLINE packDFGEdges #-}
packDFGEdges :: [(Int, Int)] -> CompactDFG
packDFGEdges edges = CompactDFG $ U.fromList
  [ (fromIntegral def `shiftL` 32) .|. (fromIntegral use .&. 0xFFFFFFFF)
  | (def, use) <- edges
  ]

{-# INLINE unpackDFGEdges #-}
unpackDFGEdges :: CompactDFG -> [(Int, Int)]
unpackDFGEdges (CompactDFG vec) =
  [ (fromIntegral (w `shiftR` 32), fromIntegral (w .&. 0xFFFFFFFF))
  | w <- U.toList vec
  ]

-- | Convert a standard ControlFlowGraph to a CompactCFG.
fromControlFlowGraph :: ControlFlowGraph -> CompactCFG
fromControlFlowGraph cfg =
  packCFGEdges [(edgeFrom e, edgeTo e) | e <- cfgEdges cfg]

-- | Convert a standard DataFlowGraph to a CompactDFG.
fromDataFlowGraph :: DataFlowGraph -> CompactDFG
fromDataFlowGraph dfg =
  packDFGEdges [(dfgSource e, dfgTarget e) | e <- dfgEdges dfg]