Sophie

Sophie

distrib > Fedora > 14 > x86_64 > by-pkgid > 8d1ef08c9e0d44c69764afc615a03d0d > files > 1726

ghc-ghc-devel-6.12.3-5.fc14.i686.rpm

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<!-- Generated by HsColour, http://www.cs.york.ac.uk/fp/darcs/hscolour/ -->
<title>simplCore/FloatOut.lhs</title>
<link type='text/css' rel='stylesheet' href='hscolour.css' />
</head>
<body>
%
% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
%
\section[FloatOut]{Float bindings outwards (towards the top level)}

``Long-distance'' floating of bindings towards the top level.

\begin{code}
<pre><a name="line-1"></a><span class='hs-keyword'>module</span> <span class='hs-conid'>FloatOut</span> <span class='hs-layout'>(</span> <span class='hs-varid'>floatOutwards</span> <span class='hs-layout'>)</span> <span class='hs-keyword'>where</span>
<a name="line-2"></a>
<a name="line-3"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>CoreSyn</span>
<a name="line-4"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>CoreUtils</span>
<a name="line-5"></a>
<a name="line-6"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>DynFlags</span>	<span class='hs-layout'>(</span> <span class='hs-conid'>DynFlags</span><span class='hs-layout'>,</span> <span class='hs-conid'>DynFlag</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-conid'>FloatOutSwitches</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span> <span class='hs-layout'>)</span>
<a name="line-7"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>ErrUtils</span>		<span class='hs-layout'>(</span> <span class='hs-varid'>dumpIfSet_dyn</span> <span class='hs-layout'>)</span>
<a name="line-8"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>CostCentre</span>	<span class='hs-layout'>(</span> <span class='hs-varid'>dupifyCC</span><span class='hs-layout'>,</span> <span class='hs-conid'>CostCentre</span> <span class='hs-layout'>)</span>
<a name="line-9"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Id</span>		<span class='hs-layout'>(</span> <span class='hs-conid'>Id</span><span class='hs-layout'>,</span> <span class='hs-varid'>idType</span> <span class='hs-layout'>)</span>
<a name="line-10"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Type</span>		<span class='hs-layout'>(</span> <span class='hs-varid'>isUnLiftedType</span> <span class='hs-layout'>)</span>
<a name="line-11"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>SetLevels</span>	<span class='hs-layout'>(</span> <span class='hs-conid'>Level</span><span class='hs-layout'>(</span><span class='hs-keyglyph'>..</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-conid'>LevelledExpr</span><span class='hs-layout'>,</span> <span class='hs-conid'>LevelledBind</span><span class='hs-layout'>,</span>
<a name="line-12"></a>			  <span class='hs-varid'>setLevels</span><span class='hs-layout'>,</span> <span class='hs-varid'>isTopLvl</span><span class='hs-layout'>,</span> <span class='hs-varid'>tOP_LEVEL</span> <span class='hs-layout'>)</span>
<a name="line-13"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>UniqSupply</span>       <span class='hs-layout'>(</span> <span class='hs-conid'>UniqSupply</span> <span class='hs-layout'>)</span>
<a name="line-14"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Bag</span>
<a name="line-15"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Util</span>
<a name="line-16"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Maybes</span>
<a name="line-17"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>UniqFM</span>
<a name="line-18"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>Outputable</span>
<a name="line-19"></a><span class='hs-keyword'>import</span> <span class='hs-conid'>FastString</span>
</pre>\end{code}

	-----------------
	Overall game plan
	-----------------

The Big Main Idea is:

  	To float out sub-expressions that can thereby get outside
	a non-one-shot value lambda, and hence may be shared.


To achieve this we may need to do two thing:

   a) Let-bind the sub-expression:

	f (g x)  ==>  let lvl = f (g x) in lvl

      Now we can float the binding for 'lvl'.  

   b) More than that, we may need to abstract wrt a type variable

	\x -> ... /\a -> let v = ...a... in ....

      Here the binding for v mentions 'a' but not 'x'.  So we
      abstract wrt 'a', to give this binding for 'v':

	    vp = /\a -> ...a...
	    v  = vp a

      Now the binding for vp can float out unimpeded.
      I can't remember why this case seemed important enough to
      deal with, but I certainly found cases where important floats
      didn't happen if we did not abstract wrt tyvars.

With this in mind we can also achieve another goal: lambda lifting.
We can make an arbitrary (function) binding float to top level by
abstracting wrt *all* local variables, not just type variables, leaving
a binding that can be floated right to top level.  Whether or not this
happens is controlled by a flag.


Random comments
~~~~~~~~~~~~~~~

At the moment we never float a binding out to between two adjacent
lambdas.  For example:

@
	\x y -> let t = x+x in ...
===>
	\x -> let t = x+x in \y -> ...
@
Reason: this is less efficient in the case where the original lambda
is never partially applied.

But there's a case I've seen where this might not be true.  Consider:
@
elEm2 x ys
  = elem' x ys
  where
    elem' _ []	= False
    elem' x (y:ys)	= x==y || elem' x ys
@
It turns out that this generates a subexpression of the form
@
	\deq x ys -> let eq = eqFromEqDict deq in ...
@
vwhich might usefully be separated to
@
	\deq -> let eq = eqFromEqDict deq in \xy -> ...
@
Well, maybe.  We don't do this at the moment.


%************************************************************************
%*									*
\subsection[floatOutwards]{@floatOutwards@: let-floating interface function}
%*									*
%************************************************************************

\begin{code}
<pre><a name="line-1"></a><a name="floatOutwards"></a><span class='hs-definition'>floatOutwards</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FloatOutSwitches</span>
<a name="line-2"></a>	      <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>DynFlags</span>
<a name="line-3"></a>	      <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>UniqSupply</span> 
<a name="line-4"></a>	      <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>CoreBind</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>IO</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>CoreBind</span><span class='hs-keyglyph'>]</span>
<a name="line-5"></a>
<a name="line-6"></a><span class='hs-definition'>floatOutwards</span> <span class='hs-varid'>float_sws</span> <span class='hs-varid'>dflags</span> <span class='hs-varid'>us</span> <span class='hs-varid'>pgm</span>
<a name="line-7"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>do</span> <span class='hs-layout'>{</span>
<a name="line-8"></a>	<span class='hs-keyword'>let</span> <span class='hs-layout'>{</span> <span class='hs-varid'>annotated_w_levels</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>setLevels</span> <span class='hs-varid'>float_sws</span> <span class='hs-varid'>pgm</span> <span class='hs-varid'>us</span> <span class='hs-layout'>;</span>
<a name="line-9"></a>	      <span class='hs-layout'>(</span><span class='hs-varid'>fss</span><span class='hs-layout'>,</span> <span class='hs-varid'>binds_s'</span><span class='hs-layout'>)</span>    <span class='hs-keyglyph'>=</span> <span class='hs-varid'>unzip</span> <span class='hs-layout'>(</span><span class='hs-varid'>map</span> <span class='hs-varid'>floatTopBind</span> <span class='hs-varid'>annotated_w_levels</span><span class='hs-layout'>)</span>
<a name="line-10"></a>	    <span class='hs-layout'>}</span> <span class='hs-layout'>;</span>
<a name="line-11"></a>
<a name="line-12"></a>	<span class='hs-varid'>dumpIfSet_dyn</span> <span class='hs-varid'>dflags</span> <span class='hs-conid'>Opt_D_verbose_core2core</span> <span class='hs-str'>"Levels added:"</span>
<a name="line-13"></a>	          <span class='hs-layout'>(</span><span class='hs-varid'>vcat</span> <span class='hs-layout'>(</span><span class='hs-varid'>map</span> <span class='hs-varid'>ppr</span> <span class='hs-varid'>annotated_w_levels</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>;</span>
<a name="line-14"></a>
<a name="line-15"></a>	<span class='hs-keyword'>let</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>tlets</span><span class='hs-layout'>,</span> <span class='hs-varid'>ntlets</span><span class='hs-layout'>,</span> <span class='hs-varid'>lams</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>get_stats</span> <span class='hs-layout'>(</span><span class='hs-varid'>sum_stats</span> <span class='hs-varid'>fss</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span><span class='hs-layout'>;</span>
<a name="line-16"></a>
<a name="line-17"></a>	<span class='hs-varid'>dumpIfSet_dyn</span> <span class='hs-varid'>dflags</span> <span class='hs-conid'>Opt_D_dump_simpl_stats</span> <span class='hs-str'>"FloatOut stats:"</span>
<a name="line-18"></a>		<span class='hs-layout'>(</span><span class='hs-varid'>hcat</span> <span class='hs-keyglyph'>[</span>	<span class='hs-varid'>int</span> <span class='hs-varid'>tlets</span><span class='hs-layout'>,</span>  <span class='hs-varid'>ptext</span> <span class='hs-layout'>(</span><span class='hs-varid'>sLit</span> <span class='hs-str'>" Lets floated to top level; "</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span>
<a name="line-19"></a>			<span class='hs-varid'>int</span> <span class='hs-varid'>ntlets</span><span class='hs-layout'>,</span> <span class='hs-varid'>ptext</span> <span class='hs-layout'>(</span><span class='hs-varid'>sLit</span> <span class='hs-str'>" Lets floated elsewhere; from "</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span>
<a name="line-20"></a>			<span class='hs-varid'>int</span> <span class='hs-varid'>lams</span><span class='hs-layout'>,</span>   <span class='hs-varid'>ptext</span> <span class='hs-layout'>(</span><span class='hs-varid'>sLit</span> <span class='hs-str'>" Lambda groups"</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span><span class='hs-layout'>;</span>
<a name="line-21"></a>
<a name="line-22"></a>	<span class='hs-varid'>return</span> <span class='hs-layout'>(</span><span class='hs-varid'>concat</span> <span class='hs-varid'>binds_s'</span><span class='hs-layout'>)</span>
<a name="line-23"></a>    <span class='hs-layout'>}</span>
<a name="line-24"></a>
<a name="line-25"></a><a name="floatTopBind"></a><span class='hs-definition'>floatTopBind</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>LevelledBind</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>FloatStats</span><span class='hs-layout'>,</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>CoreBind</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span>
<a name="line-26"></a><span class='hs-definition'>floatTopBind</span> <span class='hs-varid'>bind</span>
<a name="line-27"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatBind</span> <span class='hs-varid'>bind</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-28"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>bagToList</span> <span class='hs-layout'>(</span><span class='hs-varid'>flattenFloats</span> <span class='hs-varid'>floats</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-29"></a>    <span class='hs-layout'>}</span>
</pre>\end{code}

%************************************************************************
%*									*
\subsection[FloatOut-Bind]{Floating in a binding (the business end)}
%*									*
%************************************************************************


\begin{code}
<pre><a name="line-1"></a><a name="floatBind"></a><span class='hs-definition'>floatBind</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>LevelledBind</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>FloatStats</span><span class='hs-layout'>,</span> <span class='hs-conid'>FloatBinds</span><span class='hs-layout'>)</span>
<a name="line-2"></a>
<a name="line-3"></a><span class='hs-definition'>floatBind</span> <span class='hs-layout'>(</span><span class='hs-conid'>NonRec</span> <span class='hs-layout'>(</span><span class='hs-conid'>TB</span> <span class='hs-varid'>name</span> <span class='hs-varid'>level</span><span class='hs-layout'>)</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span>
<a name="line-4"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatRhs</span> <span class='hs-varid'>level</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs_floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-5"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs_floats</span> <span class='hs-varop'>`plusFloats`</span> <span class='hs-varid'>unitFloat</span> <span class='hs-varid'>level</span> <span class='hs-layout'>(</span><span class='hs-conid'>NonRec</span> <span class='hs-varid'>name</span> <span class='hs-varid'>rhs'</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span>
<a name="line-6"></a>
<a name="line-7"></a><span class='hs-definition'>floatBind</span> <span class='hs-varid'>bind</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>Rec</span> <span class='hs-varid'>pairs</span><span class='hs-layout'>)</span>
<a name="line-8"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>unzip3</span> <span class='hs-layout'>(</span><span class='hs-varid'>map</span> <span class='hs-varid'>do_pair</span> <span class='hs-varid'>pairs</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fss</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhss_floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>new_pairs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-9"></a>    <span class='hs-keyword'>let</span> <span class='hs-varid'>rhs_floats</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>foldr1</span> <span class='hs-varid'>plusFloats</span> <span class='hs-varid'>rhss_floats</span> <span class='hs-keyword'>in</span>
<a name="line-10"></a>
<a name="line-11"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>not</span> <span class='hs-layout'>(</span><span class='hs-varid'>isTopLvl</span> <span class='hs-varid'>bind_dest_lvl</span><span class='hs-layout'>)</span> <span class='hs-keyword'>then</span>
<a name="line-12"></a>	<span class='hs-comment'>-- Find which bindings float out at least one lambda beyond this one</span>
<a name="line-13"></a>	<span class='hs-comment'>-- These ones can't mention the binders, because they couldn't </span>
<a name="line-14"></a>	<span class='hs-comment'>-- be escaping a major level if so.</span>
<a name="line-15"></a>	<span class='hs-comment'>-- The ones that are not going further can join the letrec;</span>
<a name="line-16"></a>	<span class='hs-comment'>-- they may not be mutually recursive but the occurrence analyser will</span>
<a name="line-17"></a>	<span class='hs-comment'>-- find that out.</span>
<a name="line-18"></a>	<span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>partitionByMajorLevel</span> <span class='hs-varid'>bind_dest_lvl</span> <span class='hs-varid'>rhs_floats</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>floats'</span><span class='hs-layout'>,</span> <span class='hs-varid'>heres</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-19"></a>	<span class='hs-layout'>(</span><span class='hs-varid'>sum_stats</span> <span class='hs-varid'>fss</span><span class='hs-layout'>,</span>
<a name="line-20"></a>      <span class='hs-varid'>floats'</span> <span class='hs-varop'>`plusFloats`</span> <span class='hs-varid'>unitFloat</span> <span class='hs-varid'>bind_dest_lvl</span>
<a name="line-21"></a>                            <span class='hs-layout'>(</span><span class='hs-conid'>Rec</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatsToBindPairs</span> <span class='hs-varid'>heres</span> <span class='hs-varid'>new_pairs</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span>
<a name="line-22"></a>    <span class='hs-keyword'>else</span>
<a name="line-23"></a>	<span class='hs-comment'>-- In a recursive binding, *destined for* the top level</span>
<a name="line-24"></a>	<span class='hs-comment'>-- (only), the rhs floats may contain references to the </span>
<a name="line-25"></a>	<span class='hs-comment'>-- bound things.  For example</span>
<a name="line-26"></a>	<span class='hs-comment'>--	f = ...(let v = ...f... in b) ...</span>
<a name="line-27"></a>	<span class='hs-comment'>--  might get floated to</span>
<a name="line-28"></a>	<span class='hs-comment'>--	v = ...f...</span>
<a name="line-29"></a>	<span class='hs-comment'>--	f = ... b ...</span>
<a name="line-30"></a>	<span class='hs-comment'>-- and hence we must (pessimistically) make all the floats recursive</span>
<a name="line-31"></a>	<span class='hs-comment'>-- with the top binding.  Later dependency analysis will unravel it.</span>
<a name="line-32"></a>	<span class='hs-comment'>--</span>
<a name="line-33"></a>	<span class='hs-comment'>-- This can only happen for bindings destined for the top level,</span>
<a name="line-34"></a>	<span class='hs-comment'>-- because only then will partitionByMajorLevel allow through a binding</span>
<a name="line-35"></a>	<span class='hs-comment'>-- that only differs in its minor level</span>
<a name="line-36"></a>	<span class='hs-layout'>(</span><span class='hs-varid'>sum_stats</span> <span class='hs-varid'>fss</span><span class='hs-layout'>,</span> <span class='hs-varid'>unitFloat</span> <span class='hs-varid'>tOP_LEVEL</span>
<a name="line-37"></a>                       <span class='hs-layout'>(</span><span class='hs-conid'>Rec</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatsToBindPairs</span> <span class='hs-layout'>(</span><span class='hs-varid'>flattenFloats</span> <span class='hs-varid'>rhs_floats</span><span class='hs-layout'>)</span> <span class='hs-varid'>new_pairs</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-38"></a>    <span class='hs-layout'>}</span>
<a name="line-39"></a>  <span class='hs-keyword'>where</span>
<a name="line-40"></a>    <span class='hs-varid'>bind_dest_lvl</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>getBindLevel</span> <span class='hs-varid'>bind</span>
<a name="line-41"></a>
<a name="line-42"></a>    <span class='hs-varid'>do_pair</span> <span class='hs-layout'>(</span><span class='hs-conid'>TB</span> <span class='hs-varid'>name</span> <span class='hs-varid'>level</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span>
<a name="line-43"></a>      <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatRhs</span> <span class='hs-varid'>level</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs_floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-44"></a>	<span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs_floats</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varid'>name</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs'</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-45"></a>	<span class='hs-layout'>}</span>
</pre>\end{code}

%************************************************************************

\subsection[FloatOut-Expr]{Floating in expressions}
%*									*
%************************************************************************

\begin{code}
<pre><a name="line-1"></a><a name="floatExpr"></a><span class='hs-definition'>floatExpr</span><span class='hs-layout'>,</span> <span class='hs-varid'>floatRhs</span><span class='hs-layout'>,</span> <span class='hs-varid'>floatCaseAlt</span>
<a name="line-2"></a>	 <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Level</span>
<a name="line-3"></a>	 <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>LevelledExpr</span>
<a name="line-4"></a>	 <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>FloatStats</span><span class='hs-layout'>,</span> <span class='hs-conid'>FloatBinds</span><span class='hs-layout'>,</span> <span class='hs-conid'>CoreExpr</span><span class='hs-layout'>)</span>
<a name="line-5"></a>
<a name="line-6"></a><a name="floatCaseAlt"></a><span class='hs-definition'>floatCaseAlt</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>arg</span>	<span class='hs-comment'>-- Used rec rhss, and case-alternative rhss</span>
<a name="line-7"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>arg</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fsa</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>arg'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-8"></a>    <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>partitionByMajorLevel</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>floats</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>floats'</span><span class='hs-layout'>,</span> <span class='hs-varid'>heres</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-9"></a>	<span class='hs-comment'>-- Dump bindings that aren't going to escape from a lambda;</span>
<a name="line-10"></a>	<span class='hs-comment'>-- in particular, we must dump the ones that are bound by </span>
<a name="line-11"></a>	<span class='hs-comment'>-- the rec or case alternative</span>
<a name="line-12"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>fsa</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats'</span><span class='hs-layout'>,</span> <span class='hs-varid'>install</span> <span class='hs-varid'>heres</span> <span class='hs-varid'>arg'</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span><span class='hs-layout'>}</span>
<a name="line-13"></a>
<a name="line-14"></a><a name="floatRhs"></a><span class='hs-definition'>floatRhs</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>arg</span>	<span class='hs-comment'>-- Used for nested non-rec rhss, and fn args</span>
<a name="line-15"></a>			<span class='hs-comment'>-- See Note [Floating out of RHS]</span>
<a name="line-16"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>arg</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fsa</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>arg'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-17"></a>    <span class='hs-keyword'>if</span> <span class='hs-varid'>exprIsCheap</span> <span class='hs-varid'>arg'</span> <span class='hs-keyword'>then</span>	
<a name="line-18"></a>	<span class='hs-layout'>(</span><span class='hs-varid'>fsa</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>arg'</span><span class='hs-layout'>)</span>
<a name="line-19"></a>    <span class='hs-keyword'>else</span>
<a name="line-20"></a>    <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>partitionByMajorLevel</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>floats</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>floats'</span><span class='hs-layout'>,</span> <span class='hs-varid'>heres</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-21"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>fsa</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats'</span><span class='hs-layout'>,</span> <span class='hs-varid'>install</span> <span class='hs-varid'>heres</span> <span class='hs-varid'>arg'</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span><span class='hs-layout'>}</span>
<a name="line-22"></a>
<a name="line-23"></a><span class='hs-comment'>-- Note [Floating out of RHSs]</span>
<a name="line-24"></a><span class='hs-comment'>-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~</span>
<a name="line-25"></a><span class='hs-comment'>-- Dump bindings that aren't going to escape from a lambda</span>
<a name="line-26"></a><span class='hs-comment'>-- This isn't a scoping issue (the binder isn't in scope in the RHS </span>
<a name="line-27"></a><span class='hs-comment'>--	of a non-rec binding)</span>
<a name="line-28"></a><span class='hs-comment'>-- Rather, it is to avoid floating the x binding out of</span>
<a name="line-29"></a><span class='hs-comment'>--	f (let x = e in b)</span>
<a name="line-30"></a><span class='hs-comment'>-- unnecessarily.  But we first test for values or trival rhss,</span>
<a name="line-31"></a><span class='hs-comment'>-- because (in particular) we don't want to insert new bindings between</span>
<a name="line-32"></a><span class='hs-comment'>-- the "=" and the "\".  E.g.</span>
<a name="line-33"></a><span class='hs-comment'>--	f = \x -&gt; let &lt;bind&gt; in &lt;body&gt;</span>
<a name="line-34"></a><span class='hs-comment'>-- We do not want</span>
<a name="line-35"></a><span class='hs-comment'>--	f = let &lt;bind&gt; in \x -&gt; &lt;body&gt;</span>
<a name="line-36"></a><span class='hs-comment'>-- (a) The simplifier will immediately float it further out, so we may</span>
<a name="line-37"></a><span class='hs-comment'>--	as well do so right now; in general, keeping rhss as manifest </span>
<a name="line-38"></a><span class='hs-comment'>--	values is good</span>
<a name="line-39"></a><span class='hs-comment'>-- (b) If a float-in pass follows immediately, it might add yet more</span>
<a name="line-40"></a><span class='hs-comment'>--	bindings just after the '='.  And some of them might (correctly)</span>
<a name="line-41"></a><span class='hs-comment'>--	be strict even though the 'let f' is lazy, because f, being a value,</span>
<a name="line-42"></a><span class='hs-comment'>--	gets its demand-info zapped by the simplifier.</span>
<a name="line-43"></a><span class='hs-comment'>--</span>
<a name="line-44"></a><span class='hs-comment'>-- We use exprIsCheap because that is also what's used by the simplifier</span>
<a name="line-45"></a><span class='hs-comment'>-- to decide whether to float a let out of a let</span>
<a name="line-46"></a>
<a name="line-47"></a><span class='hs-definition'>floatExpr</span> <span class='hs-keyword'>_</span> <span class='hs-layout'>(</span><span class='hs-conid'>Var</span> <span class='hs-varid'>v</span><span class='hs-layout'>)</span>   <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>zeroStats</span><span class='hs-layout'>,</span> <span class='hs-varid'>emptyFloats</span><span class='hs-layout'>,</span> <span class='hs-conid'>Var</span> <span class='hs-varid'>v</span><span class='hs-layout'>)</span>
<a name="line-48"></a><span class='hs-definition'>floatExpr</span> <span class='hs-keyword'>_</span> <span class='hs-layout'>(</span><span class='hs-conid'>Type</span> <span class='hs-varid'>ty</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>zeroStats</span><span class='hs-layout'>,</span> <span class='hs-varid'>emptyFloats</span><span class='hs-layout'>,</span> <span class='hs-conid'>Type</span> <span class='hs-varid'>ty</span><span class='hs-layout'>)</span>
<a name="line-49"></a><span class='hs-definition'>floatExpr</span> <span class='hs-keyword'>_</span> <span class='hs-layout'>(</span><span class='hs-conid'>Lit</span> <span class='hs-varid'>lit</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>zeroStats</span><span class='hs-layout'>,</span> <span class='hs-varid'>emptyFloats</span><span class='hs-layout'>,</span> <span class='hs-conid'>Lit</span> <span class='hs-varid'>lit</span><span class='hs-layout'>)</span>
<a name="line-50"></a>	  
<a name="line-51"></a><span class='hs-definition'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-layout'>(</span><span class='hs-conid'>App</span> <span class='hs-varid'>e</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span>
<a name="line-52"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatExpr</span>      <span class='hs-varid'>lvl</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fse</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats_e</span><span class='hs-layout'>,</span> <span class='hs-varid'>e'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-53"></a>    <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatRhs</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>a</span><span class='hs-layout'>)</span> 	<span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fsa</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats_a</span><span class='hs-layout'>,</span> <span class='hs-varid'>a'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-54"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>fse</span> <span class='hs-varop'>`add_stats`</span> <span class='hs-varid'>fsa</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats_e</span> <span class='hs-varop'>`plusFloats`</span> <span class='hs-varid'>floats_a</span><span class='hs-layout'>,</span> <span class='hs-conid'>App</span> <span class='hs-varid'>e'</span> <span class='hs-varid'>a'</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span><span class='hs-layout'>}</span>
<a name="line-55"></a>
<a name="line-56"></a><span class='hs-definition'>floatExpr</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>lam</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>Lam</span> <span class='hs-keyword'>_</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span>
<a name="line-57"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>let</span>
<a name="line-58"></a>	<span class='hs-layout'>(</span><span class='hs-varid'>bndrs_w_lvls</span><span class='hs-layout'>,</span> <span class='hs-varid'>body</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>collectBinders</span> <span class='hs-varid'>lam</span>
<a name="line-59"></a>	<span class='hs-varid'>bndrs</span>		     <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>b</span> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>TB</span> <span class='hs-varid'>b</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>bndrs_w_lvls</span><span class='hs-keyglyph'>]</span>
<a name="line-60"></a>	<span class='hs-varid'>lvls</span>		     <span class='hs-keyglyph'>=</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>l</span> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>TB</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>l</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>bndrs_w_lvls</span><span class='hs-keyglyph'>]</span>
<a name="line-61"></a>
<a name="line-62"></a>	<span class='hs-comment'>-- For the all-tyvar case we are prepared to pull </span>
<a name="line-63"></a>	<span class='hs-comment'>-- the lets out, to implement the float-out-of-big-lambda</span>
<a name="line-64"></a>	<span class='hs-comment'>-- transform; but otherwise we only float bindings that are</span>
<a name="line-65"></a>	<span class='hs-comment'>-- going to escape a value lambda.</span>
<a name="line-66"></a>	<span class='hs-comment'>-- In particular, for one-shot lambdas we don't float things</span>
<a name="line-67"></a>	<span class='hs-comment'>-- out; we get no saving by so doing.</span>
<a name="line-68"></a>	<span class='hs-varid'>partition_fn</span> <span class='hs-keyglyph'>|</span> <span class='hs-varid'>all</span> <span class='hs-varid'>isTyVar</span> <span class='hs-varid'>bndrs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>partitionByLevel</span>
<a name="line-69"></a>		     <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>	 <span class='hs-keyglyph'>=</span> <span class='hs-varid'>partitionByMajorLevel</span>
<a name="line-70"></a>    <span class='hs-keyword'>in</span>
<a name="line-71"></a>    <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatExpr</span> <span class='hs-layout'>(</span><span class='hs-varid'>last</span> <span class='hs-varid'>lvls</span><span class='hs-layout'>)</span> <span class='hs-varid'>body</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>body'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-72"></a>
<a name="line-73"></a>	<span class='hs-comment'>-- Dump any bindings which absolutely cannot go any further</span>
<a name="line-74"></a>    <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>partition_fn</span> <span class='hs-layout'>(</span><span class='hs-varid'>head</span> <span class='hs-varid'>lvls</span><span class='hs-layout'>)</span> <span class='hs-varid'>floats</span><span class='hs-layout'>)</span>	<span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>floats'</span><span class='hs-layout'>,</span> <span class='hs-varid'>heres</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-75"></a>
<a name="line-76"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>add_to_stats</span> <span class='hs-varid'>fs</span> <span class='hs-varid'>floats'</span><span class='hs-layout'>,</span> <span class='hs-varid'>floats'</span><span class='hs-layout'>,</span> <span class='hs-varid'>mkLams</span> <span class='hs-varid'>bndrs</span> <span class='hs-layout'>(</span><span class='hs-varid'>install</span> <span class='hs-varid'>heres</span> <span class='hs-varid'>body'</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-77"></a>    <span class='hs-layout'>}</span><span class='hs-layout'>}</span>
<a name="line-78"></a>
<a name="line-79"></a><span class='hs-definition'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-layout'>(</span><span class='hs-conid'>Note</span> <span class='hs-varid'>note</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>SCC</span> <span class='hs-varid'>cc</span><span class='hs-layout'>)</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span>
<a name="line-80"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span>    <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>floating_defns</span><span class='hs-layout'>,</span> <span class='hs-varid'>expr'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-81"></a>    <span class='hs-keyword'>let</span>
<a name="line-82"></a>	<span class='hs-comment'>-- Annotate bindings floated outwards past an scc expression</span>
<a name="line-83"></a>	<span class='hs-comment'>-- with the cc.  We mark that cc as "duplicated", though.</span>
<a name="line-84"></a>
<a name="line-85"></a>	<span class='hs-varid'>annotated_defns</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>wrapCostCentre</span> <span class='hs-layout'>(</span><span class='hs-varid'>dupifyCC</span> <span class='hs-varid'>cc</span><span class='hs-layout'>)</span> <span class='hs-varid'>floating_defns</span>
<a name="line-86"></a>    <span class='hs-keyword'>in</span>
<a name="line-87"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>annotated_defns</span><span class='hs-layout'>,</span> <span class='hs-conid'>Note</span> <span class='hs-varid'>note</span> <span class='hs-varid'>expr'</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span>
<a name="line-88"></a>
<a name="line-89"></a><span class='hs-definition'>floatExpr</span> <span class='hs-keyword'>_</span> <span class='hs-layout'>(</span><span class='hs-conid'>Note</span> <span class='hs-conid'>InlineMe</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span>	<span class='hs-comment'>-- Other than SCCs</span>
<a name="line-90"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>zeroStats</span><span class='hs-layout'>,</span> <span class='hs-varid'>emptyFloats</span><span class='hs-layout'>,</span> <span class='hs-conid'>Note</span> <span class='hs-conid'>InlineMe</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-91"></a>	<span class='hs-comment'>-- Do no floating at all inside INLINE.</span>
<a name="line-92"></a>	<span class='hs-comment'>-- The SetLevels pass did not clone the bindings, so it's</span>
<a name="line-93"></a>	<span class='hs-comment'>-- unsafe to do any floating, even if we dump the results</span>
<a name="line-94"></a>	<span class='hs-comment'>-- inside the Note (which is what we used to do).</span>
<a name="line-95"></a>
<a name="line-96"></a><span class='hs-definition'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-layout'>(</span><span class='hs-conid'>Note</span> <span class='hs-varid'>note</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span>	<span class='hs-comment'>-- Other than SCCs</span>
<a name="line-97"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span>    <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>floating_defns</span><span class='hs-layout'>,</span> <span class='hs-varid'>expr'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-98"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>floating_defns</span><span class='hs-layout'>,</span> <span class='hs-conid'>Note</span> <span class='hs-varid'>note</span> <span class='hs-varid'>expr'</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span>
<a name="line-99"></a>
<a name="line-100"></a><span class='hs-definition'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-layout'>(</span><span class='hs-conid'>Cast</span> <span class='hs-varid'>expr</span> <span class='hs-varid'>co</span><span class='hs-layout'>)</span>
<a name="line-101"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>expr</span><span class='hs-layout'>)</span>	<span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>floating_defns</span><span class='hs-layout'>,</span> <span class='hs-varid'>expr'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-102"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>floating_defns</span><span class='hs-layout'>,</span> <span class='hs-conid'>Cast</span> <span class='hs-varid'>expr'</span> <span class='hs-varid'>co</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span>
<a name="line-103"></a>
<a name="line-104"></a><span class='hs-definition'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-layout'>(</span><span class='hs-conid'>Let</span> <span class='hs-layout'>(</span><span class='hs-conid'>NonRec</span> <span class='hs-layout'>(</span><span class='hs-conid'>TB</span> <span class='hs-varid'>bndr</span> <span class='hs-varid'>bndr_lvl</span><span class='hs-layout'>)</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span> <span class='hs-varid'>body</span><span class='hs-layout'>)</span>
<a name="line-105"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>isUnLiftedType</span> <span class='hs-layout'>(</span><span class='hs-varid'>idType</span> <span class='hs-varid'>bndr</span><span class='hs-layout'>)</span>	<span class='hs-comment'>-- Treat unlifted lets just like a case</span>
<a name="line-106"></a>				<span class='hs-comment'>-- I.e. floatExpr for rhs, floatCaseAlt for body</span>
<a name="line-107"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>rhs</span>	    <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-keyword'>_</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs_floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-108"></a>    <span class='hs-keyword'>case</span> <span class='hs-varid'>floatCaseAlt</span> <span class='hs-varid'>bndr_lvl</span> <span class='hs-varid'>body</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>body_floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>body'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-109"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs_floats</span> <span class='hs-varop'>`plusFloats`</span> <span class='hs-varid'>body_floats</span><span class='hs-layout'>,</span> <span class='hs-conid'>Let</span> <span class='hs-layout'>(</span><span class='hs-conid'>NonRec</span> <span class='hs-varid'>bndr</span> <span class='hs-varid'>rhs'</span><span class='hs-layout'>)</span> <span class='hs-varid'>body'</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span><span class='hs-layout'>}</span>
<a name="line-110"></a>
<a name="line-111"></a><span class='hs-definition'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-layout'>(</span><span class='hs-conid'>Let</span> <span class='hs-varid'>bind</span> <span class='hs-varid'>body</span><span class='hs-layout'>)</span>
<a name="line-112"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatBind</span> <span class='hs-varid'>bind</span><span class='hs-layout'>)</span>     <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fsb</span><span class='hs-layout'>,</span> <span class='hs-varid'>bind_floats</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-113"></a>    <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>body</span><span class='hs-layout'>)</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fse</span><span class='hs-layout'>,</span> <span class='hs-varid'>body_floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>body'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-114"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>add_stats</span> <span class='hs-varid'>fsb</span> <span class='hs-varid'>fse</span><span class='hs-layout'>,</span>
<a name="line-115"></a>     <span class='hs-varid'>bind_floats</span> <span class='hs-varop'>`plusFloats`</span> <span class='hs-varid'>body_floats</span><span class='hs-layout'>,</span>
<a name="line-116"></a>     <span class='hs-varid'>body'</span><span class='hs-layout'>)</span>  <span class='hs-layout'>}</span><span class='hs-layout'>}</span>
<a name="line-117"></a>
<a name="line-118"></a><span class='hs-definition'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-layout'>(</span><span class='hs-conid'>Case</span> <span class='hs-varid'>scrut</span> <span class='hs-layout'>(</span><span class='hs-conid'>TB</span> <span class='hs-varid'>case_bndr</span> <span class='hs-varid'>case_lvl</span><span class='hs-layout'>)</span> <span class='hs-varid'>ty</span> <span class='hs-varid'>alts</span><span class='hs-layout'>)</span>
<a name="line-119"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>floatExpr</span> <span class='hs-varid'>lvl</span> <span class='hs-varid'>scrut</span>	<span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fse</span><span class='hs-layout'>,</span> <span class='hs-varid'>fde</span><span class='hs-layout'>,</span> <span class='hs-varid'>scrut'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-120"></a>    <span class='hs-keyword'>case</span> <span class='hs-varid'>floatList</span> <span class='hs-varid'>float_alt</span> <span class='hs-varid'>alts</span>	<span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fsa</span><span class='hs-layout'>,</span> <span class='hs-varid'>fda</span><span class='hs-layout'>,</span> <span class='hs-varid'>alts'</span><span class='hs-layout'>)</span>  <span class='hs-keyglyph'>-&gt;</span>
<a name="line-121"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>add_stats</span> <span class='hs-varid'>fse</span> <span class='hs-varid'>fsa</span><span class='hs-layout'>,</span> <span class='hs-varid'>fda</span> <span class='hs-varop'>`plusFloats`</span> <span class='hs-varid'>fde</span><span class='hs-layout'>,</span> <span class='hs-conid'>Case</span> <span class='hs-varid'>scrut'</span> <span class='hs-varid'>case_bndr</span> <span class='hs-varid'>ty</span> <span class='hs-varid'>alts'</span><span class='hs-layout'>)</span>
<a name="line-122"></a>    <span class='hs-layout'>}</span><span class='hs-layout'>}</span>
<a name="line-123"></a>  <span class='hs-keyword'>where</span>
<a name="line-124"></a>	<span class='hs-comment'>-- Use floatCaseAlt for the alternatives, so that we</span>
<a name="line-125"></a>	<span class='hs-comment'>-- don't gratuitiously float bindings out of the RHSs</span>
<a name="line-126"></a>    <span class='hs-varid'>float_alt</span> <span class='hs-layout'>(</span><span class='hs-varid'>con</span><span class='hs-layout'>,</span> <span class='hs-varid'>bs</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span>
<a name="line-127"></a>	<span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-layout'>(</span><span class='hs-varid'>floatCaseAlt</span> <span class='hs-varid'>case_lvl</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span>	<span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs_floats</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs'</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-128"></a>	  <span class='hs-layout'>(</span><span class='hs-varid'>fs</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs_floats</span><span class='hs-layout'>,</span> <span class='hs-layout'>(</span><span class='hs-varid'>con</span><span class='hs-layout'>,</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>b</span> <span class='hs-keyglyph'>|</span> <span class='hs-conid'>TB</span> <span class='hs-varid'>b</span> <span class='hs-keyword'>_</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>bs</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>,</span> <span class='hs-varid'>rhs'</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span>
<a name="line-129"></a>
<a name="line-130"></a>
<a name="line-131"></a><a name="floatList"></a><span class='hs-definition'>floatList</span> <span class='hs-keyglyph'>::</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>FloatStats</span><span class='hs-layout'>,</span> <span class='hs-conid'>FloatBinds</span><span class='hs-layout'>,</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>a</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>FloatStats</span><span class='hs-layout'>,</span> <span class='hs-conid'>FloatBinds</span><span class='hs-layout'>,</span> <span class='hs-keyglyph'>[</span><span class='hs-varid'>b</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span>
<a name="line-132"></a><span class='hs-definition'>floatList</span> <span class='hs-keyword'>_</span> <span class='hs-conid'>[]</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>zeroStats</span><span class='hs-layout'>,</span> <span class='hs-varid'>emptyFloats</span><span class='hs-layout'>,</span> <span class='hs-conid'>[]</span><span class='hs-layout'>)</span>
<a name="line-133"></a><span class='hs-definition'>floatList</span> <span class='hs-varid'>f</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-conop'>:</span><span class='hs-keyword'>as</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>f</span> <span class='hs-varid'>a</span>		 <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs_a</span><span class='hs-layout'>,</span>  <span class='hs-varid'>binds_a</span><span class='hs-layout'>,</span>  <span class='hs-varid'>b</span><span class='hs-layout'>)</span>  <span class='hs-keyglyph'>-&gt;</span>
<a name="line-134"></a>		     <span class='hs-keyword'>case</span> <span class='hs-varid'>floatList</span> <span class='hs-varid'>f</span> <span class='hs-keyword'>as</span> <span class='hs-keyword'>of</span> <span class='hs-layout'>{</span> <span class='hs-layout'>(</span><span class='hs-varid'>fs_as</span><span class='hs-layout'>,</span> <span class='hs-varid'>binds_as</span><span class='hs-layout'>,</span> <span class='hs-varid'>bs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span>
<a name="line-135"></a>		     <span class='hs-layout'>(</span><span class='hs-varid'>fs_a</span> <span class='hs-varop'>`add_stats`</span> <span class='hs-varid'>fs_as</span><span class='hs-layout'>,</span> <span class='hs-varid'>binds_a</span> <span class='hs-varop'>`plusFloats`</span> <span class='hs-varid'>binds_as</span><span class='hs-layout'>,</span> <span class='hs-varid'>b</span><span class='hs-conop'>:</span><span class='hs-varid'>bs</span><span class='hs-layout'>)</span> <span class='hs-layout'>}</span><span class='hs-layout'>}</span>
<a name="line-136"></a>
<a name="line-137"></a><a name="getBindLevel"></a><span class='hs-definition'>getBindLevel</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Bind</span> <span class='hs-layout'>(</span><span class='hs-conid'>TaggedBndr</span> <span class='hs-conid'>Level</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Level</span>
<a name="line-138"></a><span class='hs-definition'>getBindLevel</span> <span class='hs-layout'>(</span><span class='hs-conid'>NonRec</span> <span class='hs-layout'>(</span><span class='hs-conid'>TB</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>lvl</span><span class='hs-layout'>)</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span>       <span class='hs-keyglyph'>=</span> <span class='hs-varid'>lvl</span>
<a name="line-139"></a><span class='hs-definition'>getBindLevel</span> <span class='hs-layout'>(</span><span class='hs-conid'>Rec</span> <span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-layout'>(</span><span class='hs-conid'>TB</span> <span class='hs-keyword'>_</span> <span class='hs-varid'>lvl</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-conop'>:</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>lvl</span>
<a name="line-140"></a><span class='hs-definition'>getBindLevel</span> <span class='hs-layout'>(</span><span class='hs-conid'>Rec</span> <span class='hs-conid'>[]</span><span class='hs-layout'>)</span>                    <span class='hs-keyglyph'>=</span> <span class='hs-varid'>panic</span> <span class='hs-str'>"getBindLevel Rec []"</span>
<a name="line-141"></a>
<a name="line-142"></a><a name="unTagBndr"></a><span class='hs-definition'>unTagBndr</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TaggedBndr</span> <span class='hs-varid'>tag</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>CoreBndr</span>
<a name="line-143"></a><span class='hs-definition'>unTagBndr</span> <span class='hs-layout'>(</span><span class='hs-conid'>TB</span> <span class='hs-varid'>b</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>b</span>
<a name="line-144"></a>
<a name="line-145"></a><a name="unTag"></a><span class='hs-definition'>unTag</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>TaggedExpr</span> <span class='hs-varid'>tag</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>CoreExpr</span>
<a name="line-146"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>Var</span> <span class='hs-varid'>v</span><span class='hs-layout'>)</span>  	  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Var</span> <span class='hs-varid'>v</span>
<a name="line-147"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>Lit</span> <span class='hs-varid'>l</span><span class='hs-layout'>)</span>  	  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Lit</span> <span class='hs-varid'>l</span>
<a name="line-148"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>Type</span> <span class='hs-varid'>ty</span><span class='hs-layout'>)</span>   <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Type</span> <span class='hs-varid'>ty</span>
<a name="line-149"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>Note</span> <span class='hs-varid'>n</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Note</span> <span class='hs-varid'>n</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>
<a name="line-150"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>App</span> <span class='hs-varid'>e1</span> <span class='hs-varid'>e2</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>App</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>e1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>e2</span><span class='hs-layout'>)</span>
<a name="line-151"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>Lam</span> <span class='hs-varid'>b</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>   <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Lam</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTagBndr</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>
<a name="line-152"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>Cast</span> <span class='hs-varid'>e</span> <span class='hs-varid'>co</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Cast</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span> <span class='hs-varid'>co</span>
<a name="line-153"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>Let</span> <span class='hs-layout'>(</span><span class='hs-conid'>Rec</span> <span class='hs-varid'>prs</span><span class='hs-layout'>)</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>    <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Let</span> <span class='hs-layout'>(</span><span class='hs-conid'>Rec</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-varid'>unTagBndr</span> <span class='hs-varid'>b</span><span class='hs-layout'>,</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span><span class='hs-layout'>,</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>prs</span><span class='hs-keyglyph'>]</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>
<a name="line-154"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>Let</span> <span class='hs-layout'>(</span><span class='hs-conid'>NonRec</span> <span class='hs-varid'>b</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Let</span> <span class='hs-layout'>(</span><span class='hs-conid'>NonRec</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTagBndr</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span>
<a name="line-155"></a><span class='hs-definition'>unTag</span> <span class='hs-layout'>(</span><span class='hs-conid'>Case</span> <span class='hs-varid'>e</span> <span class='hs-varid'>b</span> <span class='hs-varid'>ty</span> <span class='hs-varid'>alts</span><span class='hs-layout'>)</span>   <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Case</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTag</span> <span class='hs-varid'>e</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>unTagBndr</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varid'>ty</span>
<a name="line-156"></a>			          <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-varid'>c</span><span class='hs-layout'>,</span> <span class='hs-varid'>map</span> <span class='hs-varid'>unTagBndr</span> <span class='hs-varid'>bs</span><span class='hs-layout'>,</span> <span class='hs-varid'>unTag</span> <span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>|</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span><span class='hs-layout'>,</span><span class='hs-varid'>bs</span><span class='hs-layout'>,</span><span class='hs-varid'>r</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>&lt;-</span> <span class='hs-varid'>alts</span><span class='hs-keyglyph'>]</span>
</pre>\end{code}

%************************************************************************
%*									*
\subsection{Utility bits for floating stats}
%*									*
%************************************************************************

I didn't implement this with unboxed numbers.  I don't want to be too
strict in this stuff, as it is rarely turned on.  (WDP 95/09)

\begin{code}
<pre><a name="line-1"></a><a name="FloatStats"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>FloatStats</span>
<a name="line-2"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FlS</span>	<span class='hs-conid'>Int</span>  <span class='hs-comment'>-- Number of top-floats * lambda groups they've been past</span>
<a name="line-3"></a>	<span class='hs-conid'>Int</span>  <span class='hs-comment'>-- Number of non-top-floats * lambda groups they've been past</span>
<a name="line-4"></a>	<span class='hs-conid'>Int</span>  <span class='hs-comment'>-- Number of lambda (groups) seen</span>
<a name="line-5"></a>
<a name="line-6"></a><a name="get_stats"></a><span class='hs-definition'>get_stats</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FloatStats</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>Int</span><span class='hs-layout'>,</span> <span class='hs-conid'>Int</span><span class='hs-layout'>)</span>
<a name="line-7"></a><span class='hs-definition'>get_stats</span> <span class='hs-layout'>(</span><span class='hs-conid'>FlS</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span><span class='hs-layout'>,</span> <span class='hs-varid'>b</span><span class='hs-layout'>,</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span>
<a name="line-8"></a>
<a name="line-9"></a><a name="zeroStats"></a><span class='hs-definition'>zeroStats</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FloatStats</span>
<a name="line-10"></a><span class='hs-definition'>zeroStats</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FlS</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span> <span class='hs-num'>0</span>
<a name="line-11"></a>
<a name="line-12"></a><a name="sum_stats"></a><span class='hs-definition'>sum_stats</span> <span class='hs-keyglyph'>::</span> <span class='hs-keyglyph'>[</span><span class='hs-conid'>FloatStats</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatStats</span>
<a name="line-13"></a><span class='hs-definition'>sum_stats</span> <span class='hs-varid'>xs</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>foldr</span> <span class='hs-varid'>add_stats</span> <span class='hs-varid'>zeroStats</span> <span class='hs-varid'>xs</span>
<a name="line-14"></a>
<a name="line-15"></a><a name="add_stats"></a><span class='hs-definition'>add_stats</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FloatStats</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatStats</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatStats</span>
<a name="line-16"></a><span class='hs-definition'>add_stats</span> <span class='hs-layout'>(</span><span class='hs-conid'>FlS</span> <span class='hs-varid'>a1</span> <span class='hs-varid'>b1</span> <span class='hs-varid'>c1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>FlS</span> <span class='hs-varid'>a2</span> <span class='hs-varid'>b2</span> <span class='hs-varid'>c2</span><span class='hs-layout'>)</span>
<a name="line-17"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FlS</span> <span class='hs-layout'>(</span><span class='hs-varid'>a1</span> <span class='hs-varop'>+</span> <span class='hs-varid'>a2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>b1</span> <span class='hs-varop'>+</span> <span class='hs-varid'>b2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>c1</span> <span class='hs-varop'>+</span> <span class='hs-varid'>c2</span><span class='hs-layout'>)</span>
<a name="line-18"></a>
<a name="line-19"></a><a name="add_to_stats"></a><span class='hs-definition'>add_to_stats</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FloatStats</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatBinds</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatStats</span>
<a name="line-20"></a><span class='hs-definition'>add_to_stats</span> <span class='hs-layout'>(</span><span class='hs-conid'>FlS</span> <span class='hs-varid'>a</span> <span class='hs-varid'>b</span> <span class='hs-varid'>c</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>others</span><span class='hs-layout'>)</span>
<a name="line-21"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FlS</span> <span class='hs-layout'>(</span><span class='hs-varid'>a</span> <span class='hs-varop'>+</span> <span class='hs-varid'>lengthBag</span> <span class='hs-varid'>tops</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>b</span> <span class='hs-varop'>+</span> <span class='hs-varid'>lengthBag</span> <span class='hs-layout'>(</span><span class='hs-varid'>flattenMajor</span> <span class='hs-varid'>others</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>c</span> <span class='hs-varop'>+</span> <span class='hs-num'>1</span><span class='hs-layout'>)</span>
</pre>\end{code}


%************************************************************************
%*									*
\subsection{Utility bits for floating}
%*									*
%************************************************************************

Note [Representation of FloatBinds]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The FloatBinds types is somewhat important.  We can get very large numbers
of floating bindings, often all destined for the top level.  A typical example
is     x = [4,2,5,2,5, .... ]
Then we get lots of small expressions like (fromInteger 4), which all get
lifted to top level.

The trouble is that
  (a) we partition these floating bindings *at every binding site*
  (b) SetLevels introduces a new bindings site for every float
So we had better not look at each binding at each binding site!

That is why MajorEnv is represented as a finite map.

We keep the bindings destined for the *top* level separate, because
we float them out even if they don't escape a *value* lambda; see
partitionByMajorLevel.

\begin{code}
<pre><a name="line-1"></a><a name="FloatBind"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>FloatBind</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>CoreBind</span>      <span class='hs-comment'>-- INVARIANT: a FloatBind is always lifted</span>
<a name="line-2"></a>
<a name="line-3"></a><a name="FloatBinds"></a><span class='hs-keyword'>data</span> <span class='hs-conid'>FloatBinds</span>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FB</span> <span class='hs-varop'>!</span><span class='hs-layout'>(</span><span class='hs-conid'>Bag</span> <span class='hs-conid'>FloatBind</span><span class='hs-layout'>)</span>         <span class='hs-comment'>-- Destined for top level</span>
<a name="line-4"></a>                     <span class='hs-varop'>!</span><span class='hs-conid'>MajorEnv</span>                 <span class='hs-comment'>-- Levels other than top</span>
<a name="line-5"></a>     <span class='hs-comment'>-- See Note [Representation of FloatBinds]</span>
<a name="line-6"></a>
<a name="line-7"></a><a name="MajorEnv"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>MajorEnv</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>UniqFM</span> <span class='hs-conid'>MinorEnv</span>                        <span class='hs-comment'>-- Keyed by major level</span>
<a name="line-8"></a><a name="MinorEnv"></a><span class='hs-keyword'>type</span> <span class='hs-conid'>MinorEnv</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>UniqFM</span> <span class='hs-layout'>(</span><span class='hs-conid'>Bag</span> <span class='hs-conid'>FloatBind</span><span class='hs-layout'>)</span>         <span class='hs-comment'>-- Keyed by minor level</span>
<a name="line-9"></a>
<a name="line-10"></a><a name="flattenFloats"></a><span class='hs-definition'>flattenFloats</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FloatBinds</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bag</span> <span class='hs-conid'>FloatBind</span>
<a name="line-11"></a><span class='hs-definition'>flattenFloats</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>others</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>tops</span> <span class='hs-varop'>`unionBags`</span> <span class='hs-varid'>flattenMajor</span> <span class='hs-varid'>others</span>
<a name="line-12"></a>
<a name="line-13"></a><a name="flattenMajor"></a><span class='hs-definition'>flattenMajor</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>MajorEnv</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bag</span> <span class='hs-conid'>FloatBind</span>
<a name="line-14"></a><span class='hs-definition'>flattenMajor</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>foldUFM</span> <span class='hs-layout'>(</span><span class='hs-varid'>unionBags</span> <span class='hs-varop'>.</span> <span class='hs-varid'>flattenMinor</span><span class='hs-layout'>)</span> <span class='hs-varid'>emptyBag</span>
<a name="line-15"></a>
<a name="line-16"></a><a name="flattenMinor"></a><span class='hs-definition'>flattenMinor</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>MinorEnv</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>Bag</span> <span class='hs-conid'>FloatBind</span>
<a name="line-17"></a><span class='hs-definition'>flattenMinor</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>foldUFM</span> <span class='hs-varid'>unionBags</span> <span class='hs-varid'>emptyBag</span>
<a name="line-18"></a>
<a name="line-19"></a><a name="emptyFloats"></a><span class='hs-definition'>emptyFloats</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FloatBinds</span>
<a name="line-20"></a><span class='hs-definition'>emptyFloats</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FB</span> <span class='hs-varid'>emptyBag</span> <span class='hs-varid'>emptyUFM</span>
<a name="line-21"></a>
<a name="line-22"></a><a name="unitFloat"></a><span class='hs-definition'>unitFloat</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Level</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatBind</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatBinds</span>
<a name="line-23"></a><span class='hs-definition'>unitFloat</span> <span class='hs-conid'>InlineCtxt</span> <span class='hs-varid'>b</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FB</span> <span class='hs-layout'>(</span><span class='hs-varid'>unitBag</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varid'>emptyUFM</span>
<a name="line-24"></a><span class='hs-definition'>unitFloat</span> <span class='hs-varid'>lvl</span><span class='hs-keyglyph'>@</span><span class='hs-layout'>(</span><span class='hs-conid'>Level</span> <span class='hs-varid'>major</span> <span class='hs-varid'>minor</span><span class='hs-layout'>)</span> <span class='hs-varid'>b</span>
<a name="line-25"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>isTopLvl</span> <span class='hs-varid'>lvl</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FB</span> <span class='hs-layout'>(</span><span class='hs-varid'>unitBag</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span> <span class='hs-varid'>emptyUFM</span>
<a name="line-26"></a>  <span class='hs-keyglyph'>|</span> <span class='hs-varid'>otherwise</span>    <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FB</span> <span class='hs-varid'>emptyBag</span> <span class='hs-layout'>(</span><span class='hs-varid'>unitUFM</span> <span class='hs-varid'>major</span> <span class='hs-layout'>(</span><span class='hs-varid'>unitUFM</span> <span class='hs-varid'>minor</span> <span class='hs-layout'>(</span><span class='hs-varid'>unitBag</span> <span class='hs-varid'>b</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span><span class='hs-layout'>)</span>
<a name="line-27"></a>
<a name="line-28"></a><a name="plusFloats"></a><span class='hs-definition'>plusFloats</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>FloatBinds</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatBinds</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatBinds</span>
<a name="line-29"></a><span class='hs-definition'>plusFloats</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>t1</span> <span class='hs-varid'>b1</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>t2</span> <span class='hs-varid'>b2</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FB</span> <span class='hs-layout'>(</span><span class='hs-varid'>t1</span> <span class='hs-varop'>`unionBags`</span> <span class='hs-varid'>t2</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>b1</span> <span class='hs-varop'>`plusMajor`</span> <span class='hs-varid'>b2</span><span class='hs-layout'>)</span>
<a name="line-30"></a>
<a name="line-31"></a><a name="plusMajor"></a><span class='hs-definition'>plusMajor</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>MajorEnv</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>MajorEnv</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>MajorEnv</span>
<a name="line-32"></a><span class='hs-definition'>plusMajor</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>plusUFM_C</span> <span class='hs-varid'>plusMinor</span>
<a name="line-33"></a>
<a name="line-34"></a><a name="plusMinor"></a><span class='hs-definition'>plusMinor</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>MinorEnv</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>MinorEnv</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>MinorEnv</span>
<a name="line-35"></a><span class='hs-definition'>plusMinor</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>plusUFM_C</span> <span class='hs-varid'>unionBags</span>
<a name="line-36"></a>
<a name="line-37"></a><a name="floatsToBindPairs"></a><span class='hs-definition'>floatsToBindPairs</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Bag</span> <span class='hs-conid'>FloatBind</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>Id</span><span class='hs-layout'>,</span><span class='hs-conid'>CoreExpr</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-keyglyph'>[</span><span class='hs-layout'>(</span><span class='hs-conid'>Id</span><span class='hs-layout'>,</span><span class='hs-conid'>CoreExpr</span><span class='hs-layout'>)</span><span class='hs-keyglyph'>]</span>
<a name="line-38"></a><span class='hs-definition'>floatsToBindPairs</span> <span class='hs-varid'>floats</span> <span class='hs-varid'>binds</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>foldrBag</span> <span class='hs-varid'>add</span> <span class='hs-varid'>binds</span> <span class='hs-varid'>floats</span>
<a name="line-39"></a>  <span class='hs-keyword'>where</span>
<a name="line-40"></a>   <span class='hs-varid'>add</span> <span class='hs-layout'>(</span><span class='hs-conid'>Rec</span> <span class='hs-varid'>pairs</span><span class='hs-layout'>)</span>         <span class='hs-varid'>binds</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>pairs</span> <span class='hs-varop'>++</span> <span class='hs-varid'>binds</span>
<a name="line-41"></a>   <span class='hs-varid'>add</span> <span class='hs-layout'>(</span><span class='hs-conid'>NonRec</span> <span class='hs-varid'>binder</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span> <span class='hs-varid'>binds</span> <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-varid'>binder</span><span class='hs-layout'>,</span><span class='hs-varid'>rhs</span><span class='hs-layout'>)</span> <span class='hs-conop'>:</span> <span class='hs-varid'>binds</span>
<a name="line-42"></a>
<a name="line-43"></a><a name="install"></a><span class='hs-definition'>install</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Bag</span> <span class='hs-conid'>FloatBind</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>CoreExpr</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>CoreExpr</span>
<a name="line-44"></a><span class='hs-definition'>install</span> <span class='hs-varid'>defn_groups</span> <span class='hs-varid'>expr</span>
<a name="line-45"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-varid'>foldrBag</span> <span class='hs-varid'>install_group</span> <span class='hs-varid'>expr</span> <span class='hs-varid'>defn_groups</span>
<a name="line-46"></a>  <span class='hs-keyword'>where</span>
<a name="line-47"></a>    <span class='hs-varid'>install_group</span> <span class='hs-varid'>defns</span> <span class='hs-varid'>body</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Let</span> <span class='hs-varid'>defns</span> <span class='hs-varid'>body</span>
<a name="line-48"></a>
<a name="line-49"></a><a name="partitionByMajorLevel"></a><span class='hs-definition'>partitionByMajorLevel</span><span class='hs-layout'>,</span> <span class='hs-varid'>partitionByLevel</span>
<a name="line-50"></a>       <span class='hs-keyglyph'>::</span> <span class='hs-conid'>Level</span>                <span class='hs-comment'>-- Partitioning level</span>
<a name="line-51"></a>       <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatBinds</span>           <span class='hs-comment'>-- Defns to be divided into 2 piles...</span>
<a name="line-52"></a>       <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-conid'>FloatBinds</span><span class='hs-layout'>,</span>         <span class='hs-comment'>-- Defns  with level strictly &lt; partition level,</span>
<a name="line-53"></a>           <span class='hs-conid'>Bag</span> <span class='hs-conid'>FloatBind</span><span class='hs-layout'>)</span>      <span class='hs-comment'>-- The rest</span>
<a name="line-54"></a>
<a name="line-55"></a><span class='hs-comment'>--      ---- partitionByMajorLevel ----</span>
<a name="line-56"></a><span class='hs-comment'>-- Float it if we escape a value lambda, *or* if we get to the top level</span>
<a name="line-57"></a><span class='hs-comment'>-- If we can get to the top level, say "yes" anyway. This means that</span>
<a name="line-58"></a><span class='hs-comment'>--     x = f e</span>
<a name="line-59"></a><span class='hs-comment'>-- transforms to</span>
<a name="line-60"></a><span class='hs-comment'>--    lvl = e</span>
<a name="line-61"></a><span class='hs-comment'>--    x = f lvl</span>
<a name="line-62"></a><span class='hs-comment'>-- which is as it should be</span>
<a name="line-63"></a>
<a name="line-64"></a><span class='hs-definition'>partitionByMajorLevel</span> <span class='hs-conid'>InlineCtxt</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>defns</span><span class='hs-layout'>)</span>
<a name="line-65"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>emptyUFM</span><span class='hs-layout'>,</span> <span class='hs-varid'>flattenMajor</span> <span class='hs-varid'>defns</span><span class='hs-layout'>)</span>
<a name="line-66"></a>
<a name="line-67"></a><span class='hs-definition'>partitionByMajorLevel</span> <span class='hs-layout'>(</span><span class='hs-conid'>Level</span> <span class='hs-varid'>major</span> <span class='hs-keyword'>_</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>defns</span><span class='hs-layout'>)</span>
<a name="line-68"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>outer</span><span class='hs-layout'>,</span> <span class='hs-varid'>heres</span> <span class='hs-varop'>`unionBags`</span> <span class='hs-varid'>flattenMajor</span> <span class='hs-varid'>inner</span><span class='hs-layout'>)</span>
<a name="line-69"></a>  <span class='hs-keyword'>where</span>
<a name="line-70"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>outer</span><span class='hs-layout'>,</span> <span class='hs-varid'>mb_heres</span><span class='hs-layout'>,</span> <span class='hs-varid'>inner</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>splitUFM</span> <span class='hs-varid'>defns</span> <span class='hs-varid'>major</span>
<a name="line-71"></a>    <span class='hs-varid'>heres</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>mb_heres</span> <span class='hs-keyword'>of</span>
<a name="line-72"></a>               <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>emptyBag</span>
<a name="line-73"></a>               <span class='hs-conid'>Just</span> <span class='hs-varid'>h</span>  <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>flattenMinor</span> <span class='hs-varid'>h</span>
<a name="line-74"></a>
<a name="line-75"></a><a name="partitionByLevel"></a><span class='hs-definition'>partitionByLevel</span> <span class='hs-conid'>InlineCtxt</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>defns</span><span class='hs-layout'>)</span>
<a name="line-76"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>emptyUFM</span><span class='hs-layout'>,</span> <span class='hs-varid'>flattenMajor</span> <span class='hs-varid'>defns</span><span class='hs-layout'>)</span>
<a name="line-77"></a>
<a name="line-78"></a><span class='hs-definition'>partitionByLevel</span> <span class='hs-layout'>(</span><span class='hs-conid'>Level</span> <span class='hs-varid'>major</span> <span class='hs-varid'>minor</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>defns</span><span class='hs-layout'>)</span>
<a name="line-79"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-layout'>(</span><span class='hs-varid'>outer_maj</span> <span class='hs-varop'>`plusMajor`</span> <span class='hs-varid'>unitUFM</span> <span class='hs-varid'>major</span> <span class='hs-varid'>outer_min</span><span class='hs-layout'>)</span><span class='hs-layout'>,</span>
<a name="line-80"></a>     <span class='hs-varid'>here_min</span> <span class='hs-varop'>`unionBags`</span> <span class='hs-varid'>flattenMinor</span> <span class='hs-varid'>inner_min</span>
<a name="line-81"></a>              <span class='hs-varop'>`unionBags`</span> <span class='hs-varid'>flattenMajor</span> <span class='hs-varid'>inner_maj</span><span class='hs-layout'>)</span>
<a name="line-82"></a>
<a name="line-83"></a>  <span class='hs-keyword'>where</span>
<a name="line-84"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>outer_maj</span><span class='hs-layout'>,</span> <span class='hs-varid'>mb_here_maj</span><span class='hs-layout'>,</span> <span class='hs-varid'>inner_maj</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>splitUFM</span> <span class='hs-varid'>defns</span> <span class='hs-varid'>major</span>
<a name="line-85"></a>    <span class='hs-layout'>(</span><span class='hs-varid'>outer_min</span><span class='hs-layout'>,</span> <span class='hs-varid'>mb_here_min</span><span class='hs-layout'>,</span> <span class='hs-varid'>inner_min</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-keyword'>case</span> <span class='hs-varid'>mb_here_maj</span> <span class='hs-keyword'>of</span>
<a name="line-86"></a>                                            <span class='hs-conid'>Nothing</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-layout'>(</span><span class='hs-varid'>emptyUFM</span><span class='hs-layout'>,</span> <span class='hs-conid'>Nothing</span><span class='hs-layout'>,</span> <span class='hs-varid'>emptyUFM</span><span class='hs-layout'>)</span>
<a name="line-87"></a>                                            <span class='hs-conid'>Just</span> <span class='hs-varid'>min_defns</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-varid'>splitUFM</span> <span class='hs-varid'>min_defns</span> <span class='hs-varid'>minor</span>
<a name="line-88"></a>    <span class='hs-varid'>here_min</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>mb_here_min</span> <span class='hs-varop'>`orElse`</span> <span class='hs-varid'>emptyBag</span>
<a name="line-89"></a>
<a name="line-90"></a><a name="wrapCostCentre"></a><span class='hs-definition'>wrapCostCentre</span> <span class='hs-keyglyph'>::</span> <span class='hs-conid'>CostCentre</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatBinds</span> <span class='hs-keyglyph'>-&gt;</span> <span class='hs-conid'>FloatBinds</span>
<a name="line-91"></a><span class='hs-definition'>wrapCostCentre</span> <span class='hs-varid'>cc</span> <span class='hs-layout'>(</span><span class='hs-conid'>FB</span> <span class='hs-varid'>tops</span> <span class='hs-varid'>defns</span><span class='hs-layout'>)</span>
<a name="line-92"></a>  <span class='hs-keyglyph'>=</span> <span class='hs-conid'>FB</span> <span class='hs-layout'>(</span><span class='hs-varid'>wrap_defns</span> <span class='hs-varid'>tops</span><span class='hs-layout'>)</span> <span class='hs-layout'>(</span><span class='hs-varid'>mapUFM</span> <span class='hs-layout'>(</span><span class='hs-varid'>mapUFM</span> <span class='hs-varid'>wrap_defns</span><span class='hs-layout'>)</span> <span class='hs-varid'>defns</span><span class='hs-layout'>)</span>
<a name="line-93"></a>  <span class='hs-keyword'>where</span>
<a name="line-94"></a>    <span class='hs-varid'>wrap_defns</span> <span class='hs-keyglyph'>=</span> <span class='hs-varid'>mapBag</span> <span class='hs-varid'>wrap_one</span>
<a name="line-95"></a>    <span class='hs-varid'>wrap_one</span> <span class='hs-layout'>(</span><span class='hs-conid'>NonRec</span> <span class='hs-varid'>binder</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span> <span class='hs-keyglyph'>=</span> <span class='hs-conid'>NonRec</span> <span class='hs-varid'>binder</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkSCC</span> <span class='hs-varid'>cc</span> <span class='hs-varid'>rhs</span><span class='hs-layout'>)</span>
<a name="line-96"></a>    <span class='hs-varid'>wrap_one</span> <span class='hs-layout'>(</span><span class='hs-conid'>Rec</span> <span class='hs-varid'>pairs</span><span class='hs-layout'>)</span>         <span class='hs-keyglyph'>=</span> <span class='hs-conid'>Rec</span> <span class='hs-layout'>(</span><span class='hs-varid'>mapSnd</span> <span class='hs-layout'>(</span><span class='hs-varid'>mkSCC</span> <span class='hs-varid'>cc</span><span class='hs-layout'>)</span> <span class='hs-varid'>pairs</span><span class='hs-layout'>)</span>
</pre>\end{code}

</body>
</html>