module GHC.CmmToAsm.CFG.Weight
   ( Weights (..)
   , defaultWeights
   , parseWeights
   )
where

import GHC.Prelude
import GHC.Utils.Panic

-- | Edge weights to use when generating a CFG from CMM
data Weights = Weights
   { Weights -> Int
uncondWeight       :: Int
   , Weights -> Int
condBranchWeight   :: Int
   , Weights -> Int
switchWeight       :: Int
   , Weights -> Int
callWeight         :: Int
   , Weights -> Int
likelyCondWeight   :: Int
   , Weights -> Int
unlikelyCondWeight :: Int
   , Weights -> Int
infoTablePenalty   :: Int
   , Weights -> Int
backEdgeBonus      :: Int
   }

-- | Default edge weights
defaultWeights :: Weights
defaultWeights :: Weights
defaultWeights = Weights
   { uncondWeight :: Int
uncondWeight       = Int
1000
   , condBranchWeight :: Int
condBranchWeight   = Int
800
   , switchWeight :: Int
switchWeight       = Int
1
   , callWeight :: Int
callWeight         = -Int
10
   , likelyCondWeight :: Int
likelyCondWeight   = Int
900
   , unlikelyCondWeight :: Int
unlikelyCondWeight = Int
300
   , infoTablePenalty :: Int
infoTablePenalty   = Int
300
   , backEdgeBonus :: Int
backEdgeBonus      = Int
400
   }

parseWeights :: String -> Weights -> Weights
parseWeights :: String -> Weights -> Weights
parseWeights String
s Weights
oldWeights =
        forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (\Weights
cfg (String
n,Int
v) -> String -> Int -> Weights -> Weights
update String
n Int
v Weights
cfg) Weights
oldWeights [(String, Int)]
assignments
    where
        assignments :: [(String, Int)]
assignments = forall a b. (a -> b) -> [a] -> [b]
map forall {b}. Read b => String -> (String, b)
assignment forall a b. (a -> b) -> a -> b
$ String -> [String]
settings String
s
        update :: String -> Int -> Weights -> Weights
update String
"uncondWeight" Int
n Weights
w =
            Weights
w {uncondWeight :: Int
uncondWeight = Int
n}
        update String
"condBranchWeight" Int
n Weights
w =
            Weights
w {condBranchWeight :: Int
condBranchWeight = Int
n}
        update String
"switchWeight" Int
n Weights
w =
            Weights
w {switchWeight :: Int
switchWeight = Int
n}
        update String
"callWeight" Int
n Weights
w =
            Weights
w {callWeight :: Int
callWeight = Int
n}
        update String
"likelyCondWeight" Int
n Weights
w =
            Weights
w {likelyCondWeight :: Int
likelyCondWeight = Int
n}
        update String
"unlikelyCondWeight" Int
n Weights
w =
            Weights
w {unlikelyCondWeight :: Int
unlikelyCondWeight = Int
n}
        update String
"infoTablePenalty" Int
n Weights
w =
            Weights
w {infoTablePenalty :: Int
infoTablePenalty = Int
n}
        update String
"backEdgeBonus" Int
n Weights
w =
            Weights
w {backEdgeBonus :: Int
backEdgeBonus = Int
n}
        update String
other Int
_ Weights
_
            = forall a. String -> a
panic forall a b. (a -> b) -> a -> b
$ String
other forall a. [a] -> [a] -> [a]
++
                      String
" is not a CFG weight parameter. " forall a. [a] -> [a] -> [a]
++
                      String
exampleString
        settings :: String -> [String]
settings String
s
            | (String
s1,String
rest) <- forall a. (a -> Bool) -> [a] -> ([a], [a])
break (forall a. Eq a => a -> a -> Bool
== Char
',') String
s
            , forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
rest
            = [String
s1]
            | (String
s1,String
rest) <- forall a. (a -> Bool) -> [a] -> ([a], [a])
break (forall a. Eq a => a -> a -> Bool
== Char
',') String
s
            = String
s1 forall a. a -> [a] -> [a]
: String -> [String]
settings (forall a. Int -> [a] -> [a]
drop Int
1 String
rest)

        assignment :: String -> (String, b)
assignment String
as
            | (String
name, Char
_:String
val) <- forall a. (a -> Bool) -> [a] -> ([a], [a])
break (forall a. Eq a => a -> a -> Bool
== Char
'=') String
as
            = (String
name,forall a. Read a => String -> a
read String
val)
            | Bool
otherwise
            = forall a. String -> a
panic forall a b. (a -> b) -> a -> b
$ String
"Invalid CFG weight parameters." forall a. [a] -> [a] -> [a]
++ String
exampleString

        exampleString :: String
exampleString = String
"Example parameters: uncondWeight=1000," forall a. [a] -> [a] -> [a]
++
            String
"condBranchWeight=800,switchWeight=0,callWeight=300" forall a. [a] -> [a] -> [a]
++
            String
",likelyCondWeight=900,unlikelyCondWeight=300" forall a. [a] -> [a] -> [a]
++
            String
",infoTablePenalty=300,backEdgeBonus=400"