module Hoopl.Dataflow
( DataflowLattice(..), OldFact(..), NewFact(..), Fact, mkFactBase
, ChangeFlag(..)
, FwdPass(..), FwdTransfer, mkFTransfer, mkFTransfer3, getFTransfer3
, FwdRewrite, mkFRewrite, mkFRewrite3, getFRewrite3, noFwdRewrite
, wrapFR, wrapFR2
, BwdPass(..), BwdTransfer, mkBTransfer, mkBTransfer3, getBTransfer3
, wrapBR, wrapBR2
, BwdRewrite, mkBRewrite, mkBRewrite3, getBRewrite3, noBwdRewrite
, analyzeAndRewriteFwd, analyzeAndRewriteBwd
, analyzeFwd, analyzeFwdBlocks, analyzeBwd
)
where
import UniqSupply
import Data.Maybe
import Data.Array
import Compiler.Hoopl hiding
( mkBRewrite3, mkFRewrite3, noFwdRewrite, noBwdRewrite
, analyzeAndRewriteBwd, analyzeAndRewriteFwd
)
import Compiler.Hoopl.Internals
( wrapFR, wrapFR2
, wrapBR, wrapBR2
, splice
)
noRewrite :: a -> b -> UniqSM (Maybe c)
noRewrite _ _ = return Nothing
noFwdRewrite :: FwdRewrite UniqSM n f
noFwdRewrite = FwdRewrite3 (noRewrite, noRewrite, noRewrite)
mkFRewrite3 :: forall n f.
(n C O -> f -> UniqSM (Maybe (Graph n C O)))
-> (n O O -> f -> UniqSM (Maybe (Graph n O O)))
-> (n O C -> f -> UniqSM (Maybe (Graph n O C)))
-> FwdRewrite UniqSM n f
mkFRewrite3 f m l = FwdRewrite3 (lift f, lift m, lift l)
where lift :: forall t t1 a. (t -> t1 -> UniqSM (Maybe a))
-> t -> t1 -> UniqSM (Maybe (a, FwdRewrite UniqSM n f))
lift rw node fact = do
a <- rw node fact
case a of
Nothing -> return Nothing
Just a -> return (Just (a,noFwdRewrite))
noBwdRewrite :: BwdRewrite UniqSM n f
noBwdRewrite = BwdRewrite3 (noRewrite, noRewrite, noRewrite)
mkBRewrite3 :: forall n f.
(n C O -> f -> UniqSM (Maybe (Graph n C O)))
-> (n O O -> f -> UniqSM (Maybe (Graph n O O)))
-> (n O C -> FactBase f -> UniqSM (Maybe (Graph n O C)))
-> BwdRewrite UniqSM n f
mkBRewrite3 f m l = BwdRewrite3 (lift f, lift m, lift l)
where lift :: forall t t1 a. (t -> t1 -> UniqSM (Maybe a))
-> t -> t1 -> UniqSM (Maybe (a, BwdRewrite UniqSM n f))
lift rw node fact = do
a <- rw node fact
case a of
Nothing -> return Nothing
Just a -> return (Just (a,noBwdRewrite))
analyzeAndRewriteFwd
:: forall n f e x . NonLocal n =>
FwdPass UniqSM n f
-> MaybeC e [Label]
-> Graph n e x -> Fact e f
-> UniqSM (Graph n e x, FactBase f, MaybeO x f)
analyzeAndRewriteFwd pass entries g f =
do (rg, fout) <- arfGraph pass (fmap targetLabels entries) g f
let (g', fb) = normalizeGraph rg
return (g', fb, distinguishedExitFact g' fout)
distinguishedExitFact :: forall n e x f . Graph n e x -> Fact x f -> MaybeO x f
distinguishedExitFact g f = maybe g
where maybe :: Graph n e x -> MaybeO x f
maybe GNil = JustO f
maybe (GUnit {}) = JustO f
maybe (GMany _ _ x) = case x of NothingO -> NothingO
JustO _ -> JustO f
type Entries e = MaybeC e [Label]
arfGraph :: forall n f e x . NonLocal n =>
FwdPass UniqSM n f ->
Entries e -> Graph n e x -> Fact e f -> UniqSM (DG f n e x, Fact x f)
arfGraph pass@FwdPass { fp_lattice = lattice,
fp_transfer = transfer,
fp_rewrite = rewrite } entries g in_fact = graph g in_fact
where
graph :: Graph n e x -> Fact e f -> UniqSM (DG f n e x, Fact x f)
block :: forall e x .
Block n e x -> f -> UniqSM (DG f n e x, Fact x f)
body :: [Label] -> LabelMap (Block n C C)
-> Fact C f -> UniqSM (DG f n C C, Fact C f)
cat :: forall e a x f1 f2 f3.
(f1 -> UniqSM (DG f n e a, f2))
-> (f2 -> UniqSM (DG f n a x, f3))
-> (f1 -> UniqSM (DG f n e x, f3))
graph GNil f = return (dgnil, f)
graph (GUnit blk) f = block blk f
graph (GMany e bdy x) f = ((e `ebcat` bdy) `cat` exit x) f
where
ebcat :: MaybeO e (Block n O C) -> Body n -> Fact e f -> UniqSM (DG f n e C, Fact C f)
exit :: MaybeO x (Block n C O) -> Fact C f -> UniqSM (DG f n C x, Fact x f)
exit (JustO blk) f = arfx block blk f
exit NothingO f = return (dgnilC, f)
ebcat entry bdy f = c entries entry f
where c :: MaybeC e [Label] -> MaybeO e (Block n O C)
-> Fact e f -> UniqSM (DG f n e C, Fact C f)
c NothingC (JustO entry) f = (block entry `cat` body (successors entry) bdy) f
c (JustC entries) NothingO f = body entries bdy f
block BNil f = return (dgnil, f)
block (BlockCO n b) f = (node n `cat` block b) f
block (BlockCC l b n) f = (node l `cat` block b `cat` node n) f
block (BlockOC b n) f = (block b `cat` node n) f
block (BMiddle n) f = node n f
block (BCat b1 b2) f = (block b1 `cat` block b2) f
block (BSnoc h n) f = (block h `cat` node n) f
block (BCons n t) f = (node n `cat` block t) f
node :: forall e x . (ShapeLifter e x)
=> n e x -> f -> UniqSM (DG f n e x, Fact x f)
node n f
= do { grw <- frewrite rewrite n f
; case grw of
Nothing -> return ( singletonDG f n
, ftransfer transfer n f )
Just (g, rw) ->
let pass' = pass { fp_rewrite = rw }
f' = fwdEntryFact n f
in arfGraph pass' (fwdEntryLabel n) g f' }
cat ft1 ft2 f = do { (g1,f1) <- ft1 f
; (g2,f2) <- ft2 f1
; let !g = g1 `dgSplice` g2
; return (g, f2) }
arfx :: forall x .
(Block n C x -> f -> UniqSM (DG f n C x, Fact x f))
-> (Block n C x -> Fact C f -> UniqSM (DG f n C x, Fact x f))
arfx arf thing fb =
arf thing $ fromJust $ lookupFact (entryLabel thing) $ joinInFacts lattice fb
body entries blockmap init_fbase
= fixpoint Fwd lattice do_block entries blockmap init_fbase
where
lattice = fp_lattice pass
do_block :: forall x . Block n C x -> FactBase f
-> UniqSM (DG f n C x, Fact x f)
do_block b fb = block b entryFact
where entryFact = getFact lattice (entryLabel b) fb
joinInFacts :: DataflowLattice f -> FactBase f -> FactBase f
joinInFacts (lattice @ DataflowLattice {fact_bot = bot, fact_join = fj}) fb =
mkFactBase lattice $ map botJoin $ mapToList fb
where botJoin (l, f) = (l, snd $ fj l (OldFact bot) (NewFact f))
forwardBlockList :: (NonLocal n)
=> [Label] -> Body n -> [Block n C C]
forwardBlockList entries blks = postorder_dfs_from blks entries
analyzeFwd
:: forall n f e . NonLocal n =>
FwdPass UniqSM n f
-> MaybeC e [Label]
-> Graph n e C -> Fact e f
-> FactBase f
analyzeFwd FwdPass { fp_lattice = lattice,
fp_transfer = FwdTransfer3 (ftr, mtr, ltr) }
entries g in_fact = graph g in_fact
where
graph :: Graph n e C -> Fact e f -> FactBase f
graph (GMany entry blockmap NothingO)
= case (entries, entry) of
(NothingC, JustO entry) -> block entry `cat` body (successors entry)
(JustC entries, NothingO) -> body entries
where
body :: [Label] -> Fact C f -> Fact C f
body entries f
= fixpointAnal Fwd lattice do_block entries blockmap f
where
do_block :: forall x . Block n C x -> FactBase f -> Fact x f
do_block b fb = block b entryFact
where entryFact = getFact lattice (entryLabel b) fb
block :: forall e x . Block n e x -> f -> Fact x f
block BNil f = f
block (BlockCO n b) f = (ftr n `cat` block b) f
block (BlockCC l b n) f = (ftr l `cat` (block b `cat` ltr n)) f
block (BlockOC b n) f = (block b `cat` ltr n) f
block (BMiddle n) f = mtr n f
block (BCat b1 b2) f = (block b1 `cat` block b2) f
block (BSnoc h n) f = (block h `cat` mtr n) f
block (BCons n t) f = (mtr n `cat` block t) f
cat :: forall f1 f2 f3 . (f1 -> f2) -> (f2 -> f3) -> (f1 -> f3)
cat ft1 ft2 = \f -> ft2 $! ft1 f
analyzeFwdBlocks
:: forall n f e . NonLocal n =>
FwdPass UniqSM n f
-> MaybeC e [Label]
-> Graph n e C -> Fact e f
-> FactBase f
analyzeFwdBlocks FwdPass { fp_lattice = lattice,
fp_transfer = FwdTransfer3 (ftr, _, ltr) }
entries g in_fact = graph g in_fact
where
graph :: Graph n e C -> Fact e f -> FactBase f
graph (GMany entry blockmap NothingO)
= case (entries, entry) of
(NothingC, JustO entry) -> block entry `cat` body (successors entry)
(JustC entries, NothingO) -> body entries
where
body :: [Label] -> Fact C f -> Fact C f
body entries f
= fixpointAnal Fwd lattice do_block entries blockmap f
where
do_block :: forall x . Block n C x -> FactBase f -> Fact x f
do_block b fb = block b entryFact
where entryFact = getFact lattice (entryLabel b) fb
block :: forall e x . Block n e x -> f -> Fact x f
block BNil f = f
block (BlockCO n _) f = ftr n f
block (BlockCC l _ n) f = (ftr l `cat` ltr n) f
block (BlockOC _ n) f = ltr n f
block _ _ = error "analyzeFwdBlocks"
cat :: forall f1 f2 f3 . (f1 -> f2) -> (f2 -> f3) -> (f1 -> f3)
cat ft1 ft2 = \f -> ft2 $! ft1 f
analyzeBwd
:: forall n f e . NonLocal n =>
BwdPass UniqSM n f
-> MaybeC e [Label]
-> Graph n e C -> Fact C f
-> FactBase f
analyzeBwd BwdPass { bp_lattice = lattice,
bp_transfer = BwdTransfer3 (ftr, mtr, ltr) }
entries g in_fact = graph g in_fact
where
graph :: Graph n e C -> Fact C f -> FactBase f
graph (GMany entry blockmap NothingO)
= case (entries, entry) of
(NothingC, JustO entry) -> body (successors entry)
(JustC entries, NothingO) -> body entries
where
body :: [Label] -> Fact C f -> Fact C f
body entries f
= fixpointAnal Bwd lattice do_block entries blockmap f
where
do_block :: forall x . Block n C x -> Fact x f -> FactBase f
do_block b fb = mapSingleton (entryLabel b) (block b fb)
block :: forall e x . Block n e x -> Fact x f -> f
block BNil f = f
block (BlockCO n b) f = (ftr n `cat` block b) f
block (BlockCC l b n) f = ((ftr l `cat` block b) `cat` ltr n) f
block (BlockOC b n) f = (block b `cat` ltr n) f
block (BMiddle n) f = mtr n f
block (BCat b1 b2) f = (block b1 `cat` block b2) f
block (BSnoc h n) f = (block h `cat` mtr n) f
block (BCons n t) f = (mtr n `cat` block t) f
cat :: forall f1 f2 f3 . (f2 -> f3) -> (f1 -> f2) -> (f1 -> f3)
cat ft1 ft2 = \f -> ft1 $! ft2 f
analyzeAndRewriteBwd
:: NonLocal n
=> BwdPass UniqSM n f
-> MaybeC e [Label] -> Graph n e x -> Fact x f
-> UniqSM (Graph n e x, FactBase f, MaybeO e f)
analyzeAndRewriteBwd pass entries g f =
do (rg, fout) <- arbGraph pass (fmap targetLabels entries) g f
let (g', fb) = normalizeGraph rg
return (g', fb, distinguishedEntryFact g' fout)
distinguishedEntryFact :: forall n e x f . Graph n e x -> Fact e f -> MaybeO e f
distinguishedEntryFact g f = maybe g
where maybe :: Graph n e x -> MaybeO e f
maybe GNil = JustO f
maybe (GUnit {}) = JustO f
maybe (GMany e _ _) = case e of NothingO -> NothingO
JustO _ -> JustO f
arbGraph :: forall n f e x .
NonLocal n =>
BwdPass UniqSM n f ->
Entries e -> Graph n e x -> Fact x f -> UniqSM (DG f n e x, Fact e f)
arbGraph pass@BwdPass { bp_lattice = lattice,
bp_transfer = transfer,
bp_rewrite = rewrite } entries g in_fact = graph g in_fact
where
graph :: Graph n e x -> Fact x f -> UniqSM (DG f n e x, Fact e f)
block :: forall e x . Block n e x -> Fact x f -> UniqSM (DG f n e x, f)
body :: [Label] -> Body n -> Fact C f -> UniqSM (DG f n C C, Fact C f)
node :: forall e x . (ShapeLifter e x)
=> n e x -> Fact x f -> UniqSM (DG f n e x, f)
cat :: forall e a x info info' info''.
(info' -> UniqSM (DG f n e a, info''))
-> (info -> UniqSM (DG f n a x, info'))
-> (info -> UniqSM (DG f n e x, info''))
graph GNil f = return (dgnil, f)
graph (GUnit blk) f = block blk f
graph (GMany e bdy x) f = ((e `ebcat` bdy) `cat` exit x) f
where
ebcat :: MaybeO e (Block n O C) -> Body n -> Fact C f -> UniqSM (DG f n e C, Fact e f)
exit :: MaybeO x (Block n C O) -> Fact x f -> UniqSM (DG f n C x, Fact C f)
exit (JustO blk) f = arbx block blk f
exit NothingO f = return (dgnilC, f)
ebcat entry bdy f = c entries entry f
where c :: MaybeC e [Label] -> MaybeO e (Block n O C)
-> Fact C f -> UniqSM (DG f n e C, Fact e f)
c NothingC (JustO entry) f = (block entry `cat` body (successors entry) bdy) f
c (JustC entries) NothingO f = body entries bdy f
block BNil f = return (dgnil, f)
block (BlockCO n b) f = (node n `cat` block b) f
block (BlockCC l b n) f = (node l `cat` block b `cat` node n) f
block (BlockOC b n) f = (block b `cat` node n) f
block (BMiddle n) f = node n f
block (BCat b1 b2) f = (block b1 `cat` block b2) f
block (BSnoc h n) f = (block h `cat` node n) f
block (BCons n t) f = (node n `cat` block t) f
node n f
= do { bwdres <- brewrite rewrite n f
; case bwdres of
Nothing -> return (singletonDG entry_f n, entry_f)
where entry_f = btransfer transfer n f
Just (g, rw) ->
do { let pass' = pass { bp_rewrite = rw }
; (g, f) <- arbGraph pass' (fwdEntryLabel n) g f
; return (g, bwdEntryFact lattice n f)} }
cat ft1 ft2 f = do { (g2,f2) <- ft2 f
; (g1,f1) <- ft1 f2
; let !g = g1 `dgSplice` g2
; return (g, f1) }
arbx :: forall x .
(Block n C x -> Fact x f -> UniqSM (DG f n C x, f))
-> (Block n C x -> Fact x f -> UniqSM (DG f n C x, Fact C f))
arbx arb thing f = do { (rg, f) <- arb thing f
; let fb = joinInFacts (bp_lattice pass) $
mapSingleton (entryLabel thing) f
; return (rg, fb) }
body entries blockmap init_fbase
= fixpoint Bwd (bp_lattice pass) do_block entries blockmap init_fbase
where
do_block :: forall x. Block n C x -> Fact x f -> UniqSM (DG f n C x, LabelMap f)
do_block b f = do (g, f) <- block b f
return (g, mapSingleton (entryLabel b) f)
data Direction = Fwd | Bwd
fixpointAnal :: forall n f. NonLocal n
=> Direction
-> DataflowLattice f
-> (Block n C C -> Fact C f -> Fact C f)
-> [Label]
-> LabelMap (Block n C C)
-> Fact C f -> FactBase f
fixpointAnal direction DataflowLattice{ fact_bot = _, fact_join = join }
do_block entries blockmap init_fbase
= loop start init_fbase
where
blocks = sortBlocks direction entries blockmap
n = length blocks
block_arr = listArray (0,n1) blocks
start = [0..n1]
dep_blocks = mkDepBlocks direction blocks
loop
:: IntHeap
-> FactBase f
-> FactBase f
loop [] fbase = fbase
loop (ix:todo) fbase =
let
blk = block_arr ! ix
out_facts = do_block blk fbase
!(todo', fbase') =
mapFoldWithKey (updateFact join dep_blocks)
(todo,fbase) out_facts
in
loop todo' fbase'
fixpoint :: forall n f. NonLocal n
=> Direction
-> DataflowLattice f
-> (Block n C C -> Fact C f -> UniqSM (DG f n C C, Fact C f))
-> [Label]
-> LabelMap (Block n C C)
-> (Fact C f -> UniqSM (DG f n C C, Fact C f))
fixpoint direction DataflowLattice{ fact_bot = _, fact_join = join }
do_block entries blockmap init_fbase
= do
(fbase, newblocks) <- loop start init_fbase mapEmpty
return (GMany NothingO newblocks NothingO,
mapDeleteList (mapKeys blockmap) fbase)
where
blocks = sortBlocks direction entries blockmap
n = length blocks
block_arr = listArray (0,n1) blocks
start = [0..n1]
dep_blocks = mkDepBlocks direction blocks
loop
:: IntHeap
-> FactBase f
-> LabelMap (DBlock f n C C)
-> UniqSM (FactBase f, LabelMap (DBlock f n C C))
loop [] fbase newblocks = return (fbase, newblocks)
loop (ix:todo) fbase !newblocks = do
let blk = block_arr ! ix
(rg, out_facts) <- do_block blk fbase
let !(todo', fbase') =
mapFoldWithKey (updateFact join dep_blocks)
(todo,fbase) out_facts
let newblocks' = case rg of
GMany _ blks _ -> mapUnion blks newblocks
loop todo' fbase' newblocks'
sortBlocks :: NonLocal n => Direction -> [Label] -> LabelMap (Block n C C)
-> [Block n C C]
sortBlocks direction entries blockmap
= case direction of Fwd -> fwd
Bwd -> reverse fwd
where fwd = forwardBlockList entries blockmap
mkDepBlocks :: NonLocal n => Direction -> [Block n C C] -> LabelMap [Int]
mkDepBlocks Fwd blocks = go blocks 0 mapEmpty
where go [] !_ m = m
go (b:bs) !n m = go bs (n+1) $! mapInsert (entryLabel b) [n] m
mkDepBlocks Bwd blocks = go blocks 0 mapEmpty
where go [] !_ m = m
go (b:bs) !n m = go bs (n+1) $! go' (successors b) m
where go' [] m = m
go' (l:ls) m = go' ls (mapInsertWith (++) l [n] m)
updateFact :: JoinFun f -> LabelMap [Int]
-> Label -> f
-> (IntHeap, FactBase f)
-> (IntHeap, FactBase f)
updateFact fact_join dep_blocks lbl new_fact (todo, fbase)
= case lookupFact lbl fbase of
Nothing -> let !z = mapInsert lbl new_fact fbase in (changed, z)
Just old_fact ->
case fact_join lbl (OldFact old_fact) (NewFact new_fact) of
(NoChange, _) -> (todo, fbase)
(_, f) -> let !z = mapInsert lbl f fbase in (changed, z)
where
changed = foldr insertIntHeap todo $
mapFindWithDefault [] lbl dep_blocks
type DG f = Graph' (DBlock f)
data DBlock f n e x = DBlock f (Block n e x)
instance NonLocal n => NonLocal (DBlock f n) where
entryLabel (DBlock _ b) = entryLabel b
successors (DBlock _ b) = successors b
dgnil :: DG f n O O
dgnilC :: DG f n C C
dgSplice :: NonLocal n => DG f n e a -> DG f n a x -> DG f n e x
normalizeGraph :: forall n f e x .
NonLocal n => DG f n e x
-> (Graph n e x, FactBase f)
normalizeGraph g = (mapGraphBlocks dropFact g, facts g)
where dropFact :: DBlock t t1 t2 t3 -> Block t1 t2 t3
dropFact (DBlock _ b) = b
facts :: DG f n e x -> FactBase f
facts GNil = noFacts
facts (GUnit _) = noFacts
facts (GMany _ body exit) = bodyFacts body `mapUnion` exitFacts exit
exitFacts :: MaybeO x (DBlock f n C O) -> FactBase f
exitFacts NothingO = noFacts
exitFacts (JustO (DBlock f b)) = mapSingleton (entryLabel b) f
bodyFacts :: LabelMap (DBlock f n C C) -> FactBase f
bodyFacts body = mapFoldWithKey f noFacts body
where f :: forall t a x. Label -> DBlock a t C x -> LabelMap a -> LabelMap a
f lbl (DBlock f _) fb = mapInsert lbl f fb
dgnil = GNil
dgnilC = GMany NothingO emptyBody NothingO
dgSplice = splice fzCat
where fzCat :: DBlock f n e O -> DBlock t n O x -> DBlock f n e x
fzCat (DBlock f b1) (DBlock _ b2) = DBlock f $! b1 `blockAppend` b2
class ShapeLifter e x where
singletonDG :: f -> n e x -> DG f n e x
fwdEntryFact :: NonLocal n => n e x -> f -> Fact e f
fwdEntryLabel :: NonLocal n => n e x -> MaybeC e [Label]
ftransfer :: FwdTransfer n f -> n e x -> f -> Fact x f
frewrite :: FwdRewrite m n f -> n e x
-> f -> m (Maybe (Graph n e x, FwdRewrite m n f))
bwdEntryFact :: NonLocal n => DataflowLattice f -> n e x -> Fact e f -> f
btransfer :: BwdTransfer n f -> n e x -> Fact x f -> f
brewrite :: BwdRewrite m n f -> n e x
-> Fact x f -> m (Maybe (Graph n e x, BwdRewrite m n f))
instance ShapeLifter C O where
singletonDG f n = gUnitCO (DBlock f (BlockCO n BNil))
fwdEntryFact n f = mapSingleton (entryLabel n) f
bwdEntryFact lat n fb = getFact lat (entryLabel n) fb
ftransfer (FwdTransfer3 (ft, _, _)) n f = ft n f
btransfer (BwdTransfer3 (bt, _, _)) n f = bt n f
frewrite (FwdRewrite3 (fr, _, _)) n f = fr n f
brewrite (BwdRewrite3 (br, _, _)) n f = br n f
fwdEntryLabel n = JustC [entryLabel n]
instance ShapeLifter O O where
singletonDG f = gUnitOO . DBlock f . BMiddle
fwdEntryFact _ f = f
bwdEntryFact _ _ f = f
ftransfer (FwdTransfer3 (_, ft, _)) n f = ft n f
btransfer (BwdTransfer3 (_, bt, _)) n f = bt n f
frewrite (FwdRewrite3 (_, fr, _)) n f = fr n f
brewrite (BwdRewrite3 (_, br, _)) n f = br n f
fwdEntryLabel _ = NothingC
instance ShapeLifter O C where
singletonDG f n = gUnitOC (DBlock f (BlockOC BNil n))
fwdEntryFact _ f = f
bwdEntryFact _ _ f = f
ftransfer (FwdTransfer3 (_, _, ft)) n f = ft n f
btransfer (BwdTransfer3 (_, _, bt)) n f = bt n f
frewrite (FwdRewrite3 (_, _, fr)) n f = fr n f
brewrite (BwdRewrite3 (_, _, br)) n f = br n f
fwdEntryLabel _ = NothingC
getFact :: DataflowLattice f -> Label -> FactBase f -> f
getFact lat l fb = case lookupFact l fb of Just f -> f
Nothing -> fact_bot lat
type IntHeap = [Int]
insertIntHeap :: Int -> [Int] -> [Int]
insertIntHeap x [] = [x]
insertIntHeap x (y:ys)
| x < y = x : y : ys
| x == y = x : ys
| otherwise = y : insertIntHeap x ys