<div dir="ltr">Hi all,<div><br></div><div>With module-level Strict and StrictData pragmas coming soon, one obvious question is what kind of the code quality GHC can achieve for strict programs.</div><div><br></div><div>When it came up in discussion in our research group we realized we didn't actually know whether the bang patterns, `f !x`, on function arguments were enforced by caller or callee.</div><div><br></div><div>Here's a Gist that shows the compilation of a trivial function:</div><div><table class="" style="border-collapse:collapse;border-spacing:0px;color:rgb(51,51,51);font-family:Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,'Segoe UI Emoji','Segoe UI Symbol';font-size:13px;line-height:18.2px"><tbody><tr><td id="file-__origprog-hs-LC13" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal"><br></td></tr><tr><td id="file-__origprog-hs-L14" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-__origprog-hs-LC14" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal"><span class="" style="color:rgb(121,93,163)">foo</span> <span class="" style="color:rgb(167,29,93)">::</span> <span class="" style="color:rgb(0,134,179)">Maybe</span> <span class="" style="color:rgb(0,134,179)">Int</span> <span class="" style="color:rgb(167,29,93)">-></span> <span class="" style="color:rgb(0,134,179)">Int</span></td></tr><tr><td id="file-__origprog-hs-L15" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-__origprog-hs-LC15" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">foo !x =</td></tr><tr><td id="file-__origprog-hs-L16" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-__origprog-hs-LC16" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">  <span class="" style="color:rgb(167,29,93)">case</span> x <span class="" style="color:rgb(167,29,93)">of</span></td></tr><tr><td id="file-__origprog-hs-L17" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-__origprog-hs-LC17" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">   <span class="" style="color:rgb(0,134,179)">Just</span> y -> y</td></tr></tbody></table></div><div><br></div><div>   <a href="https://gist.github.com/rrnewton/1ac722189c65f26fe9ac">https://gist.github.com/rrnewton/1ac722189c65f26fe9ac</a><br></div><div><br></div><div>If that function is compiled to *assume* its input is in WHNF, it should be just as efficient as the isomorphic MLton/OCaml code, right?  It only needs to branch on the tag, do a field dereference, and return.</div><div><br></div><div>But as you can see from the STG and CMM generated, foo <i>does indeed</i> enter the thunk, adding an extra indirect jump.  Here's the body:</div><div><table class="" style="border-collapse:collapse;border-spacing:0px;color:rgb(51,51,51);font-family:Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,'Segoe UI Emoji','Segoe UI Symbol';font-size:13px;line-height:18.2px"><tbody><tr><td id="file-_optimizedcmm-c-LC21" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal"><br></td></tr><tr><td id="file-_optimizedcmm-c-L22" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC22" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">      c3aY:</td></tr><tr><td id="file-_optimizedcmm-c-L23" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC23" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          <span class="" style="color:rgb(167,29,93)">if</span> ((Sp + -<span class="" style="color:rgb(0,134,179)">8</span>) < SpLim) <span class="" style="color:rgb(167,29,93)">goto</span> c3aZ; <span class="" style="color:rgb(167,29,93)">else</span> <span class="" style="color:rgb(167,29,93)">goto</span> c3b0;</td></tr><tr><td id="file-_optimizedcmm-c-L24" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC24" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">      c3aZ:</td></tr><tr><td id="file-_optimizedcmm-c-L25" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC25" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          <span class="" style="color:rgb(150,152,150)">// nop</span></td></tr><tr><td id="file-_optimizedcmm-c-L26" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC26" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          R1 = PicBaseReg + foo_closure;</td></tr><tr><td id="file-_optimizedcmm-c-L27" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC27" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          <span class="" style="color:rgb(0,134,179)">call</span> (I64[BaseReg - <span class="" style="color:rgb(0,134,179)">8</span>])(R2, R1) args: <span class="" style="color:rgb(0,134,179)">8</span>, res: <span class="" style="color:rgb(0,134,179)">0</span>, upd: <span class="" style="color:rgb(0,134,179)">8</span>;</td></tr><tr><td id="file-_optimizedcmm-c-L28" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC28" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">      c3b0:</td></tr><tr><td id="file-_optimizedcmm-c-L29" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC29" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          I64[Sp - <span class="" style="color:rgb(0,134,179)">8</span>] = PicBaseReg + block_c3aO_info;</td></tr><tr><td id="file-_optimizedcmm-c-L30" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC30" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          R1 = R2;</td></tr><tr><td id="file-_optimizedcmm-c-L31" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC31" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          Sp = Sp - <span class="" style="color:rgb(0,134,179)">8</span>;</td></tr><tr><td id="file-_optimizedcmm-c-L32" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC32" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          <span class="" style="color:rgb(167,29,93)">if</span> (R1 & <span class="" style="color:rgb(0,134,179)">7</span> != <span class="" style="color:rgb(0,134,179)">0</span>) <span class="" style="color:rgb(167,29,93)">goto</span> c3aO; <span class="" style="color:rgb(167,29,93)">else</span> <span class="" style="color:rgb(167,29,93)">goto</span> c3aP;</td></tr><tr><td id="file-_optimizedcmm-c-L33" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC33" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">      c3aP:</td></tr><tr><td id="file-_optimizedcmm-c-L34" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC34" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          <span class="" style="color:rgb(0,134,179)">call</span> (I64[R1])(R1) returns to c3aO, args: <span class="" style="color:rgb(0,134,179)">8</span>, res: <span class="" style="color:rgb(0,134,179)">8</span>, upd: <span class="" style="color:rgb(0,134,179)">8</span>;</td></tr><tr><td id="file-_optimizedcmm-c-L35" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC35" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">      c3aO:</td></tr><tr><td id="file-_optimizedcmm-c-L36" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC36" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          <span class="" style="color:rgb(167,29,93)">if</span> (R1 & <span class="" style="color:rgb(0,134,179)">7</span> >= <span class="" style="color:rgb(0,134,179)">2</span>) <span class="" style="color:rgb(167,29,93)">goto</span> c3aW; <span class="" style="color:rgb(167,29,93)">else</span> <span class="" style="color:rgb(167,29,93)">goto</span> c3aX;</td></tr><tr><td id="file-_optimizedcmm-c-L37" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC37" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">      c3aW:</td></tr><tr><td id="file-_optimizedcmm-c-L38" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC38" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          R1 = P64[R1 + <span class="" style="color:rgb(0,134,179)">6</span>] & (-<span class="" style="color:rgb(0,134,179)">8</span>);</td></tr><tr><td id="file-_optimizedcmm-c-L39" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC39" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          Sp = Sp + <span class="" style="color:rgb(0,134,179)">8</span>;</td></tr><tr><td id="file-_optimizedcmm-c-L40" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC40" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          <span class="" style="color:rgb(0,134,179)">call</span> (I64[R1])(R1) args: <span class="" style="color:rgb(0,134,179)">8</span>, res: <span class="" style="color:rgb(0,134,179)">0</span>, upd: <span class="" style="color:rgb(0,134,179)">8</span>;</td></tr><tr><td id="file-_optimizedcmm-c-L41" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC41" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">      c3aX:</td></tr><tr><td id="file-_optimizedcmm-c-L42" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC42" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          R1 = PicBaseReg + lvl_r39S_closure;</td></tr><tr><td id="file-_optimizedcmm-c-L43" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC43" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          Sp = Sp + <span class="" style="color:rgb(0,134,179)">8</span>;</td></tr><tr><td id="file-_optimizedcmm-c-L44" class="" style="padding:0px 10px;width:50px;min-width:50px;white-space:nowrap;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;line-height:18px;color:rgba(0,0,0,0.298039);vertical-align:top;text-align:right;border-style:solid;border-color:rgb(238,238,238);border-width:0px 1px 0px 0px"></td><td id="file-_optimizedcmm-c-LC44" class="" style="padding:0px 10px;vertical-align:top;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:12px;white-space:pre;overflow:visible;word-wrap:normal">          <span class="" style="color:rgb(0,134,179)">call</span> (I64[R1])(R1) args: <span class="" style="color:rgb(0,134,179)">8</span>, res: <span class="" style="color:rgb(0,134,179)">0</span>, upd: <span class="" style="color:rgb(0,134,179)">8</span>;</td></tr></tbody></table></div><div><br></div><div><br></div><div>The call inside c3aP is entering "x" as a thunk, which also incurs all of the stack limit check code.  I believe that IF the input could be assumed to be in WHNF, everything above the label "c3aO" could be omitted.</div><div><br></div><div>So... if GHC is going to be a fabulous pure <i>and</i> imperative language, and a fabulous lazy <i>and</i> strict compiler/runtime.. is there some work we can do here to improve this situation? Would the following make sense:</div><div><ul><li>Put together a benchmark suite of all-strict programs with Strict/StrictData (compare a few benchmark's generated code to MLton, if time allows)</li><li>Modify GHC to change calling conventions for bang patterns -- caller enforces WHNF rather than callee.  Existing strictness/demand/cardinality analysis would stay the same.</li></ul></div><div>Unless there's something I'm really missing here, the result should be that you can have a whole chain of strict function calls, each of which knows its arguments and the arguments it passes to its callees are all in WHNF, without ever generating thunk-entry sequences.</div><div><i><br></i></div><div>Thanks for your time,</div><div>  -Ryan</div><div><br></div></div>