packages feed

linearscan-hoopl 0.5.1.0 → 0.6.0.0

raw patch · 10 files changed

+1746/−433 lines, 10 filesdep +QuickCheckdep +fuzzcheckdep +tardisPVP ok

version bump matches the API change (PVP)

Dependencies added: QuickCheck, fuzzcheck, tardis

API changes (from Hackage documentation)

- LinearScan.Hoopl: SUM' :: ([Int] -> (a, [Int])) -> SimpleUniqueMonad' a
- LinearScan.Hoopl: fromReg :: NodeAlloc n v r => r -> PhysReg
- LinearScan.Hoopl: fromVar :: NodeAlloc n v r => v -> Either PhysReg VarId
- LinearScan.Hoopl: newtype SimpleUniqueMonad' a
- LinearScan.Hoopl: runSimpleUniqueMonad' :: Int -> SimpleUniqueMonad a -> a
- LinearScan.Hoopl: unSUM' :: SimpleUniqueMonad' a -> [Int] -> (a, [Int])
- LinearScan.Hoopl.DSL: EnvState :: Labels -> BlockIds -> SpillStack -> Map PhysReg VarId -> EnvState
- LinearScan.Hoopl.DSL: data EnvState
- LinearScan.Hoopl.DSL: envAssignments :: EnvState -> Map PhysReg VarId
- LinearScan.Hoopl.DSL: envBlockIds :: EnvState -> BlockIds
- LinearScan.Hoopl.DSL: envLabels :: EnvState -> Labels
- LinearScan.Hoopl.DSL: envSpillStack :: EnvState -> SpillStack
- LinearScan.Hoopl.DSL: newEnvState :: Int -> Int -> EnvState
- LinearScan.Hoopl.DSL: type BlockIds = Map Label Int
- LinearScan.Hoopl: allocateHoopl :: (NonLocal (n v), NonLocal (n r), NodeAlloc n v r) => Int -> Int -> Int -> Label -> Graph (n v) C C -> Either String (Graph (n r) C C)
+ LinearScan.Hoopl: allocateHoopl :: (NodeAlloc nv nr, NonLocal nv, NonLocal nr) => Int -> Int -> Int -> Label -> Graph nv C C -> Either [String] (Graph nr C C)
- LinearScan.Hoopl: blockInfo :: (NodeAlloc n v r, NonLocal (n v)) => (Label -> Env Int) -> BlockInfo Env (Block (n v) C C) (Block (n r) C C) (NodeV (n v)) (NodeV (n r))
+ LinearScan.Hoopl: blockInfo :: (NodeAlloc nv nr, NonLocal nv, NonLocal nr) => (Label -> Env Int) -> BlockInfo Env (Block nv C C) (Block nr C C) (NodeV nv) (NodeV nr)
- LinearScan.Hoopl: class HooplNode (n v) => NodeAlloc n v r | n -> v, n -> r
+ LinearScan.Hoopl: class HooplNode nv => NodeAlloc nv nr | nv -> nr, nr -> nv
- LinearScan.Hoopl: getReferences :: NodeAlloc n v r => n v e x -> [VarInfo]
+ LinearScan.Hoopl: getReferences :: NodeAlloc nv nr => nv e x -> [VarInfo]
- LinearScan.Hoopl: isBranch :: NodeAlloc n v r => n v O C -> Bool
+ LinearScan.Hoopl: isBranch :: NodeAlloc nv nr => nv O C -> Bool
- LinearScan.Hoopl: isCall :: NodeAlloc n v r => n v O O -> Bool
+ LinearScan.Hoopl: isCall :: NodeAlloc nv nr => nv O O -> Bool
- LinearScan.Hoopl: mkJumpOp :: NodeAlloc n v r => Label -> n v O C
+ LinearScan.Hoopl: mkJumpOp :: NodeAlloc nv nr => Label -> nv O C
- LinearScan.Hoopl: mkLabelOp :: NodeAlloc n v r => Label -> n v C O
+ LinearScan.Hoopl: mkLabelOp :: NodeAlloc nv nr => Label -> nv C O
- LinearScan.Hoopl: mkMoveOps :: NodeAlloc n v r => PhysReg -> PhysReg -> Env [n r O O]
+ LinearScan.Hoopl: mkMoveOps :: NodeAlloc nv nr => PhysReg -> PhysReg -> Env [nr O O]
- LinearScan.Hoopl: mkRestoreOps :: NodeAlloc n v r => Maybe VarId -> PhysReg -> Env [n r O O]
+ LinearScan.Hoopl: mkRestoreOps :: NodeAlloc nv nr => Maybe VarId -> PhysReg -> Env [nr O O]
- LinearScan.Hoopl: mkSaveOps :: NodeAlloc n v r => PhysReg -> Maybe VarId -> Env [n r O O]
+ LinearScan.Hoopl: mkSaveOps :: NodeAlloc nv nr => PhysReg -> Maybe VarId -> Env [nr O O]
- LinearScan.Hoopl: mkSwapOps :: NodeAlloc n v r => PhysReg -> PhysReg -> Env [n r O O]
+ LinearScan.Hoopl: mkSwapOps :: NodeAlloc nv nr => PhysReg -> PhysReg -> Env [nr O O]
- LinearScan.Hoopl: op1ToString :: NodeAlloc n v r => n v e x -> String
+ LinearScan.Hoopl: op1ToString :: NodeAlloc nv nr => nv e x -> String
- LinearScan.Hoopl: opInfo :: NodeAlloc n v r => OpInfo Env (NodeV (n v)) (NodeV (n r))
+ LinearScan.Hoopl: opInfo :: NodeAlloc nv nr => OpInfo Env (NodeV nv) (NodeV nr)
- LinearScan.Hoopl: retargetBranch :: NodeAlloc n v r => n v O C -> Label -> Label -> n v O C
+ LinearScan.Hoopl: retargetBranch :: NodeAlloc nv nr => nv O C -> Label -> Label -> nv O C
- LinearScan.Hoopl: setRegisters :: NodeAlloc n v r => [(Int, PhysReg)] -> n v e x -> Env (n r e x)
+ LinearScan.Hoopl: setRegisters :: NodeAlloc nv nr => [(Int, PhysReg)] -> nv e x -> Env (nr e x)
- LinearScan.Hoopl.DSL: type Env = StateT EnvState SimpleUniqueMonad
+ LinearScan.Hoopl.DSL: type Env = Tardis (Map PhysReg VarId) ([Int], SpillStack)

Files

LinearScan/Hoopl.hs view
@@ -11,8 +11,9 @@ import           Control.Applicative import           Control.Arrow import           Control.Monad.Trans.Class-import           Control.Monad.Trans.State (evalStateT, modify)+import           Control.Monad.Trans.Tardis import           Data.Foldable+import           Data.Functor.Identity import qualified Data.Map as M import           Data.Monoid import           Debug.Trace@@ -20,36 +21,33 @@ import           LinearScan.Hoopl.DSL import           Unsafe.Coerce -class HooplNode (n v) => NodeAlloc n v r | n -> v, n -> r where-    fromVar :: v -> Either PhysReg VarId-    fromReg :: r -> PhysReg--    isCall   :: n v O O -> Bool-    isBranch :: n v O C -> Bool+class HooplNode nv => NodeAlloc nv nr | nv -> nr, nr -> nv where+    isCall   :: nv O O -> Bool+    isBranch :: nv O C -> Bool -    retargetBranch :: n v O C -> Label -> Label -> n v O C+    retargetBranch :: nv O C -> Label -> Label -> nv O C -    mkLabelOp :: Label -> n v C O-    mkJumpOp  :: Label -> n v O C+    mkLabelOp :: Label -> nv C O+    mkJumpOp  :: Label -> nv O C -    getReferences :: n v e x -> [VarInfo]-    setRegisters  :: [(Int, PhysReg)] -> n v e x -> Env (n r e x)+    getReferences :: nv e x -> [VarInfo]+    setRegisters  :: [(Int, PhysReg)] -> nv e x -> Env (nr e x) -    mkMoveOps    :: PhysReg -> PhysReg -> Env [n r O O]-    mkSwapOps    :: PhysReg -> PhysReg -> Env [n r O O]-    mkSaveOps    :: PhysReg -> Maybe VarId -> Env [n r O O]-    mkRestoreOps :: Maybe VarId -> PhysReg -> Env [n r O O]+    mkMoveOps    :: PhysReg -> PhysReg -> Env [nr O O]+    mkSwapOps    :: PhysReg -> PhysReg -> Env [nr O O]+    mkSaveOps    :: PhysReg -> Maybe VarId -> Env [nr O O]+    mkRestoreOps :: Maybe VarId -> PhysReg -> Env [nr O O] -    op1ToString  :: n v e x -> String+    op1ToString  :: nv e x -> String  data NodeV n = NodeCO { getNodeCO :: n C O }              | NodeOO { getNodeOO :: n O O }              | NodeOC { getNodeOC :: n O C } -blockInfo :: (NodeAlloc n v r, NonLocal (n v))+blockInfo :: (NodeAlloc nv nr, NonLocal nv, NonLocal nr)           => (Label -> Env Int)-          -> BlockInfo Env (Block (n v) C C) (Block (n r) C C)-                           (NodeV (n v)) (NodeV (n r))+          -> BlockInfo Env (Block nv C C) (Block nr C C)+                           (NodeV nv) (NodeV nr) blockInfo getBlockId = BlockInfo     { blockId = getBlockId . entryLabel @@ -58,14 +56,10 @@     , splitCriticalEdge = \(BlockCC b m e)                            (BlockCC next _ _) -> do         let lab = entryLabel next-        lab' <- lift freshLabel-        modify $ \st ->-            st { envLabels   = M.insert (show lab ++ "'") lab' (envLabels st)-               , envBlockIds = let m = envBlockIds st in-                               M.insert lab' (M.size m + 1) m-               }-        let e' = retargetBranch e lab lab'-        return (BlockCC b m e',+        (next:supply, stack) <- getPast+        sendFuture (supply, stack)+        let lab' = unsafeCoerce next+        return (BlockCC b m (retargetBranch e lab lab'),                 BlockCC (mkLabelOp lab') BNil (mkJumpOp lab))      , blockOps = \(BlockCC a b z) ->@@ -78,11 +72,11 @@             (getNodeOC z)     } -opInfo :: NodeAlloc n v r => OpInfo Env (NodeV (n v)) (NodeV (n r))+opInfo :: NodeAlloc nv nr => OpInfo Env (NodeV nv) (NodeV nr) opInfo = OpInfo     { opKind = \node -> case node of-           NodeOO n | isCall n  -> IsCall-                    | otherwise -> IsNormal+           NodeOO n | isCall n   -> IsCall+                    | otherwise  -> IsNormal            NodeOC n | isBranch n -> IsBranch                     | otherwise  -> IsNormal            _ -> IsNormal@@ -109,20 +103,15 @@            NodeOC n -> op1ToString n     } -newtype SimpleUniqueMonad' a = SUM' { unSUM' :: [Int] -> (a, [Int]) }--runSimpleUniqueMonad' :: Int -> SimpleUniqueMonad a -> a-runSimpleUniqueMonad' start m = fst (unSUM' (unsafeCoerce m) [start..])--allocateHoopl :: (NonLocal (n v), NonLocal (n r), NodeAlloc n v r)+allocateHoopl :: (NodeAlloc nv nr, NonLocal nv, NonLocal nr)               => Int             -- ^ Number of machine registers               -> Int             -- ^ Offset of the spill stack               -> Int             -- ^ Size of spilled register in bytes               -> Label           -- ^ Label of graph entry block-              -> Graph (n v) C C -- ^ Program graph-              -> Either String (Graph (n r) C C)+              -> Graph nv C C -- ^ Program graph+              -> Either [String] (Graph nr C C) allocateHoopl regs offset slotSize entry graph =-    newGraph <$> runSimpleUniqueMonad' (1 + length blocks) go+    newGraph <$> runIdentity (go (1 + length blocks))   where     newGraph xs = GMany NothingO (newBody xs) NothingO       where@@ -132,7 +121,7 @@       where         GMany NothingO body NothingO = graph -    go = evalStateT alloc (newEnvState offset slotSize)+    go n = evalTardisT alloc (mempty, ([n..], newSpillStack offset slotSize))       where         alloc = allocate regs (blockInfo getBlockId) opInfo blocks           where
LinearScan/Hoopl/DSL.hs view
@@ -1,20 +1,27 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE RecursiveDo #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+ module LinearScan.Hoopl.DSL where  import           Compiler.Hoopl as Hoopl hiding ((<*>)) import           Control.Applicative import           Control.Arrow (first)+import           Control.Monad+import           Control.Monad.Fix import           Control.Monad.Free import           Control.Monad.Trans.Class import qualified Control.Monad.Trans.Free as TF import           Control.Monad.Trans.Free hiding (FreeF(..), Free)-import           Control.Monad.Trans.State (StateT, evalStateT,-                                            gets, modify, get, put)+import           Control.Monad.Trans.State+import           Control.Monad.Trans.Tardis import qualified Data.Map as M+import           Data.Maybe (fromMaybe) import           Data.Monoid import           LinearScan--type Labels = M.Map String Label-type BlockIds = M.Map Label Int+import           Unsafe.Coerce+import           Test.QuickCheck  data SpillStack = SpillStack     { stackPtr      :: Int@@ -23,14 +30,7 @@     }     deriving (Eq, Show) -data EnvState = EnvState-    { envLabels      :: Labels-    , envBlockIds    :: BlockIds-    , envSpillStack  :: SpillStack-    , envAssignments :: M.Map PhysReg VarId-    }--type Env = StateT EnvState SimpleUniqueMonad+type Env = Tardis (M.Map PhysReg VarId) ([Int], SpillStack)  newSpillStack :: Int -> Int -> SpillStack newSpillStack offset slotSize = SpillStack@@ -39,30 +39,29 @@     , stackSlots    = mempty     } -newEnvState :: Int -> Int -> EnvState-newEnvState offset slotSize = EnvState-    { envLabels      = mempty-    , envBlockIds    = mempty-    , envSpillStack  = newSpillStack offset slotSize-    , envAssignments = mempty-    }- getStackSlot :: Maybe VarId -> Env Int getStackSlot vid = do-    st <- get-    let stack = envSpillStack st+    (supply, stack) <- getPast     case M.lookup vid (stackSlots stack) of         Just off -> return off         Nothing -> do             let off = stackPtr stack-            put st { envSpillStack = stack-                 { stackPtr   = off + stackSlotSize stack-                 , stackSlots =-                     M.insert vid off (stackSlots stack)-                 }}+            sendFuture (supply, stack+                { stackPtr   = off + stackSlotSize stack+                , stackSlots = M.insert vid off (stackSlots stack)+                })             return off +setAssignment :: PhysReg -> VarId -> Env ()+setAssignment = (modifyBackwards .) . M.insert++getAssignment :: PhysReg -> Env VarId+getAssignment reg =+    fromMaybe (error $ "No assignment for register r" ++ show reg)+        . M.lookup reg <$> getFuture+ -- | The 'Asm' monad lets us create labels by name and refer to them later.+type Labels = M.Map String Label type Asm = StateT Labels SimpleUniqueMonad  getLabel :: String -> Asm Label@@ -74,18 +73,6 @@             lbl <- lift freshLabel             modify (M.insert str lbl)             return lbl--setAssignment :: PhysReg -> VarId -> Env ()-setAssignment reg vid =-    modify $ \env ->-        env { envAssignments = M.insert reg vid (envAssignments env) }--getAssignment :: PhysReg -> Env VarId-getAssignment reg = do-    l <- gets (M.lookup reg . envAssignments)-    case l of-        Just vid -> return vid-        Nothing  -> error $ "No assignment for register: " ++ show reg  -- | A series of 'Nodes' is a set of assembly instructions that ends with some --   kind of closing operation, such as a jump, branch or return.
linearscan-hoopl.cabal view
@@ -1,5 +1,5 @@ name:          linearscan-hoopl-version:       0.5.1.0+version:       0.6.0.0 synopsis:      Makes it easy to use the linearscan register allocator with Hoopl homepage:      http://github.com/jwiegley/linearscan-hoopl license:       BSD3@@ -24,12 +24,15 @@   exposed-modules:     LinearScan.Hoopl     LinearScan.Hoopl.DSL-  build-depends:    base >=4.7 && <5-                  , hoopl >= 3.10.0.1-                  , linearscan >= 0.3.0.1-                  , containers-                  , transformers-                  , free+  build-depends:    +      base       >=4.7 && <5+    , hoopl      >= 3.10.0.1+    , linearscan >= 0.3.0.1+    , tardis     >= 0.3.0.0+    , containers+    , transformers+    , free+    , QuickCheck  test-suite test   default-language: Haskell2010@@ -37,18 +40,25 @@   ghc-options:      -Wall -fno-warn-deprecated-flags   hs-source-dirs:   test   main-is:          Main.hs-  other-modules:    AsmTest-                    Assembly-                    Normal+  other-modules:    +    AsmTest+    Assembly+    Normal+    Generated+    Programs.Blocked+    Programs.Exhaustion   build-depends: -        base >=3-      , linearscan-      , hspec              >= 1.4.4-      , hspec-expectations >= 0.3-      , hoopl              >= 3.10.0.1 && < 3.11-      , linearscan         >= 0.5.0.0-      , linearscan-hoopl   >= 0.5.0.0-      , containers         >= 0.5.5-      , transformers       >= 0.3.0.0-      , lens-family-core-      , deepseq+      base >=3+    , linearscan+    , hspec              >= 1.4.4+    , hspec-expectations >= 0.3+    , hoopl              >= 3.10.0.1 && < 3.11+    , linearscan         >= 0.5.0.0+    , linearscan-hoopl   >= 0.5.0.0+    , containers         >= 0.5.5+    , transformers       >= 0.3.0.0+    , tardis             >= 0.3.0.0+    , lens-family-core+    , deepseq+    , QuickCheck+    , fuzzcheck
test/AsmTest.hs view
@@ -5,25 +5,28 @@ import Assembly import Compiler.Hoopl as Hoopl hiding ((<*>)) import Control.Exception+import Data.List (intercalate) import LinearScan import LinearScan.Hoopl import LinearScan.Hoopl.DSL import Normal () import Test.Hspec -asmTestLiteral :: Int -> Program (Node IRVar) -> String -> Expectation-asmTestLiteral regs program expected = do+asmTestLiteral :: Int -> Program (Node IRVar) -> Maybe String -> Expectation+asmTestLiteral regs program mexpected = do     let (graph, entry) = runSimpleUniqueMonad $ compile "entry" program     case allocateHoopl regs 0 8 entry graph of-        Left err -> error $ "Allocation failed: " ++ err-        Right graph' -> do-            let g = showGraph show graph'-            catch (g `shouldBe` expected) $ \e -> do-                putStrLn $ "---- Parsed ----\n" ++ showGraph show graph-                putStrLn $ "---- Expecting ----\n" ++ expected-                putStrLn $ "---- Compiled  ----\n" ++ g-                putStrLn "-------------------"-                throwIO (e :: SomeException)+        Left err -> error $ "Allocation failed: " ++ intercalate "\n" err+        Right graph' -> case mexpected of+            Nothing -> return ()+            Just expected ->+                let g = showGraph show graph' in+                catch (g `shouldBe` expected) $ \e -> do+                    putStrLn $ "---- Parsed ----\n" ++ showGraph show graph+                    putStrLn $ "---- Expecting ----\n" ++ expected+                    putStrLn $ "---- Compiled  ----\n" ++ g+                    putStrLn "-------------------"+                    throwIO (e :: SomeException)  asmTest :: Int         -> Program (Node IRVar)@@ -31,7 +34,11 @@         -> Expectation asmTest regs program     = asmTestLiteral regs program+    . Just     . showGraph show     . fst     . runSimpleUniqueMonad     . compile "entry"++asmTest_ :: Int -> Program (Node IRVar) -> Expectation+asmTest_ regs program = asmTestLiteral regs program Nothing
test/Assembly.hs view
@@ -12,9 +12,9 @@  import           Compiler.Hoopl as Hoopl hiding ((<*>)) import           Control.Applicative-import           Data.Foldable+import           Data.Foldable as F import qualified Data.List-import           Data.Maybe (fromMaybe)+import           Data.Maybe (fromMaybe, maybeToList) import           Data.Monoid import           Data.Traversable import           Lens.Family hiding (Constant)@@ -25,13 +25,18 @@ default (Int)  -- | The basic instructions that have nothing to do with control flow.-data Instruction reg-    = Add reg reg reg+data Instruction v+    = Add v v v+    | Offp v v v+    | Offlpi v     | Nop     deriving (Eq, Functor, Foldable, Traversable)  instance Show r => Show (Instruction r) where     show (Add x1 x2 x3) = "add " ++ show x1 ++ " " ++ show x2 ++ " " ++ show x3+    show (Offp x1 x2 x3) =+        "offp " ++ show x1 ++ " " ++ show x2 ++ " " ++ show x3+    show (Offlpi x) = "offlpi " ++ show x     show Nop = "nop"  -- | Tests used for branching (correspond to branching instructions)@@ -73,24 +78,24 @@  deriving instance Eq v => Eq (Node v e x) -instance Show v => Show (Node v e x) where-    show (Label l)         = show l ++ ":"-    show (Alloc x1 x2)     = "\t@alloc " ++-                             (case x1 of Just v -> " " ++ show v ; _ -> " _")-                             ++ " " ++ show x2-    show (Reclaim v)       = "\t@reclaim " ++ show v-    show (Instr i)         = "\t" ++ show i-    show (Call c l)        = "\t@call " ++ show c ++ " " ++ show l-    show (LoadConst _c v)  = "\t@lc " ++ show v -- ++ " " ++ show c-    show (Move x1 x2)      = "\t@mvrr " ++ show x1 ++ " " ++ show x2-    show (Copy x1 x2)      = "\t@cprr " ++ show x1 ++ " " ++ show x2-    show (Save src dst)    = "\t@save " ++ show src ++ " " ++ show dst-    show (Restore src dst) = "\t@restore " ++ show src ++ " " ++ show dst-    show (Trace str)       = "\tTRACE " ++ " " ++ show str-    show (Jump l)          = "\t@jmp " ++ show l-    show (Branch c v t f)  = "\t@b" ++ show c ++ " " ++ show v-                          ++ " " ++ show t ++ "; @jmp " ++ show f-    show (ReturnInstr regs i) = "\t@return " ++ show regs ++ " " ++ show i+instance (Show v, VarReg v) => Show (Node v e x) where+    show (Label l)         = "    label \"" ++ show l ++ "\" $ do"+    show (Alloc x1 x2)     = "        alloc " ++ show x1 ++ " " ++ show x2+    show (Reclaim v)       = "        reclaim " ++ show v+    show (Instr i)         = "        " ++ show i+    show (Call _ l)        = "        call " ++ show l+    show (LoadConst _c v)  = "        lc " ++ show v -- ++ " " ++ show c+    show (Move x1 x2)      = "        move " ++ show x1 ++ " " ++ show x2+    show (Copy x1 x2)      = "        copy " ++ show x1 ++ " " ++ show x2+    show (Save src dst)    = "        save " ++ show (varReg src) ++ " "+                          ++ show dst+    show (Restore src dst) = "        restore " ++ show src ++ " "+                          ++ show (varReg dst)+    show (Trace str)       = "        trace " ++ " " ++ show str+    show (Jump l)          = "        jump \"" ++ show l ++ "\""+    show (Branch _ v t f)  = "        branch " ++ show v+                          ++ " \"" ++ show t ++ "\" \"" ++ show f ++ "\""+    show (ReturnInstr _regs _i) = "        return_"  instance NonLocal (Node v) where   entryLabel (Label l) = l@@ -124,12 +129,24 @@ add :: v -> v -> v -> BodyNode (Node v) add x0 x1 x2 = bodyNode $ Instr (Add x0 x1 x2) +offp :: v -> v -> v -> BodyNode (Node v)+offp x0 x1 x2 = bodyNode $ Instr (Offp x0 x1 x2)++offlpi :: v -> BodyNode (Node v)+offlpi x = bodyNode $ Instr (Offlpi x)++alloc :: Maybe v -> v -> BodyNode (Node v)+alloc src dst = bodyNode $ Alloc src dst+ nop :: BodyNode (Node v) nop = bodyNode $ Instr Nop  move :: v -> v -> BodyNode (Node v) move x0 x1 = bodyNode $ Move x0 x1 +copy :: v -> v -> BodyNode (Node v)+copy = move+ call :: Int -> BodyNode (Node v) call dst = bodyNode $ Call InlineC dst @@ -145,9 +162,9 @@ trace :: String -> BodyNode (Node v) trace str = bodyNode $ Trace str -branch :: Test -> v -> String -> String -> EndNode (Node v)-branch tst v good bad =-    endNode $ Branch tst v <$> getLabel good <*> getLabel bad+branch :: v -> String -> String -> EndNode (Node v)+branch v good bad =+    endNode $ Branch Zero v <$> getLabel good <*> getLabel bad  return_ :: EndNode (Node v) return_ = endNode $ return $ ReturnInstr [] Nop@@ -156,21 +173,25 @@  instance Show a => Show (Assign a PhysReg) where     show (Assign v (-1)) = "<<v" ++ show v ++ ">>"-    -- show (Assign v r)    = "r" ++ show r ++ "|v" ++ show v-    show (Assign _ r)    = show r+    show (Assign v r)    = "r" ++ show r ++ "|v" ++ show v +class VarReg a where+    varReg :: a -> PhysReg++instance VarReg IRVar where+    varReg (PhysicalIV r) = r+    varReg v = error $ "No register known for " ++ show v++instance VarReg (Assign a PhysReg) where+    varReg (Assign _ b) = b+ data IRVar = PhysicalIV PhysReg | VirtualIV Int deriving Eq  instance Show IRVar where-    show (PhysicalIV r) = "r" ++ show r+    show (PhysicalIV r) = "pr" ++ show r     show (VirtualIV n)  = "v" ++ show n -instance NodeAlloc Node IRVar (Assign VarId PhysReg) where-    fromVar (PhysicalIV r) = Left r-    fromVar (VirtualIV n)  = Right n--    fromReg (Assign _ r) = r-+instance NodeAlloc (Node IRVar) (Node (Assign VarId PhysReg)) where     isCall (Call {}) = True     isCall _ = False @@ -191,20 +212,29 @@       where         go :: Node IRVar e x -> [VarInfo]         go (Label _)         = mempty+        go (Alloc msrc dst)  = F.concatMap (mkv Input) (maybeToList msrc) <>+                               mkv Output dst <>+                               [ vinfo Output (Left n) | n <- [2..16] ]+        go (Reclaim src)     = mkv Input src         go (Instr i)         = fromInstr i-        go (Jump _)          = mempty         go (Call _ _)        = mempty-        go (Move src dst)    = mkv Input src <> mkv Output dst         go (LoadConst _ v)   = mkv Output v-        go (Branch _ v _ _)  = mkv Input v+        go (Move src dst)    = mkv Input src <> mkv Output dst+        go (Copy src dst)    = mkv Input src <> mkv Output dst+        go (Save src _)      = mkv Input src+        go (Restore _ dst)   = mkv Output dst         go (Trace _)         = mempty+        go (Jump _)          = mempty+        go (Branch _ v _ _)  = mkv Input v         go (ReturnInstr _ i) = fromInstr i-        go n = error $ "getReferences: unhandled node: " ++ show n          fromInstr :: Instruction IRVar -> [VarInfo]         fromInstr Nop = mempty         fromInstr (Add s1 s2 d1) =             mkv Input s1 <> mkv Input s2 <> mkv Output d1+        fromInstr (Offp x1 x2 x3) =+            mkv Input x1 <> mkv Input x2 <> mkv Output x3+        fromInstr (Offlpi x) = mkv Input x <> mkv Output x          mkv :: VarKind -> IRVar -> [VarInfo]         mkv k (PhysicalIV n) = [vinfo k (Left n)]@@ -217,7 +247,7 @@             }      setRegisters m g = do-        for_ m $ \(v, r) -> setAssignment r v+        -- for_ m $ \(v, r) -> setAssignment r v         return $ over variables go g       where         go :: IRVar -> Assign VarId PhysReg@@ -225,7 +255,8 @@         go (VirtualIV n)  = Assign n (fromMaybe (-1) (Data.List.lookup n m))      mkMoveOps src dst = do-        vid <- getAssignment src+        -- vid <- getAssignment src+        let vid = 0         return [Move (Assign vid src) (Assign vid dst)]     mkSwapOps src dst =         liftA2 (++) (mkRestoreOps Nothing dst)@@ -234,10 +265,12 @@     mkSaveOps src dst = do         off <- getStackSlot dst         vid <- getAssignment src+        -- let vid = 0         return [Save (Assign vid src) off]     mkRestoreOps src dst = do         off <- getStackSlot src-        vid <- getAssignment dst+        -- vid <- getAssignment dst+        let vid = 0         return [Restore off (Assign vid dst)]      op1ToString = show@@ -245,47 +278,544 @@ var :: Int -> IRVar var = VirtualIV -v0  = var 0-v1  = var 1-v2  = var 2-v3  = var 3-v4  = var 4-v5  = var 5-v6  = var 6-v7  = var 7-v8  = var 8-v9  = var 9-v10 = var 10-v11 = var 11-v12 = var 12-v13 = var 13-v14 = var 14-v15 = var 15-v16 = var 16-v17 = var 17-v18 = var 18-v19 = var 19-v20 = var 20-v21 = var 21-v22 = var 22-v23 = var 23-v24 = var 24-v25 = var 25-v26 = var 26-v27 = var 27-v28 = var 28-v29 = var 29-v30 = var 30-v31 = var 31-v32 = var 32-v33 = var 33-v34 = var 34-v35 = var 35-v36 = var 36-v37 = var 37-v38 = var 38-v39 = var 39-v40 = var 40+v0   = var 0+v1   = var 1+v2   = var 2+v3   = var 3+v4   = var 4+v5   = var 5+v6   = var 6+v7   = var 7+v8   = var 8+v9   = var 9+v10  = var 10+v11  = var 11+v12  = var 12+v13  = var 13+v14  = var 14+v15  = var 15+v16  = var 16+v17  = var 17+v18  = var 18+v19  = var 19+v20  = var 20+v21  = var 21+v22  = var 22+v23  = var 23+v24  = var 24+v25  = var 25+v26  = var 26+v27  = var 27+v28  = var 28+v29  = var 29+v30  = var 30+v31  = var 31+v32  = var 32+v33  = var 33+v34  = var 34+v35  = var 35+v36  = var 36+v37  = var 37+v38  = var 38+v39  = var 39+v40  = var 40+v41  = var 41+v42  = var 42+v43  = var 43+v44  = var 44+v45  = var 45+v46  = var 46+v47  = var 47+v48  = var 48+v49  = var 49+v50  = var 50+v51  = var 51+v52  = var 52+v53  = var 53+v54  = var 54+v55  = var 55+v56  = var 56+v57  = var 57+v58  = var 58+v59  = var 59+v60  = var 60+v61  = var 61+v62  = var 62+v63  = var 63+v64  = var 64+v65  = var 65+v66  = var 66+v67  = var 67+v68  = var 68+v69  = var 69+v70  = var 70+v71  = var 71+v72  = var 72+v73  = var 73+v74  = var 74+v75  = var 75+v76  = var 76+v77  = var 77+v78  = var 78+v79  = var 79+v80  = var 80+v81  = var 81+v82  = var 82+v83  = var 83+v84  = var 84+v85  = var 85+v86  = var 86+v87  = var 87+v88  = var 88+v89  = var 89+v90  = var 90+v91  = var 91+v92  = var 92+v93  = var 93+v94  = var 94+v95  = var 95+v96  = var 96+v97  = var 97+v98  = var 98+v99  = var 99+v100 = var 100+v101 = var 101+v102 = var 102+v103 = var 103+v104 = var 104+v105 = var 105+v106 = var 106+v107 = var 107+v108 = var 108+v109 = var 109+v110 = var 110+v111 = var 111+v112 = var 112+v113 = var 113+v114 = var 114+v115 = var 115+v116 = var 116+v117 = var 117+v118 = var 118+v119 = var 119+v120 = var 120+v121 = var 121+v122 = var 122+v123 = var 123+v124 = var 124+v125 = var 125+v126 = var 126+v127 = var 127+v128 = var 128+v129 = var 129+v130 = var 130+v131 = var 131+v132 = var 132+v133 = var 133+v134 = var 134+v135 = var 135+v136 = var 136+v137 = var 137+v138 = var 138+v139 = var 139+v140 = var 140+v141 = var 141+v142 = var 142+v143 = var 143+v144 = var 144+v145 = var 145+v146 = var 146+v147 = var 147+v148 = var 148+v149 = var 149+v150 = var 150+v151 = var 151+v152 = var 152+v153 = var 153+v154 = var 154+v155 = var 155+v156 = var 156+v157 = var 157+v158 = var 158+v159 = var 159+v160 = var 160+v161 = var 161+v162 = var 162+v163 = var 163+v164 = var 164+v165 = var 165+v166 = var 166+v167 = var 167+v168 = var 168+v169 = var 169+v170 = var 170+v171 = var 171+v172 = var 172+v173 = var 173+v174 = var 174+v175 = var 175+v176 = var 176+v177 = var 177+v178 = var 178+v179 = var 179+v180 = var 180+v181 = var 181+v182 = var 182+v183 = var 183+v184 = var 184+v185 = var 185+v186 = var 186+v187 = var 187+v188 = var 188+v189 = var 189+v190 = var 190+v191 = var 191+v192 = var 192+v193 = var 193+v194 = var 194+v195 = var 195+v196 = var 196+v197 = var 197+v198 = var 198+v199 = var 199+v200 = var 200+v201 = var 201+v202 = var 202+v203 = var 203+v204 = var 204+v205 = var 205+v206 = var 206+v207 = var 207+v208 = var 208+v209 = var 209+v210 = var 210+v211 = var 211+v212 = var 212+v213 = var 213+v214 = var 214+v215 = var 215+v216 = var 216+v217 = var 217+v218 = var 218+v219 = var 219+v220 = var 220+v221 = var 221+v222 = var 222+v223 = var 223+v224 = var 224+v225 = var 225+v226 = var 226+v227 = var 227+v228 = var 228+v229 = var 229+v230 = var 230+v231 = var 231+v232 = var 232+v233 = var 233+v234 = var 234+v235 = var 235+v236 = var 236+v237 = var 237+v238 = var 238+v239 = var 239+v240 = var 240+v241 = var 241+v242 = var 242+v243 = var 243+v244 = var 244+v245 = var 245+v246 = var 246+v247 = var 247+v248 = var 248+v249 = var 249+v250 = var 250+v251 = var 251+v252 = var 252+v253 = var 253+v254 = var 254+v255 = var 255+v256 = var 256+v257 = var 257+v258 = var 258+v259 = var 259+v260 = var 260+v261 = var 261+v262 = var 262+v263 = var 263+v264 = var 264+v265 = var 265+v266 = var 266+v267 = var 267+v268 = var 268+v269 = var 269+v270 = var 270+v271 = var 271+v272 = var 272+v273 = var 273+v274 = var 274+v275 = var 275+v276 = var 276+v277 = var 277+v278 = var 278+v279 = var 279+v280 = var 280+v281 = var 281+v282 = var 282+v283 = var 283+v284 = var 284+v285 = var 285+v286 = var 286+v287 = var 287+v288 = var 288+v289 = var 289+v290 = var 290+v291 = var 291+v292 = var 292+v293 = var 293+v294 = var 294+v295 = var 295+v296 = var 296+v297 = var 297+v298 = var 298+v299 = var 299+v300 = var 300+v301 = var 301+v302 = var 302+v303 = var 303+v304 = var 304+v305 = var 305+v306 = var 306+v307 = var 307+v308 = var 308+v309 = var 309+v310 = var 310+v311 = var 311+v312 = var 312+v313 = var 313+v314 = var 314+v315 = var 315+v316 = var 316+v317 = var 317+v318 = var 318+v319 = var 319+v320 = var 320+v321 = var 321+v322 = var 322+v323 = var 323+v324 = var 324+v325 = var 325+v326 = var 326+v327 = var 327+v328 = var 328+v329 = var 329+v330 = var 330+v331 = var 331+v332 = var 332+v333 = var 333+v334 = var 334+v335 = var 335+v336 = var 336+v337 = var 337+v338 = var 338+v339 = var 339+v340 = var 340+v341 = var 341+v342 = var 342+v343 = var 343+v344 = var 344+v345 = var 345+v346 = var 346+v347 = var 347+v348 = var 348+v349 = var 349+v350 = var 350+v351 = var 351+v352 = var 352+v353 = var 353+v354 = var 354+v355 = var 355+v356 = var 356+v357 = var 357+v358 = var 358+v359 = var 359+v360 = var 360+v361 = var 361+v362 = var 362+v363 = var 363+v364 = var 364+v365 = var 365+v366 = var 366+v367 = var 367+v368 = var 368+v369 = var 369+v370 = var 370+v371 = var 371+v372 = var 372+v373 = var 373+v374 = var 374+v375 = var 375+v376 = var 376+v377 = var 377+v378 = var 378+v379 = var 379+v380 = var 380+v381 = var 381+v382 = var 382+v383 = var 383+v384 = var 384+v385 = var 385+v386 = var 386+v387 = var 387+v388 = var 388+v389 = var 389+v390 = var 390+v391 = var 391+v392 = var 392+v393 = var 393+v394 = var 394+v395 = var 395+v396 = var 396+v397 = var 397+v398 = var 398+v399 = var 399+v400 = var 400+v401 = var 401+v402 = var 402+v403 = var 403+v404 = var 404+v405 = var 405+v406 = var 406+v407 = var 407+v408 = var 408+v409 = var 409+v410 = var 410+v411 = var 411+v412 = var 412+v413 = var 413+v414 = var 414+v415 = var 415+v416 = var 416+v417 = var 417+v418 = var 418+v419 = var 419+v420 = var 420+v421 = var 421+v422 = var 422+v423 = var 423+v424 = var 424+v425 = var 425+v426 = var 426+v427 = var 427+v428 = var 428+v429 = var 429+v430 = var 430+v431 = var 431+v432 = var 432+v433 = var 433+v434 = var 434+v435 = var 435+v436 = var 436+v437 = var 437+v438 = var 438+v439 = var 439+v440 = var 440+v441 = var 441+v442 = var 442+v443 = var 443+v444 = var 444+v445 = var 445+v446 = var 446+v447 = var 447+v448 = var 448+v449 = var 449+v450 = var 450+v451 = var 451+v452 = var 452+v453 = var 453+v454 = var 454+v455 = var 455+v456 = var 456+v457 = var 457+v458 = var 458+v459 = var 459+v460 = var 460+v461 = var 461+v462 = var 462+v463 = var 463+v464 = var 464+v465 = var 465+v466 = var 466+v467 = var 467+v468 = var 468+v469 = var 469+v470 = var 470+v471 = var 471+v472 = var 472+v473 = var 473+v474 = var 474+v475 = var 475+v476 = var 476+v477 = var 477+v478 = var 478+v479 = var 479+v480 = var 480+v481 = var 481+v482 = var 482+v483 = var 483+v484 = var 484+v485 = var 485+v486 = var 486+v487 = var 487+v488 = var 488+v489 = var 489+v490 = var 490+v491 = var 491+v492 = var 492+v493 = var 493+v494 = var 494+v495 = var 495+v496 = var 496+v497 = var 497+v498 = var 498+v499 = var 499+v500 = var 500++physreg :: PhysReg -> IRVar+physreg = PhysicalIV++pr0  = physreg 0+pr1  = physreg 1+pr2  = physreg 2+pr3  = physreg 3+pr4  = physreg 4+pr5  = physreg 5+pr6  = physreg 6+pr7  = physreg 7+pr8  = physreg 8+pr9  = physreg 9+pr10 = physreg 10+pr11 = physreg 11+pr12 = physreg 12+pr13 = physreg 13+pr14 = physreg 14+pr15 = physreg 15+pr16 = physreg 16+pr17 = physreg 17+pr18 = physreg 18+pr19 = physreg 19+pr20 = physreg 20+pr21 = physreg 21+pr22 = physreg 22+pr23 = physreg 23+pr24 = physreg 24+pr25 = physreg 25+pr26 = physreg 26+pr27 = physreg 27+pr28 = physreg 28+pr29 = physreg 29+pr30 = physreg 30+pr31 = physreg 31+pr32 = physreg 32  reg :: PhysReg -> IRVar -> Assign VarId PhysReg reg _ (PhysicalIV _) = error "Don't use reg to reference a literal register"
+ test/Generated.hs view
@@ -0,0 +1,114 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}++{-# OPTIONS_GHC -fno-warn-orphans #-}++module Generated (generatedTests) where++import           Assembly+import           Compiler.Hoopl hiding ((<*>))+import           Control.Applicative+import           Control.Exception (evaluate)+import           Control.Monad+import qualified Data.IntMap as IM+import qualified Data.IntSet as IS+import           Data.List (intercalate, isInfixOf)+import           LinearScan.Hoopl+import           Test.FuzzCheck as F hiding (branch)+import           Test.Hspec+import           Test.QuickCheck hiding (label)+import           Unsafe.Coerce++instance Arbitrary IRVar where+    arbitrary = sized $ \n -> frequency+        [ (1, PhysicalIV <$> choose (0,31))+        , (50, VirtualIV <$> choose (0,n))+        ]++instance Arbitrary (Instruction IRVar) where+    arbitrary = frequency+        [ (3, Add <$> arbitrary <*> arbitrary <*> arbitrary)+        , (1, Offp <$> arbitrary <*> arbitrary <*> arbitrary)+        , (1, Offlpi <$> arbitrary)+        , (1, pure Nop)+        ]++instance Arbitrary (Node IRVar O C) where+    arbitrary = sized $ \n -> frequency+        [ (1, Jump <$> unsafeCoerce <$> (choose (0,n) :: Gen Int))+        , (1, Branch <$> pure Zero+                     <*> arbitrary+                     <*> (unsafeCoerce <$> (choose (0,n) :: Gen Int))+                     <*> (unsafeCoerce <$> (choose (0,n) :: Gen Int)))+        , (1, ReturnInstr [] <$> arbitrary)+        ]++instance Arbitrary (Node IRVar O O) where+    arbitrary = sized $ \n -> frequency+        [ (1, Alloc <$> arbitrary <*> arbitrary)+        -- , (1, Reclaim <$> arbitrary)+        , (40, Instr <$> arbitrary)+        , (20, Call InlineC <$> choose (0,n))+        , (30, LoadConst <$> arbitrary <*> arbitrary)+        , (50, Move <$> arbitrary <*> arbitrary)+        , (25, Copy <$> arbitrary <*> arbitrary)+        -- , (0, Save <$> arbitrary <*> arbitrary)+        -- , (0, Restore <$> arbitrary <*> arbitrary)+        -- , (0, pure $ Trace "tracer")+        ]++-- instance Arbitrary (Block (Node IRVar) C C) where+--     arbitrary = BlockCC (Label (unsafeCoerce (0 :: Int)))+--                     <$> arbitrary <*> arbitrary++-- instance Arbitrary (Block (Node IRVar) C O) where+--     arbitrary = BlockCO (Label (unsafeCoerce (0 :: Int))) <$> arbitrary++instance Arbitrary (Block (Node IRVar) O C) where+    arbitrary = BlockOC <$> arbitrary <*> arbitrary++instance Arbitrary (Block (Node IRVar) O O) where+    arbitrary = frequency+        [ (2, pure BNil)+        , (1, BMiddle <$> arbitrary)+        , (1, BCat <$> arbitrary <*> arbitrary)+        , (2, BSnoc <$> arbitrary <*> arbitrary)+        , (3, BCons <$> arbitrary <*> arbitrary)+        ]++instance Arbitrary (Graph' Block (Node IRVar) C C) where+    arbitrary = sized $ \n ->+        GMany NothingO+            <$> (unsafeCoerce+                 <$> IM.fromList+                 <$> (forM [1..n] $ \(i :: Int) ->+                       (,) <$> pure i+                           <*> (BlockCC (Label (unsafeCoerce i))+                                    <$> arbitrary <*> arbitrary+                                :: Gen (Block (Node IRVar) C C))))+            <*> pure NothingO++instance Show (Graph' Block (Node IRVar) C C) where+    show = showGraph show++generatedTests :: SpecWith ()+generatedTests =+  it "Handles generated tests" $+    (\a -> fuzzCheck' a 10000 (return ())) $ do+      (graph :: Graph (Node IRVar) C C) <- "create graph" ?> pure <$> rand+      let GMany _ body _ = graph+      let entry = unsafeCoerce+                    (head (IS.elems (unsafeCoerce+                                     (externalEntryLabels body))))+      case allocateHoopl 32 0 8 entry graph of+          Left err+              | any ("Cannot insert interval onto unhandled list"+                     `isInfixOf`) err ->+                  True `shouldBe` True+              | otherwise ->+                  error $ "Allocation failed: " ++ intercalate "\n" err+          Right graph' -> do+              let g = showGraph show graph'+              _ <- evaluate (length g)+              return ()+              -- putStrLn $ "---- Compiled  ----\n" ++ g
test/Main.hs view
@@ -1,8 +1,14 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+ module Main where  import AsmTest import Assembly+-- import Generated import LinearScan.Hoopl.DSL+-- import Programs.Blocked+import Programs.Exhaustion import Test.Hspec  -- | The objective of these tests is to present a program to the register@@ -17,6 +23,12 @@   describe "Call tests" callTests   describe "Loop tests" loopTests +  describe "Program tests" $ do+    it "Near exhaustion program" $ asmTest_ 32 exhaustion1+    -- it "Blocked register program" $ asmTest_ 32 regBlocked++  -- describe "Generated tests" generatedTests+ sanityTests :: SpecWith () sanityTests = do   it "Single instruction" $ asmTest 32@@ -36,9 +48,9 @@         return_) $      label "entry" $ do-        add (r0 v0) (r1 v0) (r2 v0)-        add (r0 v0) (r1 v0) (r2 v0)-        add (r0 v0) (r1 v0) (r2 v0)+        add (r0 v0) (r1 v1) (r2 v2)+        add (r0 v0) (r1 v1) (r2 v2)+        add (r0 v0) (r1 v1) (r2 v2)         return_    it "Multiple instructions" $ asmTest 32@@ -49,9 +61,9 @@         return_) $      label "entry" $ do-        add (r0 v0) (r1 v0) (r2 v0)-        add (r0 v0) (r1 v0) (r3 v0)-        add (r0 v0) (r1 v0) (r2 v0)+        add (r0 v0) (r1 v1) (r2 v2)+        add (r0 v0) (r1 v1) (r3 v3)+        add (r0 v0) (r1 v1) (r2 v2)         return_    it "More variables used than registers" $ asmTest 6@@ -75,29 +87,29 @@      label "entry" $ do         lc (r0 v0)-        lc (r1 v0)-        lc (r2 v0)-        lc (r3 v0)-        lc (r4 v0)-        lc (r5 v0)-        save (r4 v0) 0-        lc (r4 v0)-        save (r4 v0) 8-        lc (r4 v0)-        save (r4 v0) 16-        lc (r4 v0)-        save (r4 v0) 24-        lc (r4 v0)-        add (r0 v0) (r1 v0) (r0 v0)-        add (r2 v0) (r3 v0) (r1 v0)+        lc (r1 v1)+        lc (r2 v3)+        lc (r3 v4)+        lc (r4 v6)+        lc (r5 v7)+        save (r5 v0) 0+        lc (r5 v9)+        save (r5 v0) 8+        lc (r5 v10)+        save (r5 v0) 16+        lc (r5 v12)+        save (r5 v0) 24+        lc (r5 v13)+        add (r0 v0) (r1 v1) (r0 v2)+        add (r2 v3) (r3 v4) (r1 v5)         restore 0 (r3 v0)-        add (r3 v0) (r5 v0) (r2 v0)+        add (r4 v6) (r3 v7) (r2 v8)         save (r0 v0) 32-        restore 8 (r5 v0)+        restore 8 (r4 v0)         restore 16 (r0 v0)-        add (r5 v0) (r0 v0) (r3 v0)-        restore 24 (r5 v0)-        add (r5 v0) (r4 v0) (r0 v0)+        add (r4 v9) (r0 v10) (r3 v11)+        restore 24 (r4 v0)+        add (r4 v12) (r5 v13) (r0 v14)         return_    it "Single long-lived variable" $ asmTest 32@@ -109,10 +121,10 @@         return_) $      label "entry" $ do-        add (r0 v0) (r1 v0) (r1 v0)-        add (r0 v0) (r2 v0) (r2 v0)-        add (r0 v0) (r3 v0) (r3 v0)-        add (r0 v0) (r4 v0) (r0 v0)+        add (r0 v0) (r1 v1) (r1 v2)+        add (r0 v0) (r2 v4) (r2 v5)+        add (r0 v0) (r3 v7) (r3 v8)+        add (r0 v0) (r4 v10) (r0 v11)         return_    it "Two long-lived variables" $ asmTest 32@@ -124,10 +136,10 @@         return_) $      label "entry" $ do-        add (r0 v0) (r1 v0) (r1 v0)-        add (r0 v0) (r2 v0) (r3 v0)-        add (r0 v0) (r2 v0) (r4 v0)-        add (r0 v0) (r2 v0) (r0 v0)+        add (r0 v0) (r1 v1) (r1 v2)+        add (r0 v0) (r2 v4) (r3 v5)+        add (r0 v0) (r2 v4) (r4 v8)+        add (r0 v0) (r2 v4) (r0 v11)         return_    it "One variable with a long interval" $ asmTest 32@@ -147,18 +159,18 @@         return_) $      label "entry" $ do-        add (r0 v0) (r1 v0) (r1 v0)-        add (r2 v0) (r3 v0) (r2 v0)-        add (r4 v0) (r5 v0) (r3 v0)-        add (r6 v0) (r7 v0) (r4 v0)-        add (r8 v0) (r9 v0) (r5 v0)-        add (r10 v0) (r11 v0) (r6 v0)-        add (r12 v0) (r13 v0) (r7 v0)-        add (r14 v0) (r15 v0) (r8 v0)-        add (r16 v0) (r17 v0) (r9 v0)-        add (r18 v0) (r19 v0) (r10 v0)-        add (r20 v0) (r21 v0) (r11 v0)-        add (r0 v0) (r22 v0) (r0 v0)+        add (r0  v0)  (r1  v1)  (r1  v2)+        add (r2  v3)  (r3  v4)  (r2  v5)+        add (r4  v6)  (r5  v7)  (r3  v8)+        add (r6  v9)  (r7  v10) (r4  v11)+        add (r8  v12) (r9  v13) (r5  v14)+        add (r10 v15) (r11 v16) (r6  v17)+        add (r12 v18) (r13 v19) (r7  v20)+        add (r14 v21) (r15 v22) (r8  v23)+        add (r16 v24) (r17 v25) (r9  v26)+        add (r18 v27) (r19 v28) (r10 v29)+        add (r20 v30) (r21 v31) (r11 v32)+        add (r0  v0)  (r22 v34) (r0  v35)         return_    it "Many variables with long intervals" $ asmTest 32@@ -186,31 +198,31 @@         return_) $      label "entry" $ do-        add (r0 v0) (r1 v0) (r20 v0)-        add (r2 v0) (r3 v0) (r21 v0)-        add (r4 v0) (r5 v0) (r22 v0)-        add (r6 v0) (r7 v0) (r23 v0)-        add (r8 v0) (r9 v0) (r24 v0)-        add (r10 v0) (r11 v0) (r25 v0)-        add (r12 v0) (r13 v0) (r26 v0)-        add (r14 v0) (r15 v0) (r27 v0)-        add (r16 v0) (r17 v0) (r28 v0)-        add (r18 v0) (r19 v0) (r29 v0)-        add (r0 v0) (r1 v0) (r20 v0)-        add (r2 v0) (r3 v0) (r21 v0)-        add (r4 v0) (r5 v0) (r22 v0)-        add (r6 v0) (r7 v0) (r23 v0)-        add (r8 v0) (r9 v0) (r24 v0)-        add (r10 v0) (r11 v0) (r25 v0)-        add (r12 v0) (r13 v0) (r26 v0)-        add (r14 v0) (r15 v0) (r27 v0)-        add (r16 v0) (r17 v0) (r28 v0)-        add (r18 v0) (r19 v0) (r29 v0)+        add (r0  v0)  (r1 v1)   (r20 v2)+        add (r2  v3)  (r3 v4)   (r21 v5)+        add (r4  v6)  (r5 v7)   (r22 v8)+        add (r6  v9)  (r7 v10)  (r23 v11)+        add (r8  v12) (r9 v13)  (r24 v14)+        add (r10 v15) (r11 v16) (r25 v17)+        add (r12 v18) (r13 v19) (r26 v20)+        add (r14 v21) (r15 v22) (r27 v23)+        add (r16 v24) (r17 v25) (r28 v26)+        add (r18 v27) (r19 v28) (r29 v29)+        add (r0  v0)  (r1 v1)   (r20 v2)+        add (r2  v3)  (r3 v4)   (r21 v5)+        add (r4  v6)  (r5 v7)   (r22 v8)+        add (r6  v9)  (r7 v10)  (r23 v11)+        add (r8  v12) (r9 v13)  (r24 v14)+        add (r10 v15) (r11 v16) (r25 v17)+        add (r12 v18) (r13 v19) (r26 v20)+        add (r14 v21) (r15 v22) (r27 v23)+        add (r16 v24) (r17 v25) (r28 v26)+        add (r18 v27) (r19 v28) (r29 v29)         return_  spillTests :: SpecWith () spillTests = do-  it "Spilling one variable" $ asmTest 32+  it "No spilling necessary" $ asmTest 32     (label "entry" $ do         add v0   v1  v2         add v3   v4  v5@@ -223,6 +235,7 @@         add v24 v25 v26         add v27 v28 v29         add v30 v31 v32+        add v33 v34 v35         add v0   v1  v2         add v3   v4  v5         add v6   v7  v8@@ -234,43 +247,106 @@         add v24 v25 v26         add v27 v28 v29         add v30 v31 v32+        add v33 v34 v35         return_) $      label "entry" $ do-        add (r0 v0) (r1 v0) (r22 v0)-        add (r2 v0) (r3 v0) (r23 v0)-        add (r4 v0) (r5 v0) (r24 v0)-        add (r6 v0) (r7 v0) (r25 v0)-        add (r8 v0) (r9 v0) (r26 v0)-        add (r10 v0) (r11 v0) (r27 v0)-        add (r12 v0) (r13 v0) (r28 v0)-        add (r14 v0) (r15 v0) (r29 v0)-        add (r16 v0) (r17 v0) (r30 v0)-        add (r18 v0) (r19 v0) (r31 v0)+        add (r0  v0) (r1 v1) (r24 v2)+        add (r2  v3) (r3 v4) (r25 v5)+        add (r4  v6) (r5 v7) (r26 v8)+        add (r6  v9) (r7 v10) (r27 v11)+        add (r8  v12) (r9 v13) (r28 v14)+        add (r10 v15) (r11 v16) (r29 v17)+        add (r12 v18) (r13 v19) (r30 v20)+        add (r14 v21) (r15 v22) (r31 v23)+        save (r31 v0) 0         -- jww (2015-05-26): These saves are unnecessary+        add (r16 v24) (r17 v25) (r31 v26)+        save (r31 v0) 8+        add (r18 v27) (r19 v28) (r31 v29)+        save (r31 v0) 16+        add (r20 v30) (r21 v31) (r31 v32)+        save (r31 v0) 24+        add (r22 v33) (r23 v34) (r31 v35)+        add (r0 v0) (r1 v1) (r24 v2)+        add (r2 v3) (r3 v4) (r25 v5)+        add (r4 v6) (r5 v7) (r26 v8)+        add (r6 v9) (r7 v10) (r27 v11)+        add (r8 v12) (r9 v13) (r28 v14)+        add (r10 v15) (r11 v16) (r29 v17)+        add (r12 v18) (r13 v19) (r30 v20)+        restore 0 (r0 v0)+        add (r14 v21) (r15 v22) (r0 v23)+        restore 8 (r1 v31)+        add (r16 v24) (r17 v25) (r1 v26)+        restore 16 (r2 v0)+        add (r18 v27) (r19 v28) (r2 v29)+        restore 24 (r3 v0)+        add (r20 v30) (r21 v31) (r3 v32)+        add (r22 v33) (r23 v34) (r31 v35)+        return_ +  it "Spilling one variable" $ asmTest 32+    (label "entry" $ do+        add v0   v1  v2+        add v3   v4  v5+        add v6   v7  v8+        add v9  v10 v11+        add v12 v13 v14+        add v15 v16 v17+        add v18 v19 v20+        add v21 v22 v23+        add v24 v25 v26+        add v27 v28 v29+        add v30 v31 v32+        add v0   v1  v2+        add v3   v4  v5+        add v6   v7  v8+        add v9  v10 v11+        add v12 v13 v14+        add v15 v16 v17+        add v18 v19 v20+        add v21 v22 v23+        add v24 v25 v26+        add v27 v29 v28+        add v30 v32 v31+        return_) $++    label "entry" $ do+        add (r0  v0)  (r1  v1)  (r22 v2)+        add (r2  v3)  (r3  v4)  (r23 v5)+        add (r4  v6)  (r5  v7)  (r24 v8)+        add (r6  v9)  (r7  v10) (r25 v11)+        add (r8  v12) (r9  v13) (r26 v14)+        add (r10 v15) (r11 v16) (r27 v17)+        add (r12 v18) (r13 v19) (r28 v20)+        add (r14 v21) (r15 v22) (r29 v23)+        add (r16 v24) (r17 v25) (r30 v26)+        add (r18 v27) (r19 v28) (r31 v29)+         -- When we reach the 32nd variable considered (which happens to be         -- v30), we must spill a register because there are not 32 registers.         -- So we pick the first register, counting from 0, whose next use-        -- position is the furthest from this position.  That happens to be-        -- 18, which is next used at position 41.-        save (r18 v0) 0-        add (r20 v0) (r21 v0) (r18 v0)-        add (r0 v0) (r1 v0) (r22 v0)-        add (r2 v0) (r3 v0) (r23 v0)-        add (r4 v0) (r5 v0) (r24 v0)-        add (r6 v0) (r7 v0) (r25 v0)-        add (r8 v0) (r9 v0) (r26 v0)-        add (r10 v0) (r11 v0) (r27 v0)-        add (r12 v0) (r13 v0) (r28 v0)-        add (r14 v0) (r15 v0) (r29 v0)-        add (r16 v0) (r17 v0) (r30 v0)+        -- position is the furthest from this position.+        save (r31 v0) 0 -        -- When it comes time to reload v29 (which had been allocated to 18),-        -- we pick the first available register which happens to be 0 in this-        -- case.+        add (r20 v30) (r21 v31) (r31 v32)++        add (r0 v0)   (r1 v1)   (r22 v2)+        add (r2 v3)   (r3 v4)   (r23 v5)+        add (r4 v6)   (r5 v7)   (r24 v8)+        add (r6 v9)   (r7 v10)  (r25 v11)+        add (r8 v12)  (r9 v13)  (r26 v14)+        add (r10 v15) (r11 v16) (r27 v17)+        add (r12 v18) (r13 v19) (r28 v20)+        add (r14 v21) (r15 v22) (r29 v23)+        add (r16 v24) (r17 v25) (r30 v26)++        -- When it comes time to reload v29, we pick the first available+        -- register.         restore 0 (r0 v0)-        add (r0 v0) (r19 v0) (r31 v0)-        add (r20 v0) (r21 v0) (r18 v0)++        add (r18 v27) (r0 v29) (r19 v28)+        add (r20 v30) (r31 v32) (r21 v31)         return_    it "Higher register pressure" $ asmTest 3@@ -289,23 +365,21 @@      label "entry" $ do         lc (r0 v0)-        lc (r1 v0)-        add (r0 v0) (r1 v0) (r2 v0)-        add (r2 v0) (r1 v0) (r0 v0)-        save (r1 v0) 0-        add (r0 v0) (r2 v0) (r1 v0)-        save (r2 v0) 8-        add (r1 v0) (r0 v0) (r2 v0)-        save (r1 v0) 16-        restore 8 (r1 v0)-        add (r1 v0) (r0 v0) (r0 v0)-        save (r0 v0) 24-        restore 16 (r0 v0)-        add (r0 v0) (r2 v0) (r1 v0)-        restore 24 (r2 v0)-        add (r2 v0) (r1 v0) (r0 v0)-        restore 0 (r1 v0)-        add (r0 v0) (r1 v0) (r0 v0)+        lc (r1 v1)+        add (r0 v0) (r1 v1) (r2 v2)+        add (r2 v2) (r1 v1) (r0 v3)+        save (r1 v1) 0+        add (r0 v3) (r2 v2) (r1 v4)+        save (r2 v2) 8+        add (r1 v4) (r0 v3) (r2 v5)+        save (r2 v5) 16+        restore 8 (r2 v2)+        add (r2 v2) (r0 v3) (r0 v6)+        restore 16 (r2 v5)+        add (r1 v4) (r2 v5) (r1 v7)+        add (r0 v6) (r1 v7) (r0 v8)+        restore 0 (r1 v1)+        add (r0 v8) (r1 v1) (r0 v0)         return_    it "Inserts necessary saves and restores" $ asmTest 4@@ -324,17 +398,17 @@      label "entry" $ do         lc (r0 v0)-        lc (r1 v0)-        add (r0 v0) (r1 v0) (r2 v0)-        add (r2 v0) (r1 v0) (r3 v0)-        add (r3 v0) (r2 v0) (r0 v0)+        lc (r1 v1)+        add (r0 v0) (r1 v1) (r2 v2)+        add (r2 v2) (r1 v1) (r3 v3)         save (r1 v0) 0-        add (r0 v0) (r3 v0) (r1 v0)-        add (r2 v0) (r3 v0) (r2 v0)-        add (r0 v0) (r1 v0) (r0 v0)-        add (r2 v0) (r0 v0) (r0 v0)+        add (r3 v3) (r2 v2) (r1 v4)+        add (r1 v4) (r3 v3) (r0 v5)+        add (r2 v2) (r3 v3) (r2 v6)+        add (r1 v4) (r0 v5) (r0 v7)+        add (r2 v6) (r0 v7) (r0 v8)         restore 0 (r1 v0)-        add (r0 v0) (r1 v0) (r0 v0)+        add (r0 v8) (r1 v1) (r0 v0)         return_  blockTests :: SpecWith ()@@ -356,18 +430,18 @@             return_) $      do label "entry" $ do-           add (r0 v0) (r1 v0) (r0 v0)+           add (r0 v0) (r1 v1) (r0 v2)            jump "L2"         label "L2" $ do-           add (r0 v0) (r2 v0) (r1 v0)-           add (r0 v0) (r1 v0) (r1 v0)+           add (r0 v2) (r2 v3) (r1 v4)+           add (r0 v2) (r1 v4) (r1 v5)            jump "L3"         label "L3" $ do-           add (r0 v0) (r1 v0) (r1 v0)-           add (r0 v0) (r1 v0) (r1 v0)-           add (r0 v0) (r1 v0) (r0 v0)+           add (r0 v2) (r1 v5) (r1 v6)+           add (r0 v2) (r1 v6) (r1 v7)+           add (r0 v2) (r1 v7) (r0 v8)            return_    it "Inserts resolving moves" $ asmTest 3@@ -375,7 +449,7 @@             lc v0             lc v1             add v0 v1 v2-            branch Zero v2 "B3" "B2"+            branch v2 "B3" "B2"          label "B2" $ do             add v1 v2 v3@@ -395,35 +469,35 @@      do label "entry" $ do            lc (r0 v0)-           lc (r1 v0)-           add (r0 v0) (r1 v0) (r2 v0)-           branch Zero (r2 v0) "B2" "B3"+           lc (r1 v1)+           add (r0 v0) (r1 v1) (r2 v2)+           branch (r2 v2) "B3" "B2"         label "B2" $ do-           move (r1 v0) (r0 v0)-           add (r0 v0) (r2 v0) (r1 v0)+           save (r0 v0) 0+           add (r1 v1) (r2 v2) (r0 v3)+           restore 0 (r1 v0)+           add (r1 v0) (r0 v3) (r2 v4)+           save (r0 v3) 8+           add (r1 v0) (r2 v4) (r0 v5)+           add (r2 v4) (r0 v5) (r0 v6)+           restore 8 (r2 v3)+           add (r0 v6) (r2 v3) (r0 v7)            jump "B4"         label "B3" $ do-           save (r0 v0) 0-           add (r1 v0) (r2 v0) (r0 v0)-           restore 0 (r2 v0)-           add (r2 v0) (r0 v0) (r1 v0)-           save (r0 v0) 8-           add (r2 v0) (r1 v0) (r0 v0)-           add (r1 v0) (r0 v0) (r0 v0)-           restore 8 (r1 v0)-           add (r0 v0) (r1 v0) (r0 v0)+           move (r2 v0) (r0 v0)+           add (r1 v1) (r0 v2) (r2 v3)            jump "B4"         label "B4" $ do-           add (r1 v0) (r1 v0) (r0 v0)+           add (r2 v3) (r2 v3) (r0 v0)            return_    it "When resolving moves are not needed" $ asmTest 4     (do label "entry" $ do             add v0 v1 v2-            branch Zero v2 "B3" "B2"+            branch v2 "B3" "B2"          label "B2" $ do             add v1 v2 v3@@ -442,23 +516,23 @@             return_) $      do label "entry" $ do-           add (r0 v0) (r1 v0) (r2 v0)-           branch Zero (r2 v0) "B2" "B3"+           add (r0 v0) (r1 v1) (r2 v2)+           branch (r2 v2) "B2" "B3"         label "B2" $ do-           add (r1 v0) (r2 v0) (r3 v0)-           add (r0 v0) (r0 v0) (r1 v0)-           add (r0 v0) (r0 v0) (r2 v0)-           add (r0 v0) (r1 v0) (r1 v0)-           add (r0 v0) (r2 v0) (r1 v0)+           add (r1 v1) (r2 v2) (r3 v3)+           add (r0 v0) (r0 v0) (r1 v4)+           add (r0 v0) (r0 v0) (r2 v5)+           add (r0 v0) (r1 v4) (r1 v6)+           add (r0 v0) (r2 v5) (r1 v6)            jump "B4"         label "B3" $ do-           add (r1 v0) (r2 v0) (r3 v0)+           add (r1 v1) (r2 v2) (r3 v3)            jump "B4"         label "B4" $ do-           add (r3 v0) (r3 v0) (r0 v0)+           add (r3 v3) (r3 v3) (r0 v0)            return_    it "Another resolution case" $ asmTest 4@@ -480,7 +554,7 @@             jump "L6"          label "L6" $-            branch Zero v4 "L3" "L2"+            branch v4 "L3" "L2"          label "L2" $ do             lc v21@@ -491,53 +565,49 @@             jump "L6") $      do label "entry" $ do-           lc (r0 v0)-           lc (r1 v0)-           lc (r2 v0)-           lc (r3 v0)-           save (r3 v0) 0+           lc (r0 v3)+           lc (r1 v4)+           lc (r2 v15)+           lc (r3 v20)+           save (r3 v20) 0            jump "L3"         label "L3" $ do-           move (r0 v0) (r3 v0)-           move (r3 v0) (r3 v0)-           move (r3 v0) (r3 v0)-           move (r3 v0) (r3 v0)-           move (r3 v0) (r3 v0)-           save (r0 v0) 8-           lc (r0 v0)-           save (r0 v0) 16-           move (r2 v0) (r0 v0)+           move (r0 v3) (r3 v9)+           move (r3 v9) (r3 v11)+           move (r3 v11) (r3 v10)+           move (r3 v10) (r3 v12)+           move (r3 v12) (r3 v13)+           save (r0 v3) 8+           lc (r0 v14)+           save (r0 v14) 16+           move (r2 v15) (r0 v5)            jump "L6"         label "L2" $ do-           lc (r3 v0)-           save (r2 v0) 24-           move (r3 v0) (r2 v0)-           move (r0 v0) (r1 v0)-           save (r0 v0) 32-           lc (r0 v0)-           save (r1 v0) 48-           save (r0 v0) 40-           restore 0 (r1 v0)-           move (r1 v0) (r0 v0)-           save (r1 v0) 0-           restore 24 (r2 v0)-           restore 32 (r0 v0)-           restore 48 (r1 v0)+           lc (r3 v21)+           save (r2 v15) 24+           move (r3 v21) (r2 v18)+           move (r0 v5) (r1 v4)+           save (r3 v21) 32+           lc (r3 v19)+           save (r2 v18) 48+           save (r3 v19) 40+           restore 0 (r2 v20)+           move (r2 v20) (r3 v17)+           save (r2 v20) 0+           restore 24 (r2 v15)            jump "L6"         label "L6" $-           branch Zero (r1 v0) "L5" "L2"+           branch (r1 v4) "L5" "L2"         label "L5" $ do-           save (r1 v0) 48-           restore 0 (r1 v0)-           save (r2 v0) 24-           save (r1 v0) 0-           restore 24 (r2 v0)-           restore 48 (r1 v0)-           restore 8 (r0 v0)+           save (r2 v15) 24+           restore 0 (r2 v20)   -- jww (2015-05-26): should be unnecessary+           save (r2 v20) 0+           restore 24 (r2 v15)+           restore 8 (r0 v3)            jump "L3"  callTests :: SpecWith ()@@ -559,24 +629,24 @@      label "entry" $ do         lc (r0 v0)-        lc (r1 v1)-        add (r0 v0) (r1 v1) (r2 v2)-        add (r2 v2) (r1 v1) (r3 v3)-        add (r3 v3) (r2 v2) (r0 v4)-        save (r1 v1) 0-        add (r0 v4) (r3 v3) (r1 v5)-        save (r2 v2) 32-        save (r3 v3) 24-        save (r0 v4) 16-        save (r1 v5) 8+        lc (r3 v1)+        add (r0 v0) (r3 v1) (r2 v2)+        add (r2 v2) (r3 v1) (r1 v3)+        save (r3 v1) 0+        add (r1 v3) (r2 v2) (r3 v4)+        save (r2 v2) 8+        add (r3 v4) (r1 v3) (r2 v5)+        save (r1 v3) 32+        save (r3 v4) 24+        save (r2 v5) 16         call 1000-        restore 32 (r1 v2)-        restore 24 (r2 v3)-        add (r1 v2) (r2 v3) (r0 v6)-        restore 16 (r2 v4)-        restore 8 (r3 v5)-        add (r2 v4) (r3 v5) (r1 v7)-        add (r0 v6) (r1 v7) (r0 v8)+        restore 8 (r2 v2)+        restore 32 (r3 v3)+        add (r2 v2) (r3 v3) (r1 v6)+        restore 24 (r3 v4)+        restore 16 (r0 v5)+        add (r3 v4) (r0 v5) (r2 v7)+        add (r1 v6) (r2 v7) (r0 v8)         restore 0 (r1 v1)         add (r0 v8) (r1 v1) (r0 v0)         return_@@ -590,11 +660,11 @@          label "B1" $ do             trace "B1"-            branch Zero v1 "B3" "B2"+            branch v1 "B3" "B2"          label "B2" $ do             trace "B2"-            branch Zero v1 "B5" "B4"+            branch v1 "B5" "B4"          label "B3" $ do             trace "B3"@@ -602,7 +672,7 @@          label "B4" $ do             trace "B4"-            branch Zero v1 "B7" "B6"+            branch v1 "B7" "B6"          label "B5" $ do             trace "B5"@@ -616,29 +686,29 @@             trace "B7"             jump "B1") $ -    "L1:\n\-\\tTRACE  \"B0\"\n\-\\t@jmp L2\n\-\L2:\n\-\\tTRACE  \"B1\"\n\-\\t@bZero 0 L3; @jmp L4\n\-\L3:\n\-\\tTRACE  \"B3\"\n\-\\t@jmp L2\n\-\L4:\n\-\\tTRACE  \"B2\"\n\-\\t@bZero 0 L5; @jmp L9\n\-\L5:\n\-\\tTRACE  \"B5\"\n\-\\t@return [] nop\n\-\L6:\n\-\\tTRACE  \"B4\"\n\-\\t@bZero 0 L7; @jmp L8\n\-\L7:\n\-\\tTRACE  \"B7\"\n\-\\t@jmp L2\n\-\L8:\n\-\\tTRACE  \"B6\"\n\-\\t@jmp L6\n\-\L9:\n\-\\t@jmp L6\n"+    Just "    label \"L1\" $ do\n\+\        trace  \"B0\"\n\+\        jump \"L2\"\n\+\    label \"L2\" $ do\n\+\        trace  \"B1\"\n\+\        branch r0|v1 \"L3\" \"L4\"\n\+\    label \"L3\" $ do\n\+\        trace  \"B3\"\n\+\        jump \"L2\"\n\+\    label \"L4\" $ do\n\+\        trace  \"B2\"\n\+\        branch r0|v1 \"L5\" \"L9\"\n\+\    label \"L5\" $ do\n\+\        trace  \"B5\"\n\+\        return_\n\+\    label \"L6\" $ do\n\+\        trace  \"B4\"\n\+\        branch r0|v1 \"L7\" \"L8\"\n\+\    label \"L7\" $ do\n\+\        trace  \"B7\"\n\+\        jump \"L2\"\n\+\    label \"L8\" $ do\n\+\        trace  \"B6\"\n\+\        jump \"L6\"\n\+\    label \"L9\" $ do\n\+\        jump \"L6\"\n"
test/Normal.hs view
@@ -18,8 +18,10 @@     rnf (VirtualIV r) = r `deepseq` ()  instance NFData v => NFData (Instruction v) where-    rnf (Add x y z) = x `deepseq` y `deepseq` z `deepseq` ()-    rnf Nop = ()+    rnf (Add x y z)  = x `deepseq` y `deepseq` z `deepseq` ()+    rnf (Offp x y z) = x `deepseq` y `deepseq` z `deepseq` ()+    rnf (Offlpi x)   = x `deepseq` ()+    rnf Nop          = ()  instance NFData CConv where     rnf InlineC = ()
+ test/Programs/Blocked.hs view
@@ -0,0 +1,207 @@+module Programs.Blocked where++import Assembly+import LinearScan.Hoopl.DSL++regBlocked :: Program (Node IRVar)+regBlocked = do+    label "entry" $ do+        lc v23+        add v64 v64 pr11+        call 80+        jump "L61"++    label "L61" $ do+        add v86 v39 v98+        nop+        add v77 v47 v60+        add v71 v4 v5+        move v57 v18+        copy v20 v42+        offp v20 pr19 v19+        call 57+        add pr31 v99 pr4+        nop+        nop+        move pr5 v41+        add v47 v57 v98+        alloc (Just pr21) v28+        branch v26 "L44" "L9"++    label "L9" $ do+        copy v9 v52+        copy v42 v36+        branch v24 "L74" "L52"++    label "L52" $ do+        jump "L60"++    label "L74" $ do+        copy pr14 v8+        move v34 pr20+        branch v92 "L51" "L50"++    label "L50" $ do+        jump "L39"++    label "L51" $ do+        jump "L5"++    label "L5" $ do+        alloc (Just v3) v79+        move v81 v76+        lc v55+        call 21+        lc v70+        add v99 v20 v89+        lc v5+        move v72 pr12+        offp v90 pr13 v0+        lc v2+        offlpi v78+        branch pr21 "L29" "L49"++    label "L49" $ do+        jump "L60"++    label "L60" $ do+        lc v84+        move pr30 v47+        branch v0 "L33" "L18"++    label "L18" $ do+        call 22+        jump "L35"++    label "L35" $ do+        copy v91 pr19+        move v43 v91+        branch v37 "L48" "L17"++    label "L17" $ do+        move v66 v27+        jump "L10"++    label "L10" $ do+        add v9 pr11 pr29+        branch v54 "L98" "L21"++    label "L21" $ do+        move pr14 pr14+        copy v15 v43+        move v79 v77+        copy v4 v79+        call 61+        move pr13 v31+        alloc (Just v59) v37+        return_++    label "L98" $ do+        lc v25+        return_++    label "L33" $ do+        add v35 pr3 v59+        lc v42+        branch v62 "L94" "L63"++    label "L63" $ do+        move pr23 v47+        return_++    label "L94" $ do+        move v27 v74+        call 87+        add v48 pr2 v95+        copy v11 v92+        copy pr0 v35+        lc pr25+        copy v80 v59+        add pr28 v96 pr17+        move v92 v88+        move v77 v92+        jump "L40"++    label "L40" $ do+        branch v13 "L25" "L47"++    label "L47" $ do+        jump "L57"++    label "L57" $ do+        move v59 v3+        alloc (Just v27) pr6+        jump "L4"++    label "L4" $ do+        branch v59 "L12" "L46"++    label "L46" $ do+        jump "L48"++    label "L48" $ do+        jump "L61"++    label "L12" $ do+        branch v84 "L8" "L90"++    label "L90" $ do+        call 63+        offp v71 v37 pr15+        add v16 v91 v9+        call 18+        branch v100 "L53" "L15"++    label "L15" $ do+        nop+        add pr24 v23 v73+        jump "L66"++    label "L66" $ do+        branch v78 "L42" "L41"++    label "L41" $ do+        jump "L61"++    label "L42" $ do+        jump "L57"++    label "L53" $ do+        add v32 v3 pr16+        jump "L87"++    label "L87" $ do+        return_++    label "L8" $ do+        move v67 v2+        offlpi v85+        lc v39+        jump "L26"++    label "L26" $ do+        copy v58 v91+        return_++    label "L25" $ do+        move v5 pr30+        move pr12 v5+        move v74 v19+        copy pr1 v50+        branch v31 "L71" "L40"++    label "L71" $ do+        branch v42 "L39" "L0"++    label "L39" $ do+        offlpi v7+        branch v82 "L44" "L43"++    label "L43" $ do+        jump "L5"++    label "L44" $ do+        jump "L61"++    label "L29" $ do+        return_
+ test/Programs/Exhaustion.hs view
@@ -0,0 +1,397 @@+module Programs.Exhaustion where++import Assembly+import LinearScan.Hoopl.DSL++exhaustion1 :: Program (Node IRVar)+exhaustion1 = do+    label "entry" $ do+        move pr1 v4+        move pr2 v5+        move pr3 v6+        alloc Nothing pr0+        move v4 v1+        move v5 v2+        move v6 v3+        lc v8+        move v8 v9+        lc v10+        move v10 v11+        lc v12+        move v12 v13+        move v1 v16+        copy v16 v14+        offlpi v16+        copy v16 v15+        move v14 v17+        move v15 v18+        move v2 v21+        copy v21 v19+        offlpi v21+        copy v21 v20+        move v19 v22+        move v20 v23+        move v3 v26+        copy v26 v24+        offlpi v26+        copy v26 v25+        move v25 v28+        move v17 v30+        move v30 v29+        move v29 v32+        move v22 v34+        move v34 v33+        move v33 v36+        move v18 v39+        move v39 v37+        move v37 v40+        move v23 v43+        move v43 v41+        move v41 v44+        move v28 v47+        move v47 v45+        move v45 v48+        jump "L2"++    label "L2" $ do+        move v9 v51+        move v32 v52+        lc v53+        move v53 v54+        lc v55+        move v55 v56+        move v51 v58+        move v52 v59+        add v58 v59 v60+        move v60 v57+        jump "L9"++    label "L9" $ do+        move v57 v61+        branch v61 "L10" "L11"++    label "L11" $ do+        move v54 v62+        jump "L12"++    label "L10" $ do+        move v56 v62+        jump "L12"++    label "L12" $ do+        move v62 v50+        jump "L8"++    label "L8" $ do+        branch v50 "L5" "L6"++    label "L6" $ do+        lc v49+        jump "L7"++    label "L5" $ do+        move v11 v64+        move v36 v65+        lc v66+        move v66 v67+        lc v68+        move v68 v69+        move v64 v71+        move v65 v72+        add v71 v72 v73+        move v73 v70+        jump "L18"++    label "L18" $ do+        move v70 v74+        branch v74 "L19" "L20"++    label "L20" $ do+        move v67 v75+        jump "L21"++    label "L19" $ do+        move v69 v75+        jump "L21"++    label "L21" $ do+        move v75 v63+        jump "L17"++    label "L17" $ do+        branch v63 "L14" "L15"++    label "L15" $ do+        lc v49+        jump "L7"++    label "L14" $ do+        move v13 v76+        lc v77+        lc v78+        move v78 v79+        lc v80+        move v80 v81+        move v76 v83+        move v77 v84+        add v83 v84 v85+        move v85 v82+        jump "L24"++    label "L24" $ do+        move v82 v86+        branch v86 "L25" "L26"++    label "L26" $ do+        move v79 v87+        jump "L27"++    label "L25" $ do+        move v81 v87+        jump "L27"++    label "L27" $ do+        move v87 v49+        jump "L7"++    label "L7" $ do+        branch v49 "L3" "L75"++    label "L3" $ do+        move v40 v90+        move v9 v91+        move v91 v92+        offp v92 v90 v89+        copy v89 v88+        move v88 v93+        move v44 v96+        move v11 v97+        move v97 v98+        offp v98 v96 v95+        copy v95 v94+        move v94 v99+        move v93 v113+        copy v113 v101+        move v99 v114+        copy v114 v102+        lc v103+        move v103 v104+        lc v105+        move v105 v106+        move v101 v108+        move v102 v109+        add v108 v109 v110+        move v110 v107+        jump "L33"++    label "L33" $ do+        move v107 v111+        branch v111 "L34" "L35"++    label "L35" $ do+        move v104 v112+        jump "L36"++    label "L34" $ do+        move v106 v112+        jump "L36"++    label "L36" $ do+        move v112 v100+        jump "L32"++    label "L32" $ do+        branch v100 "L29" "L30"++    label "L30" $ do+        move v44 v130+        move v11 v131+        move v131 v132+        offp v132 v130 v129+        copy v129 v128+        move v48 v134+        move v13 v135+        move v135 v136+        offp v136 v134 v133+        move v128 v133+        move v11 v138+        lc v139+        add v138 v139 v140+        move v140 v137+        jump "L39"++    label "L39" $ do+        move v137 v11+        move v93 v145+        copy v145 v142+        move v99 v146+        copy v146 v143+        add v142 v143 v144+        move v144 v141+        jump "L43"++    label "L43" $ do+        branch v141 "L40" "L73"++    label "L40" $ do+        move v9 v148+        lc v149+        add v148 v149 v150+        move v150 v147+        jump "L44"++    label "L44" $ do+        move v147 v9+        jump "L31"++    label "L29" $ do+        move v40 v117+        move v9 v118+        move v118 v119+        offp v119 v117 v116+        copy v116 v115+        move v48 v121+        move v13 v122+        move v122 v123+        offp v123 v121 v120+        move v115 v120+        move v9 v125+        lc v126+        add v125 v126 v127+        move v127 v124+        jump "L38"++    label "L38" $ do+        move v124 v9+        jump "L31"++    label "L31" $ do+        move v13 v152+        lc v153+        add v152 v153 v154+        move v154 v151+        jump "L45"++    label "L45" $ do+        move v151 v13+        jump "L2"++    label "L73" $ do+        move v206 v210+        branch v210 "L74" "L75"++    label "L75" $ do+        jump "L46"++    label "L46" $ do+        move v9 v157+        move v32 v158+        lc v159+        move v159 v160+        lc v161+        move v161 v162+        move v157 v164+        move v158 v165+        add v164 v165 v166+        move v166 v163+        jump "L53"++    label "L53" $ do+        move v163 v167+        branch v167 "L54" "L55"++    label "L55" $ do+        move v160 v168+        jump "L56"++    label "L54" $ do+        move v162 v168+        jump "L56"++    label "L56" $ do+        move v168 v156+        jump "L52"++    label "L52" $ do+        branch v156 "L49" "L50"++    label "L50" $ do+        lc v155+        jump "L51"++    label "L49" $ do+        move v13 v169+        lc v170+        lc v171+        move v171 v172+        lc v173+        move v173 v174+        move v169 v176+        move v170 v177+        add v176 v177 v178+        move v178 v175+        jump "L59"++    label "L59" $ do+        move v175 v179+        branch v179 "L60" "L61"++    label "L61" $ do+        move v172 v180+        jump "L62"++    label "L60" $ do+        move v174 v180+        jump "L62"++    label "L62" $ do+        move v180 v155+        jump "L51"++    label "L51" $ do+        branch v155 "L47" "L74"++    label "L47" $ do+        move v40 v183+        move v9 v184+        move v184 v185+        offp v185 v183 v182+        copy v182 v181+        move v48 v187+        move v13 v188+        move v188 v189+        offp v189 v187 v186+        move v181 v186+        move v9 v191+        lc v192+        add v191 v192 v193+        move v193 v190+        jump "L64"++    label "L64" $ do+        move v190 v9+        move v13 v195+        lc v196+        add v195 v196 v197+        move v197 v194+        jump "L65"++    label "L65" $ do+        move v194 v13+        jump "L46"++    label "L74" $ do+        jump "L66"++    label "L66" $ do+        move v11 v200+        move v36 v201+        lc v202+        move v202 v203+        lc v204+        move v204 v205+        move v200 v207+        move v201 v208+        add v207 v208 v209+        move v209 v206+        jump "L73"