Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC

Commits:

7 changed files:

Changes:

  • changelog.d/add_can_drop_to_occurence_analyser
    1
    +section: ghc-lib
    
    2
    +synopsis: Add ``oa_can_drop`` option to the occurrence analyser which selects
    
    3
    +          bindings to preserve.
    
    4
    +
    
    5
    +issues: #27240
    
    6
    +mrs: !16253
    
    7
    +
    
    8
    +description: {
    
    9
    +  This is only relevant to clients of the GHC API.
    
    10
    +
    
    11
    +  The ``oa_can_drop`` option of the occurrence analyser indicates whether a
    
    12
    +  binding is ok to drop. The option is also exposed in the simple optimiser as
    
    13
    +  ``so_can_drop``.
    
    14
    +
    
    15
    +  In addition, the function ``occurAnalysePgm`` earned a record parameter of
    
    16
    +  type ``OccurAnalOpts`` which aggregates former parameters of the function.
    
    17
    +  The record type ``OccEnv`` in turn, replaces its fields ``occ_unf_act`` and
    
    18
    +  ``occ_rule_act`` with a field ``occ_opts`` of type ``OccurAnalOpts``.
    
    19
    +}

  • compiler/GHC/Core/Opt/OccurAnal.hs
    ... ... @@ -26,6 +26,7 @@ core expression with (hopefully) improved usage information.
    26 26
     -}
    
    27 27
     
    
    28 28
     module GHC.Core.Opt.OccurAnal (
    
    29
    +    OccurAnalOpts(..),
    
    29 30
         occurAnalysePgm,
    
    30 31
         occurAnalyseExpr, occurAnalyseBndrsAndExpr,
    
    31 32
         occurAnalyseExpr_Prep,
    
    ... ... @@ -103,12 +104,21 @@ occurAnalyseExpr_Prep expr = expr'
    103 104
       where
    
    104 105
         WUD _ expr' = occAnal (initOccEnv { occ_allow_weak_joins = True }) expr
    
    105 106
     
    
    107
    +-- | Options for occurrence analysis of a program
    
    108
    +data OccurAnalOpts = OccurAnalOpts
    
    109
    +  { oa_active_unf     :: Id -> Bool              -- ^ Active unfoldings
    
    110
    +  , oa_active_rule    :: ActivationGhc -> Bool   -- ^ Active rules
    
    111
    +  , oa_can_drop       :: Id -> Bool
    
    112
    +      -- ^ Can we drop this Id if it is dead?
    
    113
    +      -- See Note [Controlling elimination of dead bindings in occurrence analysis].
    
    114
    +  }
    
    115
    +
    
    106 116
     occurAnalysePgm :: Module         -- Used only in debug output
    
    107
    -                -> (Id -> Bool)         -- Active unfoldings
    
    108
    -                -> (ActivationGhc -> Bool) -- Active rules
    
    109
    -                -> [CoreRule]           -- Local rules for imported Ids
    
    110
    -                -> CoreProgram -> CoreProgram
    
    111
    -occurAnalysePgm this_mod active_unf active_rule imp_rules binds
    
    117
    +                -> OccurAnalOpts
    
    118
    +                -> [CoreRule]     -- Local rules for imported Ids
    
    119
    +                -> CoreProgram
    
    120
    +                -> CoreProgram
    
    121
    +occurAnalysePgm this_mod opts imp_rules binds
    
    112 122
       | isEmptyDetails final_usage
    
    113 123
       = occ_anald_binds
    
    114 124
     
    
    ... ... @@ -116,8 +126,7 @@ occurAnalysePgm this_mod active_unf active_rule imp_rules binds
    116 126
       = warnPprTrace True "Glomming in" (hang (ppr this_mod <> colon) 2 (ppr final_usage))
    
    117 127
         occ_anald_glommed_binds
    
    118 128
       where
    
    119
    -    init_env = initOccEnv { occ_rule_act = active_rule
    
    120
    -                          , occ_unf_act  = active_unf }
    
    129
    +    init_env = initOccEnv { occ_opts = opts }
    
    121 130
     
    
    122 131
         WUD final_usage occ_anald_binds = go binds init_env
    
    123 132
         WUD _ occ_anald_glommed_binds = occAnalRecBind init_env TopLevel
    
    ... ... @@ -1033,6 +1042,27 @@ Note [Occurrences in stable unfoldings and RULES]: occurrences in an unfolding
    1033 1042
     or RULE are treated as ManyOcc anyway.
    
    1034 1043
     
    
    1035 1044
     But NB that tail-call info is preserved so that we don't thereby lose join points.
    
    1045
    +
    
    1046
    +Note [Controlling elimination of dead bindings in occurrence analysis]
    
    1047
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    1048
    +Sometimes, plugins might want to retain dead bindings.
    
    1049
    +
    
    1050
    +For instance, Liquid Haskell might be the sole consumer of a binding that is
    
    1051
    +providing a proof. Or it might provide a lemma that is needed to check other
    
    1052
    +parts of the program. Or it might provide a value that is only referred from a
    
    1053
    +refinement type, but not from the Haskell code itself. See #27240 for more
    
    1054
    +details.
    
    1055
    +
    
    1056
    +For this reason, the occurrence analyser can be configured to retain
    
    1057
    +some bindings even if they are dead. This is done by setting the `oa_can_drop`
    
    1058
    +field of `OccAnalOpts` to a function that returns `False` for the bindings that
    
    1059
    +should be retained. All calls to the occurrence analyser from within GHC itself
    
    1060
    +use `const True` for this predicate; only calls from plugins might return
    
    1061
    +`False` in some cases.
    
    1062
    +
    
    1063
    +Alternatively, the plugin could avoid running the occurrence analyser, but that
    
    1064
    +would also disable other effects, such as the split of the program in strongly
    
    1065
    +connected components.
    
    1036 1066
     -}
    
    1037 1067
     
    
    1038 1068
     ------------------------------------------------------------------
    
    ... ... @@ -1078,7 +1108,7 @@ occAnalBind !env lvl ire (NonRec bndr rhs) thing_inside combine
    1078 1108
             !(WUD body_uds (occ, body)) = occAnalNonRecBody env_body bndr' $ \env ->
    
    1079 1109
                                           thing_inside (addJoinPoint env bndr' rhs_uds)
    
    1080 1110
         in
    
    1081
    -    if isDeadOcc occ     -- Drop dead code; see Note [Dead code]
    
    1111
    +    if isDeadOcc occ && oa_can_drop (occ_opts env) bndr  -- Drop dead code; see Note [Dead code]
    
    1082 1112
         then WUD body_uds body
    
    1083 1113
         else WUD (combineJoinPointUDs env rhs_uds body_uds)    -- Note `orUDs`
    
    1084 1114
                  (combine [NonRec (fst (tagNonRecBinder lvl occ bndr')) rhs']
    
    ... ... @@ -1088,7 +1118,7 @@ occAnalBind !env lvl ire (NonRec bndr rhs) thing_inside combine
    1088 1118
       -- Analyse the body and /then/ the RHS
    
    1089 1119
       | let env_body = addLocalLet env lvl bndr
    
    1090 1120
       , WUD body_uds (occ,body) <- occAnalNonRecBody env_body bndr thing_inside
    
    1091
    -  = if isDeadOcc occ   -- Drop dead code; see Note [Dead code]
    
    1121
    +  = if isDeadOcc occ && oa_can_drop (occ_opts env) bndr  -- Drop dead code; see Note [Dead code]
    
    1092 1122
         then WUD body_uds body
    
    1093 1123
         else let
    
    1094 1124
             -- Get the join info from the *new* decision; NB: bndr is not already a JoinId
    
    ... ... @@ -1225,10 +1255,10 @@ occAnalRec :: OccEnv -> TopLevelFlag
    1225 1255
                -> WithUsageDetails [CoreBind]
    
    1226 1256
     
    
    1227 1257
     -- The NonRec case is just like a Let (NonRec ...) above
    
    1228
    -occAnalRec !_ lvl
    
    1258
    +occAnalRec !env lvl
    
    1229 1259
                (AcyclicSCC (ND { nd_bndr = bndr, nd_rhs = wtuds }))
    
    1230 1260
                (WUD body_uds binds)
    
    1231
    -  | isDeadOcc occ  -- Check for dead code: see Note [Dead code]
    
    1261
    +  | isDeadOcc occ && oa_can_drop (occ_opts env) bndr  -- Check for dead code: see Note [Dead code]
    
    1232 1262
       = WUD body_uds binds
    
    1233 1263
       | otherwise
    
    1234 1264
       = let (bndr', mb_join) = tagNonRecBinder lvl occ bndr
    
    ... ... @@ -1463,8 +1493,8 @@ However, tagZero can only be inlined in phase 1 and later, while
    1463 1493
     the RULE is only active *before* phase 1.  So there's no problem.
    
    1464 1494
     
    
    1465 1495
     To make this work, we look for the RHS free vars only for
    
    1466
    -*active* rules. That's the reason for the occ_rule_act field
    
    1467
    -of the OccEnv.
    
    1496
    +*active* rules. That's the reason for the oa_active_rule field
    
    1497
    +of occ_opts in OccEnv.
    
    1468 1498
     
    
    1469 1499
     Note [loopBreakNodes]
    
    1470 1500
     ~~~~~~~~~~~~~~~~~~~~~
    
    ... ... @@ -1854,7 +1884,7 @@ makeNode !env imp_rule_edges bndr_set (bndr, rhs)
    1854 1884
           -- of Note [Join arity prediction based on joinRhsArity]
    
    1855 1885
     
    
    1856 1886
         --------- IMP-RULES --------
    
    1857
    -    is_active     = occ_rule_act env :: ActivationGhc -> Bool
    
    1887
    +    is_active     = oa_active_rule (occ_opts env) :: ActivationGhc -> Bool
    
    1858 1888
         imp_rule_info = lookupImpRules imp_rule_edges bndr
    
    1859 1889
         imp_rule_uds  = impRulesScopeUsage imp_rule_info
    
    1860 1890
         imp_rule_fvs  = impRulesActiveFvs is_active bndr_set imp_rule_info
    
    ... ... @@ -1963,8 +1993,8 @@ nodeScore !env new_bndr lb_deps
    1963 1993
       | old_bndr `elemVarSet` lb_deps  -- Self-recursive things are great loop breakers
    
    1964 1994
       = (0, 0, True)                   -- See Note [Self-recursion and loop breakers]
    
    1965 1995
     
    
    1966
    -  | not (occ_unf_act env old_bndr) -- A binder whose inlining is inactive (e.g. has
    
    1967
    -  = (0, 0, True)                   -- a NOINLINE pragma) makes a great loop breaker
    
    1996
    +  | not (oa_active_unf (occ_opts env) old_bndr) -- A binder whose inlining is inactive (e.g. has
    
    1997
    +  = (0, 0, True)                                -- a NOINLINE pragma) makes a great loop breaker
    
    1968 1998
     
    
    1969 1999
       | exprIsTrivial rhs
    
    1970 2000
       = mk_score 10  -- Practically certain to be inlined
    
    ... ... @@ -2985,8 +3015,7 @@ scrutinised y).
    2985 3015
     data OccEnv
    
    2986 3016
       = OccEnv { occ_encl       :: !OccEncl      -- Enclosing context information
    
    2987 3017
                , occ_one_shots  :: !OneShots     -- See Note [OneShots]
    
    2988
    -           , occ_unf_act    :: Id -> Bool    -- Which Id unfoldings are active
    
    2989
    -           , occ_rule_act   :: ActivationGhc -> Bool  -- Which rules are active
    
    3018
    +           , occ_opts       :: !OccurAnalOpts
    
    2990 3019
                  -- See Note [Finding rule RHS free vars]
    
    2991 3020
     
    
    2992 3021
                , occ_allow_weak_joins :: !Bool
    
    ... ... @@ -3055,18 +3084,19 @@ initOccEnv :: OccEnv
    3055 3084
     initOccEnv
    
    3056 3085
       = OccEnv { occ_encl      = OccVanilla
    
    3057 3086
                , occ_one_shots = []
    
    3058
    -
    
    3059
    -                 -- To be conservative, we say that all
    
    3060
    -                 -- inlines and rules are active
    
    3061
    -           , occ_unf_act   = \_ -> True
    
    3062
    -           , occ_rule_act  = \_ -> True
    
    3063
    -
    
    3064 3087
                , occ_allow_weak_joins = False
    
    3065
    -
    
    3066 3088
                , occ_join_points = emptyVarEnv
    
    3067 3089
                , occ_bs_env = emptyVarEnv
    
    3068 3090
                , occ_bs_rng = emptyVarSet
    
    3069
    -           , occ_nested_lets = emptyVarSet }
    
    3091
    +           , occ_nested_lets = emptyVarSet
    
    3092
    +             -- To be conservative, we say that all
    
    3093
    +             -- inlines and rules are active
    
    3094
    +           , occ_opts = OccurAnalOpts
    
    3095
    +              { oa_active_rule  = \_ -> True
    
    3096
    +              , oa_active_unf  = \_ -> True
    
    3097
    +              , oa_can_drop = \_ -> True
    
    3098
    +              }
    
    3099
    +           }
    
    3070 3100
     
    
    3071 3101
     noBinderSwaps :: OccEnv -> Bool
    
    3072 3102
     noBinderSwaps (OccEnv { occ_bs_env = bs_env }) = isEmptyVarEnv bs_env
    

  • compiler/GHC/Core/Opt/Simplify.hs
    ... ... @@ -12,7 +12,7 @@ import GHC.Driver.Flags
    12 12
     import GHC.Core
    
    13 13
     import GHC.Core.Rules
    
    14 14
     import GHC.Core.Ppr     ( pprCoreBindings, pprCoreExpr )
    
    15
    -import GHC.Core.Opt.OccurAnal ( occurAnalysePgm, occurAnalyseExpr )
    
    15
    +import GHC.Core.Opt.OccurAnal ( OccurAnalOpts(..), occurAnalysePgm, occurAnalyseExpr )
    
    16 16
     import GHC.Core.Stats   ( coreBindsSize, coreBindsStats, exprSize )
    
    17 17
     import GHC.Core.FVs     ( exprFreeVars )
    
    18 18
     import GHC.Core.Utils   ( mkTicks, stripTicksTop )
    
    ... ... @@ -252,8 +252,15 @@ simplifyPgm logger unit_env name_ppr_ctx opts
    252 252
           = do {
    
    253 253
                     -- Occurrence analysis
    
    254 254
                let { tagged_binds = {-# SCC "OccAnal" #-}
    
    255
    -                     occurAnalysePgm this_mod active_unf active_rule
    
    256
    -                                     local_rules binds
    
    255
    +                     occurAnalysePgm
    
    256
    +                       this_mod
    
    257
    +                       OccurAnalOpts
    
    258
    +                         { oa_active_unf = active_unf
    
    259
    +                         , oa_active_rule = active_rule
    
    260
    +                         , oa_can_drop = const True
    
    261
    +                         }
    
    262
    +                       local_rules
    
    263
    +                       binds
    
    257 264
                    } ;
    
    258 265
                Logger.putDumpFileMaybe logger Opt_D_dump_occur_anal "Occurrence analysis"
    
    259 266
                          FormatCore
    

  • compiler/GHC/Core/SimpleOpt.hs
    ... ... @@ -28,7 +28,7 @@ import GHC.Core.FVs
    28 28
     import GHC.Core.Unfold
    
    29 29
     import GHC.Core.Unfold.Make
    
    30 30
     import GHC.Core.Make
    
    31
    -import GHC.Core.Opt.OccurAnal( occurAnalyseExpr, occurAnalysePgm, zapLambdaBndrs )
    
    31
    +import GHC.Core.Opt.OccurAnal( OccurAnalOpts(..), occurAnalyseExpr, occurAnalysePgm, zapLambdaBndrs )
    
    32 32
     import GHC.Core.DataCon
    
    33 33
     import GHC.Core.Coercion.Opt ( optCoercion, optTransCo, OptCoercionOpts (..) )
    
    34 34
     import GHC.Core.Type hiding ( substTy, extendTvSubst, extendCvSubst, extendTvSubstList
    
    ... ... @@ -208,6 +208,8 @@ data SimpleOpts = SimpleOpts
    208 208
                                         --   used-once things
    
    209 209
                                         --
    
    210 210
                                         --   See Note [Controlling inlining in the simple optimiser]
    
    211
    +   , so_can_drop :: !(Var -> Bool)  -- ^ True <=> can drop the given binding if it is dead
    
    212
    +                                    -- See 'oa_can_drop' in 'OccurAnalOpts'.
    
    211 213
        }
    
    212 214
     
    
    213 215
     -- | Default options for the Simple optimiser.
    
    ... ... @@ -217,6 +219,7 @@ defaultSimpleOpts = SimpleOpts
    217 219
        , so_co_opts = OptCoercionOpts { optCoercionEnabled = False }
    
    218 220
        , so_eta_red = False
    
    219 221
        , so_inline  = const True
    
    222
    +   , so_can_drop = const True
    
    220 223
        }
    
    221 224
     
    
    222 225
     simpleOptExpr :: HasDebugCallStack => SimpleOpts -> CoreExpr -> CoreExpr
    
    ... ... @@ -282,10 +285,15 @@ simpleOptPgm :: SimpleOpts
    282 285
     simpleOptPgm opts this_mod binds rules =
    
    283 286
         (reverse binds', rules', occ_anald_binds)
    
    284 287
       where
    
    285
    -    occ_anald_binds  = occurAnalysePgm this_mod
    
    286
    -                          (\_ -> True)  {- All unfoldings active -}
    
    287
    -                          (\_ -> False) {- No rules active -}
    
    288
    -                          rules binds
    
    288
    +    occ_anald_binds  = occurAnalysePgm
    
    289
    +                         this_mod
    
    290
    +                         OccurAnalOpts
    
    291
    +                           { oa_active_unf = \_ -> True  {- All unfoldings active -}
    
    292
    +                           , oa_active_rule = \_ -> False {- No rules active -}
    
    293
    +                           , oa_can_drop = so_can_drop opts
    
    294
    +                           }
    
    295
    +                         rules
    
    296
    +                         binds
    
    289 297
     
    
    290 298
         (final_env, binds') = foldl' do_one (emptyEnv opts, []) occ_anald_binds
    
    291 299
         final_subst = soe_subst final_env
    

  • compiler/GHC/Driver/Config.hs
    ... ... @@ -27,6 +27,7 @@ initSimpleOpts dflags = SimpleOpts
    27 27
        , so_co_opts = initOptCoercionOpts dflags
    
    28 28
        , so_eta_red = gopt Opt_DoEtaReduction dflags
    
    29 29
        , so_inline  = const True
    
    30
    +   , so_can_drop = const True
    
    30 31
        }
    
    31 32
     
    
    32 33
     -- | Instruct the interpreter evaluation to break...
    

  • testsuite/tests/ghc-api/T27240.hs
    1
    +
    
    2
    +-- This test checks that bindings are preserved when configuring the occurrence
    
    3
    +-- analyzer and the simple optimizer to not drop dead bindings with names
    
    4
    +-- selected by a predicate.
    
    5
    +--
    
    6
    +-- This feature is important for the LiquidHaskell plugin, which relies on the
    
    7
    +-- simple optimizer to make core programs easier to read, but needs to preserve
    
    8
    +-- bindings that are relevant for verification.
    
    9
    +--
    
    10
    +-- See https://gitlab.haskell.org/ghc/ghc/-/issues/27240 for the full discussion.
    
    11
    +--
    
    12
    +
    
    13
    +import           Control.Monad
    
    14
    +import           Data.List (find)
    
    15
    +import           Data.Time (getCurrentTime)
    
    16
    +import GHC
    
    17
    +import GHC.Core
    
    18
    +import GHC.Core.SimpleOpt
    
    19
    +import GHC.Data.StringBuffer
    
    20
    +import GHC.Driver.Config
    
    21
    +import GHC.Driver.DynFlags
    
    22
    +import GHC.Driver.Env.Types
    
    23
    +import GHC.Types.Name
    
    24
    +import GHC.Unit.Module.ModGuts
    
    25
    +import GHC.Unit.Types
    
    26
    +import GHC.Utils.Error
    
    27
    +import GHC.Utils.Outputable
    
    28
    +
    
    29
    +import System.Environment (getArgs)
    
    30
    +
    
    31
    +
    
    32
    +main :: IO ()
    
    33
    +main =
    
    34
    +  testLocalBindingsDesugaring
    
    35
    +
    
    36
    +testLocalBindingsDesugaring :: IO ()
    
    37
    +testLocalBindingsDesugaring = do
    
    38
    +    let inputSource = unlines
    
    39
    +          [ "module LocalDeadBindingsDesugaring where"
    
    40
    +          , "f :: ()"
    
    41
    +          , "f = ()"
    
    42
    +          , "  where"
    
    43
    +          , "    w = ()"
    
    44
    +          , "    z = ()"
    
    45
    +          ]
    
    46
    +
    
    47
    +        isExpectedDesugaring p = case findExpr "f" p of
    
    48
    +          Just (Let (NonRec b _) _)
    
    49
    +            -> isIdNamed "z" b
    
    50
    +          _ -> False
    
    51
    +
    
    52
    +        isIdNamed name v = occNameString (occName v) == name
    
    53
    +
    
    54
    +    coreProgram <-
    
    55
    +       compileToCore
    
    56
    +         (not . isIdNamed "z")
    
    57
    +         "LocalDeadBindingsDesugaring"
    
    58
    +         inputSource
    
    59
    +    unless (isExpectedDesugaring coreProgram) $
    
    60
    +      fail $ unlines $
    
    61
    +        "Unexpected desugaring: No local binding for `z` found in the Core program."
    
    62
    +        : map showPprQualified coreProgram
    
    63
    +
    
    64
    +-- | Find the Core expression bound to the given name.
    
    65
    +findExpr :: String -> CoreProgram -> Maybe CoreExpr
    
    66
    +findExpr _ [] =
    
    67
    +  Nothing
    
    68
    +findExpr name (p:ps) = case p of
    
    69
    +  NonRec b e
    
    70
    +    | occNameString (occName b) == name
    
    71
    +    -> Just e
    
    72
    +  Rec binds
    
    73
    +    | Just (_, e) <- find (\(b, _e) -> occNameString (occName b) == name) binds
    
    74
    +    -> Just e
    
    75
    +  _ -> findExpr name ps
    
    76
    +
    
    77
    +showPprQualified :: Outputable a => a -> String
    
    78
    +showPprQualified = showSDocQualified . ppr
    
    79
    +
    
    80
    +showSDocQualified :: SDoc -> String
    
    81
    +showSDocQualified = renderWithContext ctx
    
    82
    +  where
    
    83
    +    ctx = defaultSDocContext { sdocStyle = cmdlineParserStyle }
    
    84
    +
    
    85
    +
    
    86
    +
    
    87
    +compileToCore :: (Id -> Bool) -> String -> String -> IO [CoreBind]
    
    88
    +compileToCore canDrop modName inputSource = do
    
    89
    +    [libdir] <- getArgs
    
    90
    +    now <- getCurrentTime
    
    91
    +    runGhc (Just libdir) $ do
    
    92
    +      df1 <- getSessionDynFlags
    
    93
    +      GHC.setSessionDynFlags $ df1 { GHC.backend = GHC.bytecodeBackend }
    
    94
    +      let target = Target {
    
    95
    +                   targetId           = TargetFile (modName ++ ".hs") Nothing
    
    96
    +                 , targetUnitId       = homeUnitId_ df1
    
    97
    +                 , targetAllowObjCode = False
    
    98
    +                 , targetContents     = Just (stringToStringBuffer inputSource, now)
    
    99
    +                 }
    
    100
    +      setTargets [target]
    
    101
    +      void $ GHC.depanal [] False
    
    102
    +
    
    103
    +      dsMod <- getModSummary
    
    104
    +                 (mkModule mainUnit (mkModuleName modName))
    
    105
    +             >>= parseModule
    
    106
    +             >>= typecheckModule NoTcMPlugins
    
    107
    +             >>= desugarModule
    
    108
    +      hsc_env <- getSession
    
    109
    +      return $ mg_binds $ simpleOptimize canDrop hsc_env $ dm_core_module dsMod
    
    110
    +
    
    111
    +-- Run the simple optimizer
    
    112
    +simpleOptimize :: (Id -> Bool) -> GHC.HscEnv -> ModGuts -> ModGuts
    
    113
    +simpleOptimize canDrop hsc_env guts@(ModGuts
    
    114
    +                               { mg_module  = mgmod
    
    115
    +                               , mg_binds   = binds
    
    116
    +                               , mg_rules   = rules
    
    117
    +                               }) =
    
    118
    +    let dflags = hsc_dflags hsc_env
    
    119
    +        simpl_opts = (initSimpleOpts dflags)
    
    120
    +          { so_inline = canDrop
    
    121
    +          , so_can_drop = canDrop
    
    122
    +          }
    
    123
    +        (binds2, rules2, _occ_anald_binds) =
    
    124
    +          simpleOptPgm simpl_opts mgmod binds rules
    
    125
    +      in guts
    
    126
    +          { mg_binds = binds2
    
    127
    +          , mg_rules = rules2
    
    128
    +          }

  • testsuite/tests/ghc-api/all.T
    ... ... @@ -82,6 +82,7 @@ test('TypeMapStringLiteral', normal, compile_and_run, ['-package ghc'])
    82 82
     
    
    83 83
     test('T25121_status', normal, compile_and_run, ['-package ghc'])
    
    84 84
     test('T24386', [extra_run_opts(f'"{config.libdir}"')], compile_and_run, ['-package ghc'])
    
    85
    +test('T27240', [extra_run_opts(f'"{config.libdir}"')], compile_and_run, ['-package ghc'])
    
    85 86
     test('T27273', [extra_run_opts(f'"{config.libdir}"')],
    
    86 87
                    compile_and_run,
    
    87 88
                    ['-package ghc'])