Simon Jakobi pushed to branch wip/sjakobi/T27619-liveness-fixpoint-formats at Glasgow Haskell Compiler / GHC

Commits:

4 changed files:

Changes:

  • compiler/GHC/CmmToAsm/Format.hs
    ... ... @@ -23,6 +23,7 @@ module GHC.CmmToAsm.Format (
    23 23
         vecFormat,
    
    24 24
         isVecFormat,
    
    25 25
         cmmTypeFormat,
    
    26
    +    compareFormat,
    
    26 27
         formatToWidth,
    
    27 28
         scalarWidth,
    
    28 29
         formatInBytes,
    
    ... ... @@ -40,11 +41,13 @@ where
    40 41
     
    
    41 42
     import GHC.Prelude
    
    42 43
     
    
    44
    +import Data.Semigroup ( (<>) )
    
    45
    +
    
    43 46
     import GHC.Cmm
    
    44 47
     import GHC.Platform.Reg ( Reg(..), RealReg, VirtualReg )
    
    45 48
     import GHC.Types.Unique ( Uniquable(..) )
    
    46 49
     import GHC.Types.Unique.Set
    
    47
    -import GHC.Utils.Outputable
    
    50
    +import GHC.Utils.Outputable hiding ( (<>) )
    
    48 51
     import GHC.Utils.Panic
    
    49 52
     
    
    50 53
     {- Note [GHC's data format representations]
    
    ... ... @@ -92,7 +95,9 @@ data Format
    92 95
             | FF64
    
    93 96
             | VecFormat !Length       -- ^ number of elements (always at least 2)
    
    94 97
                         !ScalarFormat -- ^ format of each element
    
    95
    -        deriving (Show, Eq, Ord)
    
    98
    +        deriving (Show, Eq)
    
    99
    +        -- No Ord: compare via 'formatToWidth', or use 'compareFormat' where a
    
    100
    +        -- total order is needed.
    
    96 101
     
    
    97 102
     pattern IntegerFormat :: Format
    
    98 103
     pattern IntegerFormat <- ( isIntegerFormat -> True )
    
    ... ... @@ -117,7 +122,7 @@ data ScalarFormat
    117 122
       | FmtInt64
    
    118 123
       | FmtFloat
    
    119 124
       | FmtDouble
    
    120
    -  deriving (Show, Eq, Ord)
    
    125
    +  deriving (Show, Eq)
    
    121 126
     
    
    122 127
     scalarFormatFormat :: ScalarFormat -> Format
    
    123 128
     scalarFormatFormat = \case
    
    ... ... @@ -248,6 +253,33 @@ scalarWidth = \case
    248 253
     formatInBytes :: Format -> Int
    
    249 254
     formatInBytes = widthInBytes . formatToWidth
    
    250 255
     
    
    256
    +-- | Total order on formats: by width, with an arbitrary but fixed tiebreak
    
    257
    +-- between distinct formats of the same width.
    
    258
    +--
    
    259
    +-- See Note [Convergence of the liveness fixpoint] in GHC.CmmToAsm.Reg.Liveness.
    
    260
    +compareFormat :: Format -> Format -> Ordering
    
    261
    +compareFormat f1 f2 =
    
    262
    +    compare (formatToWidth f1) (formatToWidth f2) <> compare (tag f1) (tag f2)
    
    263
    +  where
    
    264
    +    tag :: Format -> (Int, Length)
    
    265
    +    tag = \case
    
    266
    +      II8           -> (0, 0)
    
    267
    +      II16          -> (1, 0)
    
    268
    +      II32          -> (2, 0)
    
    269
    +      II64          -> (3, 0)
    
    270
    +      FF32          -> (4, 0)
    
    271
    +      FF64          -> (5, 0)
    
    272
    +      VecFormat l s -> (6 + scalarTag s, l)
    
    273
    +
    
    274
    +    scalarTag :: ScalarFormat -> Int
    
    275
    +    scalarTag = \case
    
    276
    +      FmtInt8   -> 0
    
    277
    +      FmtInt16  -> 1
    
    278
    +      FmtInt32  -> 2
    
    279
    +      FmtInt64  -> 3
    
    280
    +      FmtFloat  -> 4
    
    281
    +      FmtDouble -> 5
    
    282
    +
    
    251 283
     --------------------------------------------------------------------------------
    
    252 284
     
    
    253 285
     -- | A typed virtual register: a virtual register, together with the specific
    

  • compiler/GHC/CmmToAsm/PPC/CodeGen.hs
    ... ... @@ -484,7 +484,7 @@ getRegister' _ _ (CmmMachOp (MO_SS_Conv src tgt) [CmmLoad mem pk _])
    484 484
       , src < tgt = do
    
    485 485
           let format = cmmTypeFormat pk
    
    486 486
           -- lwa is DS-form. See Note [Power instruction format]
    
    487
    -      let form = if format >= II32 then DS else D
    
    487
    +      let form = if formatToWidth format >= W32 then DS else D
    
    488 488
           Amode addr addr_code <- getAmode form mem
    
    489 489
           let code dst = assert (format == intFormat src)
    
    490 490
                          $ addr_code `snocOL` LA format dst addr
    

  • compiler/GHC/CmmToAsm/Reg/Liveness.hs
    ... ... @@ -937,9 +937,9 @@ test:
    937 937
       dependency order. Comparing the whole accumulated block map would make the
    
    938 938
       fixpoint quadratic in procedure size (#27437).
    
    939 939
     
    
    940
    -The fixpoint terminates because the entries can only grow: registers are
    
    941
    -only added, formats only increase via 'maxRegWithFormat' joins, and both
    
    942
    -lattices are finite.
    
    940
    +To ensure termination, 'maxRegWithFormat' uses 'compareFormat' which defines a
    
    941
    +total order on formats. Comparing the widths only would introduce the risk of
    
    942
    +an infinite loop where each iteration swaps two formats of the same width.
    
    943 943
     -}
    
    944 944
     
    
    945 945
     
    

  • compiler/GHC/CmmToAsm/Reg/Regs.hs
    ... ... @@ -20,7 +20,8 @@ module GHC.CmmToAsm.Reg.Regs (
    20 20
     import GHC.Prelude
    
    21 21
     
    
    22 22
     import GHC.Platform.Reg     ( Reg )
    
    23
    -import GHC.CmmToAsm.Format  ( Format, RegWithFormat(..), isVecFormat )
    
    23
    +import GHC.CmmToAsm.Format  ( Format, RegWithFormat(..), isVecFormat,
    
    24
    +                              compareFormat, formatToWidth )
    
    24 25
     
    
    25 26
     import GHC.Utils.Outputable ( Outputable )
    
    26 27
     import GHC.Types.Unique     ( Uniquable(..) )
    
    ... ... @@ -39,11 +40,12 @@ newtype Regs = Regs { getRegs :: UniqSet RegWithFormat }
    39 40
     
    
    40 41
     maxRegWithFormat :: RegWithFormat -> RegWithFormat -> RegWithFormat
    
    41 42
     maxRegWithFormat r1@(RegWithFormat _ fmt1) r2@(RegWithFormat _ fmt2)
    
    42
    -  = if fmt1 >= fmt2
    
    43
    -    then r1
    
    44
    -    else r2
    
    45
    -  -- Re-using one of the arguments avoids allocating a new 'RegWithFormat',
    
    46
    -  -- compared with returning 'RegWithFormat r1 (max fmt1 fmt2)'.
    
    43
    +  | LT <- compareFormat fmt1 fmt2 = r2
    
    44
    +  | otherwise                     = r1
    
    45
    +  -- See Note [Convergence of the liveness fixpoint] in
    
    46
    +  -- GHC.CmmToAsm.Reg.Liveness.
    
    47
    +  --
    
    48
    +  -- Re-using one of the arguments avoids allocating a new 'RegWithFormat'.
    
    47 49
     
    
    48 50
     noRegs :: Regs
    
    49 51
     noRegs = Regs emptyUniqSet
    
    ... ... @@ -66,7 +68,7 @@ minusCoveredRegs = coerce $ minusUniqSet_C f
    66 68
       where
    
    67 69
         f :: RegWithFormat -> RegWithFormat -> Maybe RegWithFormat
    
    68 70
         f r1@(RegWithFormat _ fmt1) (RegWithFormat _ fmt2) =
    
    69
    -      if fmt2 >= fmt1
    
    71
    +      if formatToWidth fmt2 >= formatToWidth fmt1
    
    70 72
                ||
    
    71 73
              not ( isVecFormat fmt1 )
    
    72 74
               -- See Wrinkle [Don't allow scalar partial writes]
    
    ... ... @@ -99,7 +101,7 @@ shrinkingRegs = coerce $ minusUniqSet_C f
    99 101
       where
    
    100 102
         f :: RegWithFormat -> RegWithFormat -> Maybe RegWithFormat
    
    101 103
         f (RegWithFormat _ fmt1) r2@(RegWithFormat _ fmt2)
    
    102
    -      | fmt2 < fmt1
    
    104
    +      | formatToWidth fmt2 < formatToWidth fmt1
    
    103 105
           = Just r2
    
    104 106
           | otherwise
    
    105 107
           = Nothing