Remove ufmToList
authorBartosz Nitka <niteria@gmail.com>
Thu, 30 Jun 2016 15:20:41 +0000 (08:20 -0700)
committerBartosz Nitka <niteria@gmail.com>
Thu, 30 Jun 2016 17:22:41 +0000 (10:22 -0700)
This documents nondeterminism in code generation and removes
the nondeterministic ufmToList function. In the future someone
will have to use nonDetUFMToList (with proper explanation)
or pprUFMWithKeys.

compiler/nativeGen/RegAlloc/Graph/Stats.hs
compiler/nativeGen/RegAlloc/Linear/JoinToTargets.hs
compiler/nativeGen/RegAlloc/Linear/Main.hs
compiler/nativeGen/RegAlloc/Linear/Stats.hs
compiler/nativeGen/RegAlloc/Liveness.hs
compiler/utils/UniqDFM.hs
compiler/utils/UniqFM.hs

index 07f4266..cfd8f83 100644 (file)
@@ -129,7 +129,7 @@ instance (Outputable statics, Outputable instr)
 
         $$ (if (not $ isNullUFM $ raCoalesced s)
                 then    text "#  Registers coalesced."
-                        $$ (vcat $ map ppr $ ufmToList $ raCoalesced s)
+                        $$ (pprUFMWithKeys (raCoalesced s) (vcat . map ppr))
                         $$ text ""
                 else empty)
 
@@ -160,7 +160,7 @@ instance (Outputable statics, Outputable instr)
 
         $$ (if (not $ isNullUFM $ raCoalesced s)
                 then    text "#  Registers coalesced."
-                        $$ (vcat $ map ppr $ ufmToList $ raCoalesced s)
+                        $$ (pprUFMWithKeys (raCoalesced s) (vcat . map ppr))
                         $$ text ""
                 else empty)
 
index ac38e2b..294608a 100644 (file)
@@ -87,7 +87,10 @@ joinToTargets' block_live new_blocks block_id instr (dest:dests)
 
         -- and free up those registers which are now free.
         let to_free =
-                [ r     | (reg, loc) <- ufmToList assig
+                [ r     | (reg, loc) <- nonDetUFMToList assig
+                        -- This is non-deterministic but we do not
+                        -- currently support deterministic code-generation.
+                        -- See Note [Unique Determinism and code generation]
                         , not (elemUniqSet_Directly reg live_set)
                         , r          <- regsOfLoc loc ]
 
@@ -148,7 +151,10 @@ joinToTargets_again
     src_assig dest_assig
 
         -- the assignments already match, no problem.
-        | ufmToList dest_assig == ufmToList src_assig
+        | nonDetUFMToList dest_assig == nonDetUFMToList src_assig
+        -- This is non-deterministic but we do not
+        -- currently support deterministic code-generation.
+        -- See Note [Unique Determinism and code generation]
         = joinToTargets' block_live new_blocks block_id instr dests
 
         -- assignments don't match, need fixup code
@@ -223,7 +229,10 @@ joinToTargets_again
 --
 makeRegMovementGraph :: RegMap Loc -> RegMap Loc -> [(Unique, Loc, [Loc])]
 makeRegMovementGraph adjusted_assig dest_assig
- = [ node       | (vreg, src) <- ufmToList adjusted_assig
+ = [ node       | (vreg, src) <- nonDetUFMToList adjusted_assig
+                    -- This is non-deterministic but we do not
+                    -- currently support deterministic code-generation.
+                    -- See Note [Unique Determinism and code generation]
                     -- source reg might not be needed at the dest:
                 , Just loc <- [lookupUFM_Directly dest_assig vreg]
                 , node <- expandNode vreg src loc ]
index edb2394..3e2edc7 100644 (file)
@@ -620,7 +620,10 @@ saveClobberedTemps clobbered dying
         assig   <- getAssigR
         let to_spill
                 = [ (temp,reg)
-                        | (temp, InReg reg) <- ufmToList assig
+                        | (temp, InReg reg) <- nonDetUFMToList assig
+                        -- This is non-deterministic but we do not
+                        -- currently support deterministic code-generation.
+                        -- See Note [Unique Determinism and code generation]
                         , any (realRegsAlias reg) clobbered
                         , temp `notElem` map getUnique dying  ]
 
@@ -682,7 +685,10 @@ clobberRegs clobbered
         setFreeRegsR $! foldr (frAllocateReg platform) freeregs clobbered
 
         assig           <- getAssigR
-        setAssigR $! clobber assig (ufmToList assig)
+        setAssigR $! clobber assig (nonDetUFMToList assig)
+          -- This is non-deterministic but we do not
+          -- currently support deterministic code-generation.
+          -- See Note [Unique Determinism and code generation]
 
    where
         -- if the temp was InReg and clobbered, then we will have
@@ -802,17 +808,23 @@ allocRegsAndSpill_spill reading keep spills alloc r rs assig spill_loc
                 -- the vregs we could kick out that are already in a slot
                 let candidates_inBoth
                         = [ (temp, reg, mem)
-                                | (temp, InBoth reg mem) <- ufmToList assig
-                                , temp `notElem` keep'
-                                , targetClassOfRealReg platform reg == classOfVirtualReg r ]
+                          | (temp, InBoth reg mem) <- nonDetUFMToList assig
+                          -- This is non-deterministic but we do not
+                          -- currently support deterministic code-generation.
+                          -- See Note [Unique Determinism and code generation]
+                          , temp `notElem` keep'
+                          , targetClassOfRealReg platform reg == classOfVirtualReg r ]
 
                 -- the vregs we could kick out that are only in a reg
                 --      this would require writing the reg to a new slot before using it.
                 let candidates_inReg
                         = [ (temp, reg)
-                                | (temp, InReg reg)     <- ufmToList assig
-                                , temp `notElem` keep'
-                                , targetClassOfRealReg platform reg == classOfVirtualReg r ]
+                          | (temp, InReg reg) <- nonDetUFMToList assig
+                          -- This is non-deterministic but we do not
+                          -- currently support deterministic code-generation.
+                          -- See Note [Unique Determinism and code generation]
+                          , temp `notElem` keep'
+                          , targetClassOfRealReg platform reg == classOfVirtualReg r ]
 
                 let result
 
@@ -857,7 +869,7 @@ allocRegsAndSpill_spill reading keep spills alloc r rs assig spill_loc
                         = pprPanic ("RegAllocLinear.allocRegsAndSpill: no spill candidates\n")
                         $ vcat
                                 [ text "allocating vreg:  " <> text (show r)
-                                , text "assignment:       " <> text (show $ ufmToList assig)
+                                , text "assignment:       " <> ppr assig
                                 , text "freeRegs:         " <> text (show freeRegs)
                                 , text "initFreeRegs:     " <> text (show (frInitFreeRegs platform `asTypeOf` freeRegs)) ]
 
index b7d93f4..c55df6b 100644 (file)
@@ -80,7 +80,6 @@ pprStats code statss
         $$ text ""
         $$ text "-- spills-added"
         $$ text "--    (reg_name, allocs, clobbers, loads, joinRR, joinRM)"
-        $$ (vcat $ map pprSpill
-                 $ ufmToList spills)
+        $$ (pprUFMWithKeys spills (vcat . map pprSpill))
         $$ text "")
 
index b972460..e4a903e 100644 (file)
@@ -462,10 +462,14 @@ slurpReloadCoalesce live
         mergeSlotMaps :: UniqFM Reg -> UniqFM Reg -> UniqFM Reg
         mergeSlotMaps map1 map2
                 = listToUFM
-                $ [ (k, r1)     | (k, r1)       <- ufmToList map1
-                                , case lookupUFM map2 k of
-                                        Nothing -> False
-                                        Just r2 -> r1 == r2 ]
+                $ [ (k, r1)
+                  | (k, r1) <- nonDetUFMToList map1
+                  -- This is non-deterministic but we do not
+                  -- currently support deterministic code-generation.
+                  -- See Note [Unique Determinism and code generation]
+                  , case lookupUFM map2 k of
+                          Nothing -> False
+                          Just r2 -> r1 == r2 ]
 
 
 -- | Strip away liveness information, yielding NatCmmDecl
index 8ed1451..bbf6bb0 100644 (file)
@@ -66,7 +66,7 @@ import qualified Data.IntMap as M
 import Data.Data
 import Data.List (sortBy)
 import Data.Function (on)
-import UniqFM (UniqFM, listToUFM_Directly, ufmToList, ufmToIntMap)
+import UniqFM (UniqFM, listToUFM_Directly, nonDetUFMToList, ufmToIntMap)
 
 -- Note [Deterministic UniqFM]
 -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -372,7 +372,7 @@ instance Monoid (UniqDFM a) where
 -- This should not be used in commited code, provided for convenience to
 -- make ad-hoc conversions when developing
 alwaysUnsafeUfmToUdfm :: UniqFM elt -> UniqDFM elt
-alwaysUnsafeUfmToUdfm = listToUDFM_Directly . ufmToList
+alwaysUnsafeUfmToUdfm = listToUDFM_Directly . nonDetUFMToList
 
 -- Output-ery
 
index f9832d5..261dd1c 100644 (file)
@@ -64,8 +64,8 @@ module UniqFM (
         lookupWithDefaultUFM, lookupWithDefaultUFM_Directly,
         nonDetEltsUFM, eltsUFM, nonDetKeysUFM,
         ufmToSet_Directly,
-        nonDetUFMToList, ufmToList, ufmToIntMap,
-        pprUniqFM, pprUFM, pluralUFM
+        nonDetUFMToList, ufmToIntMap,
+        pprUniqFM, pprUFM, pprUFMWithKeys, pluralUFM
     ) where
 
 import Unique           ( Uniquable(..), Unique, getKey )
@@ -184,7 +184,6 @@ lookupWithDefaultUFM_Directly
                 :: UniqFM elt -> elt -> Unique -> elt
 eltsUFM         :: UniqFM elt -> [elt]
 ufmToSet_Directly :: UniqFM elt -> S.IntSet
-ufmToList       :: UniqFM elt -> [(Unique, elt)]
 
 {-
 ************************************************************************
@@ -286,7 +285,6 @@ lookupWithDefaultUFM (UFM m) v k = M.findWithDefault v (getKey $ getUnique k) m
 lookupWithDefaultUFM_Directly (UFM m) v u = M.findWithDefault v (getKey u) m
 eltsUFM (UFM m) = M.elems m
 ufmToSet_Directly (UFM m) = M.keysSet m
-ufmToList (UFM m) = map (\(k, v) -> (getUnique k, v)) $ M.toList m
 
 anyUFM :: (elt -> Bool) -> UniqFM elt -> Bool
 anyUFM p (UFM m) = M.fold ((||) . p) False m
@@ -357,6 +355,18 @@ pprUFM :: UniqFM a      -- ^ The things to be pretty printed
                         -- printed
 pprUFM ufm pp = pp (nonDetEltsUFM ufm)
 
+-- | Pretty-print a non-deterministic set.
+-- The order of variables is non-deterministic and for pretty-printing that
+-- shouldn't be a problem.
+-- Having this function helps contain the non-determinism created with
+-- nonDetUFMToList.
+pprUFMWithKeys
+       :: UniqFM a                -- ^ The things to be pretty printed
+       -> ([(Unique, a)] -> SDoc) -- ^ The pretty printing function to use on the elements
+       -> SDoc                    -- ^ 'SDoc' where the things have been pretty
+                                  -- printed
+pprUFMWithKeys ufm pp = pp (nonDetUFMToList ufm)
+
 -- | Determines the pluralisation suffix appropriate for the length of a set
 -- in the same way that plural from Outputable does for lists.
 pluralUFM :: UniqFM a -> SDoc