2 % (c) The AQUA Project, Glasgow University, 1994-1996
4 \section[UniqFM]{Specialised finite maps, for things with @Uniques@}
6 Based on @FiniteMaps@ (as you would expect).
8 Basically, the things need to be in class @Uniquable@, and we use the
9 @uniqueOf@ method to grab their @Uniques@.
11 (A similar thing to @UniqSet@, as opposed to @Set@.)
14 #if defined(COMPILING_GHC)
15 #include "HsVersions.h"
16 #define IF_NOT_GHC(a) {--}
18 #define ASSERT(e) {--}
19 #define IF_NOT_GHC(a) a
23 UniqFM, -- abstract type
24 Uniquable(..), -- class to go with it
32 addListToUFM,addListToUFM_C,
34 addListToUFM_Directly,
42 IF_NOT_GHC(intersectUFM_C COMMA)
43 IF_NOT_GHC(foldUFM COMMA)
48 lookupUFM, lookupUFM_Directly,
49 lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
52 #if defined(COMPILING_GHC)
57 #if defined(COMPILING_GHC)
58 IMPORT_DELOOPER( SpecLoop )
61 import Unique ( Unique, u2i, mkUniqueGrimily )
63 import Pretty ( SYN_IE(Pretty), PrettyRep )
64 import Outputable ( Outputable(..) )
65 import PprStyle ( PprStyle )
66 import SrcLoc ( SrcLoc )
68 #if ! OMIT_NATIVE_CODEGEN
71 #define IF_NCG(a) {--}
75 %************************************************************************
77 \subsection{The @UniqFM@ type, and signatures for the functions}
79 %************************************************************************
81 We use @FiniteMaps@, with a (@uniqueOf@-able) @Unique@ as ``key''.
84 emptyUFM :: UniqFM elt
85 isNullUFM :: UniqFM elt -> Bool
86 unitUFM :: Uniquable key => key -> elt -> UniqFM elt
87 unitDirectlyUFM -- got the Unique already
88 :: Unique -> elt -> UniqFM elt
89 listToUFM :: Uniquable key => [(key,elt)] -> UniqFM elt
91 :: [(Unique, elt)] -> UniqFM elt
93 addToUFM :: Uniquable key => UniqFM elt -> key -> elt -> UniqFM elt
94 addListToUFM :: Uniquable key => UniqFM elt -> [(key,elt)] -> UniqFM elt
96 :: UniqFM elt -> Unique -> elt -> UniqFM elt
98 addToUFM_C :: Uniquable key => (elt -> elt -> elt)
99 -> UniqFM elt -> key -> elt -> UniqFM elt
100 addListToUFM_C :: Uniquable key => (elt -> elt -> elt)
101 -> UniqFM elt -> [(key,elt)]
104 delFromUFM :: Uniquable key => UniqFM elt -> key -> UniqFM elt
105 delListFromUFM :: Uniquable key => UniqFM elt -> [key] -> UniqFM elt
106 delFromUFM_Directly :: UniqFM elt -> Unique -> UniqFM elt
108 plusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
110 plusUFM_C :: (elt -> elt -> elt)
111 -> UniqFM elt -> UniqFM elt -> UniqFM elt
113 minusUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
115 intersectUFM :: UniqFM elt -> UniqFM elt -> UniqFM elt
116 intersectUFM_C :: (elt -> elt -> elt)
117 -> UniqFM elt -> UniqFM elt -> UniqFM elt
118 foldUFM :: (elt -> a -> a) -> a -> UniqFM elt -> a
119 mapUFM :: (elt1 -> elt2) -> UniqFM elt1 -> UniqFM elt2
120 filterUFM :: (elt -> Bool) -> UniqFM elt -> UniqFM elt
122 sizeUFM :: UniqFM elt -> Int
124 lookupUFM :: Uniquable key => UniqFM elt -> key -> Maybe elt
125 lookupUFM_Directly -- when you've got the Unique already
126 :: UniqFM elt -> Unique -> Maybe elt
128 :: Uniquable key => UniqFM elt -> elt -> key -> elt
129 lookupWithDefaultUFM_Directly
130 :: UniqFM elt -> elt -> Unique -> elt
132 eltsUFM :: UniqFM elt -> [elt]
133 ufmToList :: UniqFM elt -> [(Unique, elt)]
136 %************************************************************************
138 \subsection{The @IdFinMap@ and @TyVarFinMap@ specialisations for Ids/TyVars}
140 %************************************************************************
143 #ifdef __GLASGOW_HASKELL__
144 -- I don't think HBC was too happy about this (WDP 94/10)
147 addListToUFM :: UniqFM elt -> [(Name, elt)] -> UniqFM elt
150 addListToUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Name, elt)] -> UniqFM elt
153 addToUFM :: UniqFM elt -> Unique -> elt -> UniqFM elt
156 listToUFM :: [(Unique, elt)] -> UniqFM elt
159 lookupUFM :: UniqFM elt -> Name -> Maybe elt
160 , UniqFM elt -> Unique -> Maybe elt
163 #endif {- __GLASGOW_HASKELL__ -}
166 %************************************************************************
168 \subsection{Andy Gill's underlying @UniqFM@ machinery}
170 %************************************************************************
172 ``Uniq Finite maps'' are the heart and soul of the compiler's
173 lookup-tables/environments. Important stuff! It works well with
174 Dense and Sparse ranges.
175 Both @Uq@ Finite maps and @Hash@ Finite Maps
176 are built ontop of Int Finite Maps.
178 This code is explained in the paper:
180 A Gill, S Peyton Jones, B O'Sullivan, W Partain and Aqua Friends
181 "A Cheap balancing act that grows on a tree"
182 Glasgow FP Workshop, Sep 1994, pp??-??
185 %************************************************************************
187 \subsubsection{The @UniqFM@ type, and signatures for the functions}
189 %************************************************************************
191 @UniqFM a@ is a mapping from Unique to a.
193 First, the DataType itself; which is either a Node, a Leaf, or an Empty.
198 | LeafUFM FAST_INT ele
199 | NodeUFM FAST_INT -- the switching
200 FAST_INT -- the delta
204 class Uniquable a where
205 uniqueOf :: a -> Unique
207 -- for debugging only :-)
209 instance Text (UniqFM a) where
210 showsPrec _ (NodeUFM a b t1 t2) =
211 showString "NodeUFM " . shows (IBOX(a))
212 . showString " " . shows (IBOX(b))
213 . showString " (" . shows t1
214 . showString ") (" . shows t2
216 showsPrec _ (LeafUFM x a) = showString "LeafUFM " . shows (IBOX(x))
217 showsPrec _ (EmptyUFM) = id
221 %************************************************************************
223 \subsubsection{The @UniqFM@ functions}
225 %************************************************************************
227 First the ways of building a UniqFM.
231 unitUFM key elt = mkLeafUFM (u2i (uniqueOf key)) elt
232 unitDirectlyUFM key elt = mkLeafUFM (u2i key) elt
234 listToUFM key_elt_pairs
235 = addListToUFM_C use_snd EmptyUFM key_elt_pairs
237 listToUFM_Directly uniq_elt_pairs
238 = addListToUFM_directly_C use_snd EmptyUFM uniq_elt_pairs
241 Now ways of adding things to UniqFMs.
243 There is an alternative version of @addListToUFM_C@, that uses @plusUFM@,
244 but the semantics of this operation demands a linear insertion;
245 perhaps the version without the combinator function
246 could be optimised using it.
249 addToUFM fm key elt = addToUFM_C use_snd fm key elt
251 addToUFM_Directly fm u elt = insert_ele use_snd fm (u2i u) elt
253 addToUFM_C combiner fm key elt
254 = insert_ele combiner fm (u2i (uniqueOf key)) elt
256 addListToUFM fm key_elt_pairs = addListToUFM_C use_snd fm key_elt_pairs
257 addListToUFM_Directly fm uniq_elt_pairs = addListToUFM_directly_C use_snd fm uniq_elt_pairs
259 addListToUFM_C combiner fm key_elt_pairs
260 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i (uniqueOf k)) e)
263 addListToUFM_directly_C combiner fm uniq_elt_pairs
264 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i k) e)
268 Now ways of removing things from UniqFM.
271 delListFromUFM fm lst = foldl delFromUFM fm lst
273 delFromUFM fm key = delete fm (u2i (uniqueOf key))
274 delFromUFM_Directly fm u = delete fm (u2i u)
276 delete EmptyUFM _ = EmptyUFM
277 delete fm key = del_ele fm
279 del_ele :: UniqFM a -> UniqFM a
281 del_ele lf@(LeafUFM j _)
282 | j _EQ_ key = EmptyUFM
283 | otherwise = lf -- no delete!
285 del_ele nd@(NodeUFM j p t1 t2)
287 = mkSLNodeUFM (NodeUFMData j p) (del_ele t1) t2
289 = mkLSNodeUFM (NodeUFMData j p) t1 (del_ele t2)
291 del_ele _ = panic "Found EmptyUFM FM when rec-deleting"
294 Now ways of adding two UniqFM's together.
297 plusUFM tr1 tr2 = plusUFM_C use_snd tr1 tr2
299 plusUFM_C f EmptyUFM tr = tr
300 plusUFM_C f tr EmptyUFM = tr
301 plusUFM_C f fm1 fm2 = mix_trees fm1 fm2
303 mix_trees (LeafUFM i a) t2 = insert_ele (flip f) t2 i a
304 mix_trees t1 (LeafUFM i a) = insert_ele f t1 i a
306 mix_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
308 (ask_about_common_ancestor
312 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
316 -- t1 t2 t1' t2' j j'
321 mix_branches (NewRoot nd False)
322 = mkLLNodeUFM nd left_t right_t
323 mix_branches (NewRoot nd True)
324 = mkLLNodeUFM nd right_t left_t
330 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
332 mix_branches (SameRoot)
333 = mkSSNodeUFM (NodeUFMData j p)
336 -- Now the 4 different other ways; all like this:
338 -- Given j >^ j' (and, say, j > j')
342 -- t1 t2 t1' t2' t1 t2 + j'
345 mix_branches (LeftRoot Leftt) -- | trace "LL" True
348 (mix_trees t1 right_t)
351 mix_branches (LeftRoot Rightt) -- | trace "LR" True
355 (mix_trees t2 right_t)
357 mix_branches (RightRoot Leftt) -- | trace "RL" True
360 (mix_trees left_t t1')
363 mix_branches (RightRoot Rightt) -- | trace "RR" True
367 (mix_trees left_t t2')
369 mix_trees _ _ = panic "EmptyUFM found when inserting into plusInt"
372 And ways of subtracting them. First the base cases,
373 then the full D&C approach.
376 minusUFM EmptyUFM _ = EmptyUFM
377 minusUFM t1 EmptyUFM = t1
378 minusUFM fm1 fm2 = minus_trees fm1 fm2
381 -- Notice the asymetry of subtraction
383 minus_trees lf@(LeafUFM i a) t2 =
388 minus_trees t1 (LeafUFM i _) = delete t1 i
390 minus_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
392 (ask_about_common_ancestor
396 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
400 -- t1 t2 t1' t2' t1 t2
405 minus_branches (NewRoot nd _) = left_t
411 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
413 minus_branches (SameRoot)
414 = mkSSNodeUFM (NodeUFMData j p)
417 -- Now the 4 different other ways; all like this:
418 -- again, with asymatry
421 -- The left is above the right
423 minus_branches (LeftRoot Leftt)
426 (minus_trees t1 right_t)
428 minus_branches (LeftRoot Rightt)
432 (minus_trees t2 right_t)
435 -- The right is above the left
437 minus_branches (RightRoot Leftt)
438 = minus_trees left_t t1'
439 minus_branches (RightRoot Rightt)
440 = minus_trees left_t t2'
442 minus_trees _ _ = panic "EmptyUFM found when insering into plusInt"
445 And taking the intersection of two UniqFM's.
448 intersectUFM t1 t2 = intersectUFM_C use_snd t1 t2
450 intersectUFM_C f EmptyUFM _ = EmptyUFM
451 intersectUFM_C f _ EmptyUFM = EmptyUFM
452 intersectUFM_C f fm1 fm2 = intersect_trees fm1 fm2
454 intersect_trees (LeafUFM i a) t2 =
457 Just b -> mkLeafUFM i (f a b)
459 intersect_trees t1 (LeafUFM i a) =
462 Just b -> mkLeafUFM i (f b a)
464 intersect_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
466 (ask_about_common_ancestor
470 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
473 -- / \ + / \ ==> EmptyUFM
478 intersect_branches (NewRoot nd _) = EmptyUFM
484 -- t1 t2 t1' t2' t1 x t1' t2 x t2'
486 intersect_branches (SameRoot)
487 = mkSSNodeUFM (NodeUFMData j p)
488 (intersect_trees t1 t1')
489 (intersect_trees t2 t2')
490 -- Now the 4 different other ways; all like this:
492 -- Given j >^ j' (and, say, j > j')
496 -- t1 t2 t1' t2' t1' t2'
498 -- This does cut down the search space quite a bit.
500 intersect_branches (LeftRoot Leftt)
501 = intersect_trees t1 right_t
502 intersect_branches (LeftRoot Rightt)
503 = intersect_trees t2 right_t
504 intersect_branches (RightRoot Leftt)
505 = intersect_trees left_t t1'
506 intersect_branches (RightRoot Rightt)
507 = intersect_trees left_t t2'
509 intersect_trees x y = panic ("EmptyUFM found when intersecting trees")
512 Now the usual set of `collection' operators, like map, fold, etc.
515 foldUFM fn a EmptyUFM = a
516 foldUFM fn a fm = fold_tree fn a fm
518 mapUFM fn EmptyUFM = EmptyUFM
519 mapUFM fn fm = map_tree fn fm
521 filterUFM fn EmptyUFM = EmptyUFM
522 filterUFM fn fm = filter_tree fn fm
525 Note, this takes a long time, O(n), but
526 because we dont want to do this very often, we put up with this.
527 O'rable, but how often do we look at the size of
532 sizeUFM (NodeUFM _ _ t1 t2) = sizeUFM t1 + sizeUFM t2
533 sizeUFM (LeafUFM _ _) = 1
535 isNullUFM EmptyUFM = True
539 looking up in a hurry is the {\em whole point} of this binary tree lark.
540 Lookup up a binary tree is easy (and fast).
543 lookupUFM fm key = lookUp fm (u2i (uniqueOf key))
544 lookupUFM_Directly fm key = lookUp fm (u2i key)
546 lookupWithDefaultUFM fm deflt key
547 = case lookUp fm (u2i (uniqueOf key)) of
551 lookupWithDefaultUFM_Directly fm deflt key
552 = case lookUp fm (u2i key) of
556 lookUp EmptyUFM _ = Nothing
557 lookUp fm i = lookup_tree fm
559 lookup_tree :: UniqFM a -> Maybe a
561 lookup_tree (LeafUFM j b)
563 | otherwise = Nothing
564 lookup_tree (NodeUFM j p t1 t2)
565 | j _GT_ i = lookup_tree t1
566 | otherwise = lookup_tree t2
568 lookup_tree EmptyUFM = panic "lookup Failed"
571 folds are *wonderful* things.
574 eltsUFM EmptyUFM = []
575 eltsUFM fm = fold_tree (:) [] fm
577 ufmToList EmptyUFM = []
579 = fold_tree (\ iu elt rest -> (mkUniqueGrimily iu, elt) : rest) [] fm
581 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
582 fold_tree f a (LeafUFM iu obj) = f iu obj a
584 fold_tree f a EmptyUFM = panic "Should Never fold over an EmptyUFM"
587 %************************************************************************
589 \subsubsection{The @UniqFM@ type, and its functions}
591 %************************************************************************
593 You should always use these to build the tree.
594 There are 4 versions of mkNodeUFM, depending on
595 the strictness of the two sub-tree arguments.
596 The strictness is used *both* to prune out
597 empty trees, *and* to improve performance,
598 stoping needless thunks lying around.
599 The rule of thumb (from experence with these trees)
600 is make thunks strict, but data structures lazy.
601 If in doubt, use mkSSNodeUFM, which has the `strongest'
602 functionality, but may do a few needless evaluations.
605 mkLeafUFM :: FAST_INT -> a -> UniqFM a
606 mkLeafUFM i a = LeafUFM i a
608 -- The *ONLY* ways of building a NodeUFM.
610 mkSSNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
611 mkSSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
612 mkSSNodeUFM (NodeUFMData j p) t1 t2
613 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
616 mkSLNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
617 mkSLNodeUFM (NodeUFMData j p) t1 t2
618 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
621 mkLSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
622 mkLSNodeUFM (NodeUFMData j p) t1 t2
623 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
626 mkLLNodeUFM (NodeUFMData j p) t1 t2
627 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
637 correctNodeUFM j p t1 t2
638 = correct (j-p) (j-1) p t1 && correct j ((j-1)+p) p t2
640 correct low high _ (LeafUFM i _)
641 = low <= IBOX(i) && IBOX(i) <= high
642 correct low high above_p (NodeUFM j p _ _)
643 = low <= IBOX(j) && IBOX(j) <= high && above_p > IBOX(p)
644 correct _ _ _ EmptyUFM = panic "EmptyUFM stored inside a tree"
647 Note: doing SAT on this by hand seems to make it worse. Todo: Investigate,
648 and if necessary do $\lambda$ lifting on our functions that are bound.
658 insert_ele f EmptyUFM i new = mkLeafUFM i new
660 insert_ele f (LeafUFM j old) i new
662 mkLLNodeUFM (getCommonNodeUFMData
667 | j _EQ_ i = mkLeafUFM j (f old new)
669 mkLLNodeUFM (getCommonNodeUFMData
675 insert_ele f n@(NodeUFM j p t1 t2) i a
677 = if (i _GE_ (j _SUB_ p))
678 then mkSLNodeUFM (NodeUFMData j p) (insert_ele f t1 i a) t2
679 else mkLLNodeUFM (getCommonNodeUFMData
685 = if (i _LE_ ((j _SUB_ ILIT(1)) _ADD_ p))
686 then mkLSNodeUFM (NodeUFMData j p) t1 (insert_ele f t2 i a)
687 else mkLLNodeUFM (getCommonNodeUFMData
694 This has got a left to right ordering.
697 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
698 fold_tree f a (LeafUFM _ obj) = f obj a
700 fold_tree f a EmptyUFM = panic "Should Never fold over an EmptyUFM"
704 map_tree f (NodeUFM j p t1 t2)
705 = mkSSNodeUFM (NodeUFMData j p) (map_tree f t1) (map_tree f t2)
706 map_tree f (LeafUFM i obj)
707 = mkLeafUFM i (f obj)
709 map_tree f _ = panic "map_tree failed"
713 filter_tree f nd@(NodeUFM j p t1 t2)
714 = mkSSNodeUFM (NodeUFMData j p) (filter_tree f t1) (filter_tree f t2)
716 filter_tree f lf@(LeafUFM i obj)
718 | otherwise = EmptyUFM
721 %************************************************************************
723 \subsubsection{The @UniqFM@ type, and signatures for the functions}
725 %************************************************************************
729 This is the information that is held inside a NodeUFM, packaged up for
734 = NodeUFMData FAST_INT
738 This is the information used when computing new NodeUFMs.
741 data Side = Leftt | Rightt -- NB: avoid 1.3 names "Left" and "Right"
743 = LeftRoot Side -- which side is the right down ?
744 | RightRoot Side -- which side is the left down ?
745 | SameRoot -- they are the same !
746 | NewRoot NodeUFMData -- here's the new, common, root
747 Bool -- do you need to swap left and right ?
750 This specifies the relationship between NodeUFMData and CalcNodeUFMData.
753 indexToRoot :: FAST_INT -> NodeUFMData
757 l = (ILIT(1) :: FAST_INT)
759 NodeUFMData (((i `shiftR_` l) `shiftL_` l) _ADD_ ILIT(1)) l
761 getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData
763 getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
764 | p _EQ_ p2 = getCommonNodeUFMData_ p j j2
765 | p _LT_ p2 = getCommonNodeUFMData_ p2 (j _QUOT_ (p2 _QUOT_ p)) j2
766 | otherwise = getCommonNodeUFMData_ p j (j2 _QUOT_ (p _QUOT_ p2))
768 l = (ILIT(1) :: FAST_INT)
769 j = i _QUOT_ (p `shiftL_` l)
770 j2 = i2 _QUOT_ (p2 `shiftL_` l)
772 getCommonNodeUFMData_ :: FAST_INT -> FAST_INT -> FAST_INT -> NodeUFMData
774 getCommonNodeUFMData_ p j j_
776 = NodeUFMData (((j `shiftL_` l) _ADD_ l) _MUL_ p) p
778 = getCommonNodeUFMData_ (p `shiftL_` l) (j `shiftR_` l) (j_ `shiftR_` l)
780 ask_about_common_ancestor :: NodeUFMData -> NodeUFMData -> CommonRoot
782 ask_about_common_ancestor x@(NodeUFMData j p) y@(NodeUFMData j2 p2)
783 | j _EQ_ j2 = SameRoot
785 = case getCommonNodeUFMData x y of
786 nd@(NodeUFMData j3 p3)
787 | j3 _EQ_ j -> LeftRoot (decideSide (j _GT_ j2))
788 | j3 _EQ_ j2 -> RightRoot (decideSide (j _LT_ j2))
789 | otherwise -> NewRoot nd (j _GT_ j2)
791 decideSide :: Bool -> Side
792 decideSide True = Leftt
793 decideSide False = Rightt
796 This might be better in Util.lhs ?
799 Now the bit twiddling functions.
801 shiftL_ :: FAST_INT -> FAST_INT -> FAST_INT
802 shiftR_ :: FAST_INT -> FAST_INT -> FAST_INT
804 #if __GLASGOW_HASKELL__
805 {-# INLINE shiftL_ #-}
806 {-# INLINE shiftR_ #-}
807 shiftL_ n p = word2Int#((int2Word# n) `shiftL#` p)
808 shiftR_ n p = word2Int#((int2Word# n) `shiftr` p)
810 shiftr x y = shiftRA# x y
813 shiftL_ n p = n * (2 ^ p)
814 shiftR_ n p = n `quot` (2 ^ p)
820 use_snd :: a -> b -> b