{-# LANGUAGE BlockArguments #-}
module RegAlloc.Interference (module RegAlloc.UGraph, Interferences, Operands, interferes, interferences) where

import Control.Monad.Trans.State (state, evalState)
import Data.Functor.Reverse (Reverse (..))
import Data.Map.Class (Union (..))
import qualified Data.Map.Class as Map
import Data.IntSet (IntSet)
import qualified Data.IntSet as IS
import Util hiding (())

import RegAlloc.Nodes.Private
import RegAlloc.UGraph
import RegAlloc.UGraph.Private

type Interferences = UGraph

interferes :: Node -> Int -> Interferences -> Bool
interferes = hasEdge

interferences :: (Traversable f) => f Operands -> UGraph
interferences = (.) UGr $
    liveSets & foldMap \ ks -> Union $ Map.fromList [(k, ks) | k <- IS.toList ks]

liveSets :: (Traversable f) => f Operands -> f LiveSet
liveSets = getReverse . flip evalState IS.empty . traverse (go . fmap unNodes) . Reverse . count
  where go (k, ks) = state $ (,) <*> IS.insert k . flip IS.difference ks

type Operands = Nodes
type LiveSet = IntSet