2 /* --------------------------------------------------------------------------
5 * The Hugs 98 system is Copyright (c) Mark P Jones, Alastair Reid, the
6 * Yale Haskell Group, and the Oregon Graduate Institute of Science and
7 * Technology, 1994-1999, All rights reserved. It is distributed as
8 * free software under the license in the file "License", which is
9 * included in the distribution.
11 * $RCSfile: optimise.c,v $
13 * $Date: 1999/10/15 21:40:52 $
14 * ------------------------------------------------------------------------*/
22 #include "Assembler.h"
24 /* #define DEBUG_OPTIMISE */
26 extern void print ( Cell, Int );
28 /* --------------------------------------------------------------------------
30 * ------------------------------------------------------------------------*/
32 Int nLoopBreakersInlined;
41 Int nLetrecGroupsDropped;
43 Int nCaseDefaultsDropped;
45 Int nLetsFloatedOutOfFn;
46 Int nLetsFloatedIntoCase;
47 Int nCasesFloatedOutOfFn;
57 static void local optimiseTopBind( StgVar v );
66 /* Exactly like whatIs except it avoids a fn call for STG tags */
67 #define whatIsStg(xx) ((isPair(xx) ? (isTag(fst(xx)) ? fst(xx) : AP) : whatIs(xx)))
70 /* --------------------------------------------------------------------------
71 * Transformation stats
72 * ------------------------------------------------------------------------*/
74 void initOptStats ( void )
76 nLoopBreakersInlined = 0;
85 nLetrecGroupsDropped = 0;
87 nCaseDefaultsDropped = 0;
89 nLetsFloatedOutOfFn = 0;
90 nLetsFloatedIntoCase = 0;
91 nCasesFloatedOutOfFn = 0;
97 void printOptStats ( FILE* f )
99 fflush(stdout); fflush(stderr); fflush(f);
101 fprintf(f, "Inlining: topvar %-5d letvar %-5d"
102 " loopbrkr %-5d betaredn %-5d\n",
103 nTopvarsInlined, nLetvarsInlined, nLoopBreakersInlined,
105 fprintf(f, "Case-of-: let %-5d case %-5d"
106 " con %-5d case# %-5d\n",
107 nCaseOfLet, nCaseOfCase, nCaseOfCon, nCaseOfPrimCase );
108 fprintf(f, "Dropped: letbind %-5d letgroup %-5d"
110 nLetBindsDropped, nLetrecGroupsDropped, nCaseDefaultsDropped );
111 fprintf(f, "Merges: lambda %-5d app %-5d\n",
112 nLambdasMerged, nAppsMerged );
113 fprintf(f, "Fn-float: let %-5d case %-5d\n",
114 nLetsFloatedOutOfFn, nCasesFloatedOutOfFn );
115 fprintf(f, "Misc: case-outer %-5d let-into-case %-5d\n",
116 nCaseOfOuter, nLetsFloatedIntoCase );
117 fprintf(f, "total size: in %-5d out %-5d\n",
118 nTotSizeIn, nTotSizeOut );
123 /* --------------------------------------------------------------------------
124 * How big is this STG tree (viz (primarily), do I want to inline it?)
125 * ------------------------------------------------------------------------*/
127 Int stgSize_list ( List es )
130 for (; nonNull(es); es=tl(es)) n += stgSize(hd(es));
134 Int stgSize ( StgExpr e )
139 if (isNull(e)) return 0;
141 switch(whatIsStg(e)) {
145 for (xs = stgLetBinds(e); nonNull(xs);xs=tl(xs))
146 n += stgSize(stgVarBody(hd(xs)));
147 n += stgSize(stgLetBody(e));
150 n += stgSize(stgLambdaBody(e));
153 n += stgSize_list(stgCaseAlts(e));
154 n += stgSize(stgCaseScrut(e));
157 n += stgSize_list(stgPrimCaseAlts(e));
158 n += stgSize(stgPrimCaseScrut(e));
161 n += stgSize_list(stgAppArgs(e));
162 n += stgSize(stgAppFun(e));
165 n += stgSize_list(stgPrimArgs(e));
166 n += stgSize(stgPrimOp(e));
169 n += stgSize_list(stgConArgs(e));
170 n += stgSize(stgConCon(e));
173 n = stgSize(stgDefaultBody(e));
176 n = stgSize(stgCaseAltBody(e));
179 n = stgSize(stgPrimAltBody(e));
191 fprintf(stderr, "sizeStg: unknown stuff %d\n",whatIsStg(e));
198 /* --------------------------------------------------------------------------
199 * Stacks of pairs of collectable things. Used to implement associations.
200 * cloneStg() uses its stack to map old var names to new ones.
201 * ------------------------------------------------------------------------*/
204 #define SP_NOT_IN_USE (-123456789)
207 struct { Cell pfst; Cell psnd; }
211 static StgPair pairClone[M_PAIRS];
213 void markPairs ( void )
216 if (spClone != SP_NOT_IN_USE) {
217 for (i = 0; i <= spClone; i++) {
218 mark(pairClone[i].pfst);
219 mark(pairClone[i].psnd);
224 void pushClone ( Cell a, Cell b )
227 if (spClone >= M_PAIRS) internal("pushClone -- M_PAIRS too small");
228 pairClone[spClone].pfst = a;
229 pairClone[spClone].psnd = b;
232 void dropClone ( void )
234 if (spClone < 0) internal("dropClone");
238 Cell findClone ( Cell x )
241 for (i = spClone; i >= 0; i--)
242 if (pairClone[i].pfst == x)
243 return pairClone[i].psnd;
248 /* --------------------------------------------------------------------------
249 * Cloning of STG trees
250 * ------------------------------------------------------------------------*/
252 /* Clone v to create a new var. Works for both StgVar and StgPrimVar. */
253 StgVar cloneStgVar ( StgVar v )
255 return ap(STGVAR,triple(stgVarBody(v),stgVarRep(v),NIL));
259 /* For each StgVar in origVars, make a new one with cloneStgVar,
260 and push the (old,new) pair on the clone pair stack. Returns
261 the list of new vars.
263 List cloneStg_addVars ( List origVars )
266 while (nonNull(origVars)) {
267 StgVar newv = cloneStgVar(hd(origVars));
268 pushClone ( hd(origVars), newv );
269 newVars = cons(newv,newVars);
270 origVars = tl(origVars);
272 newVars = rev(newVars);
277 void cloneStg_dropVars ( List vs )
279 for (; nonNull(vs); vs=tl(vs))
284 /* Print the clone pair stack. Just for debugging purposes. */
285 void ppCloneEnv ( char* s )
288 fflush(stdout);fflush(stderr);
289 printf ( "\nenv-%s\n", s );
290 for (i = 0; i <= spClone; i++) {
292 ppStgExpr(pairClone[i].pfst);
293 ppStgExpr(pairClone[i].psnd);
296 printf ( "vne-%s\n", s );
300 StgExpr cloneStg ( StgExpr e )
306 switch(whatIsStg(e)) {
309 if (nonNull(newv)) return newv; else return e;
311 newvs = cloneStg_addVars ( stgLetBinds(e) );
312 for (xs = newvs; nonNull(xs);xs=tl(xs))
313 stgVarBody(hd(xs)) = cloneStg(stgVarBody(hd(xs)));
314 t = mkStgLet(newvs,cloneStg(stgLetBody(e)));
315 cloneStg_dropVars ( stgLetBinds(e) );
318 newvs = cloneStg_addVars ( stgLambdaArgs(e) );
319 t = mkStgLambda(newvs, cloneStg(stgLambdaBody(e)));
320 cloneStg_dropVars ( stgLambdaArgs(e) );
323 xs = dupList(stgCaseAlts(e));
324 mapOver(cloneStg,xs);
325 return mkStgCase(cloneStg(stgCaseScrut(e)),xs);
327 xs = dupList(stgPrimCaseAlts(e));
328 mapOver(cloneStg,xs);
329 return mkStgPrimCase(cloneStg(stgPrimCaseScrut(e)),xs);
331 xs = dupList(stgAppArgs(e));
332 mapOver(cloneStg,xs);
333 return mkStgApp(cloneStg(stgAppFun(e)),xs);
335 xs = dupList(stgPrimArgs(e));
336 mapOver(cloneStg,xs);
337 return mkStgPrim(cloneStg(stgPrimOp(e)),xs);
339 xs = dupList(stgConArgs(e));
340 mapOver(cloneStg,xs);
341 return mkStgCon(cloneStg(stgConCon(e)),xs);
343 newv = cloneStgVar(stgDefaultVar(e));
344 pushClone ( stgDefaultVar(e), newv );
345 t = mkStgDefault(newv,cloneStg(stgDefaultBody(e)));
349 newvs = cloneStg_addVars ( stgCaseAltVars(e) );
350 t = mkStgCaseAlt(stgCaseAltCon(e),newvs,
351 cloneStg(stgCaseAltBody(e)));
352 cloneStg_dropVars ( stgCaseAltVars(e) );
355 newvs = cloneStg_addVars ( stgPrimAltVars(e) );
356 t = mkStgPrimAlt(newvs, cloneStg(stgPrimAltBody(e)));
357 cloneStg_dropVars ( stgPrimAltVars(e) );
369 fprintf(stderr, "cloneStg: unknown stuff %d\n",whatIsStg(e));
375 /* Main entry point. Checks against re-entrant use. */
376 StgExpr cloneStgTop ( StgExpr e )
379 if (spClone != SP_NOT_IN_USE)
380 internal("cloneStgTop");
382 res = cloneStg ( e );
383 assert(spClone == -1);
384 spClone = SP_NOT_IN_USE;
390 /* --------------------------------------------------------------------------
391 * Sets of StgVars, used by the strongly-connected-components machinery.
392 * Represented as an array of variables. The vars
393 * must be in strictly nondecreasing order. Each value may appear
394 * more than once, so as to make deletion relatively cheap.
396 * After a garbage collection happens, the values may have changed,
397 * so the array will need to be sorted.
399 * Using a binary search, membership costs O(log N). Union and
400 * intersection cost O(N + M). Deletion of a single element costs
401 * O(N) in the worst case, although if it happens infrequently
402 * compared to the other ops, it should asymptotically approach O(1).
403 * ------------------------------------------------------------------------*/
405 #define M_VAR_SETS 4000
406 #define MIN_VAR_SET_SIZE 4
407 #define M_UNION_TMP 20000
419 typedef Int StgVarSet;
421 StgVarSetRec varSet[M_VAR_SETS];
424 Cell union_tmp[M_UNION_TMP];
426 #if 0 /* unused since unnecessary */
427 /* Shellsort set elems to restore representation invariants */
428 static Int shellCells_incs[10]
429 = { 1, 4, 13, 40, 121, 364, 1093, 3280, 9841, 29524 };
430 static void shellCells ( Cell* a, Int lo, Int hi )
435 N = hi - lo + 1; if (N < 2) return;
437 while (hp < 10 && shellCells_incs[hp] < N) hp++; hp--;
439 for (; hp >= 0; hp--) {
440 h = shellCells_incs[hp];
447 a[j] = a[j-h]; j = j - h;
448 if (j <= (lo + h - 1)) break;
456 /* check that representation invariant still holds */
457 static void checkCells ( Cell* a, Int lo, Int hi )
460 for (i = lo; i < hi; i++)
462 internal("checkCells");
466 /* Mark set contents for GC */
467 void markStgVarSets ( void )
470 for (i = 0; i < M_VAR_SETS; i++)
472 for (j = 0; j < varSet[i].used; j++)
473 mark(varSet[i].vs[j]);
477 /* Check representation invariants after GC */
478 void checkStgVarSets ( void )
481 for (i = 0; i < M_VAR_SETS; i++)
483 checkCells ( varSet[i].vs, 0, varSet[i].used-1 );
487 /* Allocate a set of a given size */
488 StgVarSet allocStgVarSet ( Int size )
491 if (varSet_nextfree == -1)
492 internal("allocStgVarSet -- run out of var sets");
494 varSet_nextfree = varSet[i].nextfree;
495 varSet[i].inUse = TRUE;
496 j = MIN_VAR_SET_SIZE;
497 while (j <= size) j *= 2;
500 varSet[i].vs = malloc(j * sizeof(StgVar) );
502 internal("allocStgVarSet -- can't malloc memory");
508 /* resize (upwards) */
509 void resizeStgVarSet ( StgVarSet s, Int size )
514 Int j = MIN_VAR_SET_SIZE;
515 while (j <= size) j *= 2;
516 if (j < varSet[s].size) return;
518 tmp2 = malloc( j * sizeof(StgVar) );
519 if (!tmp2) internal("resizeStgVarSet -- can't malloc memory");
521 for (i = 0; i < varSet[s].used; i++)
527 /* Deallocation ... */
528 void freeStgVarSet ( StgVarSet s )
530 if (s < 0 || s >= M_VAR_SETS ||
531 !varSet[s].inUse || !varSet[s].vs)
532 internal("freeStgVarSet");
534 varSet[s].inUse = FALSE;
536 varSet[s].nextfree = varSet_nextfree;
543 void initStgVarSets ( void )
546 for (i = M_VAR_SETS-1; i >= 0; i--) {
547 varSet[i].inUse = FALSE;
549 varSet[i].nextfree = i+1;
551 varSet[M_VAR_SETS-1].nextfree = -1;
553 varSet_nfree = M_VAR_SETS;
557 /* Find a var using binary search */
558 Int findInStgVarSet ( StgVarSet s, StgVar v )
562 hi = varSet[s].used-1;
564 if (lo > hi) return -1;
566 if (varSet[s].vs[mid] == v) return mid;
567 if (varSet[s].vs[mid] < v) lo = mid+1; else hi = mid-1;
572 Bool elemStgVarSet ( StgVarSet s, StgVar v )
574 return findInStgVarSet(s,v) != -1;
577 void ppSet ( StgVarSet s )
580 fprintf(stderr, "{ ");
581 for (i = 0; i < varSet[s].used; i++)
582 fprintf(stderr, "%d ", varSet[s].vs[i] );
583 fprintf(stderr, "}\n" );
587 void deleteFromStgVarSet ( StgVarSet s, StgVar v )
590 i = findInStgVarSet(s,v);
592 j = varSet[s].used-1;
593 for (; i < j; i++) varSet[s].vs[i] = varSet[s].vs[i+1];
598 void singletonStgVarSet ( StgVarSet s, StgVar v )
605 void emptyStgVarSet ( StgVarSet s )
611 void copyStgVarSets ( StgVarSet dst, StgVarSet src )
614 varSet[dst].used = varSet[src].used;
615 for (i = 0; i < varSet[dst].used; i++)
616 varSet[dst].vs[i] = varSet[src].vs[i];
620 Int sizeofVarSet ( StgVarSet s )
622 return varSet[s].used;
626 void unionStgVarSets ( StgVarSet dst, StgVarSet src )
629 Int pd, ps, i, res_used, tmp_used, dst_used, src_used;
634 dst_vs = varSet[dst].vs;
636 /* fast track a common (~ 50%) case */
637 if (varSet[src].used == 1) {
638 v1 = varSet[src].vs[0];
639 pd = findInStgVarSet(dst,v1);
640 if (pd != -1) return;
641 if (varSet[dst].used < varSet[dst].size) {
642 i = varSet[dst].used;
643 while (i > 0 && dst_vs[i-1] > v1) {
644 dst_vs[i] = dst_vs[i-1];
653 res_used = varSet[dst].used + varSet[src].used;
654 if (res_used > M_UNION_TMP)
655 internal("unionStgVarSets -- M_UNION_TMP too small");
657 resizeStgVarSet(dst,res_used);
658 dst_vs = varSet[dst].vs;
659 src_vs = varSet[src].vs;
662 dst_used = varSet[dst].used;
663 src_used = varSet[src].used;
665 /* merge the two sets into tmp */
667 while (pd < dst_used || ps < src_used) {
669 tmp_vs[tmp_used++] = src_vs[ps++];
672 tmp_vs[tmp_used++] = dst_vs[pd++];
674 StgVar vald = dst_vs[pd];
675 StgVar vals = src_vs[ps];
677 tmp_vs[tmp_used++] = vald, pd++;
680 tmp_vs[tmp_used++] = vals, ps++;
682 tmp_vs[tmp_used++] = vals, ps++, pd++;
686 /* copy setTmp back to dst */
687 varSet[dst].used = tmp_used;
688 for (i = 0; i < tmp_used; i++) {
689 dst_vs[i] = tmp_vs[i];
695 /* --------------------------------------------------------------------------
696 * Strongly-connected-components machinery for STG let bindings.
697 * Arranges let bindings in minimal mutually recursive groups, and
698 * then throws away any groups not referred to in the body of the let.
700 * How it works: does a bottom-up sweep of the tree. Each call returns
701 * the set of variables free in the tree. All nodes except LETREC are
704 * When 'let v1=e1 .. vn=en in e' is encountered:
705 * -- recursively make a call on e. This returns fvs(e) and scc-ifies
707 * -- do recursive calls for e1 .. en too, giving fvs(e1) ... fvs(en).
709 * Then, using fvs(e1) ... fvs(en), the dependancy graph for v1 ... vn
710 * can be cheaply computed. Using that, compute the strong components
711 * and rearrange the let binding accordingly.
712 * Finally, for each of the strong components, we can use fvs(en) to
713 * cheaply determine if the component is used in the body of the let,
714 * and if not, it can be omitted.
716 * oaScc destructively modifies the tree -- when it gets to a let --
717 * we need to pass the address of the expression to scc, not the
718 * (more usual) heap index of it.
720 * The main requirement of this algorithm is an efficient implementation
721 * of sets of variables. Because there is no name shadowing in these
722 * trees, either mentioned-sets or free-sets would be ok, although
723 * free sets are presumably smaller.
724 * ------------------------------------------------------------------------*/
727 #define SCC stgScc /* make scc algorithm for StgVars */
728 #define LOWLINK stgLowlink
729 #define DEPENDS(t) thd3(t)
730 #define SETDEPENDS(c,v) thd3(c)=v
738 StgVarSet oaScc ( StgExpr* e_orig )
742 StgVarSet e_fvs, s1, s2;
743 List bs, bs2, bs3, bsFinal, augs, augsL;
745 bs=bs2=bs3=bsFinal=augs=augsL=e_fvs=s1=s2=e=NIL;
750 //fprintf(stderr,"\n==================\n");
751 //ppStgExpr(*e_orig);
752 //fprintf(stderr,"\n\n");fflush(stderr);fflush(stdout);
755 switch(whatIsStg(e)) {
757 /* first, recurse into the let body */
758 e_fvs = oaScc(&stgLetBody(*e_orig));
760 /* Make bs :: [StgVar] and e :: Stgexpr. */
764 /* make augs :: [(StgVar,fvs(bindee),NIL)] */
766 for (; nonNull(bs); bs=tl(bs)) {
767 StgVarSet fvs_bindee = oaScc(&stgVarBody(hd(bs)));
768 augs = cons( triple(hd(bs),mkInt(fvs_bindee),NIL), augs );
771 bs2=bs3=bsFinal=augsL=s1=s2=NIL;
773 /* In each of the triples in aug, replace the NIL field with
774 a list of the let-bound vars appearing in the bindee.
775 ie, construct the adjacency list for the graph.
777 augs :: [(StgVar,fvs(bindee),[pointers-back-to-this-list-of-pairs])]
779 for (bs=augs;nonNull(bs);bs=tl(bs)) {
781 for (bs2=augs;nonNull(bs2);bs2=tl(bs2))
782 if (elemStgVarSet( intOf(snd3(hd(bs))), fst3(hd(bs2)) ))
783 augsL = cons(hd(bs2),augsL);
784 thd3(hd(bs)) = augsL;
787 bs2=bs3=bsFinal=augsL=s1=s2=NIL;
790 augs becomes :: [[(StgVar,fvs(bindee),aux_info_field)]] */
793 /* work backwards through augs, reconstructing the expression,
794 dumping any unused groups as you go.
797 for (augs=rev(augs); nonNull(augs); augs=tl(augs)) {
799 for (augsL=hd(augs);nonNull(augsL); augsL=tl(augsL))
800 bs2 = cons(fst3(hd(augsL)),bs2);
802 for (bs3=bs2;nonNull(bs3);bs3=tl(bs3))
803 if (elemStgVarSet(e_fvs,hd(bs3))) { grpUsed=TRUE; break; }
805 //e = mkStgLet(bs2,e);
806 bsFinal = dupOnto(bs2,bsFinal);
807 for (augsL=hd(augs);nonNull(augsL);augsL=tl(augsL)) {
808 unionStgVarSets(e_fvs, intOf(snd3(hd(augsL))) );
809 freeStgVarSet(intOf(snd3(hd(augsL))));
812 nLetrecGroupsDropped++;
813 for (augsL=hd(augs);nonNull(augsL);augsL=tl(augsL)) {
814 freeStgVarSet(intOf(snd3(hd(augsL))));
819 *e_orig = mkStgLet(bsFinal,e);
823 s1 = oaScc(&stgLambdaBody(e));
824 for (bs=stgLambdaArgs(e);nonNull(bs);bs=tl(bs))
825 deleteFromStgVarSet(s1,hd(bs));
828 s1 = oaScc(&stgCaseScrut(e));
829 for (bs=stgCaseAlts(e);nonNull(bs);bs=tl(bs)) {
831 unionStgVarSets(s1,s2);
836 s1 = oaScc(&stgPrimCaseScrut(e));
837 for (bs=stgPrimCaseAlts(e);nonNull(bs);bs=tl(bs)) {
839 unionStgVarSets(s1,s2);
844 s1 = oaScc(&stgAppFun(e));
845 for (bs=stgAppArgs(e);nonNull(bs);bs=tl(bs)) {
847 unionStgVarSets(s1,s2);
852 s1 = oaScc(&stgPrimOp(e));
853 for (bs=stgPrimArgs(e);nonNull(bs);bs=tl(bs)) {
855 unionStgVarSets(s1,s2);
860 s1 = allocStgVarSet(0);
861 for (bs=stgPrimArgs(e);nonNull(bs);bs=tl(bs)) {
863 unionStgVarSets(s1,s2);
868 s1 = oaScc(&stgCaseAltBody(e));
869 for (bs=stgCaseAltVars(e);nonNull(bs);bs=tl(bs))
870 deleteFromStgVarSet(s1,hd(bs));
873 s1 = oaScc(&stgDefaultBody(e));
874 deleteFromStgVarSet(s1,stgDefaultVar(e));
877 s1 = oaScc(&stgPrimAltBody(e));
878 for (bs=stgPrimAltVars(e);nonNull(bs);bs=tl(bs))
879 deleteFromStgVarSet(s1,hd(bs));
882 s1 = allocStgVarSet(1);
883 singletonStgVarSet(s1,e);
892 return allocStgVarSet(0);
895 fprintf(stderr, "oaScc: unknown stuff %d\n",whatIsStg(e));
902 /* --------------------------------------------------------------------------
903 * Occurrence analyser. Marks each let-bound var with the number of times
904 * it is used, or some number >= OCC_IN_LAMBDA if it is used inside a lambda.
906 * Firstly, oaPre traverses the tree, attaching a mutable INT cell to each
907 * let bound var, and NIL-ing the counts on all other vars.
909 * Then oaCount traveses the tree. Because variables are represented by
910 * pointers in the heap, we can just increment the count field of each
911 * variable we see. However, to deal with lambdas, the Hugs stack holds
912 * all let-bound variables currently in scope, and the uppermost portion
913 * of the stack, stack(spBase .. sp) inclusive, denotes the variables
914 * introduced into scope since the nearest enclosing lambda. When a
915 * let-bound var is seen, we search stack(spBase .. sp). If it appears
916 * there, no lambda exists between the binding site and this usage of the
917 * var, so we can safely increment its use. Otherwise, we must set it to
920 * When passing a lambda, spBase is set to sp+1, so as to effectively
921 * empty the set of vars-bound-since-the-latest-lambda.
923 * Because oaPre pre-annotates the tree with mutable INT cells, oaCount
924 * doesn't allocate any heap at all.
925 * ------------------------------------------------------------------------*/
930 #define OCC_IN_LAMBDA 50 /* any number > 1 will do */
931 #define nullCount(vv) stgVarInfo(vv)=NIL
932 #define nullCounts(vvs) { List tt=(vvs);for(;nonNull(tt);tt=tl(tt)) nullCount(hd(tt));}
936 void oaPre ( StgExpr e )
939 switch(whatIsStg(e)) {
941 for (bs = stgLetBinds(e);nonNull(bs);bs=tl(bs))
942 stgVarInfo(hd(bs)) = mkInt(0);
943 for (bs = stgLetBinds(e);nonNull(bs);bs=tl(bs))
944 oaPre(stgVarBody(hd(bs)));
945 oaPre(stgLetBody(e));
948 nullCounts(stgLambdaArgs(e));
949 oaPre(stgLambdaBody(e));
952 oaPre(stgCaseScrut(e));
953 mapProc(oaPre,stgCaseAlts(e));
956 oaPre(stgPrimCaseScrut(e));
957 mapProc(oaPre,stgPrimCaseAlts(e));
961 mapProc(oaPre,stgAppArgs(e));
964 mapProc(oaPre,stgPrimArgs(e));
967 mapProc(oaPre,stgConArgs(e));
970 nullCounts(stgCaseAltVars(e));
971 oaPre(stgCaseAltBody(e));
974 nullCount(stgDefaultVar(e));
975 oaPre(stgDefaultBody(e));
978 nullCounts(stgPrimAltVars(e));
979 oaPre(stgPrimAltBody(e));
991 fprintf(stderr, "oaPre: unknown stuff %d\n",whatIsStg(e));
998 -- the stack is always the set of let-bound vars currently
999 in scope. viz, stack(0 .. sp) inclusive.
1000 -- spBase is always >= 0 and <= sp.
1001 stack(spBase .. sp) inclusive will be the let vars bound
1002 since the nearest enclosing lambda. When entering a lambda,
1003 we set spBase=sp+1 so as record this fact, and restore spBase
1006 void oaCount ( StgExpr e )
1011 switch(whatIsStg(e)) {
1013 for (bs = stgLetBinds(e);nonNull(bs);bs=tl(bs))
1015 for (bs = stgLetBinds(e);nonNull(bs);bs=tl(bs))
1016 oaCount(stgVarBody(hd(bs)));
1017 oaCount(stgLetBody(e));
1018 for (bs = stgLetBinds(e);nonNull(bs);bs=tl(bs))
1022 spBase_saved = spBase;
1024 oaCount(stgLambdaBody(e));
1025 spBase = spBase_saved;
1028 oaCount(stgCaseScrut(e));
1029 mapProc(oaCount,stgCaseAlts(e));
1032 oaCount(stgPrimCaseScrut(e));
1033 mapProc(oaCount,stgPrimCaseAlts(e));
1036 oaCount(stgAppFun(e));
1037 mapProc(oaCount,stgAppArgs(e));
1040 mapProc(oaCount,stgPrimArgs(e));
1043 mapProc(oaCount,stgConArgs(e));
1046 nullCounts(stgCaseAltVars(e));
1047 oaCount(stgCaseAltBody(e));
1050 nullCount(stgDefaultVar(e));
1051 oaCount(stgDefaultBody(e));
1054 nullCounts(stgPrimAltVars(e));
1055 oaCount(stgPrimAltBody(e));
1058 if (isInt(stgVarInfo(e))) {
1061 for (i = sp; i >= spBase; i--)
1062 if (stack(i) == e) { j = i; break; };
1064 stgVarInfo(e) = mkInt(OCC_IN_LAMBDA); else
1065 stgVarInfo(e) = mkInt(1 + intOf(stgVarInfo(e)));
1077 fprintf(stderr, "oaCount: unknown stuff %d\n",whatIsStg(e));
1082 void stgTopSanity ( char*, StgVar );
1084 /* Top level entry point for the occurrence analyser. */
1085 void oaTop ( StgVar v )
1087 assert (varSet_nfree == M_VAR_SETS);
1088 freeStgVarSet(oaScc(&stgVarBody(v)));
1089 assert (varSet_nfree == M_VAR_SETS);
1090 oaPre(stgVarBody(v));
1091 clearStack(); spBase = 0;
1092 oaCount(stgVarBody(v));
1093 assert(stackEmpty());
1094 stgTopSanity("oaTop",stgVarBody(v));
1098 /* --------------------------------------------------------------------------
1099 * Transformation machinery proper
1100 * ------------------------------------------------------------------------*/
1102 #define streq(aa,bb) (strcmp((aa),(bb))==0)
1103 /* Return TRUE if the non-default alts in the given list are exhaustive.
1104 If in doubt, return FALSE.
1106 Bool stgAltsExhaustive ( List alts )
1114 while (nonNull(alts) && isDefaultAlt(hd(alts))) alts=tl(alts);
1118 con = stgCaseAltCon(hd(alts));
1119 /* special case: dictionary constructor */
1120 if (strncmp("Make.",textToStr(name(con).text),5)==0)
1122 /* special case: constructor boxing an unboxed value. */
1123 if (isBoxingCon(con))
1125 /* some other special cases which are not boxingCons */
1126 s = textToStr(name(con).text);
1127 if (streq(s,"Integer#")
1129 || streq(s,"PrimMutableArray#")
1130 || streq(s,"PrimMutableByteArray#")
1131 || streq(s,"PrimByteArray#")
1132 || streq(s,"PrimArray#")
1135 if (strcmp("Ref#",textToStr(name(con).text))==0)
1137 /* special case: Tuples */
1138 if (isTuple(con) || (isName(con) && con==nameUnit))
1140 if (isNull(name(con).parent)) internal("stgAltsExhaustive(1)");
1141 t = name(con).parent;
1143 if (tycon(t).what != DATATYPE) internal("stgAltsExhaustive(2)");
1144 nDefnCons = length(cs);
1145 for (; nonNull(alts0);alts0=tl(alts0)) {
1146 if (isDefaultAlt(hd(alts0))) continue;
1150 return nDefnCons == 0;
1155 /* If in doubt, return FALSE.
1157 Bool isManifestCon ( StgExpr e )
1160 switch (whatIsStg(e)) {
1161 case STGCON: return TRUE;
1162 case LETREC: return isManifestCon(stgLetBody(e));
1163 case CASE: if (length(stgCaseAlts(e))==1) {
1164 if (isDefaultAlt(hd(stgCaseAlts(e))))
1165 altB = stgDefaultBody(hd(stgCaseAlts(e))); else
1166 altB = stgCaseAltBody(hd(stgCaseAlts(e)));
1167 return isManifestCon(altB);
1171 default: return FALSE;
1176 /* Like isManifestCon, but doesn't give up at non-singular cases */
1177 Bool constructsCon ( StgExpr e )
1180 switch (whatIsStg(e)) {
1181 case STGCON: return TRUE;
1182 case LETREC: return constructsCon(stgLetBody(e));
1183 case CASE: for (as = stgCaseAlts(e); nonNull(as); as=tl(as))
1184 if (!constructsCon(hd(as))) return FALSE;
1186 case PRIMCASE: for (as = stgPrimCaseAlts(e); nonNull(as); as=tl(as))
1187 if (!constructsCon(hd(as))) return FALSE;
1189 case CASEALT: return constructsCon(stgCaseAltBody(e));
1190 case DEEFALT: return constructsCon(stgDefaultBody(e));
1191 case PRIMALT: return constructsCon(stgPrimAltBody(e));
1192 default: return FALSE;
1197 /* Inline v in the special case where expr is
1198 case v of C a1 ... an -> E
1199 and v's bindee returns a product constructed with C.
1200 and v does not appear in E
1201 and v does not appear in letDefs (ie, this expr isn't
1202 part of the definition of v.
1204 void tryLoopbreakerHack ( List letDefs, StgExpr expr )
1207 StgExpr scrut, ee, v_bindee;
1210 assert (whatIsStg(expr)==CASE);
1211 alts = stgCaseAlts(expr);
1212 scrut = stgCaseScrut(expr);
1213 if (whatIsStg(scrut) != STGVAR || isNull(stgVarBody(scrut))) return;
1214 if (length(alts) != 1 || isDefaultAlt(hd(alts))) return;
1215 if (!stgAltsExhaustive(alts)) return;
1217 ee = stgCaseAltBody(alt);
1218 if (nonNull(cellIsMember(scrut,letDefs))) return;
1220 v_bindee = stgVarBody(scrut);
1221 if (!isManifestCon(v_bindee)) return;
1223 stgCaseScrut(expr) = cloneStgTop(v_bindee);
1224 nLoopBreakersInlined++;
1228 /* Traverse a tree. Replace let-bound vars marked as used-once
1229 by their definitions. Replace references to top-level
1230 values marked inlineMe with their bodies. Carry around a list
1231 of let-bound variables whose definitions we are currently in
1232 so as to know not to inline let-bound vars in their own
1235 StgExpr copyIn ( List letDefs, InlineCtx ctx, StgExpr e )
1239 switch(whatIsStg(e)) {
1240 // these are the only two interesting cases
1242 assert(isPtr(stgVarInfo(e)) || isNull(stgVarInfo(e)) ||
1243 isInt(stgVarInfo(e)));
1244 if (isInt(stgVarInfo(e)) && intOf(stgVarInfo(e))==1) {
1246 return cloneStgTop(stgVarBody(e));
1250 // if we're not inlining top vars on this round, do nothing
1251 if (!copyInTopvar) return e;
1252 // if it doesn't want to be inlined, do nothing
1253 if (!name(e).inlineMe) return e;
1254 // we decline to inline dictionary builders inside other builders
1255 if (inDBuilder && name(e).isDBuilder) {
1256 //fprintf(stderr, "decline to inline dbuilder %s\n", textToStr(name(e).text));
1259 // in fact, only inline dict builders into a case scrutinee
1260 if (name(e).isDBuilder && ctx != CTX_SCRUT)
1264 assert( stgSize(stgVarBody(name(e).stgVar)) == name(e).stgSize );
1267 // only inline large dict builders if it returns a manifest con
1268 if (name(e).isDBuilder &&
1269 name(e).stgSize > 180 &&
1270 !isManifestCon(stgVarBody(name(e).stgVar)))
1273 // if it's huge, don't inline into a boring place
1274 if (ctx != CTX_SCRUT &&
1275 name(e).stgSize > 270)
1280 return cloneStgTop(stgVarBody(name(e).stgVar));
1282 // the rest are a boring recursive traversal of the tree
1284 stgLetBody(e) = copyIn(letDefs,CTX_OTHER,stgLetBody(e));
1285 letDefs = dupOnto(stgLetBinds(e),letDefs);
1286 for (bs=stgLetBinds(e);nonNull(bs);bs=tl(bs))
1287 stgVarBody(hd(bs)) = copyIn(letDefs,CTX_OTHER,stgVarBody(hd(bs)));
1290 stgLambdaBody(e) = copyIn(letDefs,CTX_OTHER,stgLambdaBody(e));
1293 stgCaseScrut(e) = copyIn(letDefs,CTX_SCRUT,stgCaseScrut(e));
1294 map2Over(copyIn,letDefs,CTX_OTHER,stgCaseAlts(e));
1295 if (copyInTopvar) tryLoopbreakerHack(letDefs,e);
1298 stgPrimCaseScrut(e) = copyIn(letDefs,CTX_OTHER,stgPrimCaseScrut(e));
1299 map2Over(copyIn,letDefs,CTX_OTHER,stgPrimCaseAlts(e));
1302 stgAppFun(e) = copyIn(letDefs,CTX_OTHER,stgAppFun(e));
1305 stgCaseAltBody(e) = copyIn(letDefs,CTX_OTHER,stgCaseAltBody(e));
1308 stgDefaultBody(e) = copyIn(letDefs,CTX_OTHER,stgDefaultBody(e));
1311 stgPrimAltBody(e) = copyIn(letDefs,CTX_OTHER,stgPrimAltBody(e));
1322 fprintf(stderr, "copyIn: unknown stuff %d\n",whatIsStg(e));
1334 /* case (C a1 ... an) of
1339 e with v1/a1 ... vn/an
1341 StgExpr doCaseOfCon ( StgExpr expr, Bool* done )
1346 List alts, altvs, as, sub;
1349 alts = stgCaseAlts(expr);
1350 scrut = stgCaseScrut(expr);
1352 apC = stgConCon(scrut);
1355 for (alts = stgCaseAlts(expr); nonNull(alts); alts=tl(alts))
1356 if (!isDefaultAlt(hd(alts)) && stgCaseAltCon(hd(alts)) == apC) {
1361 if (isNull(theAlt)) return expr;
1362 altvs = stgCaseAltVars(theAlt);
1363 e = stgCaseAltBody(theAlt);
1364 as = stgConArgs(scrut);
1366 if (length(as)!=length(altvs)) return expr;
1369 while (nonNull(altvs)) {
1370 sub = cons(pair(hd(altvs),hd(as)),sub);
1376 return zubstExpr(sub,e);
1380 /* case (let binds in e) of alts
1382 let binds in case e of alts
1384 StgExpr doCaseOfLet ( StgExpr expr, Bool* done )
1389 letexpr = stgCaseScrut(expr);
1390 e = stgLetBody(letexpr);
1391 binds = stgLetBinds(letexpr);
1392 alts = stgCaseAlts(expr);
1395 return mkStgLet(binds,mkStgCase(e,alts));
1400 /* case (case e of p1 -> e1 ... pn -> en) of
1406 p1 -> case e1 of q1 -> h1 ... qk -> hk
1408 pn -> case en of q1 -> h1 ... qk -> kl
1410 StgExpr doCaseOfCase ( StgExpr expr )
1412 StgExpr innercase, e, tmpcase, protocase;
1413 List ps_n_es, qs_n_hs, newAlts;
1414 StgCaseAlt newAlt, p_n_e;
1418 innercase = stgCaseScrut(expr);
1419 e = stgCaseScrut(innercase);
1420 ps_n_es = stgCaseAlts(innercase);
1421 qs_n_hs = stgCaseAlts(expr);
1423 /* protocase = case (hole-to-fill-in) of q1 -> h1 ... qk -> hk */
1424 protocase = mkStgCase( mkInt(0), qs_n_hs);
1427 for (;nonNull(ps_n_es);ps_n_es = tl(ps_n_es)) {
1428 tmpcase = cloneStgTop(protocase);
1429 p_n_e = hd(ps_n_es);
1430 if (isDefaultAlt(p_n_e)) {
1431 stgCaseScrut(tmpcase) = stgDefaultBody(p_n_e);
1432 newAlt = mkStgDefault(stgDefaultVar(p_n_e), tmpcase);
1434 stgCaseScrut(tmpcase) = stgCaseAltBody(p_n_e);
1435 newAlt = mkStgCaseAlt(stgCaseAltCon(p_n_e),stgCaseAltVars(p_n_e),tmpcase);
1437 newAlts = cons(newAlt,newAlts);
1439 newAlts = rev(newAlts);
1441 mkStgCase(e, newAlts);
1446 /* case (case# e of p1 -> e1 ... pn -> en) of
1452 p1 -> case e1 of q1 -> h1 ... qk -> hk
1454 pn -> case en of q1 -> h1 ... qk -> kl
1456 StgExpr doCaseOfPrimCase ( StgExpr expr )
1458 StgExpr innercase, e, tmpcase, protocase;
1459 List ps_n_es, qs_n_hs, newAlts;
1460 StgCaseAlt newAlt, p_n_e;
1464 innercase = stgCaseScrut(expr);
1465 e = stgPrimCaseScrut(innercase);
1466 ps_n_es = stgPrimCaseAlts(innercase);
1467 qs_n_hs = stgCaseAlts(expr);
1469 /* protocase = case (hole-to-fill-in) of q1 -> h1 ... qk -> hk */
1470 protocase = mkStgCase( mkInt(0), qs_n_hs);
1473 for (;nonNull(ps_n_es);ps_n_es = tl(ps_n_es)) {
1474 tmpcase = cloneStgTop(protocase);
1475 p_n_e = hd(ps_n_es);
1476 stgPrimCaseScrut(tmpcase) = stgPrimAltBody(p_n_e);
1477 newAlt = mkStgPrimAlt(stgPrimAltVars(p_n_e),tmpcase);
1478 newAlts = cons(newAlt,newAlts);
1480 newAlts = rev(newAlts);
1482 mkStgPrimCase(e, newAlts);
1486 Bool isStgCaseWithSingleNonDefaultAlt ( StgExpr e )
1489 whatIsStg(e)==CASE &&
1490 length(stgCaseAlts(e))==1 &&
1491 !isDefaultAlt(hd(stgCaseAlts(e)));
1495 /* Do simplifications on an Stg tree. Invariant is that the
1496 input and output trees should have no name shadowing.
1502 -- dump individual let-bindings with usage counts of zero
1504 -- dump let-binding groups for which none of the bound vars
1505 occur in the let body
1507 -- (\v1 ... vn -> e) a1 ... am
1509 -- the usual beta reduction. There are no constraints on n and m, so
1510 the result can be a lambda term (if n > m), or an application of e
1511 to the unused args (if n < m).
1514 Scheme is: bottom-up traversal of the tree. First simplify child
1515 trees. Then try to do local transformations. If a local transformation
1516 succeeds, jump to the local-transformation code for whatever node
1517 is produced -- so as to try and maximise the amount of work which
1518 happens on each call to simplify.
1520 StgExpr simplify ( List caseEnv, StgExpr e )
1527 switch(whatIsStg(e)) {
1535 /* first dump dead binds, so as not to waste effort simplifying them */
1537 for (bs=stgLetBinds(e);nonNull(bs);bs=tl(bs))
1538 if (!isInt(stgVarInfo(hd(bs))) ||
1539 intOf(stgVarInfo(hd(bs))) > 0) {
1540 bs2=cons(hd(bs),bs2);
1544 if (isNull(bs2)) { e = stgLetBody(e); goto restart; };
1545 stgLetBinds(e) = rev(bs2);
1547 for (bs=stgLetBinds(e);nonNull(bs);bs=tl(bs))
1548 stgVarBody(hd(bs)) = simplify(caseEnv,stgVarBody(hd(bs)));
1549 stgLetBody(e) = simplify(caseEnv,stgLetBody(e));
1551 /* Merge let ... in let ... in e. Grouping lets together
1552 sometimes reduces the number of iterations needed.
1553 oaScc should do this anyway, but this just to make sure.
1555 while (whatIsStg(stgLetBody(e))==LETREC) {
1556 stgLetBinds(e) = dupOnto(stgLetBinds(stgLetBody(e)),stgLetBinds(e));
1557 stgLetBody(e) = stgLetBody(stgLetBody(e));
1561 /* let binds in case v-not-in-binds of singleAlt -> expr
1563 case v-not-in-binds of singleAlt -> let binds in expr
1565 if (isStgCaseWithSingleNonDefaultAlt(stgLetBody(e)) &&
1566 whatIsStg(stgCaseScrut(stgLetBody(e)))==STGVAR &&
1567 isNull(cellIsMember(stgCaseScrut(stgLetBody(e)),stgLetBinds(e)))) {
1568 StgVar v = stgCaseScrut(stgLetBody(e));
1569 StgCaseAlt a = hd(stgCaseAlts(stgLetBody(e)));
1570 nLetsFloatedIntoCase++;
1577 mkStgLet(stgLetBinds(e),stgCaseAltBody(a))
1581 assert(whatIsStg(e)==CASE);
1588 stgLambdaBody(e) = simplify(caseEnv,stgLambdaBody(e));
1591 while (whatIsStg(stgLambdaBody(e))==LAMBDA) {
1593 stgLambdaArgs(e) = appendOnto(stgLambdaArgs(e),
1594 stgLambdaArgs(stgLambdaBody(e)));
1595 stgLambdaBody(e) = stgLambdaBody(stgLambdaBody(e));
1601 stgCaseScrut(e) = simplify(caseEnv,stgCaseScrut(e));
1602 if (isStgCaseWithSingleNonDefaultAlt(e) &&
1603 (whatIsStg(stgCaseScrut(e))==STGVAR ||
1604 whatIsStg(stgCaseScrut(e))==NAME)) {
1605 List caseEnv2 = cons(
1606 pair(stgCaseScrut(e),stgCaseAltVars(hd(stgCaseAlts(e)))),
1609 map1Over(simplify,caseEnv2,stgCaseAlts(e));
1611 map1Over(simplify,caseEnv,stgCaseAlts(e));
1615 /* zap redundant default alternatives */
1616 if (stgAltsExhaustive(stgCaseAlts(e))) {
1617 Bool droppedDef = FALSE;
1619 for (bs = dupList(stgCaseAlts(e));nonNull(bs);bs=tl(bs))
1620 if (!isDefaultAlt(hd(bs))) {
1621 bs2=cons(hd(bs),bs2);
1626 stgCaseAlts(e) = bs2;
1627 if (droppedDef) nCaseDefaultsDropped++;
1630 switch (whatIsStg(stgCaseScrut(e))) {
1632 /* attempt case-of-case */
1633 n = length(stgCaseAlts(e));
1636 (stgSize(e)-stgSize(stgCaseScrut(e))) < 100 &&
1637 constructsCon(stgCaseScrut(e)))
1639 e = doCaseOfCase(e);
1640 assert(whatIsStg(e)==CASE);
1645 /* attempt case-of-case# */
1646 n = length(stgCaseAlts(e));
1649 (stgSize(e)-stgSize(stgCaseScrut(e))) < 100 &&
1650 constructsCon(stgCaseScrut(e)))
1652 e = doCaseOfPrimCase(e);
1653 assert(whatIsStg(e)==PRIMCASE);
1654 goto primcase_local;
1658 /* attempt case-of-let */
1659 e = doCaseOfLet(e,&done);
1660 if (done) { assert(whatIsStg(e)==LETREC); goto let_local; };
1663 /* attempt case-of-constructor */
1664 e = doCaseOfCon(e,&done);
1665 /* we don't know what the result is, so can't jump to local */
1669 /* attempt to remove case on something already cased on */
1670 List outervs, innervs, sub;
1672 if (!isStgCaseWithSingleNonDefaultAlt(e)) break;
1673 lookupResult = cellAssoc(stgCaseScrut(e),caseEnv);
1674 if (isNull(lookupResult)) break;
1675 outervs = snd(lookupResult);
1678 innervs = stgCaseAltVars(hd(stgCaseAlts(e)));
1679 for (; nonNull(outervs) && nonNull(innervs);
1680 outervs=tl(outervs), innervs=tl(innervs))
1681 sub = cons(pair(hd(innervs),hd(outervs)),sub);
1682 assert (isNull(outervs) && isNull(innervs));
1683 return zubstExpr(sub, stgCaseAltBody(hd(stgCaseAlts(e))));
1690 stgCaseAltBody(e) = simplify(caseEnv,stgCaseAltBody(e));
1693 stgDefaultBody(e) = simplify(caseEnv,stgDefaultBody(e));
1696 stgPrimAltBody(e) = simplify(caseEnv,stgPrimAltBody(e));
1699 stgPrimCaseScrut(e) = simplify(caseEnv,stgPrimCaseScrut(e));
1700 map1Over(simplify,caseEnv,stgPrimCaseAlts(e));
1709 stgAppFun(e) = simplify(caseEnv,stgAppFun(e));
1710 map1Over(simplify,caseEnv,stgAppArgs(e));
1713 args = stgAppArgs(e);
1715 switch (whatIsStg(fun)) {
1718 stgAppArgs(e) = appendOnto(stgAppArgs(fun),args);
1719 stgAppFun(e) = stgAppFun(fun);
1722 /* (let binds in f) args ==> let binds in (f args) */
1723 nLetsFloatedOutOfFn++;
1724 e = mkStgLet(stgLetBinds(fun),mkStgApp(stgLetBody(fun),args));
1725 assert(whatIsStg(e)==LETREC);
1729 if (length(stgCaseAlts(fun))==1 &&
1730 !isDefaultAlt(hd(stgCaseAlts(fun)))) {
1731 StgCaseAlt theAlt = hd(stgCaseAlts(fun));
1732 /* (case e of alt -> f) args ==> case e of alt -> f args */
1735 singleton(mkStgCaseAlt(stgCaseAltCon(theAlt),
1736 stgCaseAltVars(theAlt),
1737 mkStgApp(stgCaseAltBody(theAlt),args))
1740 nCasesFloatedOutOfFn++;
1741 assert(whatIsStg(e)==CASE);
1747 formals = stgLambdaArgs(fun);
1748 while (nonNull(formals) && nonNull(args)) {
1749 sub = cons(pair(hd(formals),hd(args)),sub);
1750 formals = tl(formals);
1753 subd_body = zubstExpr(sub,stgLambdaBody(fun));
1756 assert(isNull(formals) || isNull(args));
1757 if (isNull(formals) && isNull(args)) {
1758 /* fn and args match exactly */
1763 if (isNull(formals) && nonNull(args)) {
1764 /* more args than we could deal with. Build a new Ap. */
1765 e = mkStgApp(subd_body,args);
1769 if (nonNull(formals) && isNull(args)) {
1770 /* partial application. We get a new Lambda */
1771 e = mkStgLambda(formals,subd_body);
1792 fprintf(stderr, "simplify: unknown stuff %d\n",whatIsStg(e));
1803 /* Restore STG representation invariants broken by simplify.
1804 -- Let-bind any constructor applications which appear
1805 anywhere other than a let.
1806 -- Let-bind non-atomic case scrutinees (ToDo).
1808 StgExpr restoreStg ( StgExpr e )
1813 if (isNull(e)) return e;
1815 switch(whatIsStg(e)) {
1817 for (bs=stgLetBinds(e); nonNull(bs); bs=tl(bs)) {
1818 if (whatIsStg(stgVarBody(hd(bs))) == STGCON) {
1822 if (whatIsStg(stgVarBody(hd(bs))) == LAMBDA) {
1823 stgLambdaBody(stgVarBody(hd(bs)))
1824 = restoreStg(stgLambdaBody(stgVarBody(hd(bs))));
1827 stgVarBody(hd(bs)) = restoreStg(stgVarBody(hd(bs)));
1830 stgLetBody(e) = restoreStg(stgLetBody(e));
1833 /* note that the check in LETREC above ensures we won't
1834 get here for legitimate (let-bound) lambdas. */
1835 stgLambdaBody(e) = restoreStg(stgLambdaBody(e));
1836 newv = mkStgVar(e,NIL);
1837 e = mkStgLet(singleton(newv),newv);
1840 stgCaseScrut(e) = restoreStg(stgCaseScrut(e));
1841 mapOver(restoreStg,stgCaseAlts(e));
1842 if (!isAtomic(stgCaseScrut(e))) {
1843 newv = mkStgVar(stgCaseScrut(e),NIL);
1844 return mkStgLet(singleton(newv),mkStgCase(newv,stgCaseAlts(e)));
1848 stgPrimCaseScrut(e) = restoreStg(stgPrimCaseScrut(e));
1849 mapOver(restoreStg,stgPrimCaseAlts(e));
1852 stgAppFun(e) = restoreStg(stgAppFun(e));
1853 mapOver(restoreStg,stgAppArgs(e)); /* probably incorrect */
1854 if (!isAtomic(stgAppFun(e))) {
1855 newv = mkStgVar(stgAppFun(e),NIL);
1856 e = mkStgLet(singleton(newv),mkStgApp(newv,stgAppArgs(e)));
1860 mapOver(restoreStg,stgPrimArgs(e));
1863 /* note that the check in LETREC above ensures we won't
1864 get here for legitimate constructor applications. */
1865 mapOver(restoreStg,stgConArgs(e));
1866 newv = mkStgVar(e,NIL);
1867 return mkStgLet(singleton(newv),newv);
1870 stgCaseAltBody(e) = restoreStg(stgCaseAltBody(e));
1871 if (whatIsStg(stgCaseAltBody(e))==LAMBDA) {
1872 newv = mkStgVar(stgCaseAltBody(e),NIL);
1873 stgCaseAltBody(e) = mkStgLet(singleton(newv),newv);
1877 stgDefaultBody(e) = restoreStg(stgDefaultBody(e));
1878 if (whatIsStg(stgDefaultBody(e))==LAMBDA) {
1879 newv = mkStgVar(stgDefaultBody(e),NIL);
1880 stgDefaultBody(e) = mkStgLet(singleton(newv),newv);
1884 stgPrimAltBody(e) = restoreStg(stgPrimAltBody(e));
1895 fprintf(stderr, "restoreStg: unknown stuff %d\n",whatIsStg(e));
1904 StgExpr restoreStgTop ( StgExpr e )
1906 if (whatIs(e)==LAMBDA)
1907 stgLambdaBody(e) = restoreStg(stgLambdaBody(e)); else
1913 void simplTopRefs ( StgExpr e )
1917 switch(whatIsStg(e)) {
1918 /* the only interesting case */
1920 if (name(e).inlineMe && !name(e).simplified) {
1921 /* printf("\n((%d)) request for %s\n",rDepth, textToStr(name(e).text)); */
1922 name(e).simplified = TRUE;
1923 optimiseTopBind(name(e).stgVar);
1924 /* printf("((%d)) done for %s\n",rDepth, textToStr(name(e).text)); */
1928 simplTopRefs(stgLetBody(e));
1929 for (bs=stgLetBinds(e); nonNull(bs); bs=tl(bs))
1930 simplTopRefs(stgVarBody(hd(bs)));
1933 simplTopRefs(stgLambdaBody(e));
1936 simplTopRefs(stgCaseScrut(e));
1937 mapProc(simplTopRefs,stgCaseAlts(e));
1940 simplTopRefs(stgPrimCaseScrut(e));
1941 mapProc(simplTopRefs,stgPrimCaseAlts(e));
1944 simplTopRefs(stgAppFun(e));
1945 mapProc(simplTopRefs,stgAppArgs(e));
1948 mapProc(simplTopRefs,stgConArgs(e));
1951 simplTopRefs(stgPrimOp(e));
1952 mapProc(simplTopRefs,stgPrimArgs(e));
1955 simplTopRefs(stgCaseAltBody(e));
1958 simplTopRefs(stgDefaultBody(e));
1961 simplTopRefs(stgPrimAltBody(e));
1973 fprintf(stderr, "simplTopRefs: unknown stuff %d\n",whatIsStg(e));
1982 char* maybeName ( StgVar v )
1984 Name n = nameFromStgVar(v);
1985 if (isNull(n)) return "(unknown)";
1986 return textToStr(name(n).text);
1990 /* --------------------------------------------------------------------------
1991 * Sanity checking (weak :-(
1992 * ------------------------------------------------------------------------*/
1996 int stgSanity_checkStack ( StgVar v )
2000 for (i = 0; i <= sp; i++)
2001 if (stack(i)==v) j++;
2005 void stgSanity_dropVar ( StgVar v )
2010 void stgSanity_pushVar ( StgVar v )
2012 if (stgSanity_checkStack(v) != 0) stgError = TRUE;
2017 void stgSanity ( StgExpr e )
2021 switch(whatIsStg(e)) {
2023 mapProc(stgSanity_pushVar,stgLetBinds(e));
2024 stgSanity(stgLetBody(e));
2025 for (bs=stgLetBinds(e); nonNull(bs); bs=tl(bs))
2026 stgSanity(stgVarBody(hd(bs)));
2027 mapProc(stgSanity_dropVar,stgLetBinds(e));
2030 mapProc(stgSanity_pushVar,stgLambdaArgs(e));
2031 stgSanity(stgLambdaBody(e));
2032 mapProc(stgSanity_dropVar,stgLambdaArgs(e));
2035 stgSanity(stgCaseScrut(e));
2036 mapProc(stgSanity,stgCaseAlts(e));
2039 stgSanity(stgPrimCaseScrut(e));
2040 mapProc(stgSanity,stgPrimCaseAlts(e));
2043 stgSanity(stgAppFun(e));
2044 mapProc(stgSanity,stgAppArgs(e));
2047 stgSanity(stgConCon(e));
2048 mapProc(stgSanity,stgConArgs(e));
2051 stgSanity(stgPrimOp(e));
2052 mapProc(stgSanity,stgPrimArgs(e));
2055 mapProc(stgSanity_pushVar,stgCaseAltVars(e));
2056 stgSanity(stgCaseAltBody(e));
2057 mapProc(stgSanity_dropVar,stgCaseAltVars(e));
2060 stgSanity_pushVar(stgDefaultVar(e));
2061 stgSanity(stgDefaultBody(e));
2062 stgSanity_dropVar(stgDefaultVar(e));
2065 mapProc(stgSanity_pushVar,stgPrimAltVars(e));
2066 stgSanity(stgPrimAltBody(e));
2067 mapProc(stgSanity_dropVar,stgPrimAltVars(e));
2070 if (stgSanity_checkStack(e) == 1) break;
2071 if (nonNull(nameFromStgVar(e))) return;
2082 fprintf(stderr, "stgSanity: unknown stuff %d\n",whatIsStg(e));
2092 void stgTopSanity ( char* caller, StgExpr e )
2101 fprintf(stderr, "\n\nstgTopSanity (caller = %s):\n\n", caller );
2109 /* Check if e is in a form which the code generator can deal with.
2110 * stgexpr-ness is what we need to enforce. The extended version,
2111 * expr, may only occur as the rhs of a let binding.
2113 * stgexpr ::= case atom of alts
2114 * | case# primop{atom*} of primalts
2115 * | let v_i = expr_i in stgexpr
2122 * alt ::= con vars -> stgexpr (primalt and default similarly)
2124 * atom ::= var | int | char etc (unboxed, that is)
2126 Bool isStgExpr ( StgExpr e );
2127 Bool isStgFullExpr ( StgExpr e );
2129 Bool isStgExpr ( StgExpr e )
2132 switch (whatIs(e)) {
2137 for (bs=stgLetBinds(e); nonNull(bs); bs=tl(bs))
2138 if (!isStgFullExpr(stgVarBody(hd(bs))))
2140 return isStgExpr(stgLetBody(e));
2142 for (bs=stgCaseAlts(e); nonNull(bs); bs=tl(bs))
2143 if (!isStgExpr(hd(bs))) return FALSE;
2144 return isAtomic(stgCaseScrut(e));
2146 for (bs=stgPrimCaseAlts(e); nonNull(bs); bs=tl(bs))
2147 if (!isStgExpr(hd(bs))) return FALSE;
2148 if (isAtomic(stgPrimCaseScrut(e))) return TRUE;
2149 if (whatIs(stgPrimCaseScrut(e))==STGPRIM)
2150 return isStgExpr(stgPrimCaseScrut(e));
2156 for (bs=stgAppArgs(e); nonNull(bs); bs=tl(bs))
2157 if (!isAtomic(hd(bs))) return FALSE;
2158 if (isStgVar(stgAppFun(e)) || isName(stgAppFun(e))) return TRUE;
2161 for (bs=stgPrimArgs(e); nonNull(bs); bs=tl(bs))
2162 if (!isAtomic(hd(bs))) return FALSE;
2163 if (isName(stgPrimOp(e))) return TRUE;
2166 return isStgExpr(stgCaseAltBody(e));
2168 return isStgExpr(stgDefaultBody(e));
2170 return isStgExpr(stgPrimAltBody(e));
2177 Bool isStgFullExpr ( StgExpr e )
2180 switch (whatIs(e)) {
2182 return isStgExpr(stgLambdaBody(e));
2184 for (bs=stgConArgs(e); nonNull(bs); bs=tl(bs))
2185 if (!isAtomic(hd(bs))) return FALSE;
2186 if (isName(stgConCon(e)) || isTuple(stgConCon(e)))
2190 return isStgExpr(e);
2195 /* --------------------------------------------------------------------------
2197 * ------------------------------------------------------------------------*/
2199 /* Set ddumpSimpl to TRUE if you want to see simplified code. */
2200 static Bool ddumpSimpl = FALSE;
2202 /* Leave this one alone ... */
2206 static void local optimiseTopBind( StgVar v )
2208 /* Bool ppPrel = FALSE; */
2211 Int oldSize, newSize;
2214 /* printf( "[[%d]] looking at %s\n", rDepth, maybeName(v)); */
2215 assert(whatIsStg(v)==STGVAR);
2218 if (nonNull(stgVarBody(v))) simplTopRefs(stgVarBody(v));
2222 //me= 0&& 0==strcmp("tcUnify",maybeName(v));
2223 me= 0&& 0==strcmp("ttt",maybeName(v));
2225 nTotSizeIn += stgSize(stgVarBody(v));
2227 printf( "%28s: in %4d ", maybeName(v),stgSize(stgVarBody(v)));
2232 naam = nameFromStgVar(v);
2233 if (nonNull(naam) && name(naam).isDBuilder) inDBuilder = TRUE;
2236 if (nonNull(naam)) {
2237 assert(name(naam).stgSize == stgSize(stgVarBody(name(naam).stgVar)));
2242 fflush(stdout); fflush(stderr);
2243 fprintf ( stderr, "{{%d}}-----------------------------\n", -v );fflush(stderr);
2244 printStg ( stderr, v );
2245 fprintf(stderr, "\n" );
2248 stgTopSanity ( "initial", stgVarBody(v));
2250 if (nonNull(stgVarBody(v))) {
2253 for (n = 0; n < 8; n++) { // originally 7
2254 if (noisy) printf("%4d", stgSize(stgVarBody(v)));
2255 copyInTopvar = TRUE;
2256 stgTopSanity ( "outer-1", stgVarBody(v));
2258 stgTopSanity ( "outer-2", stgVarBody(v));
2259 stgVarBody(v) = copyIn ( NIL, CTX_OTHER, stgVarBody(v) );
2260 stgTopSanity ( "outer-3", stgVarBody(v));
2261 stgVarBody(v) = simplify ( NIL, stgVarBody(v) );
2262 stgTopSanity ( "outer-4", stgVarBody(v));
2264 for (m = 0; m < 3; m++) { // oprignally 3
2265 if (noisy) printf(".");
2267 copyInTopvar = FALSE;
2268 stgTopSanity ( "inner-1", stgVarBody(v));
2270 stgTopSanity ( "inner-2", stgVarBody(v));
2271 stgVarBody(v) = copyIn ( NIL, CTX_OTHER, stgVarBody(v) );
2272 stgTopSanity ( "inner-3", stgVarBody(v));
2273 stgVarBody(v) = simplify ( NIL, stgVarBody(v) );
2276 fprintf(stderr,"\n-%d- - - - - - - - - - - - - -\n", n+1);
2277 printStg ( stderr,v );
2279 stgTopSanity ( "inner-post", stgVarBody(v));
2284 fprintf(stderr,"\n-%d-=-=-=-=-=-=-=-=-=-=-=-=-=-\n", n+1);
2285 printStg ( stderr,v );
2288 stgTopSanity ( "outer-post", stgVarBody(v));
2290 newSize = stgSize ( stgVarBody(v) );
2291 if (newSize == oldSize) break;
2294 n++; for (; n < 8; n++) for (m = 0; m <= 3+3; m++) if (noisy) printf ( " " );
2295 if (noisy) printf(" --> %4d\n", stgSize(stgVarBody(v)) );
2296 stgVarBody(v) = restoreStgTop ( stgVarBody(v) );
2298 if (nonNull(naam)) {
2299 assert(name(naam).stgVar == v);
2300 name(naam).stgSize = stgSize(stgVarBody(v));
2305 if (!isStgFullExpr(stgVarBody(v))) {
2306 fprintf(stderr, "\n\nrestoreStg failed!\n\n" );
2307 printStg(stderr, v);
2308 fprintf(stderr, "\n" );
2314 nTotSizeOut += stgSize(stgVarBody(v));
2317 fprintf(stderr,"\n=============================\n");
2318 printStg ( stderr,v );
2319 fprintf(stderr, "\n\n" );
2326 void optimiseTopBinds ( List bs )
2332 noisy = ddumpSimpl && (lastModule() != modulePrelude);
2335 if (noisy) printf("\n");
2338 for (t = bs; nonNull(t); t=tl(t)) {
2339 n = nameFromStgVar(hd(t));
2340 if (isNull(n) || !name(n).simplified) {
2342 optimiseTopBind(hd(t));
2346 if (noisy) printOptStats ( stderr );
2351 /* --------------------------------------------------------------------------
2352 * Optimiser control:
2353 * ------------------------------------------------------------------------*/
2355 Void optimiser(what)
2360 case RESET : spClone = SP_NOT_IN_USE;
2365 case MARK : markPairs();
2370 case GCDONE : checkStgVarSets();
2375 /*-------------------------------------------------------------------------*/