Simon Peyton Jones pushed to branch wip/T26115 at Glasgow Haskell Compiler / GHC

Commits:

8 changed files:

Changes:

  • compiler/GHC/Core.hs
    ... ... @@ -39,7 +39,7 @@ module GHC.Core (
    39 39
             isId, cmpAltCon, cmpAlt, ltAlt,
    
    40 40
     
    
    41 41
             -- ** Simple 'Expr' access functions and predicates
    
    42
    -        bindersOf, bindersOfBinds, rhssOfBind, rhssOfAlts,
    
    42
    +        bindersOf, bindersOfBinds, rhssOfBind, rhssOfBinds, rhssOfAlts,
    
    43 43
             foldBindersOfBindStrict, foldBindersOfBindsStrict,
    
    44 44
             collectBinders, collectTyBinders, collectTyAndValBinders,
    
    45 45
             collectNBinders, collectNValBinders_maybe,
    
    ... ... @@ -2154,6 +2154,11 @@ rhssOfBind :: Bind b -> [Expr b]
    2154 2154
     rhssOfBind (NonRec _ rhs) = [rhs]
    
    2155 2155
     rhssOfBind (Rec pairs)    = [rhs | (_,rhs) <- pairs]
    
    2156 2156
     
    
    2157
    +rhssOfBinds :: [Bind b] -> [Expr b]
    
    2158
    +rhssOfBinds []             = []
    
    2159
    +rhssOfBinds (NonRec _ rhs : bs) = rhs : rhssOfBinds bs
    
    2160
    +rhssOfBinds (Rec pairs    : bs) = map snd pairs ++ rhssOfBinds bs
    
    2161
    +
    
    2157 2162
     rhssOfAlts :: [Alt b] -> [Expr b]
    
    2158 2163
     rhssOfAlts alts = [e | Alt _ _ e <- alts]
    
    2159 2164
     
    

  • compiler/GHC/HsToCore/Binds.hs
    ... ... @@ -66,11 +66,11 @@ import GHC.Builtin.Types ( naturalTy, typeSymbolKind, charTy )
    66 66
     import GHC.Tc.Types.Evidence
    
    67 67
     
    
    68 68
     import GHC.Types.Id
    
    69
    -import GHC.Types.Id.Info (IdDetails(..))
    
    69
    +import GHC.Types.Id.Info
    
    70 70
     import GHC.Types.Name
    
    71 71
     import GHC.Types.Var.Set
    
    72 72
     import GHC.Types.Var.Env
    
    73
    -import GHC.Types.Var( EvVar )
    
    73
    +import GHC.Types.Var( EvVar, mkLocalVar )
    
    74 74
     import GHC.Types.SrcLoc
    
    75 75
     import GHC.Types.Basic
    
    76 76
     import GHC.Types.Unique.Set( nonDetEltsUniqSet )
    
    ... ... @@ -1141,7 +1141,7 @@ dsSpec poly_rhs (SpecPrag poly_id spec_co spec_inl)
    1141 1141
     
    
    1142 1142
     dsSpec poly_rhs (SpecPragE { spe_fn_nm = poly_nm
    
    1143 1143
                                , spe_fn_id = poly_id
    
    1144
    -                           , spe_inl   = inl
    
    1144
    +                           , spe_inl   = spec_inl
    
    1145 1145
                                , spe_bndrs = bndrs
    
    1146 1146
                                , spe_call  = the_call })
    
    1147 1147
       -- SpecPragE case: See Note [Handling new-form SPECIALISE pragmas] in GHC.Tc.Gen.Sig
    
    ... ... @@ -1149,68 +1149,134 @@ dsSpec poly_rhs (SpecPragE { spe_fn_nm = poly_nm
    1149 1149
                         unsetWOptM Opt_WarnIdentities     $
    
    1150 1150
                         zapUnspecables $
    
    1151 1151
                         dsLExpr the_call
    
    1152
    -       ; dsSpec_help poly_nm poly_id poly_rhs inl bndrs ds_call }
    
    1152
    +       ; dsSpec_help poly_nm poly_id poly_rhs spec_inl bndrs ds_call }
    
    1153 1153
     
    
    1154 1154
     dsSpec_help :: Name -> Id -> CoreExpr              -- Function to specialise
    
    1155 1155
                 -> InlinePragma -> [Var] -> CoreExpr
    
    1156 1156
                 -> DsM (Maybe (OrdList (Id,CoreExpr), CoreRule))
    
    1157
    -dsSpec_help poly_nm poly_id poly_rhs inl orig_bndrs ds_call
    
    1158
    -  = do {
    
    1159
    -       -- Simplify the (desugared) call; see wrinkle (SP1)
    
    1160
    -       -- in Note [Desugaring new-form SPECIALISE pragmas]
    
    1161
    -       ; dflags  <- getDynFlags
    
    1162
    -       ; let simpl_opts = initSimpleOpts dflags
    
    1163
    -             core_call  = simpleOptExprNoInline simpl_opts ds_call
    
    1164
    -
    
    1165
    -       ; case decomposeCall poly_id core_call of {
    
    1166
    -            Nothing -> do { diagnosticDs (DsRuleLhsTooComplicated ds_call core_call)
    
    1167
    -                           ; return Nothing } ;
    
    1168
    -
    
    1157
    +dsSpec_help poly_nm poly_id poly_rhs spec_inl orig_bndrs ds_call
    
    1158
    +  = do { mb_call_info <- decomposeCall poly_id ds_call
    
    1159
    +       ; case mb_call_info of {
    
    1160
    +            Nothing -> return Nothing ;
    
    1169 1161
                 Just (binds, rule_lhs_args) ->
    
    1170 1162
     
    
    1171
    -    do { let locals = mkVarSet orig_bndrs `extendVarSetList` bindersOfBinds binds
    
    1163
    +    do { dflags   <- getDynFlags
    
    1164
    +       ; this_mod <- getModule
    
    1165
    +       ; uniq     <- newUnique
    
    1166
    +       ; let locals = mkVarSet orig_bndrs `extendVarSetList` bindersOfBinds binds
    
    1172 1167
                  is_local :: Var -> Bool
    
    1173 1168
                  is_local v = v `elemVarSet` locals
    
    1174 1169
     
    
    1175 1170
                  rule_bndrs = scopedSort (exprsSomeFreeVarsList is_local rule_lhs_args)
    
    1176
    -             rn_binds = getRenamings orig_bndrs binds rule_bndrs
    
    1171
    +             rn_binds   = getRenamings orig_bndrs binds rule_bndrs
    
    1177 1172
     
    
    1178
    -             spec_binds = pickSpecBinds is_local (mkVarSet rule_bndrs)
    
    1179
    -                                        (rn_binds ++ binds)
    
    1173
    +             spec_binds = pickSpecBinds is_local (mkVarSet rule_bndrs) binds
    
    1180 1174
     
    
    1175
    +             -- Make spec_bndrs, the variables to pass to the specialised
    
    1176
    +             -- function, by filtering out the rule_bndrs that aren't needed
    
    1181 1177
                  spec_binds_bndr_set = mkVarSet (bindersOfBinds spec_binds)
    
    1178
    +                                   `minusVarSet` exprsFreeVars (rhssOfBinds rn_binds)
    
    1182 1179
                  spec_bndrs = filterOut (`elemVarSet` spec_binds_bndr_set) rule_bndrs
    
    1183 1180
     
    
    1184
    -             mk_spec_body fn_body = mkLets spec_binds  $
    
    1181
    +             mk_spec_body fn_body = mkLets (rn_binds ++ spec_binds)  $
    
    1185 1182
                                         mkApps fn_body rule_lhs_args
    
    1186 1183
                                         -- ToDo: not mkCoreApps!  That uses exprType on fun which
    
    1187 1184
                                         --       fails in specUnfolding, sigh
    
    1188 1185
     
    
    1186
    +             poly_name  = idName poly_id
    
    1187
    +             spec_occ   = mkSpecOcc (getOccName poly_name)
    
    1188
    +             spec_name  = mkInternalName uniq spec_occ (getSrcSpan poly_name)
    
    1189
    +             id_inl     = idInlinePragma poly_id
    
    1190
    +
    
    1191
    +             simpl_opts = initSimpleOpts dflags
    
    1192
    +             fn_unf     = realIdUnfolding poly_id
    
    1193
    +             spec_unf   = specUnfolding simpl_opts spec_bndrs mk_spec_body rule_lhs_args fn_unf
    
    1194
    +             spec_info  = vanillaIdInfo
    
    1195
    +                          `setInlinePragInfo` specFunInlinePrag poly_id id_inl spec_inl
    
    1196
    +                          `setUnfoldingInfo`  spec_unf
    
    1197
    +             spec_id    = mkLocalVar (idDetails poly_id) spec_name ManyTy spec_ty spec_info
    
    1198
    +                          -- Specialised binding is toplevel, hence Many.
    
    1199
    +
    
    1200
    +             -- The RULE looks like
    
    1201
    +             --    RULE "USPEC" forall rule_bndrs. f rule_lhs_args = $sf spec_bndrs
    
    1202
    +             -- The specialised function looks like
    
    1203
    +             --    $sf spec_bndrs = mk_spec_body <f's original rhs>
    
    1204
    +             -- We also use mk_spec_body to specialise the methods in f's stable unfolding
    
    1205
    +             -- NB: spec_bindrs is a subset of rule_bndrs
    
    1206
    +             rule = mkSpecRule dflags this_mod False rule_act (text "USPEC")
    
    1207
    +                               poly_id rule_bndrs rule_lhs_args
    
    1208
    +                               (mkVarApps (Var spec_id) spec_bndrs)
    
    1209
    +
    
    1210
    +             rule_ty  = exprType (mkApps (Var poly_id) rule_lhs_args)
    
    1211
    +             spec_ty  = mkLamTypes spec_bndrs rule_ty
    
    1212
    +             spec_rhs = mkLams spec_bndrs (mk_spec_body poly_rhs)
    
    1213
    +
    
    1214
    +             result = (unitOL (spec_id, spec_rhs), rule)
    
    1215
    +            -- NB: do *not* use makeCorePair on (spec_id,spec_rhs), because
    
    1216
    +            --     makeCorePair overwrites the unfolding, which we have
    
    1217
    +            --     just created using specUnfolding
    
    1189 1218
            ; tracePm "dsSpec(new route)" $
    
    1190 1219
              vcat [ text "poly_id" <+> ppr poly_id
    
    1191 1220
                   , text "unfolding" <+> ppr (realIdUnfolding poly_id)
    
    1192 1221
                   , text "orig_bndrs"   <+> pprCoreBinders orig_bndrs
    
    1222
    +              , text "locals" <+> ppr locals
    
    1223
    +              , text "fvs" <+> ppr (exprsSomeFreeVarsList is_local rule_lhs_args)
    
    1193 1224
                   , text "ds_call" <+> ppr ds_call
    
    1194
    -              , text "core_call" <+> ppr core_call
    
    1195 1225
                   , text "binds" <+> ppr binds
    
    1196
    -              , text "rule_bndrs" <+> ppr rule_bndrs
    
    1197 1226
                   , text "rule_lhs_args" <+> ppr rule_lhs_args
    
    1227
    +              , text "rule_bndrs" <+> ppr rule_bndrs
    
    1198 1228
                   , text "spec_bndrs" <+> ppr spec_bndrs
    
    1199 1229
                   , text "rn_binds" <+> ppr rn_binds
    
    1200 1230
                   , text "spec_binds" <+> ppr spec_binds ]
    
    1201 1231
     
    
    1202
    -       ; finishSpecPrag poly_nm poly_rhs
    
    1203
    -                        rule_bndrs poly_id rule_lhs_args
    
    1204
    -                        spec_bndrs mk_spec_body inl } } }
    
    1232
    +       ; dsWarnOrphanRule rule
    
    1233
    +
    
    1234
    +       ; case checkUselessSpecPrag poly_id rule_lhs_args spec_bndrs
    
    1235
    +                 no_act_spec spec_inl rule_act of
    
    1236
    +           Nothing -> return (Just result)
    
    1237
    +
    
    1238
    +           Just reason -> do { diagnosticDs $ DsUselessSpecialisePragma poly_nm is_dfun reason
    
    1239
    +                             ; if uselessSpecialisePragmaKeepAnyway reason
    
    1240
    +                               then return (Just result)
    
    1241
    +                               else return Nothing } } } }
    
    1242
    +
    
    1243
    +  where
    
    1244
    +    -- See Note [Activation pragmas for SPECIALISE]
    
    1245
    +    -- no_act_spec is True if the user didn't write an explicit
    
    1246
    +    -- phase specification in the SPECIALISE pragma
    
    1247
    +    id_inl        = idInlinePragma poly_id
    
    1248
    +    inl_prag_act  = inlinePragmaActivation id_inl
    
    1249
    +    spec_prag_act = inlinePragmaActivation spec_inl
    
    1250
    +    no_act_spec = case inlinePragmaSpec spec_inl of
    
    1251
    +                    NoInline _   -> isNeverActive  spec_prag_act
    
    1252
    +                    Opaque _     -> isNeverActive  spec_prag_act
    
    1253
    +                    _            -> isAlwaysActive spec_prag_act
    
    1254
    +    rule_act | no_act_spec = inl_prag_act    -- Inherit
    
    1255
    +             | otherwise   = spec_prag_act   -- Specified by user
    
    1256
    +
    
    1257
    +    is_dfun = case idDetails poly_id of
    
    1258
    +      DFunId {} -> True
    
    1259
    +      _ -> False
    
    1205 1260
     
    
    1206 1261
     decomposeCall :: Id -> CoreExpr
    
    1207
    -               -> Maybe ( [CoreBind]
    
    1208
    -                        , [CoreExpr] )  -- Args of the call
    
    1209
    -decomposeCall poly_id binds
    
    1210
    -  = go [] binds
    
    1262
    +              -> DsM (Maybe ([CoreBind], [CoreExpr] ))
    
    1263
    +-- Decompose the call into (let <binds> in f <args>)
    
    1264
    +decomposeCall poly_id ds_call
    
    1265
    +  = do { -- Simplify the (desugared) call; see wrinkle (SP1)
    
    1266
    +         -- in Note [Desugaring new-form SPECIALISE pragmas]
    
    1267
    +       ; dflags  <- getDynFlags
    
    1268
    +       ; let simpl_opts = initSimpleOpts dflags
    
    1269
    +             core_call  = simpleOptExprNoInline simpl_opts ds_call
    
    1270
    +
    
    1271
    +       ; case go [] core_call of {
    
    1272
    +           Nothing -> do { diagnosticDs (DsRuleLhsTooComplicated ds_call core_call)
    
    1273
    +                         ; return Nothing } ;
    
    1274
    +           Just result -> return (Just result) } }
    
    1211 1275
       where
    
    1212
    -    go acc (Let bind body)
    
    1213
    -      = go (bind:acc) body
    
    1276
    +    go :: [CoreBind] -> CoreExpr -> Maybe ([CoreBind],[CoreExpr])
    
    1277
    +    go acc (Let bind body) = go (bind:acc) body
    
    1278
    +    go acc (Cast e _)      = go acc e  -- Discard outer casts
    
    1279
    +                                       -- ToDo: document this
    
    1214 1280
         go acc e
    
    1215 1281
           | (Var fun, args) <- collectArgs e
    
    1216 1282
           = assertPpr (fun == poly_id) (ppr fun $$ ppr poly_id) $
    
    ... ... @@ -1218,6 +1284,40 @@ decomposeCall poly_id binds
    1218 1284
           | otherwise
    
    1219 1285
           = Nothing
    
    1220 1286
     
    
    1287
    +    -- Is this SPECIALISE pragma useless?
    
    1288
    +checkUselessSpecPrag :: Id -> [CoreExpr]
    
    1289
    +   -> [Var] -> Bool -> InlinePragma -> Activation
    
    1290
    +   ->  Maybe UselessSpecialisePragmaReason
    
    1291
    +checkUselessSpecPrag poly_id rule_lhs_args
    
    1292
    +                     spec_bndrs no_act_spec spec_inl rule_act
    
    1293
    +  | isJust (isClassOpId_maybe poly_id)
    
    1294
    +  -- There is no point in trying to specialise a class op
    
    1295
    +  -- Moreover, classops don't (currently) have an inl_sat arity set
    
    1296
    +  -- (it would be Just 0) and that in turn makes makeCorePair bleat
    
    1297
    +  = Just UselessSpecialiseForClassMethodSelector
    
    1298
    +
    
    1299
    +  | no_act_spec, isNeverActive rule_act
    
    1300
    +  -- Function is NOINLINE, and the specialisation inherits that
    
    1301
    +  -- See Note [Activation pragmas for SPECIALISE]
    
    1302
    +  = Just UselessSpecialiseForNoInlineFunction
    
    1303
    +
    
    1304
    +  | all is_nop_arg rule_lhs_args, not (isInlinePragma spec_inl)
    
    1305
    +  -- The specialisation does nothing.
    
    1306
    +  -- But don't complain if it is SPECIALISE INLINE (#4444)
    
    1307
    +  = Just UselessSpecialiseNoSpecialisation
    
    1308
    +
    
    1309
    +  | otherwise
    
    1310
    +  = Nothing
    
    1311
    +
    
    1312
    +  where
    
    1313
    +    is_nop_arg (Type {})     = True
    
    1314
    +    is_nop_arg (Coercion {}) = True
    
    1315
    +    is_nop_arg (Cast e _)    = is_nop_arg e
    
    1316
    +    is_nop_arg (Tick _ e)    = is_nop_arg e
    
    1317
    +    is_nop_arg (Var x)       = x `elem` spec_bndrs
    
    1318
    +    is_nop_arg _             = False
    
    1319
    +
    
    1320
    +
    
    1221 1321
     getRenamings :: [Var] -> [CoreBind]  -- orig_bndrs and bindings
    
    1222 1322
                  -> [Var]                -- rule_bndrs
    
    1223 1323
                  -> [CoreBind]           -- Binds some of the orig_bndrs to a rule_bndr
    
    ... ... @@ -1238,8 +1338,8 @@ getRenamings orig_bndrs binds rule_bndrs
    1238 1338
         go (bind : binds)
    
    1239 1339
            | NonRec b rhs <- bind
    
    1240 1340
            , Just (v, mco) <- getCastedVar rhs
    
    1241
    -       , Just e <- lookupVarEnv renamings v
    
    1242
    -       = extendVarEnv renamings b (mkCastMCo e (mkSymMCo mco))
    
    1341
    +       , Just e <- lookupVarEnv renamings b
    
    1342
    +       = extendVarEnv renamings v (mkCastMCo e (mkSymMCo mco))
    
    1243 1343
            | otherwise
    
    1244 1344
            = renamings
    
    1245 1345
            where
    
    ... ... @@ -1256,201 +1356,12 @@ pickSpecBinds is_local known_bndrs (bind:binds)
    1256 1356
           where
    
    1257 1357
             keep_me rhs = isEmptyVarSet (exprSomeFreeVars bad_var rhs)
    
    1258 1358
             bad_var v = is_local v && not (v `elemVarSet` known_bndrs)
    
    1259
    -{-
    
    1260
    -grabSpecBinds :: (Var -> Bool) -> VarSet -> [CoreBind]
    
    1261
    -              -> ([CoreBind], [CoreBind])
    
    1262
    -grabSpecBinds is_local rule_bndrs rev_binds
    
    1263
    -   = (reverse rename_binds, spec_binds)
    
    1264
    -  where
    
    1265
    -    (known_bndrs, (rename_binds, other_binds))
    
    1266
    -        = get_renamings rule_bndrs ([],[]) rev_binds
    
    1267
    -    spec_binds = pick_spec_binds known_bndrs other_binds
    
    1268
    -
    
    1269
    -    ------------------------
    
    1270
    -    get_renamings :: VarSet  -- Variables bound by a successful match on the call
    
    1271
    -                  -> ([CoreBind],[CoreBind])   -- Accumulating parameter, in order
    
    1272
    -                  -> [CoreBind]     -- Reversed, innermost first
    
    1273
    -                  -> ( VarSet
    
    1274
    -                     , ([CoreBind]    -- Renamings, in order
    
    1275
    -                     ,  [CoreBind]))  -- Other bindings, in order
    
    1276
    -    get_renamings bndrs acc [] = (bndrs, acc)
    
    1277
    -
    
    1278
    -    get_renamings bndrs (rn_binds, other_binds) (bind : binds)
    
    1279
    -      | NonRec d r <- bind
    
    1280
    -      , d `elemVarSet` bndrs
    
    1281
    -      , Just (v, mco) <- getCastedVar r
    
    1282
    -      , is_local v
    
    1283
    -      , let flipped_bind = NonRec v (mkCastMCo (Var d) (mkSymMCo mco))
    
    1284
    -      = get_renamings (bndrs `extendVarSet` v)
    
    1285
    -                      (flipped_bind:rn_binds, other_binds)
    
    1286
    -                      binds
    
    1287
    -      | otherwise
    
    1288
    -      = get_renamings bndrs
    
    1289
    -                     (rn_binds, bind:other_binds)
    
    1290
    -                     binds
    
    1291
    -
    
    1292
    -    ------------------------
    
    1293
    -    pick_spec_binds :: VarSet -> [CoreBind] -> [CoreBind]
    
    1294
    -    pick_spec_binds _ [] = []
    
    1295
    -    pick_spec_binds known_bndrs (bind:binds)
    
    1296
    -      | all keep_me (rhssOfBind bind)
    
    1297
    -      , let known_bndrs' = known_bndrs `extendVarSetList` bindersOf bind
    
    1298
    -      = bind : pick_spec_binds known_bndrs' binds
    
    1299
    -      | otherwise
    
    1300
    -      = pick_spec_binds known_bndrs binds
    
    1301
    -      where
    
    1302
    -        keep_me rhs = isEmptyVarSet (exprSomeFreeVars bad_var rhs)
    
    1303
    -        bad_var v = is_local v && not (v `elemVarSet` known_bndrs)
    
    1304
    --}
    
    1305 1359
     
    
    1306 1360
     getCastedVar :: CoreExpr -> Maybe (Var, MCoercionR)
    
    1307 1361
     getCastedVar (Var v)           = Just (v, MRefl)
    
    1308 1362
     getCastedVar (Cast (Var v) co) = Just (v, MCo co)
    
    1309 1363
     getCastedVar _                 = Nothing
    
    1310 1364
     
    
    1311
    -{-
    
    1312
    -  where
    
    1313
    -    go :: VarSet        -- Quantified variables, or dependencies thereof
    
    1314
    -       -> [CoreBind]    -- Reversed list of constant evidence bindings
    
    1315
    -       -> CoreExpr
    
    1316
    -       -> Maybe (IdSet, [CoreBind], [CoreExpr])
    
    1317
    -    go qevs acc (Cast e _)
    
    1318
    -      = go qevs acc e
    
    1319
    -    go qevs acc (Let bind e)
    
    1320
    -      | not (all (isPredTy . varType) bndrs)
    
    1321
    -        -- A normal 'let' is too complicated
    
    1322
    -        -- But we definitely include quantified constraints
    
    1323
    -        -- E.g. this is fine:  let (d :: forall a. Eq a => Eq (f a) = d2)
    
    1324
    -      = Nothing
    
    1325
    -
    
    1326
    -      -- (a) (1) in Note [prepareSpecLHS]
    
    1327
    -      | all (transfer_to_spec_rhs qevs) $
    
    1328
    -        rhssOfBind bind            -- One of the `const_binds`
    
    1329
    -      = go qevs (bind:acc) e
    
    1330
    -
    
    1331
    -      -- (a) (2) in Note [prepareSpecLHS]
    
    1332
    -      | otherwise
    
    1333
    -      = go (qevs `extendVarSetList` bndrs) acc e
    
    1334
    -      where
    
    1335
    -        bndrs = bindersOf bind
    
    1336
    -
    
    1337
    -    go qevs acc e
    
    1338
    -      | (Var fun, args) <- collectArgs e
    
    1339
    -      -- (a) (3) in Note [prepareSpecLHS]
    
    1340
    -      = assertPpr (fun == poly_id) (ppr fun $$ ppr poly_id) $
    
    1341
    -        Just (qevs, reverse acc, args)
    
    1342
    -      | otherwise
    
    1343
    -      = Nothing
    
    1344
    -
    
    1345
    -    transfer_to_spec_rhs qevs rhs
    
    1346
    -      where
    
    1347
    -        is_quant_id v = isId v && v `elemVarSet` qevs
    
    1348
    -      -- See (a) (2) in Note [prepareSpecLHS]
    
    1349
    --}
    
    1350
    -
    
    1351
    -finishSpecPrag :: Name -> CoreExpr                    -- RHS to specialise
    
    1352
    -               -> [Var] -> Id -> [CoreExpr]           -- RULE LHS pattern
    
    1353
    -               -> [Var] -> (CoreExpr -> CoreExpr) -> InlinePragma   -- Specialised form
    
    1354
    -               -> DsM (Maybe (OrdList (Id,CoreExpr), CoreRule))
    
    1355
    -finishSpecPrag poly_nm poly_rhs rule_bndrs poly_id rule_lhs_args
    
    1356
    -                                spec_bndrs mk_spec_body spec_inl
    
    1357
    -  | Just reason <- mb_useless
    
    1358
    -  = do { diagnosticDs $ DsUselessSpecialisePragma poly_nm is_dfun reason
    
    1359
    -       ; if uselessSpecialisePragmaKeepAnyway reason
    
    1360
    -         then Just <$> finish_prag
    
    1361
    -         else return Nothing }
    
    1362
    -
    
    1363
    -  | otherwise
    
    1364
    -  = Just <$> finish_prag
    
    1365
    -
    
    1366
    -  where
    
    1367
    -    -- The RULE looks like
    
    1368
    -    --    RULE "USPEC" forall rule_bndrs. f rule_lhs_args = $sf spec_bndrs
    
    1369
    -    -- The specialised function looks like
    
    1370
    -    --    $sf spec_bndrs = mk_spec_body <f's original rhs>
    
    1371
    -    -- We also use mk_spec_body to specialise the methods in f's stable unfolding
    
    1372
    -    -- NB: spec_bindrs is a subset of rule_bndrs
    
    1373
    -    finish_prag
    
    1374
    -      = do { this_mod <- getModule
    
    1375
    -           ; uniq     <- newUnique
    
    1376
    -           ; dflags   <- getDynFlags
    
    1377
    -           ; let poly_name  = idName poly_id
    
    1378
    -                 spec_occ   = mkSpecOcc (getOccName poly_name)
    
    1379
    -                 spec_name  = mkInternalName uniq spec_occ (getSrcSpan poly_name)
    
    1380
    -
    
    1381
    -                 simpl_opts = initSimpleOpts dflags
    
    1382
    -                 fn_unf     = realIdUnfolding poly_id
    
    1383
    -                 spec_unf   = specUnfolding simpl_opts spec_bndrs mk_spec_body rule_lhs_args fn_unf
    
    1384
    -                 spec_id    = mkLocalId spec_name ManyTy spec_ty
    
    1385
    -                                -- Specialised binding is toplevel, hence Many.
    
    1386
    -                                `setInlinePragma` specFunInlinePrag poly_id id_inl spec_inl
    
    1387
    -                                `setIdUnfolding`  spec_unf
    
    1388
    -
    
    1389
    -                 rule = mkSpecRule dflags this_mod False rule_act (text "USPEC")
    
    1390
    -                                   poly_id rule_bndrs rule_lhs_args
    
    1391
    -                                   (mkVarApps (Var spec_id) spec_bndrs)
    
    1392
    -
    
    1393
    -                 rule_ty  = exprType (mkApps (Var poly_id) rule_lhs_args)
    
    1394
    -                 spec_ty  = mkLamTypes spec_bndrs rule_ty
    
    1395
    -                 spec_rhs = mkLams spec_bndrs (mk_spec_body poly_rhs)
    
    1396
    -
    
    1397
    -           ; dsWarnOrphanRule rule
    
    1398
    -
    
    1399
    -           ; tracePm "dsSpec" (vcat
    
    1400
    -                [ text "fun:" <+> ppr poly_id
    
    1401
    -                , text "spec_bndrs:" <+> ppr spec_bndrs
    
    1402
    -                , text "rule_lhs_args:" <+>  ppr rule_lhs_args ])
    
    1403
    -           ; return (unitOL (spec_id, spec_rhs), rule) }
    
    1404
    -                -- NB: do *not* use makeCorePair on (spec_id,spec_rhs), because
    
    1405
    -                --     makeCorePair overwrites the unfolding, which we have
    
    1406
    -                --     just created using specUnfolding
    
    1407
    -
    
    1408
    -    -- Is this SPECIALISE pragma useless?
    
    1409
    -    mb_useless :: Maybe UselessSpecialisePragmaReason
    
    1410
    -    mb_useless
    
    1411
    -      | isJust (isClassOpId_maybe poly_id)
    
    1412
    -      -- There is no point in trying to specialise a class op
    
    1413
    -      -- Moreover, classops don't (currently) have an inl_sat arity set
    
    1414
    -      -- (it would be Just 0) and that in turn makes makeCorePair bleat
    
    1415
    -      = Just UselessSpecialiseForClassMethodSelector
    
    1416
    -
    
    1417
    -      | no_act_spec, isNeverActive rule_act
    
    1418
    -      -- Function is NOINLINE, and the specialisation inherits that
    
    1419
    -      -- See Note [Activation pragmas for SPECIALISE]
    
    1420
    -      = Just UselessSpecialiseForNoInlineFunction
    
    1421
    -
    
    1422
    -      | all is_nop_arg rule_lhs_args, not (isInlinePragma spec_inl)
    
    1423
    -      -- The specialisation does nothing.
    
    1424
    -      -- But don't complain if it is SPECIALISE INLINE (#4444)
    
    1425
    -      = Just UselessSpecialiseNoSpecialisation
    
    1426
    -
    
    1427
    -      | otherwise
    
    1428
    -      = Nothing
    
    1429
    -
    
    1430
    -    -- See Note [Activation pragmas for SPECIALISE]
    
    1431
    -    -- no_act_spec is True if the user didn't write an explicit
    
    1432
    -    -- phase specification in the SPECIALISE pragma
    
    1433
    -    id_inl        = idInlinePragma poly_id
    
    1434
    -    inl_prag_act  = inlinePragmaActivation id_inl
    
    1435
    -    spec_prag_act = inlinePragmaActivation spec_inl
    
    1436
    -    no_act_spec = case inlinePragmaSpec spec_inl of
    
    1437
    -                    NoInline _   -> isNeverActive  spec_prag_act
    
    1438
    -                    Opaque _     -> isNeverActive  spec_prag_act
    
    1439
    -                    _            -> isAlwaysActive spec_prag_act
    
    1440
    -    rule_act | no_act_spec = inl_prag_act    -- Inherit
    
    1441
    -             | otherwise   = spec_prag_act   -- Specified by user
    
    1442
    -
    
    1443
    -    is_nop_arg (Type {})     = True
    
    1444
    -    is_nop_arg (Coercion {}) = True
    
    1445
    -    is_nop_arg (Cast e _)    = is_nop_arg e
    
    1446
    -    is_nop_arg (Tick _ e)    = is_nop_arg e
    
    1447
    -    is_nop_arg (Var x)       = x `elem` spec_bndrs
    
    1448
    -    is_nop_arg _             = False
    
    1449
    -
    
    1450
    -    is_dfun = case idDetails poly_id of
    
    1451
    -      DFunId {} -> True
    
    1452
    -      _ -> False
    
    1453
    -
    
    1454 1365
     specFunInlinePrag :: Id -> InlinePragma
    
    1455 1366
                       -> InlinePragma -> InlinePragma
    
    1456 1367
     -- See Note [Activation pragmas for SPECIALISE]
    

  • testsuite/tests/simplCore/should_compile/T26115.hs
    1
    +module T26115 where
    
    2
    +
    
    3
    +class C a b where { op1, op2 :: a -> b -> Bool
    
    4
    +                  ; op2 = op1 }
    
    5
    +
    
    6
    +instance C Bool b where { op1 _ _ = True }
    
    7
    +
    
    8
    +instance C p q => C [p] q where
    
    9
    +  op1 [x] y = op1 x y
    
    10
    +  {-# SPECIALISE instance C [Bool] b #-}

  • testsuite/tests/simplCore/should_compile/T26115.stderr
    1
    +[GblId[DFunId],
    
    2
    + Unf=DFun: \ (@b_awW) ->
    
    3
    +[GblId[DFunId],
    
    4
    + Unf=DFun: \ (@b_aBU) ->
    
    5
    +[GblId[DFunId],
    
    6
    + Unf=DFun: \ (@p_awR) (@q_awS) (v_B1 :: C p_awR q_awS) ->

  • testsuite/tests/simplCore/should_compile/T26116.hs
    1
    +{-# LANGUAGE QuantifiedConstraints #-}
    
    2
    +{-# OPTIONS_GHC -fno-warn-missing-methods #-}
    
    3
    +
    
    4
    +module T26116 where
    
    5
    +
    
    6
    +data T a = MkT a
    
    7
    +
    
    8
    +instance Eq (T a) where
    
    9
    +    x == y = True
    
    10
    +
    
    11
    +class (forall b. Eq (T b)) => D a where { dop :: a -> a }
    
    12
    +
    
    13
    +class C f a where { op1,op2 :: f a -> Int }
    
    14
    +
    
    15
    +instance (Eq (f a), D a) => C f a where
    
    16
    +    op1 x | x==x      = 3
    
    17
    +          | otherwise = 4
    
    18
    +    {-# SPECIALISE instance D a => C T a #-}

  • testsuite/tests/simplCore/should_compile/T26116.stderr
    1
    +
    
    2
    +==================== Tidy Core rules ====================
    
    3
    +"USPEC $cop1 @T @_"
    
    4
    +    forall (@a) ($dD :: D a) ($dEq :: Eq (T a)).
    
    5
    +      $fCTYPEfa_$cop1 @T @a $dEq $dD
    
    6
    +      = \ _ [Occ=Dead] -> I# 3#
    
    7
    +"USPEC $fCTYPEfa @T @_"
    
    8
    +    forall (@a) ($dD :: D a) ($dEq :: Eq (T a)).
    
    9
    +      $fCTYPEfa @T @a $dEq $dD
    
    10
    +      = $fCTYPEfa_$s$fCTYPEfa @a $dD
    
    11
    +
    
    12
    +

  • testsuite/tests/simplCore/should_compile/T26117.hs
    1
    +{-# LANGUAGE UndecidableInstances, TypeFamilies #-}
    
    2
    +
    
    3
    +module T26117 where
    
    4
    +
    
    5
    +type family F a
    
    6
    +type instance F Int = Bool
    
    7
    +
    
    8
    +class Eq (F a) => D a b where {  dop1, dop2 :: a -> b -> b }
    
    9
    +
    
    10
    +class C a b where { op1,op2 :: F a -> a -> b -> Int }
    
    11
    +
    
    12
    +instance (Eq (F a), D a b) => C a [b] where
    
    13
    +  op1 x _ _ | x==x      = 3
    
    14
    +            | otherwise = 4
    
    15
    +  {-# SPECIALISE instance D Int b => C Int [b] #-}

  • testsuite/tests/simplCore/should_compile/all.T
    ... ... @@ -548,3 +548,6 @@ test('T25965', normal, compile, ['-O'])
    548 548
     test('T25703',  [grep_errmsg(r'SPEC')], compile, ['-O -fpolymorphic-specialisation -ddump-rule-firings'])
    
    549 549
     test('T25703a', [grep_errmsg(r'SPEC')], compile, ['-O -fpolymorphic-specialisation -ddump-rule-firings'])
    
    550 550
     
    
    551
    +test('T26115', [grep_errmsg(r'DFun')], compile, ['-O -ddump-simpl'])
    
    552
    +test('T26116', normal, compile, ['-O -ddump-rules'])
    
    553
    +