summaryrefslogtreecommitdiff
path: root/optimiser.hs
diff options
context:
space:
mode:
Diffstat (limited to 'optimiser.hs')
-rw-r--r--optimiser.hs82
1 files changed, 48 insertions, 34 deletions
diff --git a/optimiser.hs b/optimiser.hs
index 61096b4..2a27a5e 100644
--- a/optimiser.hs
+++ b/optimiser.hs
@@ -1,8 +1,10 @@
module Optimiser(optimise) where
import Data.List
+import Data.Function
+import qualified Data.Map.Strict as Map
--- import Debug.Trace
+import Debug.Trace
import AST
@@ -12,11 +14,12 @@ type Optimisation = [Instruction] -> [Instruction]
optimisations :: [Optimisation]
optimisations =
- [collectSimilar, nullOps, collectAdds, propagateKnowns, firstSets, propagateSlides, uselessEnd, specialLoops, normaliseOrder, deduplicateSets]
+ [collectSimilar, nullOps, collectAdds, propagateKnowns, firstSets, propagateSlides, uselessEnd, specialLoops, normaliseOrder]
composedOpts :: Optimisation
-composedOpts = foldl1 (.) (reverse optimisations)
+-- composedOpts = foldl1 (.) (reverse optimisations)
-- composedOpts = foldl1 (.) (map (traceShowId .) $ reverse optimisations)
+composedOpts = foldl1 (.) (map ((\r -> traceShow (take 7 r) r) .) $ reverse optimisations)
optimise :: Program -> Program
optimise (Program inss) =
@@ -35,12 +38,15 @@ collectSimilar (ins : rest) = ins : collectSimilar rest
nullOps :: Optimisation
nullOps [] = []
nullOps (IAdd 0 _ : rest) = nullOps rest
+nullOps (ICopy _ _ 0 : rest) = nullOps rest
nullOps (ISlide 0 : rest) = nullOps rest
nullOps (ILoop inss off : rest) = ILoop (nullOps inss) off : nullOps rest
nullOps (ins : rest) = ins : nullOps rest
collectAdds :: Optimisation
collectAdds [] = []
+collectAdds (ICopy from1 to1 m1 : ICopy from2 to2 m2 : rest)
+ | from1 == from2, m1 == m2 = ICopy from1 to1 m1 : collectAdds (ICopy to1 to2 1 : rest)
collectAdds inss =
let adds = map (\(IAdd v o) -> (v, o)) $ takeWhile isIAdd inss
dests = nub $ map snd adds
@@ -53,13 +59,38 @@ collectAdds inss =
propagateKnowns :: Optimisation
propagateKnowns [] = []
-propagateKnowns (ISet v off : rest) =
- let pre = takeWhile (\ins -> isIAdd ins || isISet ins || isIMove ins) rest
- post = drop (length pre) rest
- relevant = filter ((== off) . offsetOf) pre
- irrelevant = filter ((/= off) . offsetOf) pre
- (res, resins) = accumSetAddMove v relevant
- in ISet res off : resins ++ propagateKnowns (irrelevant ++ post)
+propagateKnowns allinss@(ins : _) | isISet ins || isIStart ins =
+ let defaultZero = isIStart ins
+
+ go :: [Instruction] -> Map.Map Offset Byte -> ([Instruction], Map.Map Offset Byte)
+ go (IStart : rest) mp = go rest mp
+ go (ISet val off : rest) mp = go rest $ Map.insert off val mp
+ go inss@(IAdd val off : rest) mp = case Map.lookup off mp of
+ Nothing -> (inss, mp)
+ Just origval -> go rest $ Map.insert off (origval + val) mp
+ go inss@(ICopy from to mult : rest) mp =
+ if defaultZero
+ then let fromval = maybe 0 id $ Map.lookup from mp
+ toval = maybe 0 id $ Map.lookup to mp
+ in go rest $ Map.insert to (toval + mult * fromval) mp
+ else case (Map.lookup from mp, Map.lookup to mp) of
+ (Nothing, _) -> (inss, mp)
+ (_, Nothing) -> (inss, mp)
+ (Just fromval, Just toval) ->
+ go rest $ Map.insert to (toval + mult * fromval) mp
+ go inss mp = (inss, mp)
+
+ compareSetAdd :: Instruction -> Instruction -> Ordering
+ compareSetAdd (ISet _ _) (IAdd _ _) = LT
+ compareSetAdd (IAdd _ _) (ISet _ _) = GT
+ compareSetAdd i1 i2 = compare (offsetOf i1) (offsetOf i2)
+
+ (after, valuemap) = go allinss Map.empty
+ sets = sortBy compareSetAdd
+ $ Map.foldlWithKey
+ (\l off val -> if not defaultZero || val /= 0 then ISet val off : l else l)
+ [] valuemap
+ in if isIStart ins then IStart : sets ++ propagateKnowns after else sets ++ propagateKnowns after
propagateKnowns (ILoop inss off : rest) = ILoop (propagateKnowns inss) off : propagateKnowns rest
propagateKnowns (ins : rest) = ins : propagateKnowns rest
@@ -99,25 +130,17 @@ specialLoops (ILoop inss off : rest)
sum (map (\(IAdd v _) -> v) $ filter ((== off) . offsetOf) inss) == -1 =
let others = map (\(IAdd v o) -> (v, o)) $ filter ((/= off) . offsetOf) inss
dests = nub $ map snd others
- tos = [(d, sum $ map fst $ filter ((== d) . snd) others) | d <- dests]
- in IMove off tos : specialLoops rest
+ copies = [ICopy off d (sum $ map fst $ filter ((== d) . snd) others) | d <- dests]
+ in copies ++ ISet 0 off : specialLoops rest
specialLoops (ILoop inss off : rest) = ILoop (specialLoops inss) off : specialLoops rest
specialLoops (ins : rest) = ins : specialLoops rest
normaliseOrder :: Optimisation
normaliseOrder [] = []
-normaliseOrder inss =
- let pre = takeWhile (\ins -> isIAdd ins || isISet ins) inss
- post = drop (length pre) inss
- in if null pre
- then head inss : normaliseOrder (tail inss)
- else filter isISet pre ++ filter isIAdd pre ++ normaliseOrder post
-
-deduplicateSets :: Optimisation
-deduplicateSets [] = []
-deduplicateSets (IStart : ISet 0 _ : rest) = IStart : deduplicateSets rest
-deduplicateSets (ISet _ o1 : ISet v o2 : rest) | o1 == o2 = deduplicateSets $ ISet v o1 : rest
-deduplicateSets (ins : rest) = ins : deduplicateSets rest
+normaliseOrder (ICopy from1 to1 m1 : ICopy from2 to2 m2 : rest)
+ | m2 < m1, to1 /= from2, to2 /= from1 = ICopy from2 to2 m2 : normaliseOrder (ICopy from1 to1 m1 : rest)
+normaliseOrder (ILoop inss off : rest) = ILoop (normaliseOrder inss) off : normaliseOrder rest
+normaliseOrder (ins : rest) = ins : normaliseOrder rest
repeated :: Optimisation -> Optimisation
@@ -128,7 +151,7 @@ incOffsets :: Offset -> [Instruction] -> [Instruction]
incOffsets _ [] = []
incOffsets inc (IAdd v off : rest) = IAdd v (off + inc) : incOffsets inc rest
incOffsets inc (ISet v off : rest) = ISet v (off + inc) : incOffsets inc rest
-incOffsets inc (IMove from tos : rest) = IMove (from + inc) [(o+inc,m) | (o,m) <- tos] : incOffsets inc rest
+incOffsets inc (ICopy from to mult : rest) = ICopy (from + inc) (to + inc) mult : incOffsets inc rest
incOffsets inc (ISlide off : rest) = ISlide off : incOffsets inc rest
incOffsets inc (ILoop inss off : rest) = ILoop (incOffsets inc inss) (off + inc) : incOffsets inc rest
incOffsets inc (IInput off : rest) = IInput (off + inc) : incOffsets inc rest
@@ -141,14 +164,5 @@ accumSetAdd _ (ISet v' _ : rest) = accumSetAdd v' rest
accumSetAdd acc (IAdd v' _ : rest) = accumSetAdd (acc + v') rest
accumSetAdd _ _ = unreachable
-accumSetAddMove :: Byte -> [Instruction] -> (Byte, [Instruction])
-accumSetAddMove acc [] = (acc, [])
-accumSetAddMove _ (ISet v' _ : rest) = accumSetAddMove v' rest
-accumSetAddMove acc (IAdd v' _ : rest) = accumSetAddMove (acc + v') rest
-accumSetAddMove acc (IMove _ tos : rest) =
- let (res, resins) = accumSetAddMove 0 rest
- in (res, [IAdd (m * acc) o | (o,m) <- tos] ++ resins)
-accumSetAddMove _ _ = unreachable
-
unreachable :: a
unreachable = error "Unreachable"