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 )
62 import Unique ( Unique, u2i, mkUniqueGrimily )
65 import Outputable ( PprStyle, Outputable(..) )
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 keysUFM :: UniqFM elt -> [Int] -- Get the keys
133 eltsUFM :: UniqFM elt -> [elt]
134 ufmToList :: UniqFM elt -> [(Unique, elt)]
137 %************************************************************************
139 \subsection{The @IdFinMap@ and @TyVarFinMap@ specialisations for Ids/TyVars}
141 %************************************************************************
144 #ifdef __GLASGOW_HASKELL__
145 -- I don't think HBC was too happy about this (WDP 94/10)
148 addListToUFM :: UniqFM elt -> [(Name, elt)] -> UniqFM elt
151 addListToUFM_C :: (elt -> elt -> elt) -> UniqFM elt -> [(Name, elt)] -> UniqFM elt
154 addToUFM :: UniqFM elt -> Unique -> elt -> UniqFM elt
157 listToUFM :: [(Unique, elt)] -> UniqFM elt
160 lookupUFM :: UniqFM elt -> Name -> Maybe elt
161 , UniqFM elt -> Unique -> Maybe elt
164 #endif {- __GLASGOW_HASKELL__ -}
167 %************************************************************************
169 \subsection{Andy Gill's underlying @UniqFM@ machinery}
171 %************************************************************************
173 ``Uniq Finite maps'' are the heart and soul of the compiler's
174 lookup-tables/environments. Important stuff! It works well with
175 Dense and Sparse ranges.
176 Both @Uq@ Finite maps and @Hash@ Finite Maps
177 are built ontop of Int Finite Maps.
179 This code is explained in the paper:
181 A Gill, S Peyton Jones, B O'Sullivan, W Partain and Aqua Friends
182 "A Cheap balancing act that grows on a tree"
183 Glasgow FP Workshop, Sep 1994, pp??-??
186 %************************************************************************
188 \subsubsection{The @UniqFM@ type, and signatures for the functions}
190 %************************************************************************
192 @UniqFM a@ is a mapping from Unique to a.
194 First, the DataType itself; which is either a Node, a Leaf, or an Empty.
199 | LeafUFM FAST_INT ele
200 | NodeUFM FAST_INT -- the switching
201 FAST_INT -- the delta
205 class Uniquable a where
206 uniqueOf :: a -> Unique
208 -- for debugging only :-)
210 instance Text (UniqFM a) where
211 showsPrec _ (NodeUFM a b t1 t2) =
212 showString "NodeUFM " . shows (IBOX(a))
213 . showString " " . shows (IBOX(b))
214 . showString " (" . shows t1
215 . showString ") (" . shows t2
217 showsPrec _ (LeafUFM x a) = showString "LeafUFM " . shows (IBOX(x))
218 showsPrec _ (EmptyUFM) = id
222 %************************************************************************
224 \subsubsection{The @UniqFM@ functions}
226 %************************************************************************
228 First the ways of building a UniqFM.
232 unitUFM key elt = mkLeafUFM (u2i (uniqueOf key)) elt
233 unitDirectlyUFM key elt = mkLeafUFM (u2i key) elt
235 listToUFM key_elt_pairs
236 = addListToUFM_C use_snd EmptyUFM key_elt_pairs
238 listToUFM_Directly uniq_elt_pairs
239 = addListToUFM_directly_C use_snd EmptyUFM uniq_elt_pairs
242 Now ways of adding things to UniqFMs.
244 There is an alternative version of @addListToUFM_C@, that uses @plusUFM@,
245 but the semantics of this operation demands a linear insertion;
246 perhaps the version without the combinator function
247 could be optimised using it.
250 addToUFM fm key elt = addToUFM_C use_snd fm key elt
252 addToUFM_Directly fm u elt = insert_ele use_snd fm (u2i u) elt
254 addToUFM_C combiner fm key elt
255 = insert_ele combiner fm (u2i (uniqueOf key)) elt
257 addListToUFM fm key_elt_pairs = addListToUFM_C use_snd fm key_elt_pairs
258 addListToUFM_Directly fm uniq_elt_pairs = addListToUFM_directly_C use_snd fm uniq_elt_pairs
260 addListToUFM_C combiner fm key_elt_pairs
261 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i (uniqueOf k)) e)
264 addListToUFM_directly_C combiner fm uniq_elt_pairs
265 = foldl (\ fm (k, e) -> insert_ele combiner fm (u2i k) e)
269 Now ways of removing things from UniqFM.
272 delListFromUFM fm lst = foldl delFromUFM fm lst
274 delFromUFM fm key = delete fm (u2i (uniqueOf key))
275 delFromUFM_Directly fm u = delete fm (u2i u)
277 delete EmptyUFM _ = EmptyUFM
278 delete fm key = del_ele fm
280 del_ele :: UniqFM a -> UniqFM a
282 del_ele lf@(LeafUFM j _)
283 | j _EQ_ key = EmptyUFM
284 | otherwise = lf -- no delete!
286 del_ele nd@(NodeUFM j p t1 t2)
288 = mkSLNodeUFM (NodeUFMData j p) (del_ele t1) t2
290 = mkLSNodeUFM (NodeUFMData j p) t1 (del_ele t2)
292 del_ele _ = panic "Found EmptyUFM FM when rec-deleting"
295 Now ways of adding two UniqFM's together.
298 plusUFM tr1 tr2 = plusUFM_C use_snd tr1 tr2
300 plusUFM_C f EmptyUFM tr = tr
301 plusUFM_C f tr EmptyUFM = tr
302 plusUFM_C f fm1 fm2 = mix_trees fm1 fm2
304 mix_trees (LeafUFM i a) t2 = insert_ele (flip f) t2 i a
305 mix_trees t1 (LeafUFM i a) = insert_ele f t1 i a
307 mix_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
309 (ask_about_common_ancestor
313 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
317 -- t1 t2 t1' t2' j j'
322 mix_branches (NewRoot nd False)
323 = mkLLNodeUFM nd left_t right_t
324 mix_branches (NewRoot nd True)
325 = mkLLNodeUFM nd right_t left_t
331 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
333 mix_branches (SameRoot)
334 = mkSSNodeUFM (NodeUFMData j p)
337 -- Now the 4 different other ways; all like this:
339 -- Given j >^ j' (and, say, j > j')
343 -- t1 t2 t1' t2' t1 t2 + j'
346 mix_branches (LeftRoot Leftt) -- | trace "LL" True
349 (mix_trees t1 right_t)
352 mix_branches (LeftRoot Rightt) -- | trace "LR" True
356 (mix_trees t2 right_t)
358 mix_branches (RightRoot Leftt) -- | trace "RL" True
361 (mix_trees left_t t1')
364 mix_branches (RightRoot Rightt) -- | trace "RR" True
368 (mix_trees left_t t2')
370 mix_trees _ _ = panic "EmptyUFM found when inserting into plusInt"
373 And ways of subtracting them. First the base cases,
374 then the full D&C approach.
377 minusUFM EmptyUFM _ = EmptyUFM
378 minusUFM t1 EmptyUFM = t1
379 minusUFM fm1 fm2 = minus_trees fm1 fm2
382 -- Notice the asymetry of subtraction
384 minus_trees lf@(LeafUFM i a) t2 =
389 minus_trees t1 (LeafUFM i _) = delete t1 i
391 minus_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
393 (ask_about_common_ancestor
397 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
401 -- t1 t2 t1' t2' t1 t2
406 minus_branches (NewRoot nd _) = left_t
412 -- t1 t2 t1' t2' t1 + t1' t2 + t2'
414 minus_branches (SameRoot)
415 = mkSSNodeUFM (NodeUFMData j p)
418 -- Now the 4 different other ways; all like this:
419 -- again, with asymatry
422 -- The left is above the right
424 minus_branches (LeftRoot Leftt)
427 (minus_trees t1 right_t)
429 minus_branches (LeftRoot Rightt)
433 (minus_trees t2 right_t)
436 -- The right is above the left
438 minus_branches (RightRoot Leftt)
439 = minus_trees left_t t1'
440 minus_branches (RightRoot Rightt)
441 = minus_trees left_t t2'
443 minus_trees _ _ = panic "EmptyUFM found when insering into plusInt"
446 And taking the intersection of two UniqFM's.
449 intersectUFM t1 t2 = intersectUFM_C use_snd t1 t2
451 intersectUFM_C f EmptyUFM _ = EmptyUFM
452 intersectUFM_C f _ EmptyUFM = EmptyUFM
453 intersectUFM_C f fm1 fm2 = intersect_trees fm1 fm2
455 intersect_trees (LeafUFM i a) t2 =
458 Just b -> mkLeafUFM i (f a b)
460 intersect_trees t1 (LeafUFM i a) =
463 Just b -> mkLeafUFM i (f b a)
465 intersect_trees left_t@(NodeUFM j p t1 t2) right_t@(NodeUFM j' p' t1' t2')
467 (ask_about_common_ancestor
471 -- Given a disjoint j,j' (p >^ p' && p' >^ p):
474 -- / \ + / \ ==> EmptyUFM
479 intersect_branches (NewRoot nd _) = EmptyUFM
485 -- t1 t2 t1' t2' t1 x t1' t2 x t2'
487 intersect_branches (SameRoot)
488 = mkSSNodeUFM (NodeUFMData j p)
489 (intersect_trees t1 t1')
490 (intersect_trees t2 t2')
491 -- Now the 4 different other ways; all like this:
493 -- Given j >^ j' (and, say, j > j')
497 -- t1 t2 t1' t2' t1' t2'
499 -- This does cut down the search space quite a bit.
501 intersect_branches (LeftRoot Leftt)
502 = intersect_trees t1 right_t
503 intersect_branches (LeftRoot Rightt)
504 = intersect_trees t2 right_t
505 intersect_branches (RightRoot Leftt)
506 = intersect_trees left_t t1'
507 intersect_branches (RightRoot Rightt)
508 = intersect_trees left_t t2'
510 intersect_trees x y = panic ("EmptyUFM found when intersecting trees")
513 Now the usual set of `collection' operators, like map, fold, etc.
516 foldUFM f a (NodeUFM _ _ t1 t2) = foldUFM f (foldUFM f a t2) t1
517 foldUFM f a (LeafUFM _ obj) = f obj a
518 foldUFM f a EmptyUFM = a
522 mapUFM fn EmptyUFM = EmptyUFM
523 mapUFM fn fm = map_tree fn fm
525 filterUFM fn EmptyUFM = EmptyUFM
526 filterUFM fn fm = filter_tree fn fm
529 Note, this takes a long time, O(n), but
530 because we dont want to do this very often, we put up with this.
531 O'rable, but how often do we look at the size of
536 sizeUFM (NodeUFM _ _ t1 t2) = sizeUFM t1 + sizeUFM t2
537 sizeUFM (LeafUFM _ _) = 1
539 isNullUFM EmptyUFM = True
543 looking up in a hurry is the {\em whole point} of this binary tree lark.
544 Lookup up a binary tree is easy (and fast).
547 lookupUFM fm key = lookUp fm (u2i (uniqueOf key))
548 lookupUFM_Directly fm key = lookUp fm (u2i key)
550 lookupWithDefaultUFM fm deflt key
551 = case lookUp fm (u2i (uniqueOf key)) of
555 lookupWithDefaultUFM_Directly fm deflt key
556 = case lookUp fm (u2i key) of
560 lookUp EmptyUFM _ = Nothing
561 lookUp fm i = lookup_tree fm
563 lookup_tree :: UniqFM a -> Maybe a
565 lookup_tree (LeafUFM j b)
567 | otherwise = Nothing
568 lookup_tree (NodeUFM j p t1 t2)
569 | j _GT_ i = lookup_tree t1
570 | otherwise = lookup_tree t2
572 lookup_tree EmptyUFM = panic "lookup Failed"
575 folds are *wonderful* things.
578 eltsUFM fm = foldUFM (:) [] fm
580 ufmToList fm = fold_tree (\ iu elt rest -> (mkUniqueGrimily iu, elt) : rest) [] fm
582 keysUFM fm = fold_tree (\ iu elt rest -> IBOX(iu) : rest) [] fm
584 fold_tree f a (NodeUFM _ _ t1 t2) = fold_tree f (fold_tree f a t2) t1
585 fold_tree f a (LeafUFM iu obj) = f iu obj a
586 fold_tree f a EmptyUFM = a
589 %************************************************************************
591 \subsubsection{The @UniqFM@ type, and its functions}
593 %************************************************************************
595 You should always use these to build the tree.
596 There are 4 versions of mkNodeUFM, depending on
597 the strictness of the two sub-tree arguments.
598 The strictness is used *both* to prune out
599 empty trees, *and* to improve performance,
600 stoping needless thunks lying around.
601 The rule of thumb (from experence with these trees)
602 is make thunks strict, but data structures lazy.
603 If in doubt, use mkSSNodeUFM, which has the `strongest'
604 functionality, but may do a few needless evaluations.
607 mkLeafUFM :: FAST_INT -> a -> UniqFM a
608 mkLeafUFM i a = LeafUFM i a
610 -- The *ONLY* ways of building a NodeUFM.
612 mkSSNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
613 mkSSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
614 mkSSNodeUFM (NodeUFMData j p) t1 t2
615 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
618 mkSLNodeUFM (NodeUFMData j p) EmptyUFM t2 = t2
619 mkSLNodeUFM (NodeUFMData j p) t1 t2
620 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
623 mkLSNodeUFM (NodeUFMData j p) t1 EmptyUFM = t1
624 mkLSNodeUFM (NodeUFMData j p) t1 t2
625 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
628 mkLLNodeUFM (NodeUFMData j p) t1 t2
629 = ASSERT(correctNodeUFM (IBOX(j)) (IBOX(p)) t1 t2)
639 correctNodeUFM j p t1 t2
640 = correct (j-p) (j-1) p t1 && correct j ((j-1)+p) p t2
642 correct low high _ (LeafUFM i _)
643 = low <= IBOX(i) && IBOX(i) <= high
644 correct low high above_p (NodeUFM j p _ _)
645 = low <= IBOX(j) && IBOX(j) <= high && above_p > IBOX(p)
646 correct _ _ _ EmptyUFM = panic "EmptyUFM stored inside a tree"
649 Note: doing SAT on this by hand seems to make it worse. Todo: Investigate,
650 and if necessary do $\lambda$ lifting on our functions that are bound.
660 insert_ele f EmptyUFM i new = mkLeafUFM i new
662 insert_ele f (LeafUFM j old) i new
664 mkLLNodeUFM (getCommonNodeUFMData
669 | j _EQ_ i = mkLeafUFM j (f old new)
671 mkLLNodeUFM (getCommonNodeUFMData
677 insert_ele f n@(NodeUFM j p t1 t2) i a
679 = if (i _GE_ (j _SUB_ p))
680 then mkSLNodeUFM (NodeUFMData j p) (insert_ele f t1 i a) t2
681 else mkLLNodeUFM (getCommonNodeUFMData
687 = if (i _LE_ ((j _SUB_ ILIT(1)) _ADD_ p))
688 then mkLSNodeUFM (NodeUFMData j p) t1 (insert_ele f t2 i a)
689 else mkLLNodeUFM (getCommonNodeUFMData
699 map_tree f (NodeUFM j p t1 t2)
700 = mkSSNodeUFM (NodeUFMData j p) (map_tree f t1) (map_tree f t2)
701 map_tree f (LeafUFM i obj)
702 = mkLeafUFM i (f obj)
704 map_tree f _ = panic "map_tree failed"
708 filter_tree f nd@(NodeUFM j p t1 t2)
709 = mkSSNodeUFM (NodeUFMData j p) (filter_tree f t1) (filter_tree f t2)
711 filter_tree f lf@(LeafUFM i obj)
713 | otherwise = EmptyUFM
714 filter_tree f _ = panic "filter_tree failed"
717 %************************************************************************
719 \subsubsection{The @UniqFM@ type, and signatures for the functions}
721 %************************************************************************
725 This is the information that is held inside a NodeUFM, packaged up for
730 = NodeUFMData FAST_INT
734 This is the information used when computing new NodeUFMs.
737 data Side = Leftt | Rightt -- NB: avoid 1.3 names "Left" and "Right"
739 = LeftRoot Side -- which side is the right down ?
740 | RightRoot Side -- which side is the left down ?
741 | SameRoot -- they are the same !
742 | NewRoot NodeUFMData -- here's the new, common, root
743 Bool -- do you need to swap left and right ?
746 This specifies the relationship between NodeUFMData and CalcNodeUFMData.
749 indexToRoot :: FAST_INT -> NodeUFMData
753 l = (ILIT(1) :: FAST_INT)
755 NodeUFMData (((i `shiftR_` l) `shiftL_` l) _ADD_ ILIT(1)) l
757 getCommonNodeUFMData :: NodeUFMData -> NodeUFMData -> NodeUFMData
759 getCommonNodeUFMData (NodeUFMData i p) (NodeUFMData i2 p2)
760 | p _EQ_ p2 = getCommonNodeUFMData_ p j j2
761 | p _LT_ p2 = getCommonNodeUFMData_ p2 (j _QUOT_ (p2 _QUOT_ p)) j2
762 | otherwise = getCommonNodeUFMData_ p j (j2 _QUOT_ (p _QUOT_ p2))
764 l = (ILIT(1) :: FAST_INT)
765 j = i _QUOT_ (p `shiftL_` l)
766 j2 = i2 _QUOT_ (p2 `shiftL_` l)
768 getCommonNodeUFMData_ :: FAST_INT -> FAST_INT -> FAST_INT -> NodeUFMData
770 getCommonNodeUFMData_ p j j_
772 = NodeUFMData (((j `shiftL_` l) _ADD_ l) _MUL_ p) p
774 = getCommonNodeUFMData_ (p `shiftL_` l) (j `shiftR_` l) (j_ `shiftR_` l)
776 ask_about_common_ancestor :: NodeUFMData -> NodeUFMData -> CommonRoot
778 ask_about_common_ancestor x@(NodeUFMData j p) y@(NodeUFMData j2 p2)
779 | j _EQ_ j2 = SameRoot
781 = case getCommonNodeUFMData x y of
782 nd@(NodeUFMData j3 p3)
783 | j3 _EQ_ j -> LeftRoot (decideSide (j _GT_ j2))
784 | j3 _EQ_ j2 -> RightRoot (decideSide (j _LT_ j2))
785 | otherwise -> NewRoot nd (j _GT_ j2)
787 decideSide :: Bool -> Side
788 decideSide True = Leftt
789 decideSide False = Rightt
792 This might be better in Util.lhs ?
795 Now the bit twiddling functions.
797 shiftL_ :: FAST_INT -> FAST_INT -> FAST_INT
798 shiftR_ :: FAST_INT -> FAST_INT -> FAST_INT
800 #if __GLASGOW_HASKELL__
801 {-# INLINE shiftL_ #-}
802 {-# INLINE shiftR_ #-}
803 shiftL_ n p = word2Int#((int2Word# n) `shiftL#` p)
804 shiftR_ n p = word2Int#((int2Word# n) `shiftr` p)
806 shiftr x y = shiftRA# x y
809 shiftL_ n p = n * (2 ^ p)
810 shiftR_ n p = n `quot` (2 ^ p)
816 use_snd :: a -> b -> b