    module GHC.CmmToAsm.SPARC.ShortcutJump (
            JumpDest(..), getJumpDestBlockId,
            canShortcut,
            shortcutJump,
            shortcutStatics,
            shortBlockId
    )

    where

    import GHC.Prelude

    import GHC.CmmToAsm.SPARC.Instr
    import GHC.CmmToAsm.SPARC.Imm

    import GHC.Cmm.CLabel
    import GHC.Cmm.BlockId
    import GHC.Cmm

    import GHC.Utils.Panic
    import GHC.Utils.Outputable

    data JumpDest
            = DestBlockId BlockId
            | DestImm Imm

    -- Debug Instance
    instance Outputable JumpDest where
      ppr :: JumpDest -> SDoc
    ppr (DestBlockId BlockId
    bid) = String -> SDoc
    text String
    "blk:" SDoc -> SDoc -> SDoc
    <> BlockId -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr BlockId
    bid
      ppr (DestImm Imm
    _bid)    = String -> SDoc
    text String
    "imm:?"

    getJumpDestBlockId :: JumpDest -> Maybe BlockId
    getJumpDestBlockId :: JumpDest -> Maybe BlockId
    getJumpDestBlockId (DestBlockId BlockId
    bid) = BlockId -> Maybe BlockId
    forall a. a -> Maybe a
    Just BlockId
    bid
    getJumpDestBlockId JumpDest
    _                 = Maybe BlockId
    forall a. Maybe a
    Nothing

    canShortcut :: Instr -> Maybe JumpDest
    canShortcut :: Instr -> Maybe JumpDest
    canShortcut Instr
    _ = Maybe JumpDest
    forall a. Maybe a
    Nothing

    shortcutJump :: (BlockId -> Maybe JumpDest) -> Instr -> Instr
    shortcutJump :: (BlockId -> Maybe JumpDest) -> Instr -> Instr
    shortcutJump BlockId -> Maybe JumpDest
    _ Instr
    other = Instr
    other

    shortcutStatics :: (BlockId -> Maybe JumpDest) -> RawCmmStatics -> RawCmmStatics
    shortcutStatics :: (BlockId -> Maybe JumpDest) -> RawCmmStatics -> RawCmmStatics
    shortcutStatics BlockId -> Maybe JumpDest
    fn (CmmStaticsRaw CLabel
    lbl [CmmStatic]
    statics)
      = CLabel -> [CmmStatic] -> RawCmmStatics
    forall (a :: Bool). CLabel -> [CmmStatic] -> GenCmmStatics a
    CmmStaticsRaw CLabel
    lbl ([CmmStatic] -> RawCmmStatics) -> [CmmStatic] -> RawCmmStatics
    forall a b. (a -> b) -> a -> b
    $ (CmmStatic -> CmmStatic) -> [CmmStatic] -> [CmmStatic]
    forall a b. (a -> b) -> [a] -> [b]
    map ((BlockId -> Maybe JumpDest) -> CmmStatic -> CmmStatic
    shortcutStatic BlockId -> Maybe JumpDest
    fn) [CmmStatic]
    statics
      -- we need to get the jump tables, so apply the mapping to the entries
      -- of a CmmData too.

    shortcutLabel :: (BlockId -> Maybe JumpDest) -> CLabel -> CLabel
    shortcutLabel :: (BlockId -> Maybe JumpDest) -> CLabel -> CLabel
    shortcutLabel BlockId -> Maybe JumpDest
    fn CLabel
    lab
      | Just BlockId
    blkId <- CLabel -> Maybe BlockId
    maybeLocalBlockLabel CLabel
    lab = (BlockId -> Maybe JumpDest) -> BlockId -> CLabel
    shortBlockId BlockId -> Maybe JumpDest
    fn BlockId
    blkId
      | Bool
    otherwise                              = CLabel
    lab

    shortcutStatic :: (BlockId -> Maybe JumpDest) -> CmmStatic -> CmmStatic
    shortcutStatic :: (BlockId -> Maybe JumpDest) -> CmmStatic -> CmmStatic
    shortcutStatic BlockId -> Maybe JumpDest
    fn (CmmStaticLit (CmmLabel CLabel
    lab))
            = CmmLit -> CmmStatic
    CmmStaticLit (CLabel -> CmmLit
    CmmLabel ((BlockId -> Maybe JumpDest) -> CLabel -> CLabel
    shortcutLabel BlockId -> Maybe JumpDest
    fn CLabel
    lab))
    shortcutStatic BlockId -> Maybe JumpDest
    fn (CmmStaticLit (CmmLabelDiffOff CLabel
    lbl1 CLabel
    lbl2 Int
    off Width
    w))
            = CmmLit -> CmmStatic
    CmmStaticLit (CLabel -> CLabel -> Int -> Width -> CmmLit
    CmmLabelDiffOff ((BlockId -> Maybe JumpDest) -> CLabel -> CLabel
    shortcutLabel BlockId -> Maybe JumpDest
    fn CLabel
    lbl1) CLabel
    lbl2 Int
    off Width
    w)
    -- slightly dodgy, we're ignoring the second label, but this
    -- works with the way we use CmmLabelDiffOff for jump tables now.
    shortcutStatic BlockId -> Maybe JumpDest
    _ CmmStatic
    other_static
            = CmmStatic
    other_static

    shortBlockId :: (BlockId -> Maybe JumpDest) -> BlockId -> CLabel
    shortBlockId :: (BlockId -> Maybe JumpDest) -> BlockId -> CLabel
    shortBlockId BlockId -> Maybe JumpDest
    fn BlockId
    blockid =
       case BlockId -> Maybe JumpDest
    fn BlockId
    blockid of
          Maybe JumpDest
    Nothing -> BlockId -> CLabel
    blockLbl BlockId
    blockid
          Just (DestBlockId BlockId
    blockid')  -> (BlockId -> Maybe JumpDest) -> BlockId -> CLabel
    shortBlockId BlockId -> Maybe JumpDest
    fn BlockId
    blockid'
          Just (DestImm (ImmCLbl CLabel
    lbl)) -> CLabel
    lbl
          Maybe JumpDest
    _other -> String -> CLabel
    forall a. String -> a
    panic String
    "shortBlockId"