+simplBinders :: [InBinder] -> ([OutBinder] -> SimplM a) -> SimplM a
+simplBinders bndrs thing_inside
+ = getSwitchChecker `thenSmpl` \ sw_chkr ->
+ getSimplBinderStuff `thenSmpl` \ stuff ->
+ let
+ must_clone = switchIsOn sw_chkr SimplPleaseClone
+ (stuff', bndrs') = mapAccumL (subst_binder must_clone) stuff bndrs
+ in
+ setSimplBinderStuff stuff' $
+ thing_inside bndrs'
+
+simplBinder :: InBinder -> (OutBinder -> SimplM a) -> SimplM a
+simplBinder bndr thing_inside
+ = getSwitchChecker `thenSmpl` \ sw_chkr ->
+ getSimplBinderStuff `thenSmpl` \ stuff ->
+ let
+ must_clone = switchIsOn sw_chkr SimplPleaseClone
+ (stuff', bndr') = subst_binder must_clone stuff bndr
+ in
+ setSimplBinderStuff stuff' $
+ thing_inside bndr'
+
+-- Same semantics as simplBinders, but a little less
+-- plumbing and hence a little more efficient.
+-- Maybe not worth the candle?
+simplIds :: [InBinder] -> ([OutBinder] -> SimplM a) -> SimplM a
+simplIds ids thing_inside
+ = getSwitchChecker `thenSmpl` \ sw_chkr ->
+ getSimplBinderStuff `thenSmpl` \ (ty_subst, id_subst, in_scope, us) ->
+ let
+ must_clone = switchIsOn sw_chkr SimplPleaseClone
+ (id_subst', in_scope', us', ids') = substIds (simpl_clone_fn must_clone)
+ ty_subst id_subst in_scope us ids
+ in
+ setSimplBinderStuff (ty_subst, id_subst', in_scope', us') $
+ thing_inside ids'
+
+subst_binder must_clone (ty_subst, id_subst, in_scope, us) bndr
+ | isTyVar bndr
+ = case substTyVar ty_subst in_scope bndr of
+ (ty_subst', in_scope', bndr') -> ((ty_subst', id_subst, in_scope', us), bndr')
+
+ | otherwise
+ = case substId (simpl_clone_fn must_clone) ty_subst id_subst in_scope us bndr of
+ (id_subst', in_scope', us', bndr')
+ -> ((ty_subst, id_subst', in_scope', us'), bndr')
+
+simpl_clone_fn must_clone in_scope us id
+ | (must_clone && isLocalName (idName id))
+ || id `elemVarSet` in_scope
+ = case splitUniqSupply us of
+ (us1, us2) -> Just (us1, setVarUnique id (uniqFromSupply us2))
+
+ | otherwise
+ = Nothing