+ mkCoerce to_ty1 from_ty1 (Note (Coerce to_ty2 from_ty2) body)
+ = ASSERT( from_ty1 == to_ty2 )
+ mkCoerce to_ty1 from_ty2 body
+ mkCoerce to_ty from_ty body
+ | to_ty == from_ty = body
+ | otherwise = Note (Coerce to_ty from_ty) body
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection[Simplify-scc]{SCC expressions
+%* *
+%************************************************************************
+
+1) Eliminating nested sccs ...
+We must be careful to maintain the scc counts ...
+
+\begin{code}
+simplSCC env cc1 (Note (SCC cc2) expr) args result_ty
+ | not (isSccCountCostCentre cc2) && case cmpCostCentre cc1 cc2 of { EQ -> True; _ -> False }
+ -- eliminate inner scc if no call counts and same cc as outer
+ = simplSCC env cc1 expr args result_ty
+
+ | not (isSccCountCostCentre cc2) && not (isSccCountCostCentre cc1)
+ -- eliminate outer scc if no call counts associated with either ccs
+ = simplSCC env cc2 expr args result_ty
+\end{code}
+
+2) Moving sccs inside lambdas ...
+
+\begin{code}
+simplSCC env cc (Lam binder@(ValBinder _) body) args result_ty
+ | not (isSccCountCostCentre cc)
+ -- move scc inside lambda only if no call counts
+ = simplExpr env (Lam binder (Note (SCC cc) body)) args result_ty
+
+simplSCC env cc (Lam binder body) args result_ty
+ -- always ok to move scc inside type/usage lambda
+ = simplExpr env (Lam binder (Note (SCC cc) body)) args result_ty
+\end{code}
+
+3) Eliminating dict sccs ...
+
+\begin{code}
+simplSCC env cc expr args result_ty
+ | squashableDictishCcExpr cc expr
+ -- eliminate dict cc if trivial dict expression
+ = simplExpr env expr args result_ty
+\end{code}
+
+4) Moving arguments inside the body of an scc ...
+This moves the cost of doing the application inside the scc
+(which may include the cost of extracting methods etc)
+
+\begin{code}
+simplSCC env cc body args result_ty
+ = let
+ new_env = setEnclosingCC env cc
+ in
+ simplExpr new_env body args result_ty `thenSmpl` \ body' ->
+ returnSmpl (Note (SCC cc) body')