... |
... |
@@ -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]
|