[llvm-commits] [parallel] CVS: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/LICENSE.TXT Makefile ansi.h cofactor.c cols.c compl.c contain.c copyright.h cubestr.c cvrin.c cvrm.c cvrmisc.c cvrout.c dominate.c equiv.c espresso.c espresso.h essen.c exact.c expand.c gasp.c getopt.c gimpel.c globals.c hack.c indep.c irred.c main.c main.h map.c matrix.c mincov.c mincov.h mincov_int.h opo.c pair.c part.c port.h primes.c reduce.c rows.c set.c setc.c sharp.c sminterf.c solution.c sparse.c sparse.h sparse_int.h stdlib.h unate.c utility.c utility.h verify.c

Misha Brukman brukman at cs.uiuc.edu
Mon Mar 1 21:31:47 PST 2004


Changes in directory llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso:

LICENSE.TXT added (r1.1.2.1)
Makefile added (r1.2.2.1)
ansi.h added (r1.1.2.1)
cofactor.c added (r1.1.2.1)
cols.c added (r1.1.2.1)
compl.c added (r1.1.2.1)
contain.c added (r1.1.2.1)
copyright.h added (r1.1.2.1)
cubestr.c added (r1.1.2.1)
cvrin.c added (r1.1.2.1)
cvrm.c added (r1.1.2.1)
cvrmisc.c added (r1.1.2.1)
cvrout.c added (r1.1.2.1)
dominate.c added (r1.1.2.1)
equiv.c added (r1.1.2.1)
espresso.c added (r1.1.2.1)
espresso.h added (r1.1.2.1)
essen.c added (r1.1.2.1)
exact.c added (r1.1.2.1)
expand.c added (r1.1.2.1)
gasp.c added (r1.1.2.1)
getopt.c added (r1.1.2.1)
gimpel.c added (r1.1.2.1)
globals.c added (r1.1.2.1)
hack.c added (r1.1.2.1)
indep.c added (r1.1.2.1)
irred.c added (r1.1.2.1)
main.c added (r1.1.2.1)
main.h added (r1.1.2.1)
map.c added (r1.1.2.1)
matrix.c added (r1.1.2.1)
mincov.c added (r1.1.2.1)
mincov.h added (r1.1.2.1)
mincov_int.h added (r1.1.2.1)
opo.c added (r1.1.2.1)
pair.c added (r1.1.2.1)
part.c added (r1.1.2.1)
port.h added (r1.1.2.1)
primes.c added (r1.1.2.1)
reduce.c added (r1.1.2.1)
rows.c added (r1.1.2.1)
set.c added (r1.1.2.1)
setc.c added (r1.1.2.1)
sharp.c added (r1.1.2.1)
sminterf.c added (r1.1.2.1)
solution.c added (r1.1.2.1)
sparse.c added (r1.1.2.1)
sparse.h added (r1.1.2.1)
sparse_int.h added (r1.1.2.1)
stdlib.h added (r1.1.2.1)
unate.c added (r1.1.2.1)
utility.c added (r1.1.2.1)
utility.h added (r1.1.2.1)
verify.c added (r1.1.2.1)

---
Log message:

Merge from trunk

---
Diffs of the changes:  (+14998 -0)

Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/LICENSE.TXT
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/LICENSE.TXT:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/LICENSE.TXT	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,35 ----
+ espresso - Part of the Malloc Benchmark Suite
+ -------------------------------------------------------------------------------
+ All files are licensed under the LLVM license with the following additional
+ copyrights and restrictions:
+ 
+ Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
+ All Rights Reserved.
+ 
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for educational, research and non-profit purposes, without fee,
+ and without a written agreement is hereby granted, provided that the above
+ copyright notice, this paragraph and the following three paragraphs appear in
+ all copies.
+ 
+ Permission to incorporate this software into commercial products may be
+ obtained by contacting the University of California.
+ 
+ This software program and documentation are copyrighted by The Regents of the
+ University of California. The software program and documentation are supplied
+ "as is", without any accompanying services from The Regents. The Regents does
+ not warrant that the operation of the program will be uninterrupted or
+ error-free. The end-user understands that the program was developed for
+ research purposes and is advised not to rely exclusively on the program for any
+ reason.
+ 
+ IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+ DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
+ PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+ BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
+ THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
+ UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ 


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/Makefile
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/Makefile:1.2.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/Makefile	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,5 ----
+ LEVEL = ../../../../../..
+ PROG = espresso
+ CPPFLAGS += -DNOMEMOPT
+ RUN_OPTIONS = -t $(BUILD_SRC_DIR)/INPUT/mlp4.espresso
+ include ../../../Makefile.multisrc


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/ansi.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/ansi.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/ansi.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,44 ----
+ #ifndef ANSI_H
+ #define ANSI_H
+ 
+ /*
+  * ANSI Compiler Support
+  *
+  * David Harrison
+  * University of California, Berkeley
+  * 1988
+  *
+  * ANSI compatible compilers are supposed to define the preprocessor
+  * directive __STDC__.  Based on this directive, this file defines
+  * certain ANSI specific macros.
+  *
+  * ARGS:
+  *   Used in function prototypes.  Example:
+  *   extern int foo
+  *     ARGS((char *blah, double threshold));
+  */
+ 
+ /* Function prototypes */
+ #if defined(__STDC__) || defined(__cplusplus)
+ #define ARGS(args)	args
+ #else
+ #define ARGS(args)	()
+ #endif
+ 
+ #if defined(__cplusplus)
+ #define NULLARGS	(void)
+ #else
+ #define NULLARGS	()
+ #endif
+ 
+ #ifdef __cplusplus
+ #define EXTERN extern "C"
+ #else
+ #define EXTERN extern
+ #endif
+ 
+ #if defined(__cplusplus) || defined(__STDC__) 
+ #define HAS_STDARG
+ #endif
+ 
+ #endif


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cofactor.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cofactor.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cofactor.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,373 ----
+ #include "espresso.h"
+ 
+ /*
+     The cofactor of a cover against a cube "c" is a cover formed by the
+     cofactor of each cube in the cover against c.  The cofactor of two
+     cubes is null if they are distance 1 or more apart.  If they are
+     distance zero apart, the cofactor is the restriction of the cube
+     to the minterms of c.
+ 
+     The cube list contains the following information:
+ 
+ 	T[0] = pointer to a cube identifying the variables that have
+ 		been cofactored against
+ 	T[1] = pointer to just beyond the sentinel (i.e., T[n] in this case)
+ 	T[2]
+ 	  .
+ 	  .  = pointers to cubes
+ 	  .
+ 	T[n-2]
+ 	T[n-1] = NULL pointer (sentinel)
+ 
+ 
+     Cofactoring involves repeated application of "cdist0" to check if a
+     cube of the cover intersects the cofactored cube.  This can be
+     slow, especially for the recursive descent of the espresso
+     routines.  Therefore, a special cofactor routine "scofactor" is
+     provided which assumes the cofactor is only in a single variable.
+ */
+ 
+ 
+ /* cofactor -- compute the cofactor of a cover with respect to a cube */
+ pcube *cofactor(T, c)
+ IN pcube *T;
+ IN register pcube c;
+ {
+     pcube temp = cube.temp[0], *Tc_save, *Tc, *T1;
+     register pcube p;
+     int listlen;
+ 
+     listlen = CUBELISTSIZE(T) + 5;
+ 
+     /* Allocate a new list of cube pointers (max size is previous size) */
+     Tc_save = Tc = ALLOC(pcube, listlen);
+ 
+     /* pass on which variables have been cofactored against */
+     *Tc++ = set_or(new_cube(), T[0], set_diff(temp, cube.fullset, c));
+     Tc++;
+ 
+     /* Loop for each cube in the list, determine suitability, and save */
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	if (p != c) {
+ 
+ #ifdef NO_INLINE
+ 	if (! cdist0(p, c)) goto false;
+ #else
+     {register int w,last;register unsigned int x;if((last=cube.inword)!=-1)
+     {x=p[last]&c[last];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<last;w++)
+     {x=p[w]&c[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,last;
+     register pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){
+     mask=cube.var_mask[var];last=cube.last_word[var];for(w=cube.first_word[var
+     ];w<=last;w++)if(p[w]&c[w]&mask[w])goto nextvar;goto false;nextvar:;}}
+ #endif
+ 
+ 	    *Tc++ = p;
+ 	false: ;
+ 	}
+     }
+ 
+     *Tc++ = (pcube) NULL;                       /* sentinel */
+     Tc_save[1] = (pcube) Tc;                    /* save pointer to last */
+     return Tc_save;
+ }
+ 
+ /*
+     scofactor -- compute the cofactor of a cover with respect to a cube,
+     where the cube is "active" in only a single variable.
+ 
+     This routine has been optimized for speed.
+ */
+ 
+ pcube *scofactor(T, c, var)
+ IN pcube *T, c;
+ IN int var;
+ {
+     pcube *Tc, *Tc_save;
+     register pcube p, mask = cube.temp[1], *T1;
+     register int first = cube.first_word[var], last = cube.last_word[var];
+     int listlen;
+ 
+     listlen = CUBELISTSIZE(T) + 5;
+ 
+     /* Allocate a new list of cube pointers (max size is previous size) */
+     Tc_save = Tc = ALLOC(pcube, listlen);
+ 
+     /* pass on which variables have been cofactored against */
+     *Tc++ = set_or(new_cube(), T[0], set_diff(mask, cube.fullset, c));
+     Tc++;
+ 
+     /* Setup for the quick distance check */
+     (void) set_and(mask, cube.var_mask[var], c);
+ 
+     /* Loop for each cube in the list, determine suitability, and save */
+     for(T1 = T+2; (p = *T1++) != NULL; )
+ 	if (p != c) {
+ 	    register int i = first;
+ 	    do
+ 		if (p[i] & mask[i]) {
+ 		    *Tc++ = p;
+ 		    break;
+ 		}
+ 	    while (++i <= last);
+ 	}
+ 
+     *Tc++ = (pcube) NULL;                       /* sentinel */
+     Tc_save[1] = (pcube) Tc;                    /* save pointer to last */
+     return Tc_save;
+ }
+ 
+ void massive_count(T)
+ IN pcube *T;
+ {
+     int *count = cdata.part_zeros;
+     pcube *T1;
+ 
+     /* Clear the column counts (count of # zeros in each column) */
+  {  register int i;
+     for(i = cube.size - 1; i >= 0; i--)
+ 	count[i] = 0;
+  }
+ 
+     /* Count the number of zeros in each column */
+  {  register int i, *cnt;
+     register unsigned int val;
+     register pcube p, cof = T[0], full = cube.fullset;
+     for(T1 = T+2; (p = *T1++) != NULL; )
+ 	for(i = LOOP(p); i > 0; i--)
+ 	    if (val = full[i] & ~ (p[i] | cof[i])) {
+ 		cnt = count + ((i-1) << LOGBPI);
+ #if BPI == 32
+ 	    if (val & 0xFF000000) {
+ 		if (val & 0x80000000) cnt[31]++;
+ 		if (val & 0x40000000) cnt[30]++;
+ 		if (val & 0x20000000) cnt[29]++;
+ 		if (val & 0x10000000) cnt[28]++;
+ 		if (val & 0x08000000) cnt[27]++;
+ 		if (val & 0x04000000) cnt[26]++;
+ 		if (val & 0x02000000) cnt[25]++;
+ 		if (val & 0x01000000) cnt[24]++;
+ 	    }
+ 	    if (val & 0x00FF0000) {
+ 		if (val & 0x00800000) cnt[23]++;
+ 		if (val & 0x00400000) cnt[22]++;
+ 		if (val & 0x00200000) cnt[21]++;
+ 		if (val & 0x00100000) cnt[20]++;
+ 		if (val & 0x00080000) cnt[19]++;
+ 		if (val & 0x00040000) cnt[18]++;
+ 		if (val & 0x00020000) cnt[17]++;
+ 		if (val & 0x00010000) cnt[16]++;
+ 	    }
+ #endif
+ 	    if (val & 0xFF00) {
+ 		if (val & 0x8000) cnt[15]++;
+ 		if (val & 0x4000) cnt[14]++;
+ 		if (val & 0x2000) cnt[13]++;
+ 		if (val & 0x1000) cnt[12]++;
+ 		if (val & 0x0800) cnt[11]++;
+ 		if (val & 0x0400) cnt[10]++;
+ 		if (val & 0x0200) cnt[ 9]++;
+ 		if (val & 0x0100) cnt[ 8]++;
+ 	    }
+ 	    if (val & 0x00FF) {
+ 		if (val & 0x0080) cnt[ 7]++;
+ 		if (val & 0x0040) cnt[ 6]++;
+ 		if (val & 0x0020) cnt[ 5]++;
+ 		if (val & 0x0010) cnt[ 4]++;
+ 		if (val & 0x0008) cnt[ 3]++;
+ 		if (val & 0x0004) cnt[ 2]++;
+ 		if (val & 0x0002) cnt[ 1]++;
+ 		if (val & 0x0001) cnt[ 0]++;
+ 	    }
+ 	}
+  }
+ 
+     /*
+      * Perform counts for each variable:
+      *    cdata.var_zeros[var] = number of zeros in the variable
+      *    cdata.parts_active[var] = number of active parts for each variable
+      *    cdata.vars_active = number of variables which are active
+      *    cdata.vars_unate = number of variables which are active and unate
+      *
+      *    best -- the variable which is best for splitting based on:
+      *    mostactive -- most # active parts in any variable
+      *    mostzero -- most # zeros in any variable
+      *    mostbalanced -- minimum over the maximum # zeros / part / variable
+      */
+ 
+  {  register int var, i, lastbit, active, maxactive;
+     int best = -1, mostactive = 0, mostzero = 0, mostbalanced = 32000;
+     cdata.vars_unate = cdata.vars_active = 0;
+ 
+     for(var = 0; var < cube.num_vars; var++) {
+ 	if (var < cube.num_binary_vars) { /* special hack for binary vars */
+ 	    i = count[var*2];
+ 	    lastbit = count[var*2 + 1];
+ 	    active = (i > 0) + (lastbit > 0);
+ 	    cdata.var_zeros[var] = i + lastbit;
+ 	    maxactive = MAX(i, lastbit);
+ 	} else {
+ 	    maxactive = active = cdata.var_zeros[var] = 0;
+ 	    lastbit = cube.last_part[var];
+ 	    for(i = cube.first_part[var]; i <= lastbit; i++) {
+ 		cdata.var_zeros[var] += count[i];
+ 		active += (count[i] > 0);
+ 		if (active > maxactive) maxactive = active;
+ 	    }
+ 	}
+ 
+ 	/* first priority is to maximize the number of active parts */
+ 	/* for binary case, this will usually select the output first */
+ 	if (active > mostactive)
+ 	    best = var, mostactive = active, mostzero = cdata.var_zeros[best],
+ 	    mostbalanced = maxactive;
+ 	else if (active == mostactive)
+ 	    /* secondary condition is to maximize the number zeros */
+ 	    /* for binary variables, this is the same as minimum # of 2's */
+ 	    if (cdata.var_zeros[var] > mostzero)
+ 		best = var, mostzero = cdata.var_zeros[best],
+ 		mostbalanced = maxactive;
+ 	    else if (cdata.var_zeros[var] == mostzero)
+ 		/* third condition is to pick a balanced variable */
+ 		/* for binary vars, this means roughly equal # 0's and 1's */
+ 		if (maxactive < mostbalanced)
+ 		    best = var, mostbalanced = maxactive;
+ 
+ 	cdata.parts_active[var] = active;
+ 	cdata.is_unate[var] = (active == 1);
+ 	cdata.vars_active += (active > 0);
+ 	cdata.vars_unate += (active == 1);
+     }
+     cdata.best = best;
+  }
+ }
+ 
+ int binate_split_select(T, cleft, cright, debug_flag)
+ IN pcube *T;
+ IN register pcube cleft, cright;
+ IN int debug_flag;
+ {
+     int best = cdata.best;
+     register int i, lastbit = cube.last_part[best], halfbit = 0;
+     register pcube cof=T[0];
+ 
+     /* Create the cubes to cofactor against */
+     set_diff(cleft, cube.fullset, cube.var_mask[best]);
+     set_diff(cright, cube.fullset, cube.var_mask[best]);
+     for(i = cube.first_part[best]; i <= lastbit; i++)
+ 	if (! is_in_set(cof,i))
+ 	    halfbit++;
+     for(i = cube.first_part[best], halfbit = halfbit/2; halfbit > 0; i++)
+ 	if (! is_in_set(cof,i))
+ 	    halfbit--, set_insert(cleft, i);
+     for(; i <= lastbit; i++)
+ 	if (! is_in_set(cof,i))
+ 	    set_insert(cright, i);
+ 
+     if (debug & debug_flag) {
+ 	printf("BINATE_SPLIT_SELECT: split against %d\n", best);
+ 	if (verbose_debug)
+ 	    printf("cl=%s\ncr=%s\n", pc1(cleft), pc2(cright));
+     }
+     return best;
+ }
+ 
+ 
+ pcube *cube1list(A)
+ pcover A;
+ {
+     register pcube last, p, *plist, *list;
+ 
+     list = plist = ALLOC(pcube, A->count + 3);
+     *plist++ = new_cube();
+     plist++;
+     foreach_set(A, last, p) {
+ 	*plist++ = p;
+     }
+     *plist++ = NULL;                    /* sentinel */
+     list[1] = (pcube) plist;
+     return list;
+ }
+ 
+ 
+ pcube *cube2list(A, B)
+ pcover A, B;
+ {
+     register pcube last, p, *plist, *list;
+ 
+     list = plist = ALLOC(pcube, A->count + B->count + 3);
+     *plist++ = new_cube();
+     plist++;
+     foreach_set(A, last, p) {
+ 	*plist++ = p;
+     }
+     foreach_set(B, last, p) {
+ 	*plist++ = p;
+     }
+     *plist++ = NULL;
+     list[1] = (pcube) plist;
+     return list;
+ }
+ 
+ 
+ pcube *cube3list(A, B, C)
+ pcover A, B, C;
+ {
+     register pcube last, p, *plist, *list;
+ 
+     plist = ALLOC(pcube, A->count + B->count + C->count + 3);
+     list = plist;
+     *plist++ = new_cube();
+     plist++;
+     foreach_set(A, last, p) {
+ 	*plist++ = p;
+     }
+     foreach_set(B, last, p) {
+ 	*plist++ = p;
+     }
+     foreach_set(C, last, p) {
+ 	*plist++ = p;
+     }
+     *plist++ = NULL;
+     list[1] = (pcube) plist;
+     return list;
+ }
+ 
+ 
+ pcover cubeunlist(A1)
+ pcube *A1;
+ {
+     register int i;
+     register pcube p, pdest, cof = A1[0];
+     register pcover A;
+ 
+     A = new_cover(CUBELISTSIZE(A1));
+     for(i = 2; (p = A1[i]) != NULL; i++) {
+ 	pdest = GETSET(A, i-2);
+ 	INLINEset_or(pdest, p, cof);
+     }
+     A->count = CUBELISTSIZE(A1);
+     return A;
+ }
+ 
+ simplify_cubelist(T)
+ pcube *T;
+ {
+     register pcube *Tdest;
+     register int i, ncubes;
+ 
+     set_copy(cube.temp[0], T[0]);		/* retrieve cofactor */
+ 
+     ncubes = CUBELISTSIZE(T);
+     qsort((char *) (T+2), ncubes, sizeof(pset), d1_order);
+ 
+     Tdest = T+2;
+     /*   *Tdest++ = T[2];   */
+     for(i = 3; i < ncubes; i++) {
+ 	if (d1_order(&T[i-1], &T[i]) != 0) {
+ 	    *Tdest++ = T[i];
+ 	}
+     }
+ 
+     *Tdest++ = NULL;				/* sentinel */
+     Tdest[1] = (pcube) Tdest;			/* save pointer to last */
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cols.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cols.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cols.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,305 ----
+ #include "port.h"
+ #include "sparse_int.h"
+ 
+ 
+ /*
+  *  allocate a new col vector 
+  */
+ sm_col *
+ sm_col_alloc()
+ {
+     register sm_col *pcol;
+ 
+ #ifdef FAST_AND_LOOSE
+     if (sm_col_freelist == NIL(sm_col)) {
+ 	pcol = ALLOC(sm_col, 1);
+     } else {
+ 	pcol = sm_col_freelist;
+ 	sm_col_freelist = pcol->next_col;
+     }
+ #else
+     pcol = ALLOC(sm_col, 1);
+ #endif
+ 
+     pcol->col_num = 0;
+     pcol->length = 0;
+     pcol->first_row = pcol->last_row = NIL(sm_element);
+     pcol->next_col = pcol->prev_col = NIL(sm_col);
+     pcol->flag = 0;
+     pcol->user_word = NIL(char);		/* for our user ... */
+     return pcol;
+ }
+ 
+ 
+ /*
+  *  free a col vector -- for FAST_AND_LOOSE, this is real cheap for cols;
+  *  however, freeing a rowumn must still walk down the rowumn discarding
+  *  the elements one-by-one; that is the only use for the extra '-DCOLS'
+  *  compile flag ...
+  */
+ void
+ sm_col_free(pcol)
+ register sm_col *pcol;
+ {
+ #if defined(FAST_AND_LOOSE) && ! defined(COLS)
+     if (pcol->first_row != NIL(sm_element)) {
+ 	/* Add the linked list of col items to the free list */
+ 	pcol->last_row->next_row = sm_element_freelist;
+ 	sm_element_freelist = pcol->first_row;
+     }
+ 
+     /* Add the col to the free list of cols */
+     pcol->next_col = sm_col_freelist;
+     sm_col_freelist = pcol;
+ #else
+     register sm_element *p, *pnext;
+ 
+     for(p = pcol->first_row; p != 0; p = pnext) {
+ 	pnext = p->next_row;
+ 	sm_element_free(p);
+     }
+     FREE(pcol);
+ #endif
+ }
+ 
+ 
+ /*
+  *  duplicate an existing col
+  */
+ sm_col *
+ sm_col_dup(pcol)
+ register sm_col *pcol;
+ {
+     register sm_col *pnew;
+     register sm_element *p;
+ 
+     pnew = sm_col_alloc();
+     for(p = pcol->first_row; p != 0; p = p->next_row) {
+ 	(void) sm_col_insert(pnew, p->row_num);
+     }
+     return pnew;
+ }
+ 
+ 
+ /*
+  *  insert an element into a col vector 
+  */
+ sm_element *
+ sm_col_insert(pcol, row)
+ register sm_col *pcol;
+ register int row;
+ {
+     register sm_element *test, *element;
+ 
+     /* get a new item, save its address */
+     sm_element_alloc(element);
+     test = element;
+     sorted_insert(sm_element, pcol->first_row, pcol->last_row, pcol->length, 
+ 		    next_row, prev_row, row_num, row, test);
+ 
+     /* if item was not used, free it */
+     if (element != test) {
+ 	sm_element_free(element);
+     }
+ 
+     /* either way, return the current new value */
+     return test;
+ }
+ 
+ 
+ /*
+  *  remove an element from a col vector 
+  */
+ void
+ sm_col_remove(pcol, row)
+ register sm_col *pcol;
+ register int row;
+ {
+     register sm_element *p;
+ 
+     for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+ 	;
+     if (p != 0 && p->row_num == row) {
+ 	dll_unlink(p, pcol->first_row, pcol->last_row, 
+ 			    next_row, prev_row, pcol->length);
+ 	sm_element_free(p);
+     }
+ }
+ 
+ 
+ /*
+  *  find an element (if it is in the col vector)
+  */
+ sm_element *
+ sm_col_find(pcol, row)
+ sm_col *pcol;
+ int row;
+ {
+     register sm_element *p;
+ 
+     for(p = pcol->first_row; p != 0 && p->row_num < row; p = p->next_row)
+ 	;
+     if (p != 0 && p->row_num == row) {
+ 	return p;
+     } else {
+ 	return NIL(sm_element);
+     }
+ }
+ 
+ /*
+  *  return 1 if col p2 contains col p1; 0 otherwise
+  */
+ int 
+ sm_col_contains(p1, p2)
+ sm_col *p1, *p2;
+ {
+     register sm_element *q1, *q2;
+ 
+     q1 = p1->first_row;
+     q2 = p2->first_row;
+     while (q1 != 0) {
+ 	if (q2 == 0 || q1->row_num < q2->row_num) {
+ 	    return 0;
+ 	} else if (q1->row_num == q2->row_num) {
+ 	    q1 = q1->next_row;
+ 	    q2 = q2->next_row;
+ 	} else {
+ 	    q2 = q2->next_row;
+ 	}
+     }
+     return 1;
+ }
+ 
+ 
+ /*
+  *  return 1 if col p1 and col p2 share an element in common
+  */
+ int 
+ sm_col_intersects(p1, p2)
+ sm_col *p1, *p2;
+ {
+     register sm_element *q1, *q2;
+ 
+     q1 = p1->first_row;
+     q2 = p2->first_row;
+     if (q1 == 0 || q2 == 0) return 0;
+     for(;;) {
+ 	if (q1->row_num < q2->row_num) {
+ 	    if ((q1 = q1->next_row) == 0) {
+ 		return 0;
+ 	    }
+ 	} else if (q1->row_num > q2->row_num) {
+ 	    if ((q2 = q2->next_row) == 0) {
+ 		return 0;
+ 	    }
+ 	} else {
+ 	    return 1;
+ 	}
+     }
+ }
+ 
+ 
+ /*
+  *  compare two cols, lexical ordering
+  */
+ int 
+ sm_col_compare(p1, p2)
+ sm_col *p1, *p2;
+ {
+     register sm_element *q1, *q2;
+ 
+     q1 = p1->first_row;
+     q2 = p2->first_row;
+     while(q1 != 0 && q2 != 0) {
+ 	if (q1->row_num != q2->row_num) {
+ 	    return q1->row_num - q2->row_num;
+ 	}
+ 	q1 = q1->next_row;
+ 	q2 = q2->next_row;
+     }
+ 
+     if (q1 != 0) {
+ 	return 1;
+     } else if (q2 != 0) {
+ 	return -1;
+     } else {
+ 	return 0;
+     }
+ }
+ 
+ 
+ /*
+  *  return the intersection
+  */
+ sm_col *
+ sm_col_and(p1, p2)
+ sm_col *p1, *p2;
+ {
+     register sm_element *q1, *q2;
+     register sm_col *result;
+ 
+     result = sm_col_alloc();
+     q1 = p1->first_row;
+     q2 = p2->first_row;
+     if (q1 == 0 || q2 == 0) return result;
+     for(;;) {
+ 	if (q1->row_num < q2->row_num) {
+ 	    if ((q1 = q1->next_row) == 0) {
+ 		return result;
+ 	    }
+ 	} else if (q1->row_num > q2->row_num) {
+ 	    if ((q2 = q2->next_row) == 0) {
+ 		return result;
+ 	    }
+ 	} else {
+ 	    (void) sm_col_insert(result, q1->row_num);
+ 	    if ((q1 = q1->next_row) == 0) {
+ 		return result;
+ 	    }
+ 	    if ((q2 = q2->next_row) == 0) {
+ 		return result;
+ 	    }
+ 	}
+     }
+ }
+ 
+ int 
+ sm_col_hash(pcol, modulus)
+ sm_col *pcol;
+ int modulus;
+ {
+     register int sum;
+     register sm_element *p;
+ 
+     sum = 0;
+     for(p = pcol->first_row; p != 0; p = p->next_row) {
+ 	sum = (sum*17 + p->row_num) % modulus;
+     }
+     return sum;
+ }
+ 
+ /*
+  *  remove an element from a col vector (given a pointer to the element) 
+  */
+ void
+ sm_col_remove_element(pcol, p)
+ register sm_col *pcol;
+ register sm_element *p;
+ {
+     dll_unlink(p, pcol->first_row, pcol->last_row, 
+ 			next_row, prev_row, pcol->length);
+     sm_element_free(p);
+ }
+ 
+ 
+ void
+ sm_col_print(fp, pcol)
+ FILE *fp;
+ sm_col *pcol;
+ {
+     sm_element *p;
+ 
+     for(p = pcol->first_row; p != 0; p = p->next_row) {
+ 	(void) fprintf(fp, " %d", p->row_num);
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/compl.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/compl.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/compl.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,667 ----
+ /*
+  *  module: compl.c
+  *  purpose: compute the complement of a multiple-valued function
+  *
+  *  The "unate recursive paradigm" is used.  After a set of special
+  *  cases are examined, the function is split on the "most active
+  *  variable".  These two halves are complemented recursively, and then
+  *  the results are merged.
+  *
+  *  Changes (from Version 2.1 to Version 2.2)
+  *      1. Minor bug in compl_lifting -- cubes in the left half were
+  *      not marked as active, so that when merging a leaf from the left
+  *      hand side, the active flags were essentially random.  This led
+  *      to minor impredictability problem, but never affected the
+  *      accuracy of the results.
+  */
+ 
+ #include "espresso.h"
+ 
+ #define USE_COMPL_LIFT			0
+ #define USE_COMPL_LIFT_ONSET		1
+ #define USE_COMPL_LIFT_ONSET_COMPLEX	2
+ #define NO_LIFTING			3
+ 
+ bool compl_special_cases();
+ pcover compl_merge();
+ void compl_d1merge();
+ pcover compl_cube();
+ void compl_lift();
+ void compl_lift_onset();
+ void compl_lift_onset_complex();
+ bool simp_comp_special_cases();
+ bool simplify_special_cases();
+ 
+ 
+ /* complement -- compute the complement of T */
+ pcover complement(T)
+ pcube *T;			/* T will be disposed of */
+ {
+     register pcube cl, cr;
+     register int best;
+     pcover Tbar, Tl, Tr;
+     int lifting;
+     static int compl_level = 0;
+ 
+     if (debug & COMPL)
+ 	debug_print(T, "COMPLEMENT", compl_level++);
+ 
+     if (compl_special_cases(T, &Tbar) == MAYBE) {
+ 
+ 	/* Allocate space for the partition cubes */
+ 	cl = new_cube();
+ 	cr = new_cube();
+ 	best = binate_split_select(T, cl, cr, COMPL);
+ 
+ 	/* Complement the left and right halves */
+ 	Tl = complement(scofactor(T, cl, best));
+ 	Tr = complement(scofactor(T, cr, best));
+ 
+ 	if (Tr->count*Tl->count > (Tr->count+Tl->count)*CUBELISTSIZE(T)) {
+ 	    lifting = USE_COMPL_LIFT_ONSET;
+ 	} else {
+ 	    lifting = USE_COMPL_LIFT;
+ 	}
+ 	Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+ 
+ 	free_cube(cl);
+ 	free_cube(cr);
+ 	free_cubelist(T);
+     }
+ 
+     if (debug & COMPL)
+ 	debug1_print(Tbar, "exit COMPLEMENT", --compl_level);
+     return Tbar;
+ }
+ 
+ static bool compl_special_cases(T, Tbar)
+ pcube *T;			/* will be disposed if answer is determined */
+ pcover *Tbar;			/* returned only if answer determined */
+ {
+     register pcube *T1, p, ceil, cof=T[0];
+     pcover A, ceil_compl;
+ 
+     /* Check for no cubes in the cover */
+     if (T[2] == NULL) {
+ 	*Tbar = sf_addset(new_cover(1), cube.fullset);
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for only a single cube in the cover */
+     if (T[3] == NULL) {
+ 	*Tbar = compl_cube(set_or(cof, cof, T[2]));
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for a row of all 1's (implies complement is null) */
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	if (full_row(p, cof)) {
+ 	    *Tbar = new_cover(0);
+ 	    free_cubelist(T);
+ 	    return TRUE;
+ 	}
+     }
+ 
+     /* Check for a column of all 0's which can be factored out */
+     ceil = set_save(cof);
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	INLINEset_or(ceil, ceil, p);
+     }
+     if (! setp_equal(ceil, cube.fullset)) {
+ 	ceil_compl = compl_cube(ceil);
+ 	(void) set_or(cof, cof, set_diff(ceil, cube.fullset, ceil));
+ 	set_free(ceil);
+ 	*Tbar = sf_append(complement(T), ceil_compl);
+ 	return TRUE;
+     }
+     set_free(ceil);
+ 
+     /* Collect column counts, determine unate variables, etc. */
+     massive_count(T);
+ 
+     /* If single active variable not factored out above, then tautology ! */
+     if (cdata.vars_active == 1) {
+ 	*Tbar = new_cover(0);
+ 	free_cubelist(T);
+ 	return TRUE;
+ 
+     /* Check for unate cover */
+     } else if (cdata.vars_unate == cdata.vars_active) {
+ 	A = map_cover_to_unate(T);
+ 	free_cubelist(T);
+ 	A = unate_compl(A);
+ 	*Tbar = map_unate_to_cover(A);
+ 	sf_free(A);
+ 	return TRUE;
+ 
+     /* Not much we can do about it */
+     } else {
+ 	return MAYBE;
+     }
+ }
+ 
+ /*
+  *  compl_merge -- merge the two cofactors around the splitting
+  *  variable
+  *
+  *  The merge operation involves intersecting each cube of the left
+  *  cofactor with cl, and intersecting each cube of the right cofactor
+  *  with cr.  The union of these two covers is the merged result.
+  *
+  *  In order to reduce the number of cubes, a distance-1 merge is
+  *  performed (note that two cubes can only combine distance-1 in the
+  *  splitting variable).  Also, a simple expand is performed in the
+  *  splitting variable (simple implies the covering check for the
+  *  expansion is not full containment, but single-cube containment).
+  */
+ 
+ static pcover compl_merge(T1, L, R, cl, cr, var, lifting)
+ pcube *T1;			/* Original ON-set */
+ pcover L, R;			/* Complement from each recursion branch */
+ register pcube cl, cr;		/* cubes used for cofactoring */
+ int var;			/* splitting variable */
+ int lifting;			/* whether to perform lifting or not */
+ {
+     register pcube p, last, pt;
+     pcover T, Tbar;
+     pcube *L1, *R1;
+ 
+     if (debug & COMPL) {
+ 	printf("compl_merge: left %d, right %d\n", L->count, R->count);
+ 	printf("%s (cl)\n%s (cr)\nLeft is\n", pc1(cl), pc2(cr));
+ 	cprint(L);
+ 	printf("Right is\n");
+ 	cprint(R);
+     }
+ 
+     /* Intersect each cube with the cofactored cube */
+     foreach_set(L, last, p) {
+ 	INLINEset_and(p, p, cl);
+ 	SET(p, ACTIVE);
+     }
+     foreach_set(R, last, p) {
+ 	INLINEset_and(p, p, cr);
+ 	SET(p, ACTIVE);
+     }
+ 
+     /* Sort the arrays for a distance-1 merge */
+     (void) set_copy(cube.temp[0], cube.var_mask[var]);
+     qsort((char *) (L1 = sf_list(L)), L->count, sizeof(pset), d1_order);
+     qsort((char *) (R1 = sf_list(R)), R->count, sizeof(pset), d1_order);
+ 
+     /* Perform distance-1 merge */
+     compl_d1merge(L1, R1);
+ 
+     /* Perform lifting */
+     switch(lifting) {
+ 	case USE_COMPL_LIFT_ONSET:
+ 	    T = cubeunlist(T1);
+ 	    compl_lift_onset(L1, T, cr, var);
+ 	    compl_lift_onset(R1, T, cl, var);
+ 	    free_cover(T);
+ 	    break;
+ 	case USE_COMPL_LIFT_ONSET_COMPLEX:
+ 	    T = cubeunlist(T1);
+ 	    compl_lift_onset_complex(L1, T, var);
+ 	    compl_lift_onset_complex(R1, T, var);
+ 	    free_cover(T);
+ 	    break;
+ 	case USE_COMPL_LIFT:
+ 	    compl_lift(L1, R1, cr, var);
+ 	    compl_lift(R1, L1, cl, var);
+ 	    break;
+ 	case NO_LIFTING:
+ 	    break;
+     }
+     FREE(L1);
+     FREE(R1);
+ 
+     /* Re-create the merged cover */
+     Tbar = new_cover(L->count + R->count);
+     pt = Tbar->data;
+     foreach_set(L, last, p) {
+ 	INLINEset_copy(pt, p);
+ 	Tbar->count++;
+ 	pt += Tbar->wsize;
+     }
+     foreach_active_set(R, last, p) {
+ 	INLINEset_copy(pt, p);
+ 	Tbar->count++;
+ 	pt += Tbar->wsize;
+     }
+ 
+     if (debug & COMPL) {
+ 	printf("Result %d\n", Tbar->count);
+ 	if (verbose_debug)
+ 	    cprint(Tbar);
+     }
+ 
+     free_cover(L);
+     free_cover(R);
+     return Tbar;
+ }
+ 
+ /*
+  *  compl_lift_simple -- expand in the splitting variable using single
+  *  cube containment against the other recursion branch to check
+  *  validity of the expansion, and expanding all (or none) of the
+  *  splitting variable.
+  */
+ static void compl_lift(A1, B1, bcube, var)
+ pcube *A1, *B1, bcube;
+ int var;
+ {
+     register pcube a, b, *B2, lift=cube.temp[4], liftor=cube.temp[5];
+     pcube mask = cube.var_mask[var];
+ 
+     (void) set_and(liftor, bcube, mask);
+ 
+     /* for each cube in the first array ... */
+     for(; (a = *A1++) != NULL; ) {
+ 	if (TESTP(a, ACTIVE)) {
+ 
+ 	    /* create a lift of this cube in the merging coord */
+ 	    (void) set_merge(lift, bcube, a, mask);
+ 
+ 	    /* for each cube in the second array */
+ 	    for(B2 = B1; (b = *B2++) != NULL; ) {
+ 		INLINEsetp_implies(lift, b, /* when_false => */ continue);
+ 		/* when_true => fall through to next statement */
+ 
+ 		/* cube of A1 was contained by some cube of B1, so raise */
+ 		INLINEset_or(a, a, liftor);
+ 		break;
+ 	    }
+ 	}
+     }
+ }
+ 
+ 
+ 
+ /*
+  *  compl_lift_onset -- expand in the splitting variable using a
+  *  distance-1 check against the original on-set; expand all (or
+  *  none) of the splitting variable.  Each cube of A1 is expanded
+  *  against the original on-set T.
+  */
+ static void compl_lift_onset(A1, T, bcube, var)
+ pcube *A1;
+ pcover T;
+ pcube bcube;
+ int var;
+ {
+     register pcube a, last, p, lift=cube.temp[4], mask=cube.var_mask[var];
+ 
+     /* for each active cube from one branch of the complement */
+     for(; (a = *A1++) != NULL; ) {
+ 	if (TESTP(a, ACTIVE)) {
+ 
+ 	    /* create a lift of this cube in the merging coord */
+ 	    INLINEset_and(lift, bcube, mask);	/* isolate parts to raise */
+ 	    INLINEset_or(lift, a, lift);	/* raise these parts in a */
+ 
+ 	    /* for each cube in the ON-set, check for intersection */
+ 	    foreach_set(T, last, p) {
+ 		if (cdist0(p, lift)) {
+ 		    goto nolift;
+ 		}
+ 	    }
+ 	    INLINEset_copy(a, lift);		/* save the raising */
+ 	    SET(a, ACTIVE);
+ nolift : ;
+ 	}
+     }
+ }
+ 
+ /*
+  *  compl_lift_complex -- expand in the splitting variable, but expand all
+  *  parts which can possibly expand.
+  *  T is the original ON-set
+  *  A1 is either the left or right cofactor
+  */
+ static void compl_lift_onset_complex(A1, T, var)
+ pcube *A1;			/* array of pointers to new result */
+ pcover T;			/* original ON-set */
+ int var;			/* which variable we split on */
+ {
+     register int dist;
+     register pcube last, p, a, xlower;
+ 
+     /* for each cube in the complement */
+     xlower = new_cube();
+     for(; (a = *A1++) != NULL; ) {
+ 
+ 	if (TESTP(a, ACTIVE)) {
+ 
+ 	    /* Find which parts of the splitting variable are forced low */
+ 	    INLINEset_clear(xlower, cube.size);
+ 	    foreach_set(T, last, p) {
+ 		if ((dist = cdist01(p, a)) < 2) {
+ 		    if (dist == 0) {
+ 			fatal("compl: ON-set and OFF-set are not orthogonal");
+ 		    } else {
+ 			(void) force_lower(xlower, p, a);
+ 		    }
+ 		}
+ 	    }
+ 
+ 	    (void) set_diff(xlower, cube.var_mask[var], xlower);
+ 	    (void) set_or(a, a, xlower);
+ 	    free_cube(xlower);
+ 	}
+     }
+ }
+ 
+ 
+ 
+ /*
+  *  compl_d1merge -- distance-1 merge in the splitting variable
+  */
+ static void compl_d1merge(L1, R1)
+ register pcube *L1, *R1;
+ {
+     register pcube pl, pr;
+ 
+     /* Find equal cubes between the two cofactors */
+     for(pl = *L1, pr = *R1; (pl != NULL) && (pr != NULL); )
+ 	switch (d1_order(L1, R1)) {
+ 	    case 1:
+ 		pr = *(++R1); break;            /* advance right pointer */
+ 	    case -1:
+ 		pl = *(++L1); break;            /* advance left pointer */
+ 	    case 0:
+ 		RESET(pr, ACTIVE);
+ 		INLINEset_or(pl, pl, pr);
+ 		pr = *(++R1);
+ 	}
+ }
+ 
+ 
+ 
+ /* compl_cube -- return the complement of a single cube (De Morgan's law) */
+ static pcover compl_cube(p)
+ register pcube p;
+ {
+     register pcube diff=cube.temp[7], pdest, mask, full=cube.fullset;
+     int var;
+     pcover R;
+ 
+     /* Allocate worst-case size cover (to avoid checking overflow) */
+     R = new_cover(cube.num_vars);
+ 
+     /* Compute bit-wise complement of the cube */
+     INLINEset_diff(diff, full, p);
+ 
+     for(var = 0; var < cube.num_vars; var++) {
+ 	mask = cube.var_mask[var];
+ 	/* If the bit-wise complement is not empty in var ... */
+ 	if (! setp_disjoint(diff, mask)) {
+ 	    pdest = GETSET(R, R->count++);
+ 	    INLINEset_merge(pdest, diff, full, mask);
+ 	}
+     }
+     return R;
+ }
+ 
+ /* simp_comp -- quick simplification of T */
+ void simp_comp(T, Tnew, Tbar)
+ pcube *T;			/* T will be disposed of */
+ pcover *Tnew;
+ pcover *Tbar;
+ {
+     register pcube cl, cr;
+     register int best;
+     pcover Tl, Tr, Tlbar, Trbar;
+     int lifting;
+     static int simplify_level = 0;
+ 
+     if (debug & COMPL)
+ 	debug_print(T, "SIMPCOMP", simplify_level++);
+ 
+     if (simp_comp_special_cases(T, Tnew, Tbar) == MAYBE) {
+ 
+ 	/* Allocate space for the partition cubes */
+ 	cl = new_cube();
+ 	cr = new_cube();
+ 	best = binate_split_select(T, cl, cr, COMPL);
+ 
+ 	/* Complement the left and right halves */
+ 	simp_comp(scofactor(T, cl, best), &Tl, &Tlbar);
+ 	simp_comp(scofactor(T, cr, best), &Tr, &Trbar);
+ 
+ 	lifting = USE_COMPL_LIFT;
+ 	*Tnew = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+ 
+ 	lifting = USE_COMPL_LIFT;
+ 	*Tbar = compl_merge(T, Tlbar, Trbar, cl, cr, best, lifting);
+ 
+ 	/* All of this work for nothing ? Let's hope not ... */
+ 	if ((*Tnew)->count > CUBELISTSIZE(T)) {
+ 	    sf_free(*Tnew);
+ 	    *Tnew = cubeunlist(T);
+ 	}
+ 
+ 	free_cube(cl);
+ 	free_cube(cr);
+ 	free_cubelist(T);
+     }
+ 
+     if (debug & COMPL) {
+ 	debug1_print(*Tnew, "exit SIMPCOMP (new)", simplify_level);
+ 	debug1_print(*Tbar, "exit SIMPCOMP (compl)", simplify_level);
+ 	simplify_level--;
+     }
+ }
+ 
+ static bool simp_comp_special_cases(T, Tnew, Tbar)
+ pcube *T;			/* will be disposed if answer is determined */
+ pcover *Tnew;			/* returned only if answer determined */
+ pcover *Tbar;			/* returned only if answer determined */
+ {
+     register pcube *T1, p, ceil, cof=T[0];
+     pcube last;
+     pcover A;
+ 
+     /* Check for no cubes in the cover (function is empty) */
+     if (T[2] == NULL) {
+ 	*Tnew = new_cover(1);
+ 	*Tbar = sf_addset(new_cover(1), cube.fullset);
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for only a single cube in the cover */
+     if (T[3] == NULL) {
+ 	(void) set_or(cof, cof, T[2]);
+ 	*Tnew = sf_addset(new_cover(1), cof);
+ 	*Tbar = compl_cube(cof);
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for a row of all 1's (function is a tautology) */
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	if (full_row(p, cof)) {
+ 	    *Tnew = sf_addset(new_cover(1), cube.fullset);
+ 	    *Tbar = new_cover(1);
+ 	    free_cubelist(T);
+ 	    return TRUE;
+ 	}
+     }
+ 
+     /* Check for a column of all 0's which can be factored out */
+     ceil = set_save(cof);
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	INLINEset_or(ceil, ceil, p);
+     }
+     if (! setp_equal(ceil, cube.fullset)) {
+ 	p = new_cube();
+ 	(void) set_diff(p, cube.fullset, ceil);
+ 	(void) set_or(cof, cof, p);
+ 	set_free(p);
+ 	simp_comp(T, Tnew, Tbar);
+ 
+ 	/* Adjust the ON-set */
+ 	A = *Tnew;
+ 	foreach_set(A, last, p) {
+ 	    INLINEset_and(p, p, ceil);
+ 	}
+ 
+ 	/* Compute the new complement */
+ 	*Tbar = sf_append(*Tbar, compl_cube(ceil));
+ 	set_free(ceil);
+ 	return TRUE;
+     }
+     set_free(ceil);
+ 
+     /* Collect column counts, determine unate variables, etc. */
+     massive_count(T);
+ 
+     /* If single active variable not factored out above, then tautology ! */
+     if (cdata.vars_active == 1) {
+ 	*Tnew = sf_addset(new_cover(1), cube.fullset);
+ 	*Tbar = new_cover(1);
+ 	free_cubelist(T);
+ 	return TRUE;
+ 
+     /* Check for unate cover */
+     } else if (cdata.vars_unate == cdata.vars_active) {
+ 	/* Make the cover minimum by single-cube containment */
+ 	A = cubeunlist(T);
+ 	*Tnew = sf_contain(A);
+ 
+ 	/* Now form a minimum representation of the complement */
+ 	A = map_cover_to_unate(T);
+ 	A = unate_compl(A);
+ 	*Tbar = map_unate_to_cover(A);
+ 	sf_free(A);
+ 	free_cubelist(T);
+ 	return TRUE;
+ 
+     /* Not much we can do about it */
+     } else {
+ 	return MAYBE;
+     }
+ }
+ 
+ /* simplify -- quick simplification of T */
+ pcover simplify(T)
+ pcube *T;			/* T will be disposed of */
+ {
+     register pcube cl, cr;
+     register int best;
+     pcover Tbar, Tl, Tr;
+     int lifting;
+     static int simplify_level = 0;
+ 
+     if (debug & COMPL) {
+ 	debug_print(T, "SIMPLIFY", simplify_level++);
+     }
+ 
+     if (simplify_special_cases(T, &Tbar) == MAYBE) {
+ 
+ 	/* Allocate space for the partition cubes */
+ 	cl = new_cube();
+ 	cr = new_cube();
+ 
+ 	best = binate_split_select(T, cl, cr, COMPL);
+ 
+ 	/* Complement the left and right halves */
+ 	Tl = simplify(scofactor(T, cl, best));
+ 	Tr = simplify(scofactor(T, cr, best));
+ 
+ 	lifting = USE_COMPL_LIFT;
+ 	Tbar = compl_merge(T, Tl, Tr, cl, cr, best, lifting);
+ 
+ 	/* All of this work for nothing ? Let's hope not ... */
+ 	if (Tbar->count > CUBELISTSIZE(T)) {
+ 	    sf_free(Tbar);
+ 	    Tbar = cubeunlist(T);
+ 	}
+ 
+ 	free_cube(cl);
+ 	free_cube(cr);
+ 	free_cubelist(T);
+     }
+ 
+     if (debug & COMPL) {
+ 	debug1_print(Tbar, "exit SIMPLIFY", --simplify_level);
+     }
+     return Tbar;
+ }
+ 
+ static bool simplify_special_cases(T, Tnew)
+ pcube *T;			/* will be disposed if answer is determined */
+ pcover *Tnew;			/* returned only if answer determined */
+ {
+     register pcube *T1, p, ceil, cof=T[0];
+     pcube last;
+     pcover A;
+ 
+     /* Check for no cubes in the cover */
+     if (T[2] == NULL) {
+ 	*Tnew = new_cover(0);
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for only a single cube in the cover */
+     if (T[3] == NULL) {
+ 	*Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for a row of all 1's (implies function is a tautology) */
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	if (full_row(p, cof)) {
+ 	    *Tnew = sf_addset(new_cover(1), cube.fullset);
+ 	    free_cubelist(T);
+ 	    return TRUE;
+ 	}
+     }
+ 
+     /* Check for a column of all 0's which can be factored out */
+     ceil = set_save(cof);
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	INLINEset_or(ceil, ceil, p);
+     }
+     if (! setp_equal(ceil, cube.fullset)) {
+ 	p = new_cube();
+ 	(void) set_diff(p, cube.fullset, ceil);
+ 	(void) set_or(cof, cof, p);
+ 	free_cube(p);
+ 
+ 	A = simplify(T);
+ 	foreach_set(A, last, p) {
+ 	    INLINEset_and(p, p, ceil);
+ 	}
+ 	*Tnew = A;
+ 	set_free(ceil);
+ 	return TRUE;
+     }
+     set_free(ceil);
+ 
+     /* Collect column counts, determine unate variables, etc. */
+     massive_count(T);
+ 
+     /* If single active variable not factored out above, then tautology ! */
+     if (cdata.vars_active == 1) {
+ 	*Tnew = sf_addset(new_cover(1), cube.fullset);
+ 	free_cubelist(T);
+ 	return TRUE;
+ 
+     /* Check for unate cover */
+     } else if (cdata.vars_unate == cdata.vars_active) {
+ 	A = cubeunlist(T);
+ 	*Tnew = sf_contain(A);
+ 	free_cubelist(T);
+ 	return TRUE;
+ 
+     /* Not much we can do about it */
+     } else {
+ 	return MAYBE;
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/contain.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/contain.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/contain.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,432 ----
+ /*
+     contain.c -- set containment routines
+ 
+     These are complex routines for performing containment over a
+     family of sets, but they have the advantage of being much faster
+     than a straightforward n*n routine.
+ 
+     First the cubes are sorted by size, and as a secondary key they are
+     sorted so that if two cubes are equal they end up adjacent.  We can
+     than quickly remove equal cubes from further consideration by
+     comparing each cube to its neighbor.  Finally, because the cubes
+     are sorted by size, we need only check cubes which are larger (or
+     smaller) than a given cube for containment.
+ */
+ 
+ #include "espresso.h"
+ 
+ 
+ /*
+     sf_contain -- perform containment on a set family (delete sets which
+     are contained by some larger set in the family).  No assumptions are
+     made about A, and the result will be returned in decreasing order of
+     set size.
+ */
+ pset_family sf_contain(A)
+ INOUT pset_family A;            /* disposes of A */
+ {
+     int cnt;
+     pset *A1;
+     pset_family R;
+ 
+     A1 = sf_sort(A, descend);           /* sort into descending order */
+     cnt = rm_equal(A1, descend);        /* remove duplicates */
+     cnt = rm_contain(A1);               /* remove contained sets */
+     R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+     sf_free(A);
+     return R;
+ }
+ 
+ 
+ /*
+     sf_rev_contain -- perform containment on a set family (delete sets which
+     contain some smaller set in the family).  No assumptions are made about
+     A, and the result will be returned in increasing order of set size
+ */
+ pset_family sf_rev_contain(A)
+ INOUT pset_family A;            /* disposes of A */
+ {
+     int cnt;
+     pset *A1;
+     pset_family R;
+ 
+     A1 = sf_sort(A, ascend);            /* sort into ascending order */
+     cnt = rm_equal(A1, ascend);         /* remove duplicates */
+     cnt = rm_rev_contain(A1);           /* remove containing sets */
+     R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+     sf_free(A);
+     return R;
+ }
+ 
+ 
+ /*
+     sf_ind_contain -- perform containment on a set family (delete sets which
+     are contained by some larger set in the family).  No assumptions are
+     made about A, and the result will be returned in decreasing order of
+     set size.  Also maintains a set of row_indices to track which rows
+     disappear and how the rows end up permuted.
+ */
+ pset_family sf_ind_contain(A, row_indices)
+ INOUT pset_family A;            /* disposes of A */
+ INOUT int *row_indices;         /* updated with the new values */
+ {
+     int cnt;
+     pset *A1;
+     pset_family R;
+ 
+     A1 = sf_sort(A, descend);           /* sort into descending order */
+     cnt = rm_equal(A1, descend);        /* remove duplicates */
+     cnt = rm_contain(A1);               /* remove contained sets */
+     R = sf_ind_unlist(A1, cnt, A->sf_size, row_indices, A->data);
+     sf_free(A);
+     return R;
+ }
+ 
+ 
+ /* sf_dupl -- delete duplicate sets in a set family */
+ pset_family sf_dupl(A)
+ INOUT pset_family A;            /* disposes of A */
+ {
+     register int cnt;
+     register pset *A1;
+     pset_family R;
+ 
+     A1 = sf_sort(A, descend);           /* sort the set family */
+     cnt = rm_equal(A1, descend);        /* remove duplicates */
+     R = sf_unlist(A1, cnt, A->sf_size); /* recreate the set family */
+     sf_free(A);
+     return R;
+ }
+ 
+ 
+ /*
+     sf_union -- form the contained union of two set families (delete
+     sets which are contained by some larger set in the family).  A and
+     B are assumed already sorted in decreasing order of set size (and
+     the SIZE field is assumed to contain the set size), and the result
+     will be returned sorted likewise.
+ */
+ pset_family sf_union(A, B)
+ INOUT pset_family A, B;         /* disposes of A and B */
+ {
+     int cnt;
+     pset_family R;
+     pset *A1 = sf_list(A), *B1 = sf_list(B), *E1;
+ 
+     E1 = ALLOC(pset, MAX(A->count, B->count) + 1);
+     cnt = rm2_equal(A1, B1, E1, descend);
+     cnt += rm2_contain(A1, B1) + rm2_contain(B1, A1);
+     R = sf_merge(A1, B1, E1, cnt, A->sf_size);
+     sf_free(A); sf_free(B);
+     return R;
+ }
+ 
+ 
+ /*
+     dist_merge -- consider all sets to be "or"-ed with "mask" and then
+     delete duplicates from the set family.
+ */
+ pset_family dist_merge(A, mask)
+ INOUT pset_family A;            /* disposes of A */
+ IN pset mask;                   /* defines variables to mask out */
+ {
+     pset *A1;
+     int cnt;
+     pset_family R;
+ 
+     set_copy(cube.temp[0], mask);
+     A1 = sf_sort(A, d1_order);
+     cnt = d1_rm_equal(A1, d1_order);
+     R = sf_unlist(A1, cnt, A->sf_size);
+     sf_free(A);
+     return R;
+ }
+ 
+ 
+ /*
+     d1merge -- perform an efficient distance-1 merge of cubes of A
+ */
+ pset_family d1merge(A, var)
+ INOUT pset_family A;            /* disposes of A */
+ IN int var;
+ {
+     return dist_merge(A, cube.var_mask[var]);
+ }
+ 
+ 
+ 
+ /* d1_rm_equal -- distance-1 merge (merge cubes which are equal under a mask) */
+ int d1_rm_equal(A1, compare)
+ register pset *A1;				/* array of set pointers */
+ int (*compare)();				/* comparison function */
+ {
+     register int i, j, dest;
+ 
+     dest = 0;
+     if (A1[0] != (pcube) NULL) {
+ 	for(i = 0, j = 1; A1[j] != (pcube) NULL; j++)
+ 	    if ( (*compare)(&A1[i], &A1[j]) == 0) {
+ 		/* if sets are equal (under the mask) merge them */
+ 		set_or(A1[i], A1[i], A1[j]);
+ 	    } else {
+ 		/* sets are unequal, so save the set i */
+ 		A1[dest++] = A1[i];
+ 		i = j;
+ 	    }
+ 	A1[dest++] = A1[i];
+     }
+     A1[dest] = (pcube) NULL;
+     return dest;
+ }
+ 
+ 
+ /* rm_equal -- scan a sorted array of set pointers for duplicate sets */
+ int rm_equal(A1, compare)
+ INOUT pset *A1;                 /* updated in place */
+ IN int (*compare)();
+ {
+     register pset *p, *pdest = A1;
+ 
+     if (*A1 != NULL) {                  /* If more than one set */
+ 	for(p = A1+1; *p != NULL; p++)
+ 	    if ((*compare)(p, p-1) != 0)
+ 		*pdest++ = *(p-1);
+ 	*pdest++ = *(p-1);
+ 	*pdest = NULL;
+     }
+     return pdest - A1;
+ }
+ 
+ 
+ /* rm_contain -- perform containment over a sorted array of set pointers */
+ int rm_contain(A1)
+ INOUT pset *A1;                 /* updated in place */
+ {
+     register pset *pa, *pb, *pcheck, a, b;
+     pset *pdest = A1;
+     int last_size = -1;
+ 
+     /* Loop for all cubes of A1 */
+     for(pa = A1; (a = *pa++) != NULL; ) {
+ 	/* Update the check pointer if the size has changed */
+ 	if (SIZE(a) != last_size)
+ 	    last_size = SIZE(a), pcheck = pdest;
+ 	for(pb = A1; pb != pcheck; ) {
+ 	    b = *pb++;
+ 	    INLINEsetp_implies(a, b, /* when_false => */ continue);
+ 	    goto lnext1;
+ 	}
+ 	/* set a was not contained by some larger set, so save it */
+ 	*pdest++ = a;
+     lnext1: ;
+     }
+ 
+     *pdest = NULL;
+     return pdest - A1;
+ }
+ 
+ 
+ /* rm_rev_contain -- perform rcontainment over a sorted array of set pointers */
+ int rm_rev_contain(A1)
+ INOUT pset *A1;                 /* updated in place */
+ {
+     register pset *pa, *pb, *pcheck, a, b;
+     pset *pdest = A1;
+     int last_size = -1;
+ 
+     /* Loop for all cubes of A1 */
+     for(pa = A1; (a = *pa++) != NULL; ) {
+ 	/* Update the check pointer if the size has changed */
+ 	if (SIZE(a) != last_size)
+ 	    last_size = SIZE(a), pcheck = pdest;
+ 	for(pb = A1; pb != pcheck; ) {
+ 	    b = *pb++;
+ 	    INLINEsetp_implies(b, a, /* when_false => */ continue);
+ 	    goto lnext1;
+ 	}
+ 	/* the set a did not contain some smaller set, so save it */
+ 	*pdest++ = a;
+     lnext1: ;
+     }
+ 
+     *pdest = NULL;
+     return pdest - A1;
+ }
+ 
+ 
+ /* rm2_equal -- check two sorted arrays of set pointers for equal cubes */
+ int rm2_equal(A1, B1, E1, compare)
+ INOUT register pset *A1, *B1;           /* updated in place */
+ OUT pset *E1;
+ IN int (*compare)();
+ {
+     register pset *pda = A1, *pdb = B1, *pde = E1;
+ 
+     /* Walk through the arrays advancing pointer to larger cube */
+     for(; *A1 != NULL && *B1 != NULL; )
+ 	switch((*compare)(A1, B1)) {
+ 	    case -1:    /* "a" comes before "b" */
+ 		*pda++ = *A1++; break;
+ 	    case 0:     /* equal cubes */
+ 		*pde++ = *A1++; B1++; break;
+ 	    case 1:     /* "a" is to follow "b" */
+ 		*pdb++ = *B1++; break;
+ 	}
+ 
+     /* Finish moving down the pointers of A and B */
+     while (*A1 != NULL)
+ 	*pda++ = *A1++;
+     while (*B1 != NULL)
+ 	*pdb++ = *B1++;
+     *pda = *pdb = *pde = NULL;
+ 
+     return pde - E1;
+ }
+ 
+ 
+ /* rm2_contain -- perform containment between two arrays of set pointers */
+ int rm2_contain(A1, B1)
+ INOUT pset *A1;                 /* updated in place */
+ IN pset *B1;                    /* unchanged */
+ {
+     register pset *pa, *pb, a, b, *pdest = A1;
+ 
+     /* for each set in the first array ... */
+     for(pa = A1; (a = *pa++) != NULL; ) {
+ 	/* for each set in the second array which is larger ... */
+ 	for(pb = B1; (b = *pb++) != NULL && SIZE(b) > SIZE(a); ) {
+ 	    INLINEsetp_implies(a, b, /* when_false => */ continue);
+ 	    /* set was contained in some set of B, so don't save pointer */
+ 	    goto lnext1;
+ 	}
+ 	/* set wasn't contained in any set of B, so save the pointer */
+ 	*pdest++ = a;
+     lnext1: ;
+     }
+ 
+     *pdest = NULL;                      /* sentinel */
+     return pdest - A1;                  /* # elements in A1 */
+ }
+ 
+ 
+ 
+ /* sf_sort -- sort the sets of A */
+ pset *sf_sort(A, compare)
+ IN pset_family A;
+ IN int (*compare)();
+ {
+     register pset p, last, *pdest, *A1;
+ 
+     /* Create a single array pointing to each cube of A */
+     pdest = A1 = ALLOC(pset, A->count + 1);
+     foreach_set(A, last, p) {
+ 	PUTSIZE(p, set_ord(p));         /* compute the set size */
+ 	*pdest++ = p;                   /* save the pointer */
+     }
+     *pdest = NULL;                      /* Sentinel -- never seen by sort */
+ 
+     /* Sort cubes by size */
+     qsort((char *) A1, A->count, sizeof(pset), compare);
+     return A1;
+ }
+ 
+ 
+ /* sf_list -- make a list of pointers to the sets in a set family */
+ pset *sf_list(A)
+ IN register pset_family A;
+ {
+     register pset p, last, *pdest, *A1;
+ 
+     /* Create a single array pointing to each cube of A */
+     pdest = A1 = ALLOC(pset, A->count + 1);
+     foreach_set(A, last, p)
+ 	*pdest++ = p;                   /* save the pointer */
+     *pdest = NULL;                      /* Sentinel */
+     return A1;
+ }
+ 
+ 
+ /* sf_unlist -- make a set family out of a list of pointers to sets */
+ pset_family sf_unlist(A1, totcnt, size)
+ IN pset *A1;
+ IN int totcnt, size;
+ {
+     register pset pr, p, *pa;
+     pset_family R = sf_new(totcnt, size);
+ 
+     R->count = totcnt;
+     for(pr = R->data, pa = A1; (p = *pa++) != NULL; pr += R->wsize)
+ 	INLINEset_copy(pr, p);
+     FREE(A1);
+     return R;
+ }
+ 
+ 
+ /* sf_ind_unlist -- make a set family out of a list of pointers to sets */
+ pset_family sf_ind_unlist(A1, totcnt, size, row_indices, pfirst)
+ IN pset *A1;
+ IN int totcnt, size;
+ INOUT int *row_indices;
+ IN register pset pfirst;
+ {
+     register pset pr, p, *pa;
+     register int i, *new_row_indices;
+     pset_family R = sf_new(totcnt, size);
+ 
+     R->count = totcnt;
+     new_row_indices = ALLOC(int, totcnt);
+     for(pr = R->data, pa = A1, i=0; (p = *pa++) != NULL; pr += R->wsize, i++) {
+ 	INLINEset_copy(pr, p);
+ 	new_row_indices[i] = row_indices[(p - pfirst)/R->wsize];
+     }
+     for(i = 0; i < totcnt; i++)
+ 	row_indices[i] = new_row_indices[i];
+     FREE(new_row_indices);
+     FREE(A1);
+     return R;
+ }
+ 
+ 
+ /* sf_merge -- merge three sorted lists of set pointers */
+ pset_family sf_merge(A1, B1, E1, totcnt, size)
+ INOUT pset *A1, *B1, *E1;               /* will be disposed of */
+ IN int totcnt, size;
+ {
+     register pset pr, ps, *pmin, *pmid, *pmax;
+     pset_family R;
+     pset *temp[3], *swap;
+     int i, j, n;
+ 
+     /* Allocate the result set_family */
+     R = sf_new(totcnt, size);
+     R->count = totcnt;
+     pr = R->data;
+ 
+     /* Quick bubble sort to order the top member of the three arrays */
+     n = 3;  temp[0] = A1;  temp[1] = B1;  temp[2] = E1;
+     for(i = 0; i < n-1; i++)
+ 	for(j = i+1; j < n; j++)
+ 	    if (desc1(*temp[i], *temp[j]) > 0) {
+ 		swap = temp[j];
+ 		temp[j] = temp[i];
+ 		temp[i] = swap;
+ 	    }
+     pmin = temp[0];  pmid = temp[1];  pmax = temp[2];
+ 
+     /* Save the minimum element, then update pmin, pmid, pmax */
+     while (*pmin != (pset) NULL) {
+ 	ps = *pmin++;
+ 	INLINEset_copy(pr, ps);
+ 	pr += R->wsize;
+ 	if (desc1(*pmin, *pmax) > 0) {
+ 	    swap = pmax; pmax = pmin; pmin = pmid; pmid = swap;
+ 	} else if (desc1(*pmin, *pmid) > 0) {
+ 	    swap = pmin; pmin = pmid; pmid = swap;
+ 	}
+     }
+ 
+     FREE(A1);
+     FREE(B1);
+     FREE(E1);
+     return R;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/copyright.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/copyright.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/copyright.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,29 ----
+ #ifndef OCTTOOLS_COPYRIGHT_H
+ #define OCTTOOLS_COPYRIGHT_H
+ /*
+  * Oct Tools Distribution 4.0
+  *
+  * Copyright (c) 1988, 1989, 1990, Regents of the University of California.
+  * All rights reserved.
+  *
+  * Use and copying of this software and preparation of derivative works
+  * based upon this software are permitted.  However, any distribution of
+  * this software or derivative works must include the above copyright
+  * notice.
+  *
+  * This software is made available AS IS, and neither the Electronics
+  * Research Laboratory or the University of California make any
+  * warranty about the software, its performance or its conformity to
+  * any specification.
+  *
+  * Suggestions, comments, or improvements are welcome and should be
+  * addressed to:
+  *
+  *   octtools at eros.berkeley.edu
+  *   ..!ucbvax!eros!octtools
+  */
+ 
+ #if !defined(lint) && !defined(SABER)
+ static char octtools_copyright[] = "Copyright (c) 1988, 1989, Regents of the University of California.  All rights reserved.";
+ #endif
+ #endif 


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cubestr.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cubestr.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cubestr.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,143 ----
+ /*
+     Module: cubestr.c -- routines for managing the global cube structure
+ */
+ 
+ #include "espresso.h"
+ 
+ /*
+     cube_setup -- assume that the fields "num_vars", "num_binary_vars", and
+     part_size[num_binary_vars .. num_vars-1] are setup, and initialize the
+     rest of cube and cdata.
+ 
+     If a part_size is < 0, then the field size is abs(part_size) and the
+     field read from the input is symbolic.
+ */
+ void cube_setup()
+ {
+     register int i, var;
+     register pcube p;
+ 
+     if (cube.num_binary_vars < 0 || cube.num_vars < cube.num_binary_vars)
+ 	fatal("cube size is silly, error in .i/.o or .mv");
+ 
+     cube.num_mv_vars = cube.num_vars - cube.num_binary_vars;
+     cube.output = cube.num_mv_vars > 0 ? cube.num_vars - 1 : -1;
+ 
+     cube.size = 0;
+     cube.first_part = ALLOC(int, cube.num_vars);
+     cube.last_part = ALLOC(int, cube.num_vars);
+     cube.first_word = ALLOC(int, cube.num_vars);
+     cube.last_word = ALLOC(int, cube.num_vars);
+     for(var = 0; var < cube.num_vars; var++) {
+ 	if (var < cube.num_binary_vars)
+ 	    cube.part_size[var] = 2;
+ 	cube.first_part[var] = cube.size;
+ 	cube.first_word[var] = WHICH_WORD(cube.size);
+ 	cube.size += ABS(cube.part_size[var]);
+ 	cube.last_part[var] = cube.size - 1;
+ 	cube.last_word[var] = WHICH_WORD(cube.size - 1);
+     }
+ 
+     cube.var_mask = ALLOC(pset, cube.num_vars);
+     cube.sparse = ALLOC(int, cube.num_vars);
+     cube.binary_mask = new_cube();
+     cube.mv_mask = new_cube();
+     for(var = 0; var < cube.num_vars; var++) {
+ 	p = cube.var_mask[var] = new_cube();
+ 	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ 	    set_insert(p, i);
+ 	if (var < cube.num_binary_vars) {
+ 	    INLINEset_or(cube.binary_mask, cube.binary_mask, p);
+ 	    cube.sparse[var] = 0;
+ 	} else {
+ 	    INLINEset_or(cube.mv_mask, cube.mv_mask, p);
+ 	    cube.sparse[var] = 1;
+ 	}
+     }
+     if (cube.num_binary_vars == 0)
+ 	cube.inword = -1;
+     else {
+ 	cube.inword = cube.last_word[cube.num_binary_vars - 1];
+ 	cube.inmask = cube.binary_mask[cube.inword] & DISJOINT;
+     }
+ 
+     cube.temp = ALLOC(pset, CUBE_TEMP);
+     for(i = 0; i < CUBE_TEMP; i++)
+ 	cube.temp[i] = new_cube();
+     cube.fullset = set_fill(new_cube(), cube.size);
+     cube.emptyset = new_cube();
+ 
+     cdata.part_zeros = ALLOC(int, cube.size);
+     cdata.var_zeros = ALLOC(int, cube.num_vars);
+     cdata.parts_active = ALLOC(int, cube.num_vars);
+     cdata.is_unate = ALLOC(int, cube.num_vars);
+ }
+ 
+ /*
+     setdown_cube -- free memory allocated for the cube/cdata structs
+     (free's all but the part_size array)
+ 
+     (I wanted to call this cube_setdown, but that violates the 8-character
+     external routine limit on the IBM !)
+ */
+ void setdown_cube()
+ {
+     register int i, var;
+ 
+     FREE(cube.first_part);
+     FREE(cube.last_part);
+     FREE(cube.first_word);
+     FREE(cube.last_word);
+     FREE(cube.sparse);
+ 
+     free_cube(cube.binary_mask);
+     free_cube(cube.mv_mask);
+     free_cube(cube.fullset);
+     free_cube(cube.emptyset);
+     for(var = 0; var < cube.num_vars; var++)
+ 	free_cube(cube.var_mask[var]);
+     FREE(cube.var_mask);
+ 
+     for(i = 0; i < CUBE_TEMP; i++)
+ 	free_cube(cube.temp[i]);
+     FREE(cube.temp);
+ 
+     FREE(cdata.part_zeros);
+     FREE(cdata.var_zeros);
+     FREE(cdata.parts_active);
+     FREE(cdata.is_unate);
+ 
+     cube.first_part = cube.last_part = (int *) NULL;
+     cube.first_word = cube.last_word = (int *) NULL;
+     cube.sparse = (int *) NULL;
+     cube.binary_mask = cube.mv_mask = (pcube) NULL;
+     cube.fullset = cube.emptyset = (pcube) NULL;
+     cube.var_mask = cube.temp = (pcube *) NULL;
+ 
+     cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+     cdata.is_unate = (bool *) NULL;
+ }
+ 
+ 
+ void save_cube_struct()
+ {
+     temp_cube_save = cube;              /* structure copy ! */
+     temp_cdata_save = cdata;            /*      ""          */
+ 
+     cube.first_part = cube.last_part = (int *) NULL;
+     cube.first_word = cube.last_word = (int *) NULL;
+     cube.part_size = (int *) NULL;
+     cube.binary_mask = cube.mv_mask = (pcube) NULL;
+     cube.fullset = cube.emptyset = (pcube) NULL;
+     cube.var_mask = cube.temp = (pcube *) NULL;
+ 
+     cdata.part_zeros = cdata.var_zeros = cdata.parts_active = (int *) NULL;
+     cdata.is_unate = (bool *) NULL;
+ }
+ 
+ 
+ void restore_cube_struct()
+ {
+     cube = temp_cube_save;              /* structure copy ! */
+     cdata = temp_cdata_save;            /*      ""          */
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrin.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrin.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrin.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,793 ----
+ /*
+     module: cvrin.c
+     purpose: cube and cover input routines
+ */
+ 
+ #include "espresso.h"
+ 
+ static bool line_length_error;
+ static int lineno;
+ 
+ void skip_line(fpin, fpout, echo)
+ register FILE *fpin, *fpout;
+ register bool echo;
+ {
+     register int ch;
+     while ((ch=getc(fpin)) != EOF && ch != '\n')
+ 	if (echo)
+ 	    putc(ch, fpout);
+     if (echo)
+ 	putc('\n', fpout);
+     lineno++;
+ }
+ 
+ char *get_word(fp, word)
+ register FILE *fp;
+ register char *word;
+ {
+     register int ch, i = 0;
+     while ((ch = getc(fp)) != EOF && isspace(ch))
+ 	;
+     word[i++] = ch;
+     while ((ch = getc(fp)) != EOF && ! isspace(ch))
+ 	word[i++] = ch;
+     word[i++] = '\0';
+     return word;
+ }
+ 
+ /*
+  *  Yes, I know this routine is a mess
+  */
+ void read_cube(fp, PLA)
+ register FILE *fp;
+ pPLA PLA;
+ {
+     register int var, i;
+     pcube cf = cube.temp[0], cr = cube.temp[1], cd = cube.temp[2];
+     bool savef = FALSE, saved = FALSE, saver = FALSE;
+     char token[256]; 			/* for kiss read hack */
+     int varx, first, last, offset;	/* for kiss read hack */
+ 
+     set_clear(cf, cube.size);
+ 
+     /* Loop and read binary variables */
+     for(var = 0; var < cube.num_binary_vars; var++)
+ 	switch(getc(fp)) {
+ 	    case EOF:
+ 		goto bad_char;
+ 	    case '\n':
+ 		if (! line_length_error)
+ 		    fprintf(stderr, "product term(s) %s\n",
+ 			"span more than one line (warning only)");
+ 		line_length_error = TRUE;
+ 		lineno++;
+ 		var--;
+ 		break;
+ 	    case ' ': case '|': case '\t':
+ 		var--;
+ 		break;
+ 	    case '2': case '-':
+ 		set_insert(cf, var*2+1);
+ 	    case '0':
+ 		set_insert(cf, var*2);
+ 		break;
+ 	    case '1':
+ 		set_insert(cf, var*2+1);
+ 		break;
+ 	    case '?':
+ 		break;
+ 	    default:
+ 		goto bad_char;
+ 	}
+ 
+ 
+     /* Loop for the all but one of the multiple-valued variables */	
+     for(var = cube.num_binary_vars; var < cube.num_vars-1; var++)
+ 
+ 	/* Read a symbolic multiple-valued variable */
+ 	if (cube.part_size[var] < 0) {
+ 	    (void) fscanf(fp, "%s", token);
+ 	    if (equal(token, "-") || equal(token, "ANY")) {
+ 		if (kiss && var == cube.num_vars - 2) {
+ 		    /* leave it empty */
+ 		} else {
+ 		    /* make it full */
+ 		    set_or(cf, cf, cube.var_mask[var]);
+ 		}
+ 	    } else if (equal(token, "~")) {
+ 		;
+ 		/* leave it empty ... (?) */
+ 	    } else {
+ 		if (kiss && var == cube.num_vars - 2)
+ 		    varx = var - 1, offset = ABS(cube.part_size[var-1]);
+ 		else
+ 		    varx = var, offset = 0;
+ 		/* Find the symbolic label in the label table */
+ 		first = cube.first_part[varx];
+ 		last = cube.last_part[varx];
+ 		for(i = first; i <= last; i++)
+ 		    if (PLA->label[i] == (char *) NULL) {
+ 			PLA->label[i] = util_strsav(token);	/* add new label */
+ 			set_insert(cf, i+offset);
+ 			break;
+ 		    } else if (equal(PLA->label[i], token)) {
+ 			set_insert(cf, i+offset);	/* use column i */
+ 			break;
+ 		    }
+ 		if (i > last) {
+ 		    fprintf(stderr,
+ "declared size of variable %d (counting from variable 0) is too small\n", var);
+ 		    exit(-1);
+ 		}
+ 	    }
+ 	
+ 	} else for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ 	    switch (getc(fp)) {
+ 		case EOF:
+ 		    goto bad_char;
+ 		case '\n':
+ 		    if (! line_length_error)
+ 			fprintf(stderr, "product term(s) %s\n",
+ 			    "span more than one line (warning only)");
+ 		    line_length_error = TRUE;
+ 		    lineno++;
+ 		    i--;
+ 		    break;
+ 		case ' ': case '|': case '\t':
+ 		    i--;
+ 		    break;
+ 		case '1':
+ 		    set_insert(cf, i);
+ 		case '0':
+ 		    break;
+ 		default:
+ 		    goto bad_char;
+ 	    }
+ 
+     /* Loop for last multiple-valued variable */
+     if (kiss) {
+ 	saver = savef = TRUE;
+ 	(void) set_xor(cr, cf, cube.var_mask[cube.num_vars - 2]);
+     } else
+ 	set_copy(cr, cf);
+     set_copy(cd, cf);
+     for(i = cube.first_part[var]; i <= cube.last_part[var]; i++)
+ 	switch (getc(fp)) {
+ 	    case EOF:
+ 		goto bad_char;
+ 	    case '\n':
+ 		if (! line_length_error)
+ 		    fprintf(stderr, "product term(s) %s\n",
+ 			"span more than one line (warning only)");
+ 		line_length_error = TRUE;
+ 		lineno++;
+ 		i--;
+ 		break;
+ 	    case ' ': case '|': case '\t':
+ 		i--;
+ 		break;
+ 	    case '4': case '1':
+ 		if (PLA->pla_type & F_type)
+ 		    set_insert(cf, i), savef = TRUE;
+ 		break;
+ 	    case '3': case '0':
+ 		if (PLA->pla_type & R_type)
+ 		    set_insert(cr, i), saver = TRUE;
+ 		break;
+ 	    case '2': case '-':
+ 		if (PLA->pla_type & D_type)
+ 		    set_insert(cd, i), saved = TRUE;
+ 	    case '~':
+ 		break;
+ 	    default:
+ 		goto bad_char;
+ 	}
+     if (savef) PLA->F = sf_addset(PLA->F, cf);
+     if (saved) PLA->D = sf_addset(PLA->D, cd);
+     if (saver) PLA->R = sf_addset(PLA->R, cr);
+     return;
+ 
+ bad_char:
+     fprintf(stderr, "(warning): input line #%d ignored\n", lineno);
+     skip_line(fp, stdout, TRUE);
+     return;
+ }
+ void parse_pla(fp, PLA)
+ IN FILE *fp;
+ INOUT pPLA PLA;
+ {
+     int i, var, ch, np, last;
+     char word[256];
+ 
+     lineno = 1;
+     line_length_error = FALSE;
+ 
+ loop:
+     switch(ch = getc(fp)) {
+ 	case EOF:
+ 	    return;
+ 
+ 	case '\n':
+ 	    lineno++;
+ 
+ 	case ' ': case '\t': case '\f': case '\r':
+ 	    break;
+ 
+ 	case '#':
+ 	    (void) ungetc(ch, fp);
+ 	    skip_line(fp, stdout, echo_comments);
+ 	    break;
+ 
+ 	case '.':
+ 	    /* .i gives the cube input size (binary-functions only) */
+ 	    if (equal(get_word(fp, word), "i")) {
+ 		if (cube.fullset != NULL) {
+ 		    fprintf(stderr, "extra .i ignored\n");
+ 		    skip_line(fp, stdout, /* echo */ FALSE);
+ 		} else {
+ 		    if (fscanf(fp, "%d", &cube.num_binary_vars) != 1)
+ 			fatal("error reading .i");
+ 		    cube.num_vars = cube.num_binary_vars + 1;
+ 		    cube.part_size = ALLOC(int, cube.num_vars);
+ 		}
+ 
+ 	    /* .o gives the cube output size (binary-functions only) */
+ 	    } else if (equal(word, "o")) {
+ 		if (cube.fullset != NULL) {
+ 		    fprintf(stderr, "extra .o ignored\n");
+ 		    skip_line(fp, stdout, /* echo */ FALSE);
+ 		} else {
+ 		    if (cube.part_size == NULL)
+ 			fatal(".o cannot appear before .i");
+ 		    if (fscanf(fp, "%d", &(cube.part_size[cube.num_vars-1]))!=1)
+ 			fatal("error reading .o");
+ 		    cube_setup();
+ 		    PLA_labels(PLA);
+ 		}
+ 
+ 	    /* .mv gives the cube size for a multiple-valued function */
+ 	    } else if (equal(word, "mv")) {
+ 		if (cube.fullset != NULL) {
+ 		    fprintf(stderr, "extra .mv ignored\n");
+ 		    skip_line(fp, stdout, /* echo */ FALSE);
+ 		} else {
+ 		    if (cube.part_size != NULL)
+ 			fatal("cannot mix .i and .mv");
+ 		    if (fscanf(fp,"%d %d",
+ 			&cube.num_vars,&cube.num_binary_vars) != 2)
+ 			 fatal("error reading .mv");
+ 		    if (cube.num_binary_vars < 0)
+ fatal("num_binary_vars (second field of .mv) cannot be negative");
+ 		    if (cube.num_vars < cube.num_binary_vars)
+ 			fatal(
+ "num_vars (1st field of .mv) must exceed num_binary_vars (2nd field of .mv)");
+ 		    cube.part_size = ALLOC(int, cube.num_vars);
+ 		    for(var=cube.num_binary_vars; var < cube.num_vars; var++)
+ 			if (fscanf(fp, "%d", &(cube.part_size[var])) != 1)
+ 			    fatal("error reading .mv");
+ 		    cube_setup();
+ 		    PLA_labels(PLA);
+ 		}
+ 
+ 	    /* .p gives the number of product terms -- we ignore it */
+ 	    } else if (equal(word, "p"))
+ 		(void) fscanf(fp, "%d", &np);
+ 	    /* .e and .end specify the end of the file */
+ 	    else if (equal(word, "e") || equal(word,"end"))
+ 		return;
+ 	    /* .kiss turns on the kiss-hack option */
+ 	    else if (equal(word, "kiss"))
+ 		kiss = TRUE;
+ 
+ 	    /* .type specifies a logical type for the PLA */
+ 	    else if (equal(word, "type")) {
+ 		(void) get_word(fp, word);
+ 		for(i = 0; pla_types[i].key != 0; i++)
+ 		    if (equal(pla_types[i].key + 1, word)) {
+ 			PLA->pla_type = pla_types[i].value;
+ 			break;
+ 		    }
+ 		if (pla_types[i].key == 0)
+ 		    fatal("unknown type in .type command");
+ 
+ 	    /* parse the labels */
+ 	    } else if (equal(word, "ilb")) {
+ 		if (cube.fullset == NULL)
+ 		    fatal("PLA size must be declared before .ilb or .ob");
+ 		if (PLA->label == NULL)
+ 		    PLA_labels(PLA);
+ 		for(var = 0; var < cube.num_binary_vars; var++) {
+ 		    (void) get_word(fp, word);
+ 		    i = cube.first_part[var];
+ 		    PLA->label[i+1] = util_strsav(word);
+ 		    PLA->label[i] = ALLOC(char, strlen(word) + 6);
+ 		    (void) sprintf(PLA->label[i], "%s.bar", word);
+ 		}
+ 	    } else if (equal(word, "ob")) {
+ 		if (cube.fullset == NULL)
+ 		    fatal("PLA size must be declared before .ilb or .ob");
+ 		if (PLA->label == NULL)
+ 		    PLA_labels(PLA);
+ 		var = cube.num_vars - 1;
+ 		for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 		    (void) get_word(fp, word);
+ 		    PLA->label[i] = util_strsav(word);
+ 		}
+ 	    /* .label assigns labels to multiple-valued variables */
+ 	    } else if (equal(word, "label")) {
+ 		if (cube.fullset == NULL)
+ 		    fatal("PLA size must be declared before .label");
+ 		if (PLA->label == NULL)
+ 		    PLA_labels(PLA);
+ 		if (fscanf(fp, "var=%d", &var) != 1)
+ 		    fatal("Error reading labels");
+ 		for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 		    (void) get_word(fp, word);
+ 		    PLA->label[i] = util_strsav(word);
+ 		}
+ 
+ 	    } else if (equal(word, "symbolic")) {
+ 		symbolic_t *newlist, *p1;
+ 		if (read_symbolic(fp, PLA, word, &newlist)) {
+ 		    if (PLA->symbolic == NIL(symbolic_t)) {
+ 			PLA->symbolic = newlist;
+ 		    } else {
+ 			for(p1=PLA->symbolic;p1->next!=NIL(symbolic_t);
+ 			    p1=p1->next){
+ 			}
+ 			p1->next = newlist;
+ 		    }
+ 		} else {
+ 		    fatal("error reading .symbolic");
+ 		}
+ 
+ 	    } else if (equal(word, "symbolic-output")) {
+ 		symbolic_t *newlist, *p1;
+ 		if (read_symbolic(fp, PLA, word, &newlist)) {
+ 		    if (PLA->symbolic_output == NIL(symbolic_t)) {
+ 			PLA->symbolic_output = newlist;
+ 		    } else {
+ 			for(p1=PLA->symbolic_output;p1->next!=NIL(symbolic_t);
+ 			    p1=p1->next){
+ 			}
+ 			p1->next = newlist;
+ 		    }
+ 		} else {
+ 		    fatal("error reading .symbolic-output");
+ 		}
+ 		
+ 	    /* .phase allows a choice of output phases */
+ 	    } else if (equal(word, "phase")) {
+ 		if (cube.fullset == NULL)
+ 		    fatal("PLA size must be declared before .phase");
+ 		if (PLA->phase != NULL) {
+ 		    fprintf(stderr, "extra .phase ignored\n");
+ 		    skip_line(fp, stdout, /* echo */ FALSE);
+ 		} else {
+ 		    do ch = getc(fp); while (ch == ' ' || ch == '\t');
+ 		    (void) ungetc(ch, fp);
+ 		    PLA->phase = set_save(cube.fullset);
+ 		    last = cube.last_part[cube.num_vars - 1];
+ 		    for(i=cube.first_part[cube.num_vars - 1]; i <= last; i++)
+ 			if ((ch = getc(fp)) == '0')
+ 			    set_remove(PLA->phase, i);
+ 			else if (ch != '1')
+ 			    fatal("only 0 or 1 allowed in phase description");
+ 		}
+ 
+ 	    /* .pair allows for bit-pairing input variables */
+ 	    } else if (equal(word, "pair")) {
+ 		int j;
+ 		if (PLA->pair != NULL) {
+ 		    fprintf(stderr, "extra .pair ignored\n");
+ 		} else {
+ 		    ppair pair;
+ 		    PLA->pair = pair = ALLOC(pair_t, 1);
+ 		    if (fscanf(fp, "%d", &(pair->cnt)) != 1)
+ 			fatal("syntax error in .pair");
+ 		    pair->var1 = ALLOC(int, pair->cnt);
+ 		    pair->var2 = ALLOC(int, pair->cnt);
+ 		    for(i = 0; i < pair->cnt; i++) {
+ 			(void) get_word(fp, word);
+ 			if (word[0] == '(') (void) strcpy(word, word+1);
+ 			if (label_index(PLA, word, &var, &j)) {
+ 			    pair->var1[i] = var+1;
+ 			} else {
+ 			    fatal("syntax error in .pair");
+ 			}
+ 
+ 			(void) get_word(fp, word);
+ 			if (word[strlen(word)-1] == ')') {
+ 			    word[strlen(word)-1]='\0';
+ 			}
+ 			if (label_index(PLA, word, &var, &j)) {
+ 			    pair->var2[i] = var+1;
+ 			} else {
+ 			    fatal("syntax error in .pair");
+ 			}
+ 		    }
+ 		}
+ 		
+ 	    } else {
+ 		if (echo_unknown_commands)
+ 		    printf("%c%s ", ch, word);
+ 		skip_line(fp, stdout, echo_unknown_commands);
+ 	    }
+ 	    break;
+ 	default:
+ 	    (void) ungetc(ch, fp);
+ 	    if (cube.fullset == NULL) {
+ /*		fatal("unknown PLA size, need .i/.o or .mv");*/
+ 		if (echo_comments)
+ 		    putchar('#');
+ 		skip_line(fp, stdout, echo_comments);
+ 		break;
+ 	    }
+ 	    if (PLA->F == NULL) {
+ 		PLA->F = new_cover(10);
+ 		PLA->D = new_cover(10);
+ 		PLA->R = new_cover(10);
+ 	    }
+ 	    read_cube(fp, PLA);
+     }
+     goto loop;
+ }
+ /*
+     read_pla -- read a PLA from a file
+ 
+     Input stops when ".e" is encountered in the input file, or upon reaching
+     end of file.
+ 
+     Returns the PLA in the variable PLA after massaging the "symbolic"
+     representation into a positional cube notation of the ON-set, OFF-set,
+     and the DC-set.
+ 
+     needs_dcset and needs_offset control the computation of the OFF-set
+     and DC-set (i.e., if either needs to be computed, then it will be
+     computed via complement only if the corresponding option is TRUE.)
+     pla_type specifies the interpretation to be used when reading the
+     PLA.
+ 
+     The phase of the output functions is adjusted according to the
+     global option "pos" or according to an imbedded .phase option in
+     the input file.  Note that either phase option implies that the
+     OFF-set be computed regardless of whether the caller needs it
+     explicitly or not.
+ 
+     Bit pairing of the binary variables is performed according to an
+     imbedded .pair option in the input file.
+ 
+     The global cube structure also reflects the sizes of the PLA which
+     was just read.  If these fields have already been set, then any
+     subsequent PLA must conform to these sizes.
+ 
+     The global flags trace and summary control the output produced
+     during the read.
+ 
+     Returns a status code as a result:
+ 	EOF (-1) : End of file reached before any data was read
+ 	> 0	 : Operation successful
+ */
+ 
+ int read_pla(fp, needs_dcset, needs_offset, pla_type, PLA_return)
+ IN FILE *fp;
+ IN bool needs_dcset, needs_offset;
+ IN int pla_type;
+ OUT pPLA *PLA_return;
+ {
+     pPLA PLA;
+     int i, second, third;
+     long time;
+     cost_t cost;
+ 
+     /* Allocate and initialize the PLA structure */
+     PLA = *PLA_return = new_PLA();
+     PLA->pla_type = pla_type;
+ 
+     /* Read the pla */
+     time = ptime();
+     parse_pla(fp, PLA);
+ 
+     /* Check for nothing on the file -- implies reached EOF */
+     if (PLA->F == NULL) {
+ 	return EOF;
+     }
+ 
+     /* This hack merges the next-state field with the outputs */
+     for(i = 0; i < cube.num_vars; i++) {
+ 	cube.part_size[i] = ABS(cube.part_size[i]);
+     }
+     if (kiss) {
+ 	third = cube.num_vars - 3;
+ 	second = cube.num_vars - 2;
+ 	if (cube.part_size[third] != cube.part_size[second]) {
+ 	    fprintf(stderr," with .kiss option, third to last and second\n");
+ 	    fprintf(stderr, "to last variables must be the same size.\n");
+ 	    return EOF;
+ 	}
+ 	for(i = 0; i < cube.part_size[second]; i++) {
+ 	    PLA->label[i + cube.first_part[second]] =
+ 		util_strsav(PLA->label[i + cube.first_part[third]]);
+ 	}
+ 	cube.part_size[second] += cube.part_size[cube.num_vars-1];
+ 	cube.num_vars--;
+ 	setdown_cube();
+ 	cube_setup();
+     }
+ 
+     if (trace) {
+ 	totals(time, READ_TIME, PLA->F, &cost);
+     }
+ 
+     /* Decide how to break PLA into ON-set, OFF-set and DC-set */
+     time = ptime();
+     if (pos || PLA->phase != NULL || PLA->symbolic_output != NIL(symbolic_t)) {
+ 	needs_offset = TRUE;
+     }
+     if (needs_offset && (PLA->pla_type==F_type || PLA->pla_type==FD_type)) {
+ 	free_cover(PLA->R);
+ 	PLA->R = complement(cube2list(PLA->F, PLA->D));
+     } else if (needs_dcset && PLA->pla_type == FR_type) {
+ 	pcover X;
+ 	free_cover(PLA->D);
+ 	/* hack, why not? */
+ 	X = d1merge(sf_join(PLA->F, PLA->R), cube.num_vars - 1);
+ 	PLA->D = complement(cube1list(X));
+ 	free_cover(X);
+     } else if (PLA->pla_type == R_type || PLA->pla_type == DR_type) {
+ 	free_cover(PLA->F);
+ 	PLA->F = complement(cube2list(PLA->D, PLA->R));
+     }
+ 
+     if (trace) {
+ 	totals(time, COMPL_TIME, PLA->R, &cost);
+     }
+ 
+     /* Check for phase rearrangement of the functions */
+     if (pos) {
+ 	pcover onset = PLA->F;
+ 	PLA->F = PLA->R;
+ 	PLA->R = onset;
+ 	PLA->phase = new_cube();
+ 	set_diff(PLA->phase, cube.fullset, cube.var_mask[cube.num_vars-1]);
+     } else if (PLA->phase != NULL) {
+ 	(void) set_phase(PLA);
+     }
+ 
+     /* Setup minimization for two-bit decoders */
+     if (PLA->pair != (ppair) NULL) {
+ 	set_pair(PLA);
+     }
+ 
+     if (PLA->symbolic != NIL(symbolic_t)) {
+ 	EXEC(map_symbolic(PLA), "MAP-INPUT  ", PLA->F);
+     }
+     if (PLA->symbolic_output != NIL(symbolic_t)) {
+ 	EXEC(map_output_symbolic(PLA), "MAP-OUTPUT ", PLA->F);
+ 	if (needs_offset) {
+ 	    free_cover(PLA->R);
+ EXECUTE(PLA->R=complement(cube2list(PLA->F,PLA->D)), COMPL_TIME, PLA->R, cost);
+ 	}
+     }
+ 
+     return 1;
+ }
+ 
+ void PLA_summary(PLA)
+ pPLA PLA;
+ {
+     int var, i;
+     symbolic_list_t *p2;
+     symbolic_t *p1;
+ 
+     printf("# PLA is %s", PLA->filename);
+     if (cube.num_binary_vars == cube.num_vars - 1)
+ 	printf(" with %d inputs and %d outputs\n",
+ 	    cube.num_binary_vars, cube.part_size[cube.num_vars - 1]);
+     else {
+ 	printf(" with %d variables (%d binary, mv sizes",
+ 	    cube.num_vars, cube.num_binary_vars);
+ 	for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+ 	    printf(" %d", cube.part_size[var]);
+ 	printf(")\n");
+     }
+     printf("# ON-set cost is  %s\n", print_cost(PLA->F));
+     printf("# OFF-set cost is %s\n", print_cost(PLA->R));
+     printf("# DC-set cost is  %s\n", print_cost(PLA->D));
+     if (PLA->phase != NULL)
+ 	printf("# phase is %s\n", pc1(PLA->phase));
+     if (PLA->pair != NULL) {
+ 	printf("# two-bit decoders:");
+ 	for(i = 0; i < PLA->pair->cnt; i++)
+ 	    printf(" (%d %d)", PLA->pair->var1[i], PLA->pair->var2[i]);
+ 	printf("\n");
+     }
+     if (PLA->symbolic != NIL(symbolic_t)) {
+ 	for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ 	    printf("# symbolic: ");
+ 	    for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ 		printf(" %d", p2->variable);
+ 	    }
+ 	    printf("\n");
+ 	}
+     }
+     if (PLA->symbolic_output != NIL(symbolic_t)) {
+ 	for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1->next) {
+ 	    printf("# output symbolic: ");
+ 	    for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ 		printf(" %d", p2->pos);
+ 	    }
+ 	    printf("\n");
+ 	}
+     }
+     (void) fflush(stdout);
+ }
+ 
+ 
+ pPLA new_PLA()
+ {
+     pPLA PLA;
+ 
+     PLA = ALLOC(PLA_t, 1);
+     PLA->F = PLA->D = PLA->R = (pcover) NULL;
+     PLA->phase = (pcube) NULL;
+     PLA->pair = (ppair) NULL;
+     PLA->label = (char **) NULL;
+     PLA->filename = (char *) NULL;
+     PLA->pla_type = 0;
+     PLA->symbolic = NIL(symbolic_t);
+     PLA->symbolic_output = NIL(symbolic_t);
+     return PLA;
+ }
+ 
+ 
+ PLA_labels(PLA)
+ pPLA PLA;
+ {
+     int i;
+ 
+     PLA->label = ALLOC(char *, cube.size);
+     for(i = 0; i < cube.size; i++)
+ 	PLA->label[i] = (char *) NULL;
+ }
+ 
+ 
+ void free_PLA(PLA)
+ pPLA PLA;
+ {
+     symbolic_list_t *p2, *p2next;
+     symbolic_t *p1, *p1next;
+     int i;
+ 
+     if (PLA->F != (pcover) NULL)
+ 	free_cover(PLA->F);
+     if (PLA->R != (pcover) NULL)
+ 	free_cover(PLA->R);
+     if (PLA->D != (pcover) NULL)
+ 	free_cover(PLA->D);
+     if (PLA->phase != (pcube) NULL)
+ 	free_cube(PLA->phase);
+     if (PLA->pair != (ppair) NULL) {
+ 	FREE(PLA->pair->var1);
+ 	FREE(PLA->pair->var2);
+ 	FREE(PLA->pair);
+     }
+     if (PLA->label != NULL) {
+ 	for(i = 0; i < cube.size; i++)
+ 	    if (PLA->label[i] != NULL)
+ 		FREE(PLA->label[i]);
+ 	FREE(PLA->label);
+     }
+     if (PLA->filename != NULL) {
+ 	FREE(PLA->filename);
+     }
+     for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1next) {
+ 	for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+ 	    p2next = p2->next;
+ 	    FREE(p2);
+ 	}
+ 	p1next = p1->next;
+ 	FREE(p1);
+     }
+     PLA->symbolic = NIL(symbolic_t);
+     for(p1 = PLA->symbolic_output; p1 != NIL(symbolic_t); p1 = p1next) {
+ 	for(p2 = p1->symbolic_list; p2 != NIL(symbolic_list_t); p2 = p2next) {
+ 	    p2next = p2->next;
+ 	    FREE(p2);
+ 	}
+ 	p1next = p1->next;
+ 	FREE(p1);
+     }
+     PLA->symbolic_output = NIL(symbolic_t);
+     FREE(PLA);
+ }
+ 
+ 
+ int read_symbolic(fp, PLA, word, retval)
+ FILE *fp;
+ pPLA PLA;
+ char *word;		/* scratch string for words */
+ symbolic_t **retval;
+ {
+     symbolic_list_t *listp, *prev_listp;
+     symbolic_label_t *labelp, *prev_labelp;
+     symbolic_t *newlist;
+     int i, var;
+ 
+     newlist = ALLOC(symbolic_t, 1);
+     newlist->next = NIL(symbolic_t);
+     newlist->symbolic_list = NIL(symbolic_list_t);
+     newlist->symbolic_list_length = 0;
+     newlist->symbolic_label = NIL(symbolic_label_t);
+     newlist->symbolic_label_length = 0;
+     prev_listp = NIL(symbolic_list_t);
+     prev_labelp = NIL(symbolic_label_t);
+ 
+     for(;;) {
+ 	(void) get_word(fp, word);
+ 	if (equal(word, ";"))
+ 	    break;
+ 	if (label_index(PLA, word, &var, &i)) {
+ 	    listp = ALLOC(symbolic_list_t, 1);
+ 	    listp->variable = var;
+ 	    listp->pos = i;
+ 	    listp->next = NIL(symbolic_list_t);
+ 	    if (prev_listp == NIL(symbolic_list_t)) {
+ 		newlist->symbolic_list = listp;
+ 	    } else {
+ 		prev_listp->next = listp;
+ 	    }
+ 	    prev_listp = listp;
+ 	    newlist->symbolic_list_length++;
+ 	} else {
+ 	    return FALSE;
+ 	}
+     }
+ 
+     for(;;) {
+ 	(void) get_word(fp, word);
+ 	if (equal(word, ";"))
+ 	    break;
+ 	labelp = ALLOC(symbolic_label_t, 1);
+ 	labelp->label = util_strsav(word);
+ 	labelp->next = NIL(symbolic_label_t);
+ 	if (prev_labelp == NIL(symbolic_label_t)) {
+ 	    newlist->symbolic_label = labelp;
+ 	} else {
+ 	    prev_labelp->next = labelp;
+ 	}
+ 	prev_labelp = labelp;
+ 	newlist->symbolic_label_length++;
+     }
+ 
+     *retval = newlist;
+     return TRUE;
+ }
+ 
+ 
+ int label_index(PLA, word, varp, ip)
+ pPLA PLA;
+ char *word;
+ int *varp;
+ int *ip;
+ {
+     int var, i;
+ 
+     if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char)) {
+ 	if (sscanf(word, "%d", varp) == 1) {
+ 	    *ip = *varp;
+ 	    return TRUE;
+ 	}
+     } else {
+ 	for(var = 0; var < cube.num_vars; var++) {
+ 	    for(i = 0; i < cube.part_size[var]; i++) {
+ 		if (equal(PLA->label[cube.first_part[var]+i], word)) {
+ 		    *varp = var;
+ 		    *ip = i;
+ 		    return TRUE;
+ 		}
+ 	    }
+ 	}
+     }
+     return FALSE;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrm.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrm.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrm.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,530 ----
+ /*
+     module: cvrm.c
+     Purpose: miscellaneous cover manipulation
+ 	a) verify two covers are equal, check consistency of a cover
+ 	b) unravel a multiple-valued cover into minterms
+ 	c) sort covers
+ */
+ 
+ #include "espresso.h"
+ 
+ 
+ static void cb_unravel(c, start, end, startbase, B1)
+ IN register pcube c;
+ IN int start, end;
+ IN pcube startbase;
+ INOUT pcover B1;
+ {
+     pcube base = cube.temp[0], p, last;
+     int expansion, place, skip, var, size, offset;
+     register int i, j, k, n;
+ 
+     /* Determine how many cubes it will blow up into, and create a mask
+ 	for those parts that have only a single coordinate
+     */
+     expansion = 1;
+     (void) set_copy(base, startbase);
+     for(var = start; var <= end; var++) {
+ 	if ((size = set_dist(c, cube.var_mask[var])) < 2) {
+ 	    (void) set_or(base, base, cube.var_mask[var]);
+ 	} else {
+ 	    expansion *= size;
+ 	}
+     }
+     (void) set_and(base, c, base);
+ 
+     /* Add the unravelled sets starting at the last element of B1 */
+     offset = B1->count;
+     B1->count += expansion;
+     foreach_remaining_set(B1, last, GETSET(B1, offset-1), p) {
+ 	INLINEset_copy(p, base);
+     }
+ 
+     place = expansion;
+     for(var = start; var <= end; var++) {
+ 	if ((size = set_dist(c, cube.var_mask[var])) > 1) {
+ 	    skip = place;
+ 	    place = place / size;
+ 	    n = 0;
+ 	    for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 		if (is_in_set(c, i)) {
+ 		    for(j = n; j < expansion; j += skip) {
+ 			for(k = 0; k < place; k++) {
+ 			    p = GETSET(B1, j+k+offset);
+ 			    (void) set_insert(p, i);
+ 			}
+ 		    }
+ 		    n += place;
+ 		}
+ 	    }
+ 	}
+     }
+ }
+ 
+ 
+ pcover unravel_range(B, start, end)
+ IN pcover B;
+ IN int start, end;
+ {
+     pcover B1;
+     int var, total_size, expansion, size;
+     register pcube p, last, startbase = cube.temp[1];
+ 
+     /* Create the starting base for those variables not being unravelled */
+     (void) set_copy(startbase, cube.emptyset);
+     for(var = 0; var < start; var++)
+ 	(void) set_or(startbase, startbase, cube.var_mask[var]);
+     for(var = end+1; var < cube.num_vars; var++)
+ 	(void) set_or(startbase, startbase, cube.var_mask[var]);
+ 
+     /* Determine how many cubes it will blow up into */
+     total_size = 0;
+     foreach_set(B, last, p) {
+ 	expansion = 1;
+ 	for(var = start; var <= end; var++)
+ 	    if ((size = set_dist(p, cube.var_mask[var])) >= 2)
+ 		if ((expansion *= size) > 1000000)
+ 		    fatal("unreasonable expansion in unravel");
+ 	total_size += expansion;
+     }
+ 
+     /* We can now allocate a cover of exactly the correct size */
+     B1 = new_cover(total_size);
+     foreach_set(B, last, p) {
+ 	cb_unravel(p, start, end, startbase, B1);
+     }
+     free_cover(B);
+     return B1;
+ }
+ 
+ 
+ pcover unravel(B, start)
+ IN pcover B;
+ IN int start;
+ {
+     return unravel_range(B, start, cube.num_vars-1);
+ }
+ 
+ /* lex_sort -- sort cubes in a standard lexical fashion */
+ pcover lex_sort(T)
+ pcover T;
+ {
+     pcover T1 = sf_unlist(sf_sort(T, lex_order), T->count, T->sf_size);
+     free_cover(T);
+     return T1;
+ }
+ 
+ 
+ /* size_sort -- sort cubes by their size */
+ pcover size_sort(T)
+ pcover T;
+ {
+     pcover T1 = sf_unlist(sf_sort(T, descend), T->count, T->sf_size);
+     free_cover(T);
+     return T1;
+ }
+ 
+ 
+ /*  mini_sort -- sort cubes according to the heuristics of mini */
+ pcover mini_sort(F, compare)
+ pcover F;
+ int (*compare)();
+ {
+     register int *count, cnt, n = cube.size, i;
+     register pcube p, last;
+     pcover F_sorted;
+     pcube *F1;
+ 
+     /* Perform a column sum over the set family */
+     count = sf_count(F);
+ 
+     /* weight is "inner product of the cube and the column sums" */
+     foreach_set(F, last, p) {
+ 	cnt = 0;
+ 	for(i = 0; i < n; i++)
+ 	    if (is_in_set(p, i))
+ 		cnt += count[i];
+ 	PUTSIZE(p, cnt);
+     }
+     FREE(count);
+ 
+     /* use qsort to sort the array */
+     qsort((char *) (F1 = sf_list(F)), F->count, sizeof(pcube), compare);
+     F_sorted = sf_unlist(F1, F->count, F->sf_size);
+     free_cover(F);
+ 
+     return F_sorted;
+ }
+ 
+ 
+ /* sort_reduce -- Espresso strategy for ordering the cubes before reduction */
+ pcover sort_reduce(T)
+ IN pcover T;
+ {
+     register pcube p, last, largest = NULL;
+     register int bestsize = -1, size, n = cube.num_vars;
+     pcover T_sorted;
+     pcube *T1;
+ 
+     if (T->count == 0)
+ 	return T;
+ 
+     /* find largest cube */
+     foreach_set(T, last, p)
+ 	if ((size = set_ord(p)) > bestsize)
+ 	    largest = p, bestsize = size;
+ 
+     foreach_set(T, last, p)
+ 	PUTSIZE(p, ((n - cdist(largest,p)) << 7) + MIN(set_ord(p),127));
+ 
+     qsort((char *) (T1 = sf_list(T)), T->count, sizeof(pcube), descend);
+     T_sorted = sf_unlist(T1, T->count, T->sf_size);
+     free_cover(T);
+ 
+     return T_sorted;
+ }
+ 
+ pcover random_order(F)
+ register pcover F;
+ {
+     pset temp;
+     register int i, k;
+ #ifdef RANDOM
+     long random();
+ #endif
+ 
+     temp = set_new(F->sf_size);
+     for(i = F->count - 1; i > 0; i--) {
+ 	/* Choose a random number between 0 and i */
+ #ifdef RANDOM
+ 	k = random() % i;
+ #else
+ 	/* this is not meant to be really used; just provides an easy
+ 	   "out" if random() and srandom() aren't around
+ 	*/
+ 	k = (i*23 + 997) % i;
+ #endif
+ 	/* swap sets i and k */
+ 	set_copy(temp, GETSET(F, k));
+ 	set_copy(GETSET(F, k), GETSET(F, i));
+ 	set_copy(GETSET(F, i), temp);
+     }
+     set_free(temp);
+     return F;
+ }
+ 
+ /*
+  *  cubelist_partition -- take a cubelist T and see if it has any components;
+  *  if so, return cubelist's of the two partitions A and B; the return value
+  *  is the size of the partition; if not, A and B
+  *  are undefined and the return value is 0
+  */
+ int cubelist_partition(T, A, B, comp_debug)
+ pcube *T;			/* a list of cubes */
+ pcube **A, **B;			/* cubelist of partition and remainder */
+ unsigned int comp_debug;
+ {
+     register pcube *T1, p, seed, cof;
+     pcube *A1, *B1;
+     bool change;
+     int count, numcube;
+ 
+     numcube = CUBELISTSIZE(T);
+ 
+     /* Mark all cubes -- covered cubes belong to the partition */
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	RESET(p, COVERED);
+     }
+ 
+     /*
+      *  Extract a partition from the cubelist T; start with the first cube as a
+      *  seed, and then pull in all cubes which share a variable with the seed;
+      *  iterate until no new cubes are brought into the partition.
+      */
+     seed = set_save(T[2]);
+     cof = T[0];
+     SET(T[2], COVERED);
+     count = 1;
+ 
+     do {
+ 	change = FALSE;
+ 	for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	    if (! TESTP(p, COVERED) && ccommon(p, seed, cof)) {
+ 		INLINEset_and(seed, seed, p);
+ 		SET(p, COVERED);
+ 		change = TRUE;
+ 		count++;
+ 	    }
+ 	
+ 	}
+     } while (change);
+ 
+     set_free(seed);
+ 
+     if (comp_debug) {
+ 	printf("COMPONENT_REDUCTION: split into %d %d\n",
+ 	    count, numcube - count);
+     }
+ 
+     if (count != numcube) {
+ 	/* Allocate and setup the cubelist's for the two partitions */
+ 	*A = A1 = ALLOC(pcube, numcube+3);
+ 	*B = B1 = ALLOC(pcube, numcube+3);
+ 	(*A)[0] = set_save(T[0]);
+ 	(*B)[0] = set_save(T[0]);
+ 	A1 = *A + 2;
+ 	B1 = *B + 2;
+ 
+ 	/* Loop over the cubes in T and distribute to A and B */
+ 	for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	    if (TESTP(p, COVERED)) {
+ 		*A1++ = p;
+ 	    } else {
+ 		*B1++ = p;
+ 	    }
+ 	}
+ 
+ 	/* Stuff needed at the end of the cubelist's */
+ 	*A1++ = NULL;
+ 	(*A)[1] = (pcube) A1;
+ 	*B1++ = NULL;
+ 	(*B)[1] = (pcube) B1;
+     }
+ 
+     return numcube - count;
+ }
+ 
+ /*
+  *  quick cofactor against a single output function
+  */
+ pcover cof_output(T, i)
+ pcover T;
+ register int i;
+ {
+     pcover T1;
+     register pcube p, last, pdest, mask;
+ 
+     mask = cube.var_mask[cube.output];
+     T1 = new_cover(T->count);
+     foreach_set(T, last, p) {
+ 	if (is_in_set(p, i)) {
+ 	    pdest = GETSET(T1, T1->count++);
+ 	    INLINEset_or(pdest, p, mask);
+ 	    RESET(pdest, PRIME);
+ 	}
+     }
+     return T1;
+ }
+ 
+ 
+ /*
+  *  quick intersection against a single output function
+  */
+ pcover uncof_output(T, i)
+ pcover T;
+ int i;
+ {
+     register pcube p, last, mask;
+ 
+     if (T == NULL) {
+ 	return T;
+     }
+ 
+     mask = cube.var_mask[cube.output];
+     foreach_set(T, last, p) {
+ 	INLINEset_diff(p, p, mask);
+ 	set_insert(p, i);
+     }
+     return T;
+ }
+ 
+ 
+ /*
+  *  A generic routine to perform an operation for each output function
+  *
+  *  func() is called with a PLA for each output function (with the output
+  *  part effectively removed).
+  *  func1() is called after reforming the equivalent output function
+  *
+  *  Each function returns TRUE if process is to continue
+  */
+ foreach_output_function(PLA, func, func1)
+ pPLA PLA;
+ int (*func)();
+ int (*func1)();
+ {
+     pPLA PLA1;
+     int i;
+ 
+     /* Loop for each output function */
+     for(i = 0; i < cube.part_size[cube.output]; i++) {
+ 
+ 	/* cofactor on the output part */
+ 	PLA1 = new_PLA();
+ 	PLA1->F = cof_output(PLA->F, i + cube.first_part[cube.output]);
+ 	PLA1->R = cof_output(PLA->R, i + cube.first_part[cube.output]);
+ 	PLA1->D = cof_output(PLA->D, i + cube.first_part[cube.output]);
+ 
+ 	/* Call a routine to do something with the cover */
+ 	if ((*func)(PLA1, i) == 0) {
+ 	    free_PLA(PLA1);
+ 	    return;
+ 	}
+ 
+ 	/* intersect with the particular output part again */
+ 	PLA1->F = uncof_output(PLA1->F, i + cube.first_part[cube.output]);
+ 	PLA1->R = uncof_output(PLA1->R, i + cube.first_part[cube.output]);
+ 	PLA1->D = uncof_output(PLA1->D, i + cube.first_part[cube.output]);
+ 
+ 	/* Call a routine to do something with the final result */
+ 	if ((*func1)(PLA1, i) == 0) {
+ 	    free_PLA(PLA1);
+ 	    return;
+ 	}
+ 
+ 	/* Cleanup for next go-around */
+ 	free_PLA(PLA1);
+ 	
+ 
+     }
+ }
+ 
+ static pcover Fmin;
+ static pcube phase;
+ 
+ /*
+  *  minimize each output function individually
+  */
+ void so_espresso(PLA, strategy)
+ pPLA PLA;
+ int strategy;
+ {
+     Fmin = new_cover(PLA->F->count);
+     if (strategy == 0) {
+ 	foreach_output_function(PLA, so_do_espresso, so_save);
+     } else {
+ 	foreach_output_function(PLA, so_do_exact, so_save);
+     }
+     sf_free(PLA->F);
+     PLA->F = Fmin;
+ }
+ 
+ 
+ /*
+  *  minimize each output function, choose function or complement based on the
+  *  one with the fewer number of terms
+  */
+ void so_both_espresso(PLA, strategy)
+ pPLA PLA;
+ int strategy;
+ {
+     phase = set_save(cube.fullset);
+     Fmin = new_cover(PLA->F->count);
+     if (strategy == 0) {
+ 	foreach_output_function(PLA, so_both_do_espresso, so_both_save);
+     } else {
+ 	foreach_output_function(PLA, so_both_do_exact, so_both_save);
+     }
+     sf_free(PLA->F);
+     PLA->F = Fmin;
+     PLA->phase = phase;
+ }
+ 
+ 
+ int so_do_espresso(PLA, i)
+ pPLA PLA;
+ int i;
+ {
+     char word[32];
+ 
+     /* minimize the single-output function (on-set) */
+     skip_make_sparse = 1;
+     (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+     EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+     return 1;
+ }
+ 
+ 
+ int so_do_exact(PLA, i)
+ pPLA PLA;
+ int i;
+ {
+     char word[32];
+ 
+     /* minimize the single-output function (on-set) */
+     skip_make_sparse = 1;
+     (void) sprintf(word, "EXACT-POS(%d)", i);
+     EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+     return 1;
+ }
+ 
+ 
+ /*ARGSUSED*/
+ int so_save(PLA, i)
+ pPLA PLA;
+ int i;
+ {
+     Fmin = sf_append(Fmin, PLA->F);	/* disposes of PLA->F */
+     PLA->F = NULL;
+     return 1;
+ }
+ 
+ 
+ int so_both_do_espresso(PLA, i)
+ pPLA PLA;
+ int i;
+ {
+     char word[32];
+ 
+     /* minimize the single-output function (on-set) */
+     (void) sprintf(word, "ESPRESSO-POS(%d)", i);
+     skip_make_sparse = 1;
+     EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), word, PLA->F);
+ 
+     /* minimize the single-output function (off-set) */
+     (void) sprintf(word, "ESPRESSO-NEG(%d)", i);
+     skip_make_sparse = 1;
+     EXEC_S(PLA->R = espresso(PLA->R, PLA->D, PLA->F), word, PLA->R);
+ 
+     return 1;
+ }
+ 
+ 
+ int so_both_do_exact(PLA, i)
+ pPLA PLA;
+ int i;
+ {
+     char word[32];
+ 
+     /* minimize the single-output function (on-set) */
+     (void) sprintf(word, "EXACT-POS(%d)", i);
+     skip_make_sparse = 1;
+     EXEC_S(PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1), word, PLA->F);
+ 
+     /* minimize the single-output function (off-set) */
+     (void) sprintf(word, "EXACT-NEG(%d)", i);
+     skip_make_sparse = 1;
+     EXEC_S(PLA->R = minimize_exact(PLA->R, PLA->D, PLA->F, 1), word, PLA->R);
+ 
+     return 1;
+ }
+ 
+ 
+ int so_both_save(PLA, i)
+ pPLA PLA;
+ int i;
+ {
+     if (PLA->F->count > PLA->R->count) {
+ 	sf_free(PLA->F);
+ 	PLA->F = PLA->R;
+ 	PLA->R = NULL;
+ 	i += cube.first_part[cube.output];
+ 	set_remove(phase, i);
+     } else {
+ 	sf_free(PLA->R);
+ 	PLA->R = NULL;
+     }
+     Fmin = sf_append(Fmin, PLA->F);
+     PLA->F = NULL;
+     return 1;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrmisc.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrmisc.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrmisc.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,133 ----
+ #include "espresso.h"
+ 
+ 
+ /* cost -- compute the cost of a cover */
+ void cover_cost(F, cost)
+ IN pcover F;
+ INOUT pcost cost;
+ {
+     register pcube p, last;
+     pcube *T;
+     int var;
+ 
+     /* use the routine used by cofactor to decide splitting variables */
+     massive_count(T = cube1list(F));
+     free_cubelist(T);
+ 
+     cost->cubes = F->count;
+     cost->total = cost->in = cost->out = cost->mv = cost->primes = 0;
+ 
+     /* Count transistors (zeros) for each binary variable (inputs) */
+     for(var = 0; var < cube.num_binary_vars; var++)
+ 	cost->in += cdata.var_zeros[var];
+ 
+     /* Count transistors for each mv variable based on sparse/dense */
+     for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++)
+ 	if (cube.sparse[var])
+ 	    cost->mv += F->count * cube.part_size[var] - cdata.var_zeros[var];
+ 	else
+ 	    cost->mv += cdata.var_zeros[var];
+ 
+     /* Count the transistors (ones) for the output variable */
+     if (cube.num_binary_vars != cube.num_vars) {
+ 	var = cube.num_vars - 1;
+ 	cost->out = F->count * cube.part_size[var] - cdata.var_zeros[var];
+     }
+ 
+     /* Count the number of nonprime cubes */
+     foreach_set(F, last, p)
+ 	cost->primes += TESTP(p, PRIME) != 0;
+ 
+     /* Count the total number of literals */
+     cost->total = cost->in + cost->out + cost->mv;
+ }
+ 
+ 
+ /* fmt_cost -- return a string which reports the "cost" of a cover */
+ char *fmt_cost(cost)
+ IN pcost cost;
+ {
+     static char s[200];
+ 
+     if (cube.num_binary_vars == cube.num_vars - 1)
+ 	(void) sprintf(s, "c=%d(%d) in=%d out=%d tot=%d",
+ 	    cost->cubes, cost->cubes - cost->primes, cost->in,
+ 	    cost->out, cost->total);
+     else
+ 	(void) sprintf(s, "c=%d(%d) in=%d mv=%d out=%d",
+ 	   cost->cubes, cost->cubes - cost->primes, cost->in,
+ 	   cost->mv, cost->out);
+     return s;
+ }
+ 
+ 
+ char *print_cost(F)
+ IN pcover F;
+ {
+     cost_t cost;
+     cover_cost(F, &cost);
+     return fmt_cost(&cost);
+ }
+ 
+ 
+ /* copy_cost -- copy a cost function from s to d */
+ void copy_cost(s, d)
+ pcost s, d;
+ {
+     d->cubes = s->cubes;
+     d->in = s->in;
+     d->out = s->out;
+     d->mv = s->mv;
+     d->total = s->total;
+     d->primes = s->primes;
+ }
+ 
+ 
+ /* size_stamp -- print single line giving the size of a cover */
+ void size_stamp(T, name)
+ IN pcover T;
+ IN char *name;
+ {
+     printf("# %s\tCost is %s\n", name, print_cost(T));
+     (void) fflush(stdout);
+ }
+ 
+ 
+ /* print_trace -- print a line reporting size and time after a function */
+ void print_trace(T, name, time)
+ pcover T;
+ char *name;
+ long time;
+ {
+     printf("# %s\tTime was %s, cost is %s\n",
+ 	name, print_time(time), print_cost(T));
+     (void) fflush(stdout);
+ }
+ 
+ 
+ /* totals -- add time spent in the function into the totals */
+ void totals(time, i, T, cost)
+ long time;
+ int i;
+ pcover T;
+ pcost cost;
+ {
+     time = ptime() - time;
+     total_time[i] += time;
+     total_calls[i]++;
+     cover_cost(T, cost);
+     if (trace) {
+ 	printf("# %s\tTime was %s, cost is %s\n",
+ 	    total_name[i], print_time(time), fmt_cost(cost));
+ 	(void) fflush(stdout);
+     }
+ }
+ 
+ 
+ /* fatal -- report fatal error message and take a dive */
+ void fatal(s)
+ char *s;
+ {
+     fprintf(stderr, "espresso: %s\n", s);
+     exit(1);
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrout.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrout.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/cvrout.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,588 ----
+ /*
+     module: cvrout.c
+     purpose: cube and cover output routines
+ */
+ 
+ #include "espresso.h"
+ 
+ void fprint_pla(fp, PLA, output_type)
+ INOUT FILE *fp;
+ IN pPLA PLA;
+ IN int output_type;
+ {
+     int num;
+     register pcube last, p;
+ 
+     if ((output_type & CONSTRAINTS_type) != 0) {
+ 	output_symbolic_constraints(fp, PLA, 0);
+ 	output_type &= ~ CONSTRAINTS_type;
+ 	if (output_type == 0) {
+ 	    return;
+ 	}
+     }
+ 
+     if ((output_type & SYMBOLIC_CONSTRAINTS_type) != 0) {
+ 	output_symbolic_constraints(fp, PLA, 1);
+ 	output_type &= ~ SYMBOLIC_CONSTRAINTS_type;
+ 	if (output_type == 0) {
+ 	    return;
+ 	}
+     }
+ 
+     if (output_type == PLEASURE_type) {
+ 	pls_output(PLA);
+     } else if (output_type == EQNTOTT_type) {
+ 	eqn_output(PLA);
+     } else if (output_type == KISS_type) {
+ 	kiss_output(fp, PLA);
+     } else {
+ 	fpr_header(fp, PLA, output_type);
+ 
+ 	num = 0;
+ 	if (output_type & F_type) num += (PLA->F)->count;
+ 	if (output_type & D_type) num += (PLA->D)->count;
+ 	if (output_type & R_type) num += (PLA->R)->count;
+ 	fprintf(fp, ".p %d\n", num);
+ 
+ 	/* quick patch 01/17/85 to support TPLA ! */
+ 	if (output_type == F_type) {
+ 	    foreach_set(PLA->F, last, p) {
+ 		print_cube(fp, p, "01");
+ 	    }
+ 	    fprintf(fp, ".e\n");
+ 	} else {
+ 	    if (output_type & F_type) {
+ 		foreach_set(PLA->F, last, p) {
+ 		    print_cube(fp, p, "~1");
+ 		}
+ 	    }
+ 	    if (output_type & D_type) {
+ 		foreach_set(PLA->D, last, p) {
+ 		    print_cube(fp, p, "~2");
+ 		}
+ 	    }
+ 	    if (output_type & R_type) {
+ 		foreach_set(PLA->R, last, p) {
+ 		    print_cube(fp, p, "~0");
+ 		}
+ 	    }
+ 	    fprintf(fp, ".end\n");
+ 	}
+     }
+ }
+ 
+ void fpr_header(fp, PLA, output_type)
+ FILE *fp;
+ pPLA PLA;
+ int output_type;
+ {
+     register int i, var;
+     int first, last;
+ 
+     /* .type keyword gives logical type */
+     if (output_type != F_type) {
+ 	fprintf(fp, ".type ");
+ 	if (output_type & F_type) putc('f', fp);
+ 	if (output_type & D_type) putc('d', fp);
+ 	if (output_type & R_type) putc('r', fp);
+ 	putc('\n', fp);
+     }
+ 
+     /* Check for binary or multiple-valued labels */
+     if (cube.num_mv_vars <= 1) {
+ 	fprintf(fp, ".i %d\n", cube.num_binary_vars);
+ 	if (cube.output != -1)
+ 	    fprintf(fp, ".o %d\n", cube.part_size[cube.output]);
+     } else {
+ 	fprintf(fp, ".mv %d %d", cube.num_vars, cube.num_binary_vars);
+ 	for(var = cube.num_binary_vars; var < cube.num_vars; var++)
+ 	    fprintf(fp, " %d", cube.part_size[var]);
+ 	fprintf(fp, "\n");
+     }
+ 
+     /* binary valued labels */
+     if (PLA->label != NIL(char *) && PLA->label[1] != NIL(char)
+ 	    && cube.num_binary_vars > 0) {
+ 	fprintf(fp, ".ilb");
+ 	for(var = 0; var < cube.num_binary_vars; var++)
+ 	    fprintf(fp, " %s", INLABEL(var));
+ 	putc('\n', fp);
+     }
+ 
+     /* output-part (last multiple-valued variable) labels */
+     if (PLA->label != NIL(char *) &&
+ 	    PLA->label[cube.first_part[cube.output]] != NIL(char)
+ 		&& cube.output != -1) {
+ 	fprintf(fp, ".ob");
+ 	for(i = 0; i < cube.part_size[cube.output]; i++)
+ 	    fprintf(fp, " %s", OUTLABEL(i));
+ 	putc('\n', fp);
+     }
+ 
+     /* multiple-valued labels */
+     for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+ 	first = cube.first_part[var];
+ 	last = cube.last_part[var];
+ 	if (PLA->label != NULL && PLA->label[first] != NULL) {
+ 	    fprintf(fp, ".label var=%d", var);
+ 	    for(i = first; i <= last; i++) {
+ 		fprintf(fp, " %s", PLA->label[i]);
+ 	    }
+ 	    putc('\n', fp);
+ 	}
+     }
+ 
+     if (PLA->phase != (pcube) NULL) {
+ 	first = cube.first_part[cube.output];
+ 	last = cube.last_part[cube.output];
+ 	fprintf(fp, "#.phase ");
+ 	for(i = first; i <= last; i++)
+ 	    putc(is_in_set(PLA->phase,i) ? '1' : '0', fp);
+ 	fprintf(fp, "\n");
+     }
+ }
+ 
+ void pls_output(PLA)
+ IN pPLA PLA;
+ {
+     register pcube last, p;
+ 
+     printf(".option unmerged\n");
+     makeup_labels(PLA);
+     pls_label(PLA, stdout);
+     pls_group(PLA, stdout);
+     printf(".p %d\n", PLA->F->count);
+     foreach_set(PLA->F, last, p) {
+ 	print_expanded_cube(stdout, p, PLA->phase);
+     }
+     printf(".end\n");
+ }
+ 
+ 
+ void pls_group(PLA, fp)
+ pPLA PLA;
+ FILE *fp;
+ {
+     int var, i, col, len;
+ 
+     fprintf(fp, "\n.group");
+     col = 6;
+     for(var = 0; var < cube.num_vars-1; var++) {
+ 	fprintf(fp, " ("), col += 2;
+ 	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 	    len = strlen(PLA->label[i]);
+ 	    if (col + len > 75)
+ 		fprintf(fp, " \\\n"), col = 0;
+ 	    else if (i != 0)
+ 		putc(' ', fp), col += 1;
+ 	    fprintf(fp, "%s", PLA->label[i]), col += len;
+ 	}
+ 	fprintf(fp, ")"), col += 1;
+     }
+     fprintf(fp, "\n");
+ }
+ 
+ 
+ void pls_label(PLA, fp)
+ pPLA PLA;
+ FILE *fp;
+ {
+     int var, i, col, len;
+ 
+     fprintf(fp, ".label");
+     col = 6;
+     for(var = 0; var < cube.num_vars; var++)
+ 	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 	    len = strlen(PLA->label[i]);
+ 	    if (col + len > 75)
+ 		fprintf(fp, " \\\n"), col = 0;
+ 	    else
+ 		putc(' ', fp), col += 1;
+ 	    fprintf(fp, "%s", PLA->label[i]), col += len;
+ 	}
+ }
+ 
+ 
+ 
+ /*
+     eqntott output mode -- output algebraic equations
+ */
+ void eqn_output(PLA)
+ pPLA PLA;
+ {
+     register pcube p, last;
+     register int i, var, col, len;
+     int x;
+     bool firstand, firstor;
+ 
+     if (cube.output == -1)
+ 	fatal("Cannot have no-output function for EQNTOTT output mode");
+     if (cube.num_mv_vars != 1)
+ 	fatal("Must have binary-valued function for EQNTOTT output mode");
+     makeup_labels(PLA);
+ 
+     /* Write a single equation for each output */
+     for(i = 0; i < cube.part_size[cube.output]; i++) {
+ 	printf("%s = ", OUTLABEL(i));
+ 	col = strlen(OUTLABEL(i)) + 3;
+ 	firstor = TRUE;
+ 
+ 	/* Write product terms for each cube in this output */
+ 	foreach_set(PLA->F, last, p)
+ 	    if (is_in_set(p, i + cube.first_part[cube.output])) {
+ 		if (firstor)
+ 		    printf("("), col += 1;
+ 		else
+ 		    printf(" | ("), col += 4;
+ 		firstor = FALSE;
+ 		firstand = TRUE;
+ 
+ 		/* print out a product term */
+ 		for(var = 0; var < cube.num_binary_vars; var++)
+ 		    if ((x=GETINPUT(p, var)) != DASH) {
+ 			len = strlen(INLABEL(var));
+ 			if (col+len > 72)
+ 			    printf("\n    "), col = 4;
+ 			if (! firstand)
+ 			    printf("&"), col += 1;
+ 			firstand = FALSE;
+ 			if (x == ZERO)
+ 			    printf("!"), col += 1;
+ 			printf("%s", INLABEL(var)), col += len;
+ 		    }
+ 		printf(")"), col += 1;
+ 	    }
+ 	printf(";\n\n");
+     }
+ }
+ 
+ 
+ char *fmt_cube(c, out_map, s)
+ register pcube c;
+ register char *out_map, *s;
+ {
+     register int i, var, last, len = 0;
+ 
+     for(var = 0; var < cube.num_binary_vars; var++) {
+ 	s[len++] = "?01-" [GETINPUT(c, var)];
+     }
+     for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ 	s[len++] = ' ';
+ 	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 	    s[len++] = "01" [is_in_set(c, i) != 0];
+ 	}
+     }
+     if (cube.output != -1) {
+ 	last = cube.last_part[cube.output];
+ 	s[len++] = ' ';
+ 	for(i = cube.first_part[cube.output]; i <= last; i++) {
+ 	    s[len++] = out_map [is_in_set(c, i) != 0];
+ 	}
+     }
+     s[len] = '\0';
+     return s;
+ }
+ 
+ 
+ void print_cube(fp, c, out_map)
+ register FILE *fp;
+ register pcube c;
+ register char *out_map;
+ {
+     register int i, var, ch;
+     int last;
+ 
+     for(var = 0; var < cube.num_binary_vars; var++) {
+ 	ch = "?01-" [GETINPUT(c, var)];
+ 	putc(ch, fp);
+     }
+     for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ 	putc(' ', fp);
+ 	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 	    ch = "01" [is_in_set(c, i) != 0];
+ 	    putc(ch, fp);
+ 	}
+     }
+     if (cube.output != -1) {
+ 	last = cube.last_part[cube.output];
+ 	putc(' ', fp);
+ 	for(i = cube.first_part[cube.output]; i <= last; i++) {
+ 	    ch = out_map [is_in_set(c, i) != 0];
+ 	    putc(ch, fp);
+ 	}
+     }
+     putc('\n', fp);
+ }
+ 
+ 
+ void print_expanded_cube(fp, c, phase)
+ register FILE *fp;
+ register pcube c;
+ pcube phase;
+ {
+     register int i, var, ch;
+     char *out_map;
+ 
+     for(var = 0; var < cube.num_binary_vars; var++) {
+ 	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 	    ch = "~1" [is_in_set(c, i) != 0];
+ 	    putc(ch, fp);
+ 	}
+     }
+     for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ 	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 	    ch = "1~" [is_in_set(c, i) != 0];
+ 	    putc(ch, fp);
+ 	}
+     }
+     if (cube.output != -1) {
+ 	var = cube.num_vars - 1;
+ 	putc(' ', fp);
+ 	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 	    if (phase == (pcube) NULL || is_in_set(phase, i)) {
+ 		out_map = "~1";
+ 	    } else {
+ 		out_map = "~0";
+ 	    }
+ 	    ch = out_map[is_in_set(c, i) != 0];
+ 	    putc(ch, fp);
+ 	}
+     }
+     putc('\n', fp);
+ }
+ 
+ 
+ char *pc1(c) pcube c;
+ {static char s1[256];return fmt_cube(c, "01", s1);}
+ char *pc2(c) pcube c;
+ {static char s2[256];return fmt_cube(c, "01", s2);}
+ 
+ 
+ void debug_print(T, name, level)
+ pcube *T;
+ char *name;
+ int level;
+ {
+     register pcube *T1, p, temp;
+     register int cnt;
+ 
+     cnt = CUBELISTSIZE(T);
+     temp = new_cube();
+     if (verbose_debug && level == 0)
+ 	printf("\n");
+     printf("%s[%d]: ord(T)=%d\n", name, level, cnt);
+     if (verbose_debug) {
+ 	printf("cofactor=%s\n", pc1(T[0]));
+ 	for(T1 = T+2, cnt = 1; (p = *T1++) != (pcube) NULL; cnt++)
+ 	    printf("%4d. %s\n", cnt, pc1(set_or(temp, p, T[0])));
+     }
+     free_cube(temp);
+ }
+ 
+ 
+ void debug1_print(T, name, num)
+ pcover T;
+ char *name;
+ int num;
+ {
+     register int cnt = 1;
+     register pcube p, last;
+ 
+     if (verbose_debug && num == 0)
+ 	printf("\n");
+     printf("%s[%d]: ord(T)=%d\n", name, num, T->count);
+     if (verbose_debug)
+ 	foreach_set(T, last, p)
+ 	    printf("%4d. %s\n", cnt++, pc1(p));
+ }
+ 
+ 
+ void cprint(T)
+ pcover T;
+ {
+     register pcube p, last;
+ 
+     foreach_set(T, last, p)
+ 	printf("%s\n", pc1(p));
+ }
+ 
+ 
+ int makeup_labels(PLA)
+ pPLA PLA;
+ {
+     int var, i, ind;
+ 
+     if (PLA->label == (char **) NULL)
+ 	PLA_labels(PLA);
+ 
+     for(var = 0; var < cube.num_vars; var++)
+ 	for(i = 0; i < cube.part_size[var]; i++) {
+ 	    ind = cube.first_part[var] + i;
+ 	    if (PLA->label[ind] == (char *) NULL) {
+ 		PLA->label[ind] = ALLOC(char, 15);
+ 		if (var < cube.num_binary_vars)
+ 		    if ((i % 2) == 0)
+ 			(void) sprintf(PLA->label[ind], "v%d.bar", var);
+ 		    else
+ 			(void) sprintf(PLA->label[ind], "v%d", var);
+ 		else
+ 		    (void) sprintf(PLA->label[ind], "v%d.%d", var, i);
+ 	    }
+ 	}
+ }
+ 
+ 
+ kiss_output(fp, PLA)
+ FILE *fp;
+ pPLA PLA;
+ {
+     register pset last, p;
+ 
+     foreach_set(PLA->F, last, p) {
+ 	kiss_print_cube(fp, PLA, p, "~1");
+     }
+     foreach_set(PLA->D, last, p) {
+ 	kiss_print_cube(fp, PLA, p, "~2");
+     }
+ }
+ 
+ 
+ kiss_print_cube(fp, PLA, p, out_string)
+ FILE *fp;
+ pPLA PLA;
+ pcube p;
+ char *out_string;
+ {
+     register int i, var;
+     int part, x;
+ 
+     for(var = 0; var < cube.num_binary_vars; var++) {
+ 	x = "?01-" [GETINPUT(p, var)];
+ 	putc(x, fp);
+     }
+ 
+     for(var = cube.num_binary_vars; var < cube.num_vars - 1; var++) {
+ 	putc(' ', fp);
+ 	if (setp_implies(cube.var_mask[var], p)) {
+ 	    putc('-', fp);
+ 	} else {
+ 	    part = -1;
+ 	    for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 		if (is_in_set(p, i)) {
+ 		    if (part != -1) {
+ 			fatal("more than 1 part in a symbolic variable\n");
+ 		    }
+ 		    part = i;
+ 		}
+ 	    }
+ 	    if (part == -1) {
+ 		putc('~', fp);	/* no parts, hope its an output ... */
+ 	    } else {
+ 		(void) fputs(PLA->label[part], fp);
+ 	    }
+ 	}
+     }
+ 
+     if ((var = cube.output) != -1) {
+ 	putc(' ', fp);
+ 	for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 	    x = out_string [is_in_set(p, i) != 0];
+ 	    putc(x, fp);
+ 	}
+     }
+ 
+     putc('\n', fp);
+ }
+ 
+ output_symbolic_constraints(fp, PLA, output_symbolic)
+ FILE *fp;
+ pPLA PLA;
+ int output_symbolic;
+ {
+     pset_family A;
+     register int i, j;
+     int size, var, npermute, *permute, *weight, noweight;
+ 
+     if ((cube.num_vars - cube.num_binary_vars) <= 1) {
+ 	return;
+     }
+     makeup_labels(PLA);
+ 
+     for(var=cube.num_binary_vars; var < cube.num_vars-1; var++) {
+ 
+ 	/* pull out the columns for variable "var" */
+ 	npermute = cube.part_size[var];
+ 	permute = ALLOC(int, npermute);
+ 	for(i=0; i < npermute; i++) {
+ 	    permute[i] = cube.first_part[var] + i;
+ 	}
+ 	A = sf_permute(sf_save(PLA->F), permute, npermute);
+ 	FREE(permute);
+ 
+ 
+ 	/* Delete the singletons and the full sets */
+ 	noweight = 0;
+ 	for(i = 0; i < A->count; i++) {
+ 	    size = set_ord(GETSET(A,i));
+ 	    if (size == 1 || size == A->sf_size) {
+ 		sf_delset(A, i--);
+ 		noweight++;
+ 	    }
+ 	}
+ 
+ 
+ 	/* Count how many times each is duplicated */
+ 	weight = ALLOC(int, A->count);
+ 	for(i = 0; i < A->count; i++) {
+ 	    RESET(GETSET(A, i), COVERED);
+ 	}
+ 	for(i = 0; i < A->count; i++) {
+ 	    weight[i] = 0;
+ 	    if (! TESTP(GETSET(A,i), COVERED)) {
+ 		weight[i] = 1;
+ 		for(j = i+1; j < A->count; j++) {
+ 		    if (setp_equal(GETSET(A,i), GETSET(A,j))) {
+ 			weight[i]++;
+ 			SET(GETSET(A,j), COVERED);
+ 		    }
+ 		}
+ 	    }
+ 	}
+ 
+ 
+ 	/* Print out the contraints */
+ 	if (! output_symbolic) {
+ 	    (void) fprintf(fp,
+ 	    "# Symbolic constraints for variable %d (Numeric form)\n", var);
+ 	    (void) fprintf(fp, "# unconstrained weight = %d\n", noweight);
+ 	    (void) fprintf(fp, "num_codes=%d\n", cube.part_size[var]);
+ 	    for(i = 0; i < A->count; i++) {
+ 		if (weight[i] > 0) {
+ 		    (void) fprintf(fp, "weight=%d: ", weight[i]);
+ 		    for(j = 0; j < A->sf_size; j++) {
+ 			if (is_in_set(GETSET(A,i), j)) {
+ 			    (void) fprintf(fp, " %d", j);
+ 			}
+ 		    }
+ 		    (void) fprintf(fp, "\n");
+ 		}
+ 	    }
+ 	} else {
+ 	    (void) fprintf(fp,
+ 	    "# Symbolic constraints for variable %d (Symbolic form)\n", var);
+ 	    for(i = 0; i < A->count; i++) {
+ 		if (weight[i] > 0) {
+ 		    (void) fprintf(fp, "#   w=%d: (", weight[i]);
+ 		    for(j = 0; j < A->sf_size; j++) {
+ 			if (is_in_set(GETSET(A,i), j)) {
+ 			    (void) fprintf(fp, " %s",
+ 				PLA->label[cube.first_part[var]+j]);
+ 			}
+ 		    }
+ 		    (void) fprintf(fp, " )\n");
+ 		}
+ 	    }
+ 	    FREE(weight);
+ 	}
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/dominate.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/dominate.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/dominate.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,89 ----
+ #include "mincov_int.h"
+ 
+ 
+ int 
+ sm_row_dominance(A)
+ sm_matrix *A; 
+ {
+     register sm_row *prow, *prow1;
+     register sm_col *pcol, *least_col;
+     register sm_element *p, *pnext;
+     int rowcnt;
+ 
+     rowcnt = A->nrows;
+ 
+     /* Check each row against all other rows */
+     for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 
+ 	/* Among all columns with a 1 in this row, choose smallest */
+ 	least_col = sm_get_col(A, prow->first_col->col_num);
+ 	for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+ 	    pcol = sm_get_col(A, p->col_num);
+ 	    if (pcol->length < least_col->length) {
+ 		least_col = pcol;
+ 	    }
+ 	}
+ 
+ 	/* Only check for containment against rows in this column */
+ 	for(p = least_col->first_row; p != 0; p = pnext) {
+ 	    pnext = p->next_row;
+ 
+ 	    prow1 = sm_get_row(A, p->row_num);
+ 	    if ((prow1->length > prow->length) ||
+ 	              (prow1->length == prow->length && 
+ 			      prow1->row_num > prow->row_num)) {
+ 		if (sm_row_contains(prow, prow1)) {
+ 		    sm_delrow(A, prow1->row_num);
+ 		}
+ 	    }
+ 	}
+     }
+ 
+     return rowcnt - A->nrows;
+ }
+ 
+ int 
+ sm_col_dominance(A, weight)
+ sm_matrix *A;
+ int *weight;
+ {
+     register sm_row *prow;
+     register sm_col *pcol, *pcol1;
+     register sm_element *p;
+     sm_row *least_row;
+     sm_col *next_col;
+     int colcnt;
+ 
+     colcnt = A->ncols;
+ 
+     /* Check each column against all other columns */
+     for(pcol = A->first_col; pcol != 0; pcol = next_col) {
+ 	next_col = pcol->next_col;
+ 
+ 	/* Check all rows to find the one with fewest elements */
+ 	least_row = sm_get_row(A, pcol->first_row->row_num);
+ 	for(p = pcol->first_row->next_row; p != 0; p = p->next_row) {
+ 	    prow = sm_get_row(A, p->row_num);
+ 	    if (prow->length < least_row->length) {
+ 		least_row = prow;
+ 	    }
+ 	}
+ 
+ 	/* Only check for containment against columns in this row */
+ 	for(p = least_row->first_col; p != 0; p = p->next_col) {
+ 	    pcol1 = sm_get_col(A, p->col_num);
+ 	    if (weight != 0 && weight[pcol1->col_num] > weight[pcol->col_num])
+ 		continue;
+ 	    if ((pcol1->length > pcol->length) ||
+ 	       (pcol1->length == pcol->length && 
+ 			       pcol1->col_num > pcol->col_num)) {
+ 		if (sm_col_contains(pcol, pcol1)) {
+ 		    sm_delcol(A, pcol->col_num);
+ 		    break;
+ 		}
+ 	    }
+ 	}
+     }
+ 
+     return colcnt - A->ncols;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/equiv.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/equiv.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/equiv.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,85 ----
+ #include "espresso.h"
+ 
+ 
+ find_equiv_outputs(PLA)
+ pPLA PLA;
+ {
+     int i, j, ipart, jpart, some_equiv;
+     pcover *R, *F;
+ 
+     some_equiv = FALSE;
+ 
+     makeup_labels(PLA);
+ 
+     F = ALLOC(pcover, cube.part_size[cube.output]);
+     R = ALLOC(pcover, cube.part_size[cube.output]);
+ 
+     for(i = 0; i < cube.part_size[cube.output]; i++) {
+ 	ipart = cube.first_part[cube.output] + i;
+ 	R[i] = cof_output(PLA->R, ipart);
+ 	F[i] = complement(cube1list(R[i]));
+     }
+ 	
+     for(i = 0; i < cube.part_size[cube.output]-1; i++) {
+ 	for(j = i+1; j < cube.part_size[cube.output]; j++) {
+ 	    ipart = cube.first_part[cube.output] + i;
+ 	    jpart = cube.first_part[cube.output] + j;
+ 
+ 	    if (check_equiv(F[i], F[j])) {
+ 		printf("# Outputs %d and %d (%s and %s) are equivalent\n",
+ 		    i, j, PLA->label[ipart], PLA->label[jpart]);
+ 		some_equiv = TRUE;
+ 	    } else if (check_equiv(F[i], R[j])) {
+ 		printf("# Outputs %d and NOT %d (%s and %s) are equivalent\n",
+ 		    i, j, PLA->label[ipart], PLA->label[jpart]);
+ 		some_equiv = TRUE;
+ 	    } else if (check_equiv(R[i], F[j])) {
+ 		printf("# Outputs NOT %d and %d (%s and %s) are equivalent\n",
+ 		    i, j, PLA->label[ipart], PLA->label[jpart]);
+ 		some_equiv = TRUE;
+ 	    } else if (check_equiv(R[i], R[j])) {
+ 	    printf("# Outputs NOT %d and NOT %d (%s and %s) are equivalent\n",
+ 		    i, j, PLA->label[ipart], PLA->label[jpart]);
+ 		some_equiv = TRUE;
+ 	    }
+ 	}
+     }
+ 
+     if (! some_equiv) {
+ 	printf("# No outputs are equivalent\n");
+     }
+ 
+     for(i = 0; i < cube.part_size[cube.output]; i++) {
+ 	free_cover(F[i]);
+ 	free_cover(R[i]);
+     }
+     FREE(F);
+     FREE(R);
+ }
+ 
+ 
+ 
+ int check_equiv(f1, f2)
+ pcover f1, f2;
+ {
+     register pcube *f1list, *f2list;
+     register pcube p, last;
+ 
+     f1list = cube1list(f1);
+     foreach_set(f2, last, p) {
+ 	if (! cube_is_covered(f1list, p)) {
+ 	    return FALSE;
+ 	}
+     }
+     free_cubelist(f1list);
+ 
+     f2list = cube1list(f2);
+     foreach_set(f1, last, p) {
+ 	if (! cube_is_covered(f2list, p)) {
+ 	    return FALSE;
+ 	}
+     }
+     free_cubelist(f2list);
+ 
+     return TRUE;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/espresso.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/espresso.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/espresso.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,130 ----
+ /*
+  *  Module: espresso.c
+  *  Purpose: The main espresso algorithm
+  *
+  *  Returns a minimized version of the ON-set of a function
+  *
+  *  The following global variables affect the operation of Espresso:
+  *
+  *  MISCELLANEOUS:
+  *      trace
+  *          print trace information as the minimization progresses
+  *
+  *      remove_essential
+  *          remove essential primes
+  *
+  *      single_expand
+  *          if true, stop after first expand/irredundant
+  *
+  *  LAST_GASP or SUPER_GASP strategy:
+  *      use_super_gasp
+  *          uses the super_gasp strategy rather than last_gasp
+  *
+  *  SETUP strategy:
+  *      recompute_onset
+  *          recompute onset using the complement before starting
+  *
+  *      unwrap_onset
+  *          unwrap the function output part before first expand
+  *
+  *  MAKE_SPARSE strategy:
+  *      force_irredundant
+  *          iterates make_sparse to force a minimal solution (used
+  *          indirectly by make_sparse)
+  *
+  *      skip_make_sparse
+  *          skip the make_sparse step (used by opo only)
+  */
+ 
+ #include "espresso.h"
+ 
+ pcover espresso(F, D1, R)
+ pcover F, D1, R;
+ {
+     pcover E, D, Fsave;
+     pset last, p;
+     cost_t cost, best_cost;
+ 
+ begin:
+     Fsave = sf_save(F);		/* save original function */
+     D = sf_save(D1);		/* make a scratch copy of D */
+ 
+     /* Setup has always been a problem */
+     if (recompute_onset) {
+ 	EXEC(E = simplify(cube1list(F)),     "SIMPLIFY   ", E);
+ 	free_cover(F);
+ 	F = E;
+     }
+     cover_cost(F, &cost);
+     if (unwrap_onset && (cube.part_size[cube.num_vars - 1] > 1)
+       && (cost.out != cost.cubes*cube.part_size[cube.num_vars-1])
+       && (cost.out < 5000))
+ 	EXEC(F = sf_contain(unravel(F, cube.num_vars - 1)), "SETUP      ", F);
+ 
+     /* Initial expand and irredundant */
+     foreach_set(F, last, p) {
+ 	RESET(p, PRIME);
+     }
+     EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+     EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+ 
+     if (! single_expand) {
+ 	if (remove_essential) {
+ 	    EXECUTE(E = essential(&F, &D), ESSEN_TIME, E, cost);
+ 	} else {
+ 	    E = new_cover(0);
+ 	}
+ 
+ 	cover_cost(F, &cost);
+ 	do {
+ 
+ 	    /* Repeat inner loop until solution becomes "stable" */
+ 	    do {
+ 		copy_cost(&cost, &best_cost);
+ 		EXECUTE(F = reduce(F, D), REDUCE_TIME, F, cost);
+ 		EXECUTE(F = expand(F, R, FALSE), EXPAND_TIME, F, cost);
+ 		EXECUTE(F = irredundant(F, D), IRRED_TIME, F, cost);
+ 	    } while (cost.cubes < best_cost.cubes);
+ 
+ 	    /* Perturb solution to see if we can continue to iterate */
+ 	    copy_cost(&cost, &best_cost);
+ 	    if (use_super_gasp) {
+ 		F = super_gasp(F, D, R, &cost);
+ 		if (cost.cubes >= best_cost.cubes)
+ 		    break;
+ 	    } else {
+ 		F = last_gasp(F, D, R, &cost);
+ 	    }
+ 
+ 	} while (cost.cubes < best_cost.cubes ||
+ 	    (cost.cubes == best_cost.cubes && cost.total < best_cost.total));
+ 
+ 	/* Append the essential cubes to F */
+ 	F = sf_append(F, E);                /* disposes of E */
+ 	if (trace) size_stamp(F, "ADJUST     ");
+     }
+ 
+     /* Free the D which we used */
+     free_cover(D);
+ 
+     /* Attempt to make the PLA matrix sparse */
+     if (! skip_make_sparse) {
+ 	F = make_sparse(F, D1, R);
+     }
+ 
+     /*
+      *  Check to make sure function is actually smaller !!
+      *  This can only happen because of the initial unravel.  If we fail,
+      *  then run the whole thing again without the unravel.
+      */
+     if (Fsave->count < F->count) {
+ 	free_cover(F);
+ 	F = Fsave;
+ 	unwrap_onset = FALSE;
+ 	goto begin;
+     } else {
+ 	free_cover(Fsave);
+     }
+ 
+     return F;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/espresso.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/espresso.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/espresso.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,768 ----
+ /*
+  *  espresso.h -- header file for Espresso-mv
+  */
+ 
+ #include "port.h"
+ #include "utility.h"
+ #include "sparse.h"
+ #include "mincov.h"
+ 
+ #define ptime()		util_cpu_time()
+ #define print_time(t)	util_print_time(t)
+ 
+ #ifdef IBM_WATC
+ #define void int
+ #include "short.h"
+ #endif
+ 
+ #ifdef IBMPC		/* set default options for IBM/PC */
+ #define NO_INLINE
+ #define BPI 16
+ #endif
+ 
+ /*-----THIS USED TO BE set.h----- */
+ 
+ /*
+  *  set.h -- definitions for packed arrays of bits
+  *
+  *   This header file describes the data structures which comprise a
+  *   facility for efficiently implementing packed arrays of bits
+  *   (otherwise known as sets, cf. Pascal).
+  *
+  *   A set is a vector of bits and is implemented here as an array of
+  *   unsigned integers.  The low order bits of set[0] give the index of
+  *   the last word of set data.  The higher order bits of set[0] are
+  *   used to store data associated with the set.  The set data is
+  *   contained in elements set[1] ... set[LOOP(set)] as a packed bit
+  *   array.
+  *
+  *   A family of sets is a two-dimensional matrix of bits and is
+  *   implemented with the data type "set_family".
+  *
+  *   BPI == 32 and BPI == 16 have been tested and work.
+  */
+ 
+ 
+ /* Define host machine characteristics of "unsigned int" */
+ #ifndef BPI
+ #define BPI             32              /* # bits per integer */
+ #endif
+ 
+ #if BPI == 32
+ #define LOGBPI          5               /* log(BPI)/log(2) */
+ #else
+ #define LOGBPI          4               /* log(BPI)/log(2) */
+ #endif
+ 
+ /* Define the set type */
+ typedef unsigned int *pset;
+ 
+ /* Define the set family type -- an array of sets */
+ typedef struct set_family {
+     int wsize;                  /* Size of each set in 'ints' */
+     int sf_size;                /* User declared set size */
+     int capacity;               /* Number of sets allocated */
+     int count;                  /* The number of sets in the family */
+     int active_count;           /* Number of "active" sets */
+     pset data;                  /* Pointer to the set data */
+     struct set_family *next;    /* For garbage collection */
+ } set_family_t, *pset_family;
+ 
+ /* Macros to set and test single elements */
+ #define WHICH_WORD(element)     (((element) >> LOGBPI) + 1)
+ #define WHICH_BIT(element)      ((element) & (BPI-1))
+ 
+ /* # of ints needed to allocate a set with "size" elements */
+ #if BPI == 32
+ #define SET_SIZE(size)          ((size) <= BPI ? 2 : (WHICH_WORD((size)-1) + 1))
+ #else
+ #define SET_SIZE(size)          ((size) <= BPI ? 3 : (WHICH_WORD((size)-1) + 2))
+ #endif
+ 
+ /*
+  *  Three fields are maintained in the first word of the set
+  *      LOOP is the index of the last word used for set data
+  *      LOOPCOPY is the index of the last word in the set
+  *      SIZE is available for general use (e.g., recording # elements in set)
+  *      NELEM retrieves the number of elements in the set
+  */
+ #define LOOP(set)               (set[0] & 0x03ff)
+ #define PUTLOOP(set, i)         (set[0] &= ~0x03ff, set[0] |= (i))
+ #if BPI == 32
+ #define LOOPCOPY(set)           LOOP(set)
+ #define SIZE(set)               (set[0] >> 16)
+ #define PUTSIZE(set, size)      (set[0] &= 0xffff, set[0] |= ((size) << 16))
+ #else
+ #define LOOPCOPY(set)           (LOOP(set) + 1)
+ #define SIZE(set)               (set[LOOP(set)+1])
+ #define PUTSIZE(set, size)      ((set[LOOP(set)+1]) = (size))
+ #endif
+ 
+ #define NELEM(set)		(BPI * LOOP(set))
+ #define LOOPINIT(size)		((size <= BPI) ? 1 : WHICH_WORD((size)-1))
+ 
+ /*
+  *      FLAGS store general information about the set
+  */
+ #define SET(set, flag)          (set[0] |= (flag))
+ #define RESET(set, flag)        (set[0] &= ~ (flag))
+ #define TESTP(set, flag)        (set[0] & (flag))
+ 
+ /* Flag definitions are ... */
+ #define PRIME           0x8000          /* cube is prime */
+ #define NONESSEN        0x4000          /* cube cannot be essential prime */
+ #define ACTIVE          0x2000          /* cube is still active */
+ #define REDUND          0x1000          /* cube is redundant(at this point) */
+ #define COVERED         0x0800          /* cube has been covered */
+ #define RELESSEN        0x0400          /* cube is relatively essential */
+ 
+ /* Most efficient way to look at all members of a set family */
+ #define foreach_set(R, last, p)\
+     for(p=R->data,last=p+R->count*R->wsize;p<last;p+=R->wsize)
+ #define foreach_remaining_set(R, last, pfirst, p)\
+     for(p=pfirst+R->wsize,last=R->data+R->count*R->wsize;p<last;p+=R->wsize)
+ #define foreach_active_set(R, last, p)\
+     foreach_set(R,last,p) if (TESTP(p, ACTIVE))
+ 
+ /* Another way that also keeps the index of the current set member in i */
+ #define foreachi_set(R, i, p)\
+     for(p=R->data,i=0;i<R->count;p+=R->wsize,i++)
+ #define foreachi_active_set(R, i, p)\
+     foreachi_set(R,i,p) if (TESTP(p, ACTIVE))
+ 
+ /* Looping over all elements in a set:
+  *      foreach_set_element(pset p, int i, unsigned val, int base) {
+  *		.
+  *		.
+  *		.
+  *      }
+  */
+ #define foreach_set_element(p, i, val, base) 		\
+     for(i = LOOP(p); i > 0; )				\
+ 	for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1)  \
+ 	    if (val & 1)
+ 
+ /* Return a pointer to a given member of a set family */
+ #define GETSET(family, index)   ((family)->data + (family)->wsize * (index))
+ 
+ /* Allocate and deallocate sets */
+ #define set_new(size)	set_clear(ALLOC(unsigned int, SET_SIZE(size)), size)
+ #define set_full(size)	set_fill(ALLOC(unsigned int, SET_SIZE(size)), size)
+ #define set_save(r)	set_copy(ALLOC(unsigned int, SET_SIZE(NELEM(r))), r)
+ #define set_free(r)	FREE(r)
+ 
+ /* Check for set membership, remove set element and insert set element */
+ #define is_in_set(set, e)       (set[WHICH_WORD(e)] & (1 << WHICH_BIT(e)))
+ #define set_remove(set, e)      (set[WHICH_WORD(e)] &= ~ (1 << WHICH_BIT(e)))
+ #define set_insert(set, e)      (set[WHICH_WORD(e)] |= 1 << WHICH_BIT(e))
+ 
+ /* Inline code substitution for those places that REALLY need it on a VAX */
+ #ifdef NO_INLINE
+ #define INLINEset_copy(r, a)		(void) set_copy(r,a)
+ #define INLINEset_clear(r, size)	(void) set_clear(r, size)
+ #define INLINEset_fill(r, size)		(void) set_fill(r, size)
+ #define INLINEset_and(r, a, b)		(void) set_and(r, a, b)
+ #define INLINEset_or(r, a, b)		(void) set_or(r, a, b)
+ #define INLINEset_diff(r, a, b)		(void) set_diff(r, a, b)
+ #define INLINEset_ndiff(r, a, b, f)	(void) set_ndiff(r, a, b, f)
+ #define INLINEset_xor(r, a, b)		(void) set_xor(r, a, b)
+ #define INLINEset_xnor(r, a, b, f)	(void) set_xnor(r, a, b, f)
+ #define INLINEset_merge(r, a, b, mask)	(void) set_merge(r, a, b, mask)
+ #define INLINEsetp_implies(a, b, when_false)	\
+     if (! setp_implies(a,b)) when_false
+ #define INLINEsetp_disjoint(a, b, when_false)	\
+     if (! setp_disjoint(a,b)) when_false
+ #define INLINEsetp_equal(a, b, when_false)	\
+     if (! setp_equal(a,b)) when_false
+ 
+ #else
+ 
+ #define INLINEset_copy(r, a)\
+     {register int i_=LOOPCOPY(a); do r[i_]=a[i_]; while (--i_>=0);}
+ #define INLINEset_clear(r, size)\
+     {register int i_=LOOPINIT(size); *r=i_; do r[i_] = 0; while (--i_ > 0);}
+ #define INLINEset_fill(r, size)\
+     {register int i_=LOOPINIT(size); *r=i_; \
+     r[i_]=((unsigned int)(~0))>>(i_*BPI-size); while(--i_>0) r[i_]=~0;}
+ #define INLINEset_and(r, a, b)\
+     {register int i_=LOOP(a); PUTLOOP(r,i_);\
+     do r[i_] = a[i_] & b[i_]; while (--i_>0);}
+ #define INLINEset_or(r, a, b)\
+     {register int i_=LOOP(a); PUTLOOP(r,i_);\
+     do r[i_] = a[i_] | b[i_]; while (--i_>0);}
+ #define INLINEset_diff(r, a, b)\
+     {register int i_=LOOP(a); PUTLOOP(r,i_);\
+     do r[i_] = a[i_] & ~ b[i_]; while (--i_>0);}
+ #define INLINEset_ndiff(r, a, b, fullset)\
+     {register int i_=LOOP(a); PUTLOOP(r,i_);\
+     do r[i_] = fullset[i_] & (a[i_] | ~ b[i_]); while (--i_>0);}
+ #ifdef IBM_WATC
+ #define INLINEset_xor(r, a, b)		(void) set_xor(r, a, b)
+ #define INLINEset_xnor(r, a, b, f)	(void) set_xnor(r, a, b, f)
+ #else
+ #define INLINEset_xor(r, a, b)\
+     {register int i_=LOOP(a); PUTLOOP(r,i_);\
+     do r[i_] = a[i_] ^ b[i_]; while (--i_>0);}
+ #define INLINEset_xnor(r, a, b, fullset)\
+     {register int i_=LOOP(a); PUTLOOP(r,i_);\
+     do r[i_] = fullset[i_] & ~ (a[i_] ^ b[i_]); while (--i_>0);}
+ #endif
+ #define INLINEset_merge(r, a, b, mask)\
+     {register int i_=LOOP(a); PUTLOOP(r,i_);\
+     do r[i_] = (a[i_]&mask[i_]) | (b[i_]&~mask[i_]); while (--i_>0);}
+ #define INLINEsetp_implies(a, b, when_false)\
+     {register int i_=LOOP(a); do if (a[i_]&~b[i_]) break; while (--i_>0);\
+     if (i_ != 0) when_false;}
+ #define INLINEsetp_disjoint(a, b, when_false)\
+     {register int i_=LOOP(a); do if (a[i_]&b[i_]) break; while (--i_>0);\
+     if (i_ != 0) when_false;}
+ #define INLINEsetp_equal(a, b, when_false)\
+     {register int i_=LOOP(a); do if (a[i_]!=b[i_]) break; while (--i_>0);\
+     if (i_ != 0) when_false;}
+ 
+ #endif
+ 
+ #if BPI == 32
+ #define count_ones(v)\
+     (bit_count[v & 255] + bit_count[(v >> 8) & 255]\
+     + bit_count[(v >> 16) & 255] + bit_count[(v >> 24) & 255])
+ #else
+ #define count_ones(v)   (bit_count[v & 255] + bit_count[(v >> 8) & 255])
+ #endif
+ 
+ /* Table for efficient bit counting */
+ extern int bit_count[256];
+ /*----- END OF set.h ----- */
+ 
+ /* Define a boolean type */
+ #define bool	int
+ #define FALSE	0
+ #define TRUE 	1
+ #define MAYBE	2
+ #define print_bool(x) ((x) == 0 ? "FALSE" : ((x) == 1 ? "TRUE" : "MAYBE"))
+ 
+ /* Map many cube/cover types/routines into equivalent set types/routines */
+ #define pcube                   pset
+ #define new_cube()              set_new(cube.size)
+ #define free_cube(r)            set_free(r)
+ #define pcover                  pset_family
+ #define new_cover(i)            sf_new(i, cube.size)
+ #define free_cover(r)           sf_free(r)
+ #define free_cubelist(T)        FREE(T[0]); FREE(T);
+ 
+ 
+ /* cost_t describes the cost of a cover */
+ typedef struct cost_struct {
+     int cubes;			/* number of cubes in the cover */
+     int in;			/* transistor count, binary-valued variables */
+     int out;			/* transistor count, output part */
+     int mv;			/* transistor count, multiple-valued vars */
+     int total;			/* total number of transistors */
+     int primes;			/* number of prime cubes */
+ } cost_t, *pcost;
+ 
+ 
+ /* pair_t describes bit-paired variables */
+ typedef struct pair_struct {
+     int cnt;
+     int *var1;
+     int *var2;
+ } pair_t, *ppair;
+ 
+ 
+ /* symbolic_list_t describes a single ".symbolic" line */
+ typedef struct symbolic_list_struct {
+     int variable;
+     int pos;
+     struct symbolic_list_struct *next;
+ } symbolic_list_t;
+ 
+ 
+ /* symbolic_list_t describes a single ".symbolic" line */
+ typedef struct symbolic_label_struct {
+     char *label;
+     struct symbolic_label_struct *next;
+ } symbolic_label_t;
+ 
+ 
+ /* symbolic_t describes a linked list of ".symbolic" lines */
+ typedef struct symbolic_struct {
+     symbolic_list_t *symbolic_list;	/* linked list of items */
+     int symbolic_list_length;		/* length of symbolic_list list */
+     symbolic_label_t *symbolic_label;	/* linked list of new names */
+     int symbolic_label_length;		/* length of symbolic_label list */
+     struct symbolic_struct *next;
+ } symbolic_t;
+ 
+ 
+ /* PLA_t stores the logical representation of a PLA */
+ typedef struct {
+     pcover F, D, R;		/* on-set, off-set and dc-set */
+     char *filename;             /* filename */
+     int pla_type;               /* logical PLA format */
+     pcube phase;                /* phase to split into on-set and off-set */
+     ppair pair;                 /* how to pair variables */
+     char **label;		/* labels for the columns */
+     symbolic_t *symbolic;	/* allow binary->symbolic mapping */
+     symbolic_t *symbolic_output;/* allow symbolic output mapping */
+ } PLA_t, *pPLA;
+ 
+ #define equal(a,b)      (strcmp(a,b) == 0)
+ 
+ /* This is a hack which I wish I hadn't done, but too painful to change */
+ #define CUBELISTSIZE(T)         (((pcube *) T[1] - T) - 3)
+ 
+ /* For documentation purposes */
+ #define IN
+ #define OUT
+ #define INOUT
+ 
+ /* The pla_type field describes the input and output format of the PLA */
+ #define F_type          1
+ #define D_type          2
+ #define R_type          4
+ #define PLEASURE_type   8               /* output format */
+ #define EQNTOTT_type    16              /* output format algebraic eqns */
+ #define KISS_type	128		/* output format kiss */
+ #define CONSTRAINTS_type	256	/* output the constraints (numeric) */
+ #define SYMBOLIC_CONSTRAINTS_type 512	/* output the constraints (symbolic) */
+ #define FD_type (F_type | D_type)
+ #define FR_type (F_type | R_type)
+ #define DR_type (D_type | R_type)
+ #define FDR_type (F_type | D_type | R_type)
+ 
+ /* Definitions for the debug variable */
+ #define COMPL           0x0001
+ #define ESSEN           0x0002
+ #define EXPAND          0x0004
+ #define EXPAND1         0x0008
+ #define GASP            0x0010
+ #define IRRED           0x0020
+ #define REDUCE          0x0040
+ #define REDUCE1         0x0080
+ #define SPARSE          0x0100
+ #define TAUT            0x0200
+ #define EXACT           0x0400
+ #define MINCOV          0x0800
+ #define MINCOV1         0x1000
+ #define SHARP           0x2000
+ #define IRRED1		0x4000
+ 
+ #define VERSION\
+     "UC Berkeley, Espresso Version #2.3, Release date 01/31/88"
+ 
+ /* Define constants used for recording program statistics */
+ #define TIME_COUNT      16
+ #define READ_TIME       0
+ #define COMPL_TIME      1
+ #define ONSET_TIME	2
+ #define ESSEN_TIME      3
+ #define EXPAND_TIME     4
+ #define IRRED_TIME      5
+ #define REDUCE_TIME     6
+ #define GEXPAND_TIME    7
+ #define GIRRED_TIME     8
+ #define GREDUCE_TIME    9
+ #define PRIMES_TIME     10
+ #define MINCOV_TIME	11
+ #define MV_REDUCE_TIME  12
+ #define RAISE_IN_TIME   13
+ #define VERIFY_TIME     14
+ #define WRITE_TIME	15
+ 
+ 
+ /* For those who like to think about PLAs, macros to get at inputs/outputs */
+ #define NUMINPUTS       cube.num_binary_vars
+ #define NUMOUTPUTS      cube.part_size[cube.num_vars - 1]
+ 
+ #define POSITIVE_PHASE(pos)\
+     (is_in_set(PLA->phase, cube.first_part[cube.output]+pos) != 0)
+ 
+ #define INLABEL(var)    PLA->label[cube.first_part[var] + 1]
+ #define OUTLABEL(pos)   PLA->label[cube.first_part[cube.output] + pos]
+ 
+ #define GETINPUT(c, pos)\
+     ((c[WHICH_WORD(2*pos)] >> WHICH_BIT(2*pos)) & 3)
+ #define GETOUTPUT(c, pos)\
+     (is_in_set(c, cube.first_part[cube.output] + pos) != 0)
+ 
+ #define PUTINPUT(c, pos, value)\
+     c[WHICH_WORD(2*pos)] = (c[WHICH_WORD(2*pos)] & ~(3 << WHICH_BIT(2*pos)))\
+ 		| (value << WHICH_BIT(2*pos))
+ #define PUTOUTPUT(c, pos, value)\
+     c[WHICH_WORD(pos)] = (c[WHICH_WORD(pos)] & (1 << WHICH_BIT(pos)))\
+ 		| (value << WHICH_BIT(pos))
+ 
+ #define TWO     3
+ #define DASH    3
+ #define ONE     2
+ #define ZERO    1
+ 
+ 
+ #define EXEC(fct, name, S)\
+     {long t=ptime();fct;if(trace)print_trace(S,name,ptime()-t);}
+ #define EXEC_S(fct, name, S)\
+     {long t=ptime();fct;if(summary)print_trace(S,name,ptime()-t);}
+ #define EXECUTE(fct,i,S,cost)\
+     {long t=ptime();fct;totals(t,i,S,&(cost));}
+ 
+ /*
+  *    Global Variable Declarations
+  */
+ 
+ extern unsigned int debug;              /* debug parameter */
+ extern bool verbose_debug;              /* -v:  whether to print a lot */
+ extern char *total_name[TIME_COUNT];    /* basic function names */
+ extern long total_time[TIME_COUNT];     /* time spent in basic fcts */
+ extern int total_calls[TIME_COUNT];     /* # calls to each fct */
+ 
+ extern bool echo_comments;		/* turned off by -eat option */
+ extern bool echo_unknown_commands;	/* always true ?? */
+ extern bool force_irredundant;          /* -nirr command line option */
+ extern bool skip_make_sparse;
+ extern bool kiss;                       /* -kiss command line option */
+ extern bool pos;                        /* -pos command line option */
+ extern bool print_solution;             /* -x command line option */
+ extern bool recompute_onset;            /* -onset command line option */
+ extern bool remove_essential;           /* -ness command line option */
+ extern bool single_expand;              /* -fast command line option */
+ extern bool summary;                    /* -s command line option */
+ extern bool trace;                      /* -t command line option */
+ extern bool unwrap_onset;               /* -nunwrap command line option */
+ extern bool use_random_order;		/* -random command line option */
+ extern bool use_super_gasp;		/* -strong command line option */
+ extern char *filename;			/* filename PLA was read from */
+ extern bool debug_exact_minimization;   /* dumps info for -do exact */
+ 
+ 
+ /*
+  *  pla_types are the input and output types for reading/writing a PLA
+  */
+ struct pla_types_struct {
+     char *key;
+     int value;
+ };
+ 
+ 
+ /*
+  *  The cube structure is a global structure which contains information
+  *  on how a set maps into a cube -- i.e., number of parts per variable,
+  *  number of variables, etc.  Also, many fields are pre-computed to
+  *  speed up various primitive operations.
+  */
+ #define CUBE_TEMP       10
+ 
+ struct cube_struct {
+     int size;                   /* set size of a cube */
+     int num_vars;               /* number of variables in a cube */
+     int num_binary_vars;        /* number of binary variables */
+     int *first_part;            /* first element of each variable */
+     int *last_part;             /* first element of each variable */
+     int *part_size;             /* number of elements in each variable */
+     int *first_word;            /* first word for each variable */
+     int *last_word;             /* last word for each variable */
+     pset binary_mask;           /* Mask to extract binary variables */
+     pset mv_mask;               /* mask to get mv parts */
+     pset *var_mask;             /* mask to extract a variable */
+     pset *temp;                 /* an array of temporary sets */
+     pset fullset;               /* a full cube */
+     pset emptyset;              /* an empty cube */
+     unsigned int inmask;        /* mask to get odd word of binary part */
+     int inword;                 /* which word number for above */
+     int *sparse;                /* should this variable be sparse? */
+     int num_mv_vars;            /* number of multiple-valued variables */
+     int output;                 /* which variable is "output" (-1 if none) */
+ };
+ 
+ struct cdata_struct {
+     int *part_zeros;            /* count of zeros for each element */
+     int *var_zeros;             /* count of zeros for each variable */
+     int *parts_active;          /* number of "active" parts for each var */
+     bool *is_unate;             /* indicates given var is unate */
+     int vars_active;            /* number of "active" variables */
+     int vars_unate;             /* number of unate variables */
+     int best;                   /* best "binate" variable */
+ };
+ 
+ 
+ extern struct pla_types_struct pla_types[];
+ extern struct cube_struct cube, temp_cube_save;
+ extern struct cdata_struct cdata, temp_cdata_save;
+ 
+ #ifdef lint
+ #define DISJOINT 0x5555
+ #else
+ #if BPI == 32
+ #define DISJOINT 0x55555555
+ #else
+ #define DISJOINT 0x5555
+ #endif
+ #endif
+ 
+ /* function declarations */
+ 
+ /* cofactor.c */	extern int binate_split_select();
+ /* cofactor.c */	extern pcover cubeunlist();
+ /* cofactor.c */	extern pcube *cofactor();
+ /* cofactor.c */	extern pcube *cube1list();
+ /* cofactor.c */	extern pcube *cube2list();
+ /* cofactor.c */	extern pcube *cube3list();
+ /* cofactor.c */	extern pcube *scofactor();
+ /* cofactor.c */	extern void massive_count();
+ /* compl.c */	extern pcover complement();
+ /* compl.c */	extern pcover simplify();
+ /* compl.c */	extern void simp_comp();
+ /* contain.c */	extern int d1_rm_equal();
+ /* contain.c */	extern int rm2_contain();
+ /* contain.c */	extern int rm2_equal();
+ /* contain.c */	extern int rm_contain();
+ /* contain.c */	extern int rm_equal();
+ /* contain.c */	extern int rm_rev_contain();
+ /* contain.c */	extern pset *sf_list();
+ /* contain.c */	extern pset *sf_sort();
+ /* contain.c */	extern pset_family d1merge();
+ /* contain.c */	extern pset_family dist_merge();
+ /* contain.c */	extern pset_family sf_contain();
+ /* contain.c */	extern pset_family sf_dupl();
+ /* contain.c */	extern pset_family sf_ind_contain();
+ /* contain.c */	extern pset_family sf_ind_unlist();
+ /* contain.c */	extern pset_family sf_merge();
+ /* contain.c */	extern pset_family sf_rev_contain();
+ /* contain.c */	extern pset_family sf_union();
+ /* contain.c */	extern pset_family sf_unlist();
+ /* cubestr.c */	extern void cube_setup();
+ /* cubestr.c */	extern void restore_cube_struct();
+ /* cubestr.c */	extern void save_cube_struct();
+ /* cubestr.c */	extern void setdown_cube();
+ /* cvrin.c */	extern PLA_labels();
+ /* cvrin.c */	extern char *get_word();
+ /* cvrin.c */	extern int label_index();
+ /* cvrin.c */	extern int read_pla();
+ /* cvrin.c */	extern int read_symbolic();
+ /* cvrin.c */	extern pPLA new_PLA();
+ /* cvrin.c */	extern void PLA_summary();
+ /* cvrin.c */	extern void free_PLA();
+ /* cvrin.c */	extern void parse_pla();
+ /* cvrin.c */	extern void read_cube();
+ /* cvrin.c */	extern void skip_line();
+ /* cvrm.c */	extern foreach_output_function();
+ /* cvrm.c */	extern int cubelist_partition();
+ /* cvrm.c */	extern int so_both_do_espresso();
+ /* cvrm.c */	extern int so_both_do_exact();
+ /* cvrm.c */	extern int so_both_save();
+ /* cvrm.c */	extern int so_do_espresso();
+ /* cvrm.c */	extern int so_do_exact();
+ /* cvrm.c */	extern int so_save();
+ /* cvrm.c */	extern pcover cof_output();
+ /* cvrm.c */	extern pcover lex_sort();
+ /* cvrm.c */	extern pcover mini_sort();
+ /* cvrm.c */	extern pcover random_order();
+ /* cvrm.c */	extern pcover size_sort();
+ /* cvrm.c */	extern pcover sort_reduce();
+ /* cvrm.c */	extern pcover uncof_output();
+ /* cvrm.c */	extern pcover unravel();
+ /* cvrm.c */	extern pcover unravel_range();
+ /* cvrm.c */	extern void so_both_espresso();
+ /* cvrm.c */	extern void so_espresso();
+ /* cvrmisc.c */	extern char *fmt_cost();
+ /* cvrmisc.c */	extern char *print_cost();
+ /* cvrmisc.c */	extern char *strsav();
+ /* cvrmisc.c */	extern void copy_cost();
+ /* cvrmisc.c */	extern void cover_cost();
+ /* cvrmisc.c */	extern void fatal();
+ /* cvrmisc.c */	extern void print_trace();
+ /* cvrmisc.c */	extern void size_stamp();
+ /* cvrmisc.c */	extern void totals();
+ /* cvrout.c */	extern char *fmt_cube();
+ /* cvrout.c */	extern char *fmt_expanded_cube();
+ /* cvrout.c */	extern char *pc1();
+ /* cvrout.c */	extern char *pc2();
+ /* cvrout.c */	extern char *pc3();
+ /* cvrout.c */	extern int makeup_labels();
+ /* cvrout.c */	extern kiss_output();
+ /* cvrout.c */	extern kiss_print_cube();
+ /* cvrout.c */	extern output_symbolic_constraints();
+ /* cvrout.c */	extern void cprint();
+ /* cvrout.c */	extern void debug1_print();
+ /* cvrout.c */	extern void debug_print();
+ /* cvrout.c */	extern void eqn_output();
+ /* cvrout.c */	extern void fpr_header();
+ /* cvrout.c */	extern void fprint_pla();
+ /* cvrout.c */	extern void pls_group();
+ /* cvrout.c */	extern void pls_label();
+ /* cvrout.c */	extern void pls_output();
+ /* cvrout.c */	extern void print_cube();
+ /* cvrout.c */	extern void print_expanded_cube();
+ /* cvrout.c */	extern void sf_debug_print();
+ /* equiv.c */	extern find_equiv_outputs();
+ /* equiv.c */	extern int check_equiv();
+ /* espresso.c */	extern pcover espresso();
+ /* essen.c */	extern bool essen_cube();
+ /* essen.c */	extern pcover cb_consensus();
+ /* essen.c */	extern pcover cb_consensus_dist0();
+ /* essen.c */	extern pcover essential();
+ /* exact.c */	extern pcover minimize_exact();
+ /* exact.c */	extern pcover minimize_exact_literals();
+ /* expand.c */	extern bool feasibly_covered();
+ /* expand.c */	extern int most_frequent();
+ /* expand.c */	extern pcover all_primes();
+ /* expand.c */	extern pcover expand();
+ /* expand.c */	extern pcover find_all_primes();
+ /* expand.c */	extern void elim_lowering();
+ /* expand.c */	extern void essen_parts();
+ /* expand.c */	extern void essen_raising();
+ /* expand.c */	extern void expand1();
+ /* expand.c */	extern void mincov();
+ /* expand.c */	extern void select_feasible();
+ /* expand.c */	extern void setup_BB_CC();
+ /* gasp.c */	extern pcover expand_gasp();
+ /* gasp.c */	extern pcover irred_gasp();
+ /* gasp.c */	extern pcover last_gasp();
+ /* gasp.c */	extern pcover super_gasp();
+ /* gasp.c */	extern void expand1_gasp();
+ /* getopt.c */	extern int getopt();
+ /* hack.c */	extern find_dc_inputs();
+ /* hack.c */	extern find_inputs();
+ /* hack.c */	extern form_bitvector();
+ /* hack.c */	extern map_dcset();
+ /* hack.c */	extern map_output_symbolic();
+ /* hack.c */	extern map_symbolic();
+ /* hack.c */	extern pcover map_symbolic_cover();
+ /* hack.c */	extern symbolic_hack_labels();
+ /* irred.c */	extern bool cube_is_covered();
+ /* irred.c */	extern bool taut_special_cases();
+ /* irred.c */	extern bool tautology();
+ /* irred.c */	extern pcover irredundant();
+ /* irred.c */	extern void mark_irredundant();
+ /* irred.c */	extern void irred_split_cover();
+ /* irred.c */	extern sm_matrix *irred_derive_table();
+ /* map.c */	extern pset minterms();
+ /* map.c */	extern void explode();
+ /* map.c */	extern void map();
+ /* opo.c */	extern output_phase_setup();
+ /* opo.c */	extern pPLA set_phase();
+ /* opo.c */	extern pcover opo();
+ /* opo.c */	extern pcube find_phase();
+ /* opo.c */	extern pset_family find_covers();
+ /* opo.c */	extern pset_family form_cover_table();
+ /* opo.c */	extern pset_family opo_leaf();
+ /* opo.c */	extern pset_family opo_recur();
+ /* opo.c */	extern void opoall();
+ /* opo.c */	extern void phase_assignment();
+ /* opo.c */	extern void repeated_phase_assignment();
+ /* pair.c */	extern generate_all_pairs();
+ /* pair.c */	extern int **find_pairing_cost();
+ /* pair.c */	extern int find_best_cost();
+ /* pair.c */	extern int greedy_best_cost();
+ /* pair.c */	extern int minimize_pair();
+ /* pair.c */	extern int pair_free();
+ /* pair.c */	extern pair_all();
+ /* pair.c */	extern pcover delvar();
+ /* pair.c */	extern pcover pairvar();
+ /* pair.c */	extern ppair pair_best_cost();
+ /* pair.c */	extern ppair pair_new();
+ /* pair.c */	extern ppair pair_save();
+ /* pair.c */	extern print_pair();
+ /* pair.c */	extern void find_optimal_pairing();
+ /* pair.c */	extern void set_pair();
+ /* pair.c */	extern void set_pair1();
+ /* primes.c */	extern pcover primes_consensus();
+ /* reduce.c */	extern bool sccc_special_cases();
+ /* reduce.c */	extern pcover reduce();
+ /* reduce.c */	extern pcube reduce_cube();
+ /* reduce.c */	extern pcube sccc();
+ /* reduce.c */	extern pcube sccc_cube();
+ /* reduce.c */	extern pcube sccc_merge();
+ /* set.c */	extern bool set_andp();
+ /* set.c */	extern bool set_orp();
+ /* set.c */	extern bool setp_disjoint();
+ /* set.c */	extern bool setp_empty();
+ /* set.c */	extern bool setp_equal();
+ /* set.c */	extern bool setp_full();
+ /* set.c */	extern bool setp_implies();
+ /* set.c */	extern char *pbv1();
+ /* set.c */	extern char *ps1();
+ /* set.c */	extern int *sf_count();
+ /* set.c */	extern int *sf_count_restricted();
+ /* set.c */	extern int bit_index();
+ /* set.c */	extern int set_dist();
+ /* set.c */	extern int set_ord();
+ /* set.c */	extern void set_adjcnt();
+ /* set.c */	extern pset set_and();
+ /* set.c */	extern pset set_clear();
+ /* set.c */	extern pset set_copy();
+ /* set.c */	extern pset set_diff();
+ /* set.c */	extern pset set_fill();
+ /* set.c */	extern pset set_merge();
+ /* set.c */	extern pset set_or();
+ /* set.c */	extern pset set_xor();
+ /* set.c */	extern pset sf_and();
+ /* set.c */	extern pset sf_or();
+ /* set.c */	extern pset_family sf_active();
+ /* set.c */	extern pset_family sf_addcol();
+ /* set.c */	extern pset_family sf_addset();
+ /* set.c */	extern pset_family sf_append();
+ /* set.c */	extern pset_family sf_bm_read();
+ /* set.c */	extern pset_family sf_compress();
+ /* set.c */	extern pset_family sf_copy();
+ /* set.c */	extern pset_family sf_copy_col();
+ /* set.c */	extern pset_family sf_delc();
+ /* set.c */	extern pset_family sf_delcol();
+ /* set.c */	extern pset_family sf_inactive();
+ /* set.c */	extern pset_family sf_join();
+ /* set.c */	extern pset_family sf_new();
+ /* set.c */	extern pset_family sf_permute();
+ /* set.c */	extern pset_family sf_read();
+ /* set.c */	extern pset_family sf_save();
+ /* set.c */	extern pset_family sf_transpose();
+ /* set.c */	extern void set_write();
+ /* set.c */	extern void sf_bm_print();
+ /* set.c */	extern void sf_cleanup();
+ /* set.c */	extern void sf_delset();
+ /* set.c */	extern void sf_free();
+ /* set.c */	extern void sf_print();
+ /* set.c */	extern void sf_write();
+ /* setc.c */	extern bool ccommon();
+ /* setc.c */	extern bool cdist0();
+ /* setc.c */	extern bool full_row();
+ /* setc.c */	extern int ascend();
+ /* setc.c */	extern int cactive();
+ /* setc.c */	extern int cdist();
+ /* setc.c */	extern int cdist01();
+ /* setc.c */	extern int cvolume();
+ /* setc.c */	extern int d1_order();
+ /* setc.c */	extern int d1_order_size();
+ /* setc.c */	extern int desc1();
+ /* setc.c */	extern int descend();
+ /* setc.c */	extern int lex_order();
+ /* setc.c */	extern int lex_order1();
+ /* setc.c */	extern pset force_lower();
+ /* setc.c */	extern void consensus();
+ /* sharp.c */	extern pcover cb1_dsharp();
+ /* sharp.c */	extern pcover cb_dsharp();
+ /* sharp.c */	extern pcover cb_recur_dsharp();
+ /* sharp.c */	extern pcover cb_recur_sharp();
+ /* sharp.c */	extern pcover cb_sharp();
+ /* sharp.c */	extern pcover cv_dsharp();
+ /* sharp.c */	extern pcover cv_intersect();
+ /* sharp.c */	extern pcover cv_sharp();
+ /* sharp.c */	extern pcover dsharp();
+ /* sharp.c */	extern pcover make_disjoint();
+ /* sharp.c */	extern pcover sharp();
+ /* sminterf.c */pset do_sm_minimum_cover();
+ /* sparse.c */	extern pcover make_sparse();
+ /* sparse.c */	extern pcover mv_reduce();
+ /* ucbqsort.c 	extern qsort(); */
+ /* ucbqsort.c */	extern qst();
+ /* unate.c */	extern pcover find_all_minimal_covers_petrick();
+ /* unate.c */	extern pcover map_cover_to_unate();
+ /* unate.c */	extern pcover map_unate_to_cover();
+ /* unate.c */	extern pset_family exact_minimum_cover();
+ /* unate.c */	extern pset_family gen_primes();
+ /* unate.c */	extern pset_family unate_compl();
+ /* unate.c */	extern pset_family unate_complement();
+ /* unate.c */	extern pset_family unate_intersect();
+ /* verify.c */	extern PLA_permute();
+ /* verify.c */	extern bool PLA_verify();
+ /* verify.c */	extern bool check_consistency();
+ /* verify.c */	extern bool verify();


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/essen.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/essen.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:20 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/essen.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,170 ----
+ /*
+     module: essen.c
+     purpose: Find essential primes in a multiple-valued function
+ */
+ 
+ #include "espresso.h"
+ 
+ /*
+     essential -- return a cover consisting of the cubes of F which are
+     essential prime implicants (with respect to F u D); Further, remove
+     these cubes from the ON-set F, and add them to the OFF-set D.
+ 
+     Sometimes EXPAND can determine that a cube is not an essential prime.
+     If so, it will set the "NONESSEN" flag in the cube.
+ 
+     We count on IRREDUNDANT to have set the flag RELESSEN to indicate
+     that a prime was relatively essential (i.e., covers some minterm
+     not contained in any other prime in the current cover), or to have
+     reset the flag to indicate that a prime was relatively redundant
+     (i.e., all minterms covered by other primes in the current cover).
+     Of course, after executing irredundant, all of the primes in the
+     cover are relatively essential, but we can mark the primes which
+     were redundant at the start of irredundant and avoid an extra check
+     on these primes for essentiality.
+ */
+ 
+ pcover essential(Fp, Dp)
+ IN pcover *Fp, *Dp;
+ {
+     register pcube last, p;
+     pcover E, F = *Fp, D = *Dp;
+ 
+     /* set all cubes in F active */
+     (void) sf_active(F);
+ 
+     /* Might as well start out with some cubes in E */
+     E = new_cover(10);
+ 
+     foreach_set(F, last, p) {
+ 	/* don't test a prime which EXPAND says is nonessential */
+ 	if (! TESTP(p, NONESSEN)) {
+ 	    /* only test a prime which was relatively essential */
+ 	    if (TESTP(p, RELESSEN)) {
+ 		/* Check essentiality */
+ 		if (essen_cube(F, D, p)) {
+ 		    if (debug & ESSEN)
+ 			printf("ESSENTIAL: %s\n", pc1(p));
+ 		    E = sf_addset(E, p);
+ 		    RESET(p, ACTIVE);
+ 		    F->active_count--;
+ 		}
+ 	    }
+ 	}
+     }
+ 
+     *Fp = sf_inactive(F);               /* delete the inactive cubes from F */
+     *Dp = sf_join(D, E);		/* add the essentials to D */
+     sf_free(D);
+     return E;
+ }
+ 
+ /*
+     essen_cube -- check if a single cube is essential or not
+ 
+     The prime c is essential iff
+ 
+ 	consensus((F u D) # c, c) u D
+ 
+     does not contain c.
+ */
+ bool essen_cube(F, D, c)
+ IN pcover F, D;
+ IN pcube c;
+ {
+     pcover H, FD;
+     pcube *H1;
+     bool essen;
+ 
+     /* Append F and D together, and take the sharp-consensus with c */
+     FD = sf_join(F, D);
+     H = cb_consensus(FD, c);
+     free_cover(FD);
+ 
+     /* Add the don't care set, and see if this covers c */
+     H1 = cube2list(H, D);
+     essen = ! cube_is_covered(H1, c);
+     free_cubelist(H1);
+ 
+     free_cover(H);
+     return essen;
+ }
+ 
+ 
+ /*
+  *  cb_consensus -- compute consensus(T # c, c)
+  */
+ pcover cb_consensus(T, c)
+ register pcover T;
+ register pcube c;
+ {
+     register pcube temp, last, p;
+     register pcover R;
+ 
+     R = new_cover(T->count*2);
+     temp = new_cube();
+     foreach_set(T, last, p) {
+ 	if (p != c) {
+ 	    switch (cdist01(p, c)) {
+ 		case 0:
+ 		    /* distance-0 needs special care */
+ 		    R = cb_consensus_dist0(R, p, c);
+ 		    break;
+ 
+ 		case 1:
+ 		    /* distance-1 is easy because no sharping required */
+ 		    consensus(temp, p, c);
+ 		    R = sf_addset(R, temp);
+ 		    break;
+ 	    }
+ 	}
+     }
+     set_free(temp);
+     return R;
+ }
+ 
+ 
+ /*
+  *  form the sharp-consensus for p and c when they intersect
+  *  What we are forming is consensus(p # c, c).
+  */
+ pcover cb_consensus_dist0(R, p, c)
+ pcover R;
+ register pcube p, c;
+ {
+     int var;
+     bool got_one;
+     register pcube temp, mask;
+     register pcube p_diff_c=cube.temp[0], p_and_c=cube.temp[1];
+ 
+     /* If c contains p, then this gives us no information for essential test */
+     if (setp_implies(p, c)) {
+ 	return R;
+     }
+ 
+     /* For the multiple-valued variables */
+     temp = new_cube();
+     got_one = FALSE;
+     INLINEset_diff(p_diff_c, p, c);
+     INLINEset_and(p_and_c, p, c);
+ 
+     for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ 	/* Check if c(var) is contained in p(var) -- if so, no news */
+ 	mask = cube.var_mask[var];
+ 	if (! setp_disjoint(p_diff_c, mask)) {
+ 	    INLINEset_merge(temp, c, p_and_c, mask);
+ 	    R = sf_addset(R, temp);
+ 	    got_one = TRUE;
+ 	}
+     }
+ 
+     /* if no cube so far, add one for the intersection */
+     if (! got_one && cube.num_binary_vars > 0) {
+ 	/* Add a single cube for the intersection of p and c */
+ 	INLINEset_and(temp, p, c);
+ 	R = sf_addset(R, temp);
+     }
+ 
+     set_free(temp);
+     return R;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/exact.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/exact.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/exact.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,166 ----
+ #include "espresso.h"
+ 
+ 
+ static void dump_irredundant();
+ static pcover do_minimize();
+ 
+ 
+ /*
+  *  minimize_exact -- main entry point for exact minimization
+  *
+  *  Global flags which affect this routine are:
+  *
+  *      debug
+  *      skip_make_sparse
+  */
+ 
+ pcover
+ minimize_exact(F, D, R, exact_cover)
+ pcover F, D, R;
+ int exact_cover;
+ {
+     return do_minimize(F, D, R, exact_cover, /*weighted*/ 0);
+ }
+ 
+ 
+ pcover
+ minimize_exact_literals(F, D, R, exact_cover)
+ pcover F, D, R;
+ int exact_cover;
+ {
+     return do_minimize(F, D, R, exact_cover, /*weighted*/ 1);
+ }
+ 
+ 
+ 
+ static pcover
+ do_minimize(F, D, R, exact_cover, weighted)
+ pcover F, D, R;
+ int exact_cover;
+ int weighted;
+ {
+     pcover newF, E, Rt, Rp;
+     pset p, last;
+     int heur, level, *weights;
+     sm_matrix *table;
+     sm_row *cover;
+     sm_element *pe;
+     int debug_save = debug;
+ 
+     if (debug & EXACT) {
+ 	debug |= (IRRED | MINCOV);
+     }
+ #if defined(sun) || defined(bsd4_2)			/* hack ... */
+     if (debug & MINCOV) {
+ 	setlinebuf(stdout);
+     }
+ #endif
+     level = (debug & MINCOV) ? 4 : 0;
+     heur = ! exact_cover;
+ 
+     /* Generate all prime implicants */
+     EXEC(F = primes_consensus(cube2list(F, D)), "PRIMES     ", F);
+ 
+     /* Setup the prime implicant table */
+     EXEC(irred_split_cover(F, D, &E, &Rt, &Rp), "ESSENTIALS ", E);
+     EXEC(table = irred_derive_table(D, E, Rp),  "PI-TABLE   ", Rp);
+ 
+     /* Solve either a weighted or nonweighted covering problem */
+     if (weighted) {
+ 	/* correct only for all 2-valued variables */
+ 	weights = ALLOC(int, F->count);
+ 	foreach_set(Rp, last, p) {
+ 	    weights[SIZE(p)] = cube.size - set_ord(p);
+ 	}
+     } else {
+ 	weights = NIL(int);
+     }
+     EXEC(cover=sm_minimum_cover(table,weights,heur,level), "MINCOV     ", F);
+     if (weights != 0) {
+ 	FREE(weights);
+     }
+ 
+     if (debug & EXACT) {
+ 	dump_irredundant(E, Rt, Rp, table);
+     }
+ 
+     /* Form the result cover */
+     newF = new_cover(100);
+     foreach_set(E, last, p) {
+ 	newF = sf_addset(newF, p);
+     }
+     sm_foreach_row_element(cover, pe) {
+ 	newF = sf_addset(newF, GETSET(F, pe->col_num));
+     }
+ 
+     free_cover(E);
+     free_cover(Rt);
+     free_cover(Rp);
+     sm_free(table);
+     sm_row_free(cover);
+     free_cover(F);
+ 
+     /* Attempt to make the results more sparse */
+     debug &= ~ (IRRED | SHARP | MINCOV);
+     if (! skip_make_sparse && R != 0) {
+ 	newF = make_sparse(newF, D, R);
+     }
+ 
+     debug = debug_save;
+     return newF;
+ }
+ 
+ static void
+ dump_irredundant(E, Rt, Rp, table)
+ pcover E, Rt, Rp;
+ sm_matrix *table;
+ {
+     FILE *fp_pi_table, *fp_primes;
+     pPLA PLA;
+     pset last, p;
+     char *file;
+ 
+     if (filename == 0 || strcmp(filename, "(stdin)") == 0) {
+ 	fp_pi_table = fp_primes = stdout;
+     } else {
+ 	file = ALLOC(char, strlen(filename)+20);
+ 	(void) sprintf(file, "%s.primes", filename);
+ 	if ((fp_primes = fopen(file, "w")) == NULL) {
+ 	    fprintf(stderr, "espresso: Unable to open %s\n", file);
+ 	    fp_primes = stdout;
+ 	}
+ 	(void) sprintf(file, "%s.pi", filename);
+ 	if ((fp_pi_table = fopen(file, "w")) == NULL) {
+ 	    fprintf(stderr, "espresso: Unable to open %s\n", file);
+ 	    fp_pi_table = stdout;
+ 	}
+ 	FREE(file);
+     }
+ 
+     PLA = new_PLA();
+     PLA_labels(PLA);
+ 
+     fpr_header(fp_primes, PLA, F_type);
+     free_PLA(PLA);
+ 
+     (void) fprintf(fp_primes, "# Essential primes are\n");
+     foreach_set(E, last, p) {
+ 	(void) fprintf(fp_primes, "%s\n", pc1(p));
+     }
+     fprintf(fp_primes, "# Totally redundant primes are\n");
+     foreach_set(Rt, last, p) {
+ 	(void) fprintf(fp_primes, "%s\n", pc1(p));
+     }
+     fprintf(fp_primes, "# Partially redundant primes are\n");
+     foreach_set(Rp, last, p) {
+ 	(void) fprintf(fp_primes, "%s\n", pc1(p));
+     }
+     if (fp_primes != stdout) {
+ 	(void) fclose(fp_primes);
+     }
+ 	
+     sm_write(fp_pi_table, table);
+     if (fp_pi_table != stdout) {
+ 	(void) fclose(fp_pi_table);
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/expand.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/expand.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/expand.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,680 ----
+ /*
+     module: expand.c
+     purpose: Perform the Espresso-II Expansion Step
+ 
+     The idea is to take each nonprime cube of the on-set and expand it
+     into a prime implicant such that we can cover as many other cubes
+     of the on-set.  If no cube of the on-set can be covered, then we
+     expand each cube into a large prime implicant by transforming the
+     problem into a minimum covering problem which is solved by the
+     heuristics of minimum_cover.
+ 
+     These routines revolve around having a representation of the
+     OFF-set.  (In contrast to the Espresso-II manuscript, we do NOT
+     require an "unwrapped" version of the OFF-set).
+ 
+     Some conventions on variable names:
+ 
+ 	SUPER_CUBE is the supercube of all cubes which can be covered
+ 	by an expansion of the cube being expanded
+ 
+ 	OVEREXPANDED_CUBE is the cube which would result from expanding
+ 	all parts which can expand individually of the cube being expanded
+ 
+ 	RAISE is the current expansion of the current cube
+ 
+ 	FREESET is the set of parts which haven't been raised or lowered yet.
+ 
+ 	INIT_LOWER is a set of parts to be removed from the free parts before
+ 	starting the expansion
+ */
+ 
+ #include "espresso.h"
+ 
+ /*
+     expand -- expand each nonprime cube of F into a prime implicant
+ 
+     If nonsparse is true, only the non-sparse variables will be expanded;
+     this is done by forcing all of the sparse variables out of the free set.
+ */
+ 
+ pcover expand(F, R, nonsparse)
+ INOUT pcover F;
+ IN pcover R;
+ IN bool nonsparse;              /* expand non-sparse variables only */
+ {
+     register pcube last, p;
+     pcube RAISE, FREESET, INIT_LOWER, SUPER_CUBE, OVEREXPANDED_CUBE;
+     int var, num_covered;
+     bool change;
+ 
+     /* Order the cubes according to "chewing-away from the edges" of mini */
+     if (use_random_order)
+ 	F = random_order(F);
+     else
+ 	F = mini_sort(F, ascend);
+ 
+     /* Allocate memory for variables needed by expand1() */
+     RAISE = new_cube();
+     FREESET = new_cube();
+     INIT_LOWER = new_cube();
+     SUPER_CUBE = new_cube();
+     OVEREXPANDED_CUBE = new_cube();
+ 
+     /* Setup the initial lowering set (differs only for nonsparse) */
+     if (nonsparse)
+ 	for(var = 0; var < cube.num_vars; var++)
+ 	    if (cube.sparse[var])
+ 		(void) set_or(INIT_LOWER, INIT_LOWER, cube.var_mask[var]);
+ 
+     /* Mark all cubes as not covered, and maybe essential */
+     foreach_set(F, last, p) {
+ 	RESET(p, COVERED);
+ 	RESET(p, NONESSEN);
+     }
+ 
+     /* Try to expand each nonprime and noncovered cube */
+     foreach_set(F, last, p) {
+ 	/* do not expand if PRIME or if covered by previous expansion */
+ 	if (! TESTP(p, PRIME) && ! TESTP(p, COVERED)) {
+ 
+ 	    /* expand the cube p, result is RAISE */
+ 	    expand1(R, F, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+ 		INIT_LOWER, &num_covered, p);
+ 	    if (debug & EXPAND)
+ 		printf("EXPAND: %s (covered %d)\n", pc1(p), num_covered);
+ 	    (void) set_copy(p, RAISE);
+ 	    SET(p, PRIME);
+ 	    RESET(p, COVERED);		/* not really necessary */
+ 
+ 	    /* See if we generated an inessential prime */
+ 	    if (num_covered == 0 && ! setp_equal(p, OVEREXPANDED_CUBE)) {
+ 		SET(p, NONESSEN);
+ 	    }
+ 	}
+     }
+ 
+     /* Delete any cubes of F which became covered during the expansion */
+     F->active_count = 0;
+     change = FALSE;
+     foreach_set(F, last, p) {
+ 	if (TESTP(p, COVERED)) {
+ 	    RESET(p, ACTIVE);
+ 	    change = TRUE;
+ 	} else {
+ 	    SET(p, ACTIVE);
+ 	    F->active_count++;
+ 	}
+     }
+     if (change)
+ 	F = sf_inactive(F);
+ 
+     free_cube(RAISE);
+     free_cube(FREESET);
+     free_cube(INIT_LOWER);
+     free_cube(SUPER_CUBE);
+     free_cube(OVEREXPANDED_CUBE);
+     return F;
+ }
+ 
+ /*
+     expand1 -- Expand a single cube against the OFF-set
+ */
+ void expand1(BB, CC, RAISE, FREESET, OVEREXPANDED_CUBE, SUPER_CUBE,
+ 		INIT_LOWER, num_covered, c)
+ pcover BB;			/* Blocking matrix (OFF-set) */
+ pcover CC;			/* Covering matrix (ON-set) */
+ pcube RAISE;			/* The current parts which have been raised */
+ pcube FREESET;			/* The current parts which are free */
+ pcube OVEREXPANDED_CUBE;	/* Overexpanded cube of c */
+ pcube SUPER_CUBE;		/* Supercube of all cubes of CC we cover */
+ pcube INIT_LOWER;		/* Parts to initially remove from FREESET */
+ int *num_covered;		/* Number of cubes of CC which are covered */
+ pcube c;			/* The cube to be expanded */
+ {
+     int bestindex;
+ 
+     if (debug & EXPAND1)
+ 	printf("\nEXPAND1:    \t%s\n", pc1(c));
+ 
+     /* initialize BB and CC */
+     SET(c, PRIME);		/* don't try to cover ourself */
+     setup_BB_CC(BB, CC);
+ 
+     /* initialize count of # cubes covered, and the supercube of them */
+     *num_covered = 0;
+     (void) set_copy(SUPER_CUBE, c);
+ 
+     /* Initialize the lowering, raising and unassigned sets */
+     (void) set_copy(RAISE, c);
+     (void) set_diff(FREESET, cube.fullset, RAISE);
+ 
+     /* If some parts are forced into lowering set, remove them */
+     if (! setp_empty(INIT_LOWER)) {
+ 	(void) set_diff(FREESET, FREESET, INIT_LOWER);
+ 	elim_lowering(BB, CC, RAISE, FREESET);
+     }
+ 
+     /* Determine what can be raised, and return the over-expanded cube */
+     essen_parts(BB, CC, RAISE, FREESET);
+     (void) set_or(OVEREXPANDED_CUBE, RAISE, FREESET);
+ 
+     /* While there are still cubes which can be covered, cover them ! */
+     if (CC->active_count > 0) {
+ 	select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered);
+     }
+ 
+     /* While there are still cubes covered by the overexpanded cube ... */
+     while (CC->active_count > 0) {
+ 	bestindex = most_frequent(CC, FREESET);
+ 	set_insert(RAISE, bestindex);
+ 	set_remove(FREESET, bestindex);
+ 	essen_parts(BB, CC, RAISE, FREESET);
+     }
+ 
+     /* Finally, when all else fails, choose the largest possible prime */
+     /* We will loop only if we decide unravelling OFF-set is too expensive */
+     while (BB->active_count > 0) {
+ 	mincov(BB, RAISE, FREESET);
+     }
+ 
+     /* Raise any remaining free coordinates */
+     (void) set_or(RAISE, RAISE, FREESET);
+ }
+ 
+ /*
+     essen_parts -- determine which parts are forced into the lowering
+     set to insure that the cube be orthognal to the OFF-set.
+ 
+     If any cube of the OFF-set is distance 1 from the raising cube,
+     then we must lower all parts of the conflicting variable.  (If the
+     cube is distance 0, we detect this error here.)
+ 
+     If there are essentially lowered parts, we can remove from consideration
+     any cubes of the OFF-set which are more than distance 1 from the
+     overexpanded cube of RAISE.
+ */
+ 
+ void essen_parts(BB, CC, RAISE, FREESET)
+ pcover BB, CC;
+ pcube RAISE, FREESET;
+ {
+     register pcube p, r = RAISE;
+     pcube lastp, xlower = cube.temp[0];
+     int dist;
+ 
+     (void) set_copy(xlower, cube.emptyset);
+ 
+     foreach_active_set(BB, lastp, p) {
+ #ifdef NO_INLINE
+ 	if ((dist = cdist01(p, r)) > 1) goto exit_if;
+ #else
+  {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+ {x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
+ exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
+ dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+ mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+ var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+ w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+ #endif
+ 	if (dist == 0) {
+ 	    fatal("ON-set and OFF-set are not orthogonal");
+ 	} else {
+ 	    (void) force_lower(xlower, p, r);
+ 	    BB->active_count--;
+ 	    RESET(p, ACTIVE);
+ 	}
+ exit_if: ;
+     }
+ 
+     if (! setp_empty(xlower)) {
+ 	(void) set_diff(FREESET, FREESET, xlower);/* remove from free set */
+ 	elim_lowering(BB, CC, RAISE, FREESET);
+     }
+ 
+     if (debug & EXPAND1)
+ 	printf("ESSEN_PARTS:\tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+ }
+ 
+ /*
+     essen_raising -- determine which parts may always be added to
+     the raising set without restricting further expansions
+ 
+     General rule: if some part is not blocked by any cube of BB, then
+     this part can always be raised.
+ */
+ 
+ void essen_raising(BB, RAISE, FREESET)
+ register pcover BB;
+ pcube RAISE, FREESET;
+ {
+     register pcube last, p, xraise = cube.temp[0];
+ 
+     /* Form union of all cubes of BB, and then take complement wrt FREESET */
+     (void) set_copy(xraise, cube.emptyset);
+     foreach_active_set(BB, last, p)
+ 	INLINEset_or(xraise, xraise, p);
+     (void) set_diff(xraise, FREESET, xraise);
+ 
+     (void) set_or(RAISE, RAISE, xraise);         /* add to raising set */
+     (void) set_diff(FREESET, FREESET, xraise);       /* remove from free set */
+ 
+     if (debug & EXPAND1)
+ 	printf("ESSEN_RAISING:\tRAISE=%s FREESET=%s\n",
+ 	    pc1(RAISE), pc2(FREESET));
+ }
+ 
+ /*
+     elim_lowering -- after removing parts from FREESET, we can reduce the
+     size of both BB and CC.
+ 
+     We mark as inactive any cube of BB which does not intersect the
+     overexpanded cube (i.e., RAISE + FREESET).  Likewise, we remove
+     from CC any cube which is not covered by the overexpanded cube.
+ */
+ 
+ void elim_lowering(BB, CC, RAISE, FREESET)
+ pcover BB, CC;
+ pcube RAISE, FREESET;
+ {
+     register pcube p, r = set_or(cube.temp[0], RAISE, FREESET);
+     pcube last;
+ 
+     /*
+      *  Remove sets of BB which are orthogonal to future expansions
+      */
+     foreach_active_set(BB, last, p) {
+ #ifdef NO_INLINE
+ 	if (! cdist0(p, r))
+ #else
+  {register int w,lastw;register unsigned int x;if((lastw=cube.inword)!=-1){x=p[
+ lastw]&r[lastw];if(~(x|x>>1)&cube.inmask)goto false;for(w=1;w<lastw;w++){x=p[w]
+ &r[w];if(~(x|x>>1)&DISJOINT)goto false;}}}{register int w,var,lastw;register
+ pcube mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.
+ var_mask[var];lastw=cube.last_word[var];for(w=cube.first_word[var];w<=lastw;w++)
+ if(p[w]&r[w]&mask[w])goto nextvar;goto false;nextvar:;}}continue;false:
+ #endif
+ 	    BB->active_count--, RESET(p, ACTIVE);
+     }
+ 
+ 
+     /*
+      *  Remove sets of CC which cannot be covered by future expansions
+      */
+     if (CC != (pcover) NULL) {
+ 	foreach_active_set(CC, last, p) {
+ #ifdef NO_INLINE
+ 	    if (! setp_implies(p, r))
+ #else
+ 	    INLINEsetp_implies(p, r, /* when false => */ goto false1);
+ 	    /* when true => go to end of loop */ continue;
+ 	    false1:
+ #endif
+ 		CC->active_count--, RESET(p, ACTIVE);
+ 	}
+     }
+ }
+ 
+ /*
+     most_frequent -- When all else fails, select a reasonable part to raise
+     The active cubes of CC are the cubes which are covered by the
+     overexpanded cube of the original cube (however, we know that none
+     of them can actually be covered by a feasible expansion of the
+     original cube).  We resort to the MINI strategy of selecting to
+     raise the part which will cover the same part in the most cubes of CC.
+ */
+ int most_frequent(CC, FREESET)
+ pcover CC;
+ pcube FREESET;
+ {
+     register int i, best_part, best_count, *count;
+     register pset p, last;
+ 
+     /* Count occurences of each variable */
+     count = ALLOC(int, cube.size);
+     for(i = 0; i < cube.size; i++)
+ 	count[i] = 0;
+     if (CC != (pcover) NULL)
+ 	foreach_active_set(CC, last, p)
+ 	    set_adjcnt(p, count, 1);
+ 
+     /* Now find which free part occurs most often */
+     best_count = best_part = -1;
+     for(i = 0; i < cube.size; i++)
+ 	if (is_in_set(FREESET,i) && count[i] > best_count) {
+ 	    best_part = i;
+ 	    best_count = count[i];
+ 	}
+     FREE(count);
+ 
+     if (debug & EXPAND1)
+ 	printf("MOST_FREQUENT:\tbest=%d FREESET=%s\n", best_part, pc2(FREESET));
+     return best_part;
+ }
+ 
+ /*
+     setup_BB_CC -- set up the blocking and covering set families;
+ 
+     Note that the blocking family is merely the set of cubes of R, and
+     that CC is the set of cubes of F which might possibly be covered
+     (i.e., nonprime cubes, and cubes not already covered)
+ */
+ 
+ void setup_BB_CC(BB, CC)
+ register pcover BB, CC;
+ {
+     register pcube p, last;
+ 
+     /* Create the block and cover set families */
+     BB->active_count = BB->count;
+     foreach_set(BB, last, p)
+ 	SET(p, ACTIVE);
+ 
+     if (CC != (pcover) NULL) {
+ 	CC->active_count = CC->count;
+ 	foreach_set(CC, last, p)
+ 	    if (TESTP(p, COVERED) || TESTP(p, PRIME))
+ 		CC->active_count--, RESET(p, ACTIVE);
+ 	    else
+ 		SET(p, ACTIVE);
+     }
+ }
+ 
+ /*
+     select_feasible -- Determine if there are cubes which can be covered,
+     and if so, raise those parts necessary to cover as many as possible.
+ 
+     We really don't check to maximize the number that can be covered;
+     instead, we check, for each fcc, how many other fcc remain fcc
+     after expanding to cover the fcc.  (Essentially one-level lookahead).
+ */
+ 
+ void select_feasible(BB, CC, RAISE, FREESET, SUPER_CUBE, num_covered)
+ pcover BB, CC;
+ pcube RAISE, FREESET, SUPER_CUBE;
+ int *num_covered;
+ {
+     register pcube p, last, bestfeas, *feas;
+     register int i, j;
+     pcube *feas_new_lower;
+     int bestcount, bestsize, count, size, numfeas, lastfeas;
+     pcover new_lower;
+ 
+     /*  Start out with all cubes covered by the over-expanded cube as
+      *  the "possibly" feasibly-covered cubes (pfcc)
+      */
+     feas = ALLOC(pcube, CC->active_count);
+     numfeas = 0;
+     foreach_active_set(CC, last, p)
+ 	feas[numfeas++] = p;
+ 
+     /* Setup extra cubes to record parts forced low after a covering */
+     feas_new_lower = ALLOC(pcube, CC->active_count);
+     new_lower = new_cover(numfeas);
+     for(i = 0; i < numfeas; i++)
+ 	feas_new_lower[i] = GETSET(new_lower, i);
+ 
+ 
+ loop:
+     /* Find the essentially raised parts -- this might cover some cubes
+        for us, without having to find out if they are fcc or not
+     */
+     essen_raising(BB, RAISE, FREESET);
+ 
+     /* Now check all "possibly" feasibly covered cubes to check feasibility */
+     lastfeas = numfeas;
+     numfeas = 0;
+     for(i = 0; i < lastfeas; i++) {
+ 	p = feas[i];
+ 
+ 	/* Check active because essen_parts might have removed it */
+ 	if (TESTP(p, ACTIVE)) {
+ 
+ 	    /*  See if the cube is already covered by RAISE --
+ 	     *  this can happen because of essen_raising() or because of
+ 	     *  the previous "loop"
+ 	     */
+ 	    if (setp_implies(p, RAISE)) {
+ 		(*num_covered) += 1;
+ 		(void) set_or(SUPER_CUBE, SUPER_CUBE, p);
+ 		CC->active_count--;
+ 		RESET(p, ACTIVE);
+ 		SET(p, COVERED);
+ 	    /* otherwise, test if it is feasibly covered */
+ 	    } else if (feasibly_covered(BB,p,RAISE,feas_new_lower[numfeas])) {
+ 		feas[numfeas] = p;			/* save the fcc */
+ 		numfeas++;
+ 	    }
+ 	}
+     }
+     if (debug & EXPAND1)
+ 	printf("SELECT_FEASIBLE: started with %d pfcc, ended with %d fcc\n",
+ 	    lastfeas, numfeas);
+ 
+     /* Exit here if there are no feasibly covered cubes */
+     if (numfeas == 0) {
+ 	FREE(feas);
+ 	FREE(feas_new_lower);
+ 	free_cover(new_lower);
+ 	return;
+     }
+ 
+     /* Now find which is the best feasibly covered cube */
+     bestcount = 0;
+     bestsize = 9999;
+     for(i = 0; i < numfeas; i++) {
+ 	size = set_dist(feas[i], FREESET);	/* # of newly raised parts */
+ 	count = 0;	/* # of other cubes which remain fcc after raising */
+ 
+ #define NEW
+ #ifdef NEW
+ 	for(j = 0; j < numfeas; j++)
+ 	    if (setp_disjoint(feas_new_lower[i], feas[j]))
+ 		count++;
+ #else
+ 	for(j = 0; j < numfeas; j++)
+ 	    if (setp_implies(feas[j], feas[i]))
+ 		count++;
+ #endif
+ 	if (count > bestcount) {
+ 	    bestcount = count;
+ 	    bestfeas = feas[i];
+ 	    bestsize = size;
+ 	} else if (count == bestcount && size < bestsize) {
+ 	    bestfeas = feas[i];
+ 	    bestsize = size;
+ 	}
+     }
+ 
+     /* Add the necessary parts to the raising set */
+     (void) set_or(RAISE, RAISE, bestfeas);
+     (void) set_diff(FREESET, FREESET, RAISE);
+     if (debug & EXPAND1)
+ 	printf("FEASIBLE:  \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+     essen_parts(BB, CC, RAISE, FREESET);
+     goto loop;
+ /* NOTREACHED */
+ }
+ 
+ /*
+     feasibly_covered -- determine if the cube c is feasibly covered
+     (i.e., if it is possible to raise all of the necessary variables
+     while still insuring orthogonality with R).  Also, if c is feasibly
+     covered, then compute the new set of parts which are forced into
+     the lowering set.
+ */
+ 
+ bool feasibly_covered(BB, c, RAISE, new_lower)
+ pcover BB;
+ pcube c, RAISE, new_lower;
+ {
+     register pcube p, r = set_or(cube.temp[0], RAISE, c);
+     int dist;
+     pcube lastp;
+ 
+     set_copy(new_lower, cube.emptyset);
+     foreach_active_set(BB, lastp, p) {
+ #ifdef NO_INLINE
+ 	if ((dist = cdist01(p, r)) > 1) goto exit_if;
+ #else
+  {register int w,last;register unsigned int x;dist=0;if((last=cube.inword)!=-1)
+ {x=p[last]&r[last];if(x=~(x|x>>1)&cube.inmask)if((dist=count_ones(x))>1)goto
+ exit_if;for(w=1;w<last;w++){x=p[w]&r[w];if(x=~(x|x>>1)&DISJOINT)if(dist==1||(
+ dist+=count_ones(x))>1)goto exit_if;}}}{register int w,var,last;register pcube
+ mask;for(var=cube.num_binary_vars;var<cube.num_vars;var++){mask=cube.var_mask[
+ var];last=cube.last_word[var];for(w=cube.first_word[var];w<=last;w++)if(p[w]&r[
+ w]&mask[w])goto nextvar;if(++dist>1)goto exit_if;nextvar:;}}
+ #endif
+ 	if (dist == 0)
+ 	    return FALSE;
+ 	else
+ 	    (void) force_lower(new_lower, p, r);
+     exit_if: ;
+     }
+     return TRUE;
+ }
+ 
+ /*
+     mincov -- transform the problem of expanding a cube to a maximally-
+     large prime implicant into the problem of selecting a minimum
+     cardinality cover over a family of sets.
+ 
+     When we get to this point, we must unravel the remaining off-set.
+     This may be painful.
+ */
+ 
+ void mincov(BB, RAISE, FREESET)
+ pcover BB;
+ pcube RAISE, FREESET;
+ {
+     int expansion, nset, var, dist;
+     pset_family B;
+     register pcube xraise=cube.temp[0], xlower, p, last, plower;
+ 
+ #ifdef RANDOM_MINCOV
+     dist = random() % set_ord(FREESET);
+     for(var = 0; var < cube.size && dist >= 0; var++) {
+ 	if (is_in_set(FREESET, var)) {
+ 	    dist--;
+ 	}
+     }
+ 
+     set_insert(RAISE, var);
+     set_remove(FREESET, var);
+     (void) essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+ #else
+ 
+     /* Create B which are those cubes which we must avoid intersecting */
+     B = new_cover(BB->active_count);
+     foreach_active_set(BB, last, p) {
+ 	plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+ 	(void) force_lower(plower, p, RAISE);
+     }
+ 
+     /* Determine how many sets it will blow up into after the unravel */
+     nset = 0;
+     foreach_set(B, last, p) {
+ 	expansion = 1;
+ 	for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ 	    if ((dist=set_dist(p, cube.var_mask[var])) > 1) {
+ 		expansion *= dist;
+ 		if (expansion > 500) goto heuristic_mincov;
+ 	    }
+ 	}
+ 	nset += expansion;
+ 	if (nset > 500) goto heuristic_mincov;
+     }
+ 
+     B = unravel(B, cube.num_binary_vars);
+     xlower = do_sm_minimum_cover(B);
+ 
+     /* Add any remaining free parts to the raising set */
+     (void) set_or(RAISE, RAISE, set_diff(xraise, FREESET, xlower));
+     (void) set_copy(FREESET, cube.emptyset);	/* free set is empty */
+     BB->active_count = 0;			/* BB satisfied */
+     if (debug & EXPAND1) {
+ 	printf("MINCOV:    \tRAISE=%s FREESET=%s\n", pc1(RAISE), pc2(FREESET));
+     }
+     sf_free(B);
+     set_free(xlower);
+     return;
+ 
+ heuristic_mincov:
+     sf_free(B);
+     /* most_frequent will pick first free part */
+     set_insert(RAISE, most_frequent(/*CC*/ (pcover) NULL, FREESET));
+     (void) set_diff(FREESET, FREESET, RAISE);
+     essen_parts(BB, /*CC*/ (pcover) NULL, RAISE, FREESET);
+     return;
+ #endif
+ }
+ 
+ /*
+     find_all_primes -- find all of the primes which cover the
+     currently reduced BB
+ */
+ pcover find_all_primes(BB, RAISE, FREESET)
+ pcover BB;
+ register pcube RAISE, FREESET;
+ {
+     register pset last, p, plower;
+     pset_family B, B1;
+ 
+     if (BB->active_count == 0) {
+ 	B1 = new_cover(1);
+ 	p = GETSET(B1, B1->count++);
+ 	(void) set_copy(p, RAISE);
+ 	SET(p, PRIME);
+     } else {
+ 	B = new_cover(BB->active_count);
+ 	foreach_active_set(BB, last, p) {
+ 	    plower = set_copy(GETSET(B, B->count++), cube.emptyset);
+ 	    (void) force_lower(plower, p, RAISE);
+ 	}
+ 	B = sf_rev_contain(unravel(B, cube.num_binary_vars));
+ 	B1 = exact_minimum_cover(B);
+ 	foreach_set(B1, last, p) {
+ 	    INLINEset_diff(p, FREESET, p);
+ 	    INLINEset_or(p, p, RAISE);
+ 	    SET(p, PRIME);
+ 	}
+ 	free_cover(B);
+     }
+     return B1;
+ }
+ 
+ /*
+     all_primes -- foreach cube in F, generate all of the primes
+     which cover the cube.
+ */
+ 
+ pcover all_primes(F, R)
+ pcover F, R;
+ {
+     register pcube last, p, RAISE, FREESET;
+     pcover Fall_primes, B1;
+ 
+     FREESET = new_cube();
+     RAISE = new_cube();
+     Fall_primes = new_cover(F->count);
+ 
+     foreach_set(F, last, p) {
+ 	if (TESTP(p, PRIME)) {
+ 	    Fall_primes = sf_addset(Fall_primes, p);
+ 	} else {
+ 	    /* Setup for call to essential parts */
+ 	    (void) set_copy(RAISE, p);
+ 	    (void) set_diff(FREESET, cube.fullset, RAISE);
+ 	    setup_BB_CC(R, /* CC */ (pcover) NULL);
+ 	    essen_parts(R, /* CC */ (pcover) NULL, RAISE, FREESET);
+ 
+ 	    /* Find all of the primes, and add them to the prime set */
+ 	    B1 = find_all_primes(R, RAISE, FREESET);
+ 	    Fall_primes = sf_append(Fall_primes, B1);
+ 	}
+     }
+ 
+     set_free(RAISE);
+     set_free(FREESET);
+     return Fall_primes;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/gasp.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/gasp.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/gasp.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,219 ----
+ /*
+     module: gasp.c
+ 
+     The "last_gasp" heuristic computes the reduction of each cube in
+     the cover (without replacement) and then performs an expansion of
+     these cubes.  The cubes which expand to cover some other cube are
+     added to the original cover and irredundant finds a minimal subset.
+ 
+     If one of the reduced cubes expands to cover some other reduced
+     cube, then the new prime thus generated is a candidate for reducing
+     the size of the cover.
+ 
+     super_gasp is a variation on this strategy which extracts a minimal
+     subset from the set of all prime implicants which cover all
+     maximally reduced cubes.
+ */
+ 
+ #include "espresso.h"
+ 
+ 
+ /*
+  *  reduce_gasp -- compute the maximal reduction of each cube of F
+  *
+  *  If a cube does not reduce, it remains prime; otherwise, it is marked
+  *  as nonprime.   If the cube is redundant (should NEVER happen here) we
+  *  just crap out ...
+  *
+  *  A cover with all of the cubes of F is returned.  Those that did
+  *  reduce are marked "NONPRIME"; those that reduced are marked "PRIME".
+  *  The cubes are in the same order as in F.
+  */
+ static pcover reduce_gasp(F, D)
+ pcover F, D;
+ {
+     pcube p, last, cunder, *FD;
+     pcover G;
+ 
+     G = new_cover(F->count);
+     FD = cube2list(F, D);
+ 
+     /* Reduce cubes of F without replacement */
+     foreach_set(F, last, p) {
+ 	cunder = reduce_cube(FD, p);
+ 	if (setp_empty(cunder)) {
+ 	    fatal("empty reduction in reduce_gasp, shouldn't happen");
+ 	} else if (setp_equal(cunder, p)) {
+ 	    SET(cunder, PRIME);			/* just to make sure */
+ 	    G = sf_addset(G, p);		/* it did not reduce ... */
+ 	} else {
+ 	    RESET(cunder, PRIME);		/* it reduced ... */
+ 	    G = sf_addset(G, cunder);
+ 	}
+ 	if (debug & GASP) {
+ 	    printf("REDUCE_GASP: %s reduced to %s\n", pc1(p), pc2(cunder));
+ 	}
+ 	free_cube(cunder);
+     }
+ 
+     free_cubelist(FD);
+     return G;
+ }
+ 
+ /*
+  *  expand_gasp -- expand each nonprime cube of F into a prime implicant
+  *
+  *  The gasp strategy differs in that only those cubes which expand to
+  *  cover some other cube are saved; also, all cubes are expanded
+  *  regardless of whether they become covered or not.
+  */
+ 
+ pcover expand_gasp(F, D, R, Foriginal)
+ INOUT pcover F;
+ IN pcover D;
+ IN pcover R;
+ IN pcover Foriginal;
+ {
+     int c1index;
+     pcover G;
+ 
+     /* Try to expand each nonprime and noncovered cube */
+     G = new_cover(10);
+     for(c1index = 0; c1index < F->count; c1index++) {
+ 	expand1_gasp(F, D, R, Foriginal, c1index, &G);
+     }
+     G = sf_dupl(G);
+     G = expand(G, R, /*nonsparse*/ FALSE);	/* Make them prime ! */
+     return G;
+ }
+ 
+ 
+ 
+ /*
+  *  expand1 -- Expand a single cube against the OFF-set, using the gasp strategy
+  */
+ void expand1_gasp(F, D, R, Foriginal, c1index, G)
+ pcover F;		/* reduced cubes of ON-set */
+ pcover D;		/* DC-set */
+ pcover R;		/* OFF-set */
+ pcover Foriginal;	/* ON-set before reduction (same order as F) */
+ int c1index;		/* which index of F (or Freduced) to be checked */
+ pcover *G;
+ {
+     register int c2index;
+     register pcube p, last, c2under;
+     pcube RAISE, FREESET, temp, *FD, c2essential;
+     pcover F1;
+ 
+     if (debug & EXPAND1) {
+ 	printf("\nEXPAND1_GASP:    \t%s\n", pc1(GETSET(F, c1index)));
+     }
+ 
+     RAISE = new_cube();
+     FREESET = new_cube();
+     temp = new_cube();
+ 
+     /* Initialize the OFF-set */
+     R->active_count = R->count;
+     foreach_set(R, last, p) {
+ 	SET(p, ACTIVE);
+     }
+     /* Initialize the reduced ON-set, all nonprime cubes become active */
+     F->active_count = F->count;
+     foreachi_set(F, c2index, c2under) {
+ 	if (c1index == c2index || TESTP(c2under, PRIME)) {
+ 	    F->active_count--;
+ 	    RESET(c2under, ACTIVE);
+ 	} else {
+ 	    SET(c2under, ACTIVE);
+ 	}
+     }
+ 
+     /* Initialize the raising and unassigned sets */
+     (void) set_copy(RAISE, GETSET(F, c1index));
+     (void) set_diff(FREESET, cube.fullset, RAISE);
+ 
+     /* Determine parts which must be lowered */
+     essen_parts(R, F, RAISE, FREESET);
+ 
+     /* Determine parts which can always be raised */
+     essen_raising(R, RAISE, FREESET);
+ 
+     /* See which, if any, of the reduced cubes we can cover */
+     foreachi_set(F, c2index, c2under) {
+ 	if (TESTP(c2under, ACTIVE)) {
+ 	    /* See if this cube can be covered by an expansion */
+ 	    if (setp_implies(c2under, RAISE) ||
+ 	      feasibly_covered(R, c2under, RAISE, temp)) {
+ 		
+ 		/* See if c1under can expanded to cover c2 reduced against
+ 		 * (F - c1) u c1under; if so, c2 can definitely be removed !
+ 		 */
+ 
+ 		/* Copy F and replace c1 with c1under */
+ 		F1 = sf_save(Foriginal);
+ 		(void) set_copy(GETSET(F1, c1index), GETSET(F, c1index));
+ 
+ 		/* Reduce c2 against ((F - c1) u c1under) */
+ 		FD = cube2list(F1, D);
+ 		c2essential = reduce_cube(FD, GETSET(F1, c2index));
+ 		free_cubelist(FD);
+ 		sf_free(F1);
+ 
+ 		/* See if c2essential is covered by an expansion of c1under */
+ 		if (feasibly_covered(R, c2essential, RAISE, temp)) {
+ 		    (void) set_or(temp, RAISE, c2essential);
+ 		    RESET(temp, PRIME);		/* cube not prime */
+ 		    *G = sf_addset(*G, temp);
+ 		}
+ 		set_free(c2essential);
+ 	    }
+ 	}
+     }
+ 
+     free_cube(RAISE);
+     free_cube(FREESET);
+     free_cube(temp);
+ }
+ 
+ /* irred_gasp -- Add new primes to F and find an irredundant subset */
+ pcover irred_gasp(F, D, G)
+ pcover F, D, G;                 /* G is disposed of */
+ {
+     if (G->count != 0)
+ 	F = irredundant(sf_append(F, G), D);
+     else
+ 	free_cover(G);
+     return F;
+ }
+ 
+ 
+ /* last_gasp */
+ pcover last_gasp(F, D, R, cost)
+ pcover F, D, R;
+ cost_t *cost;
+ {
+     pcover G, G1;
+ 
+     EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+     EXECUTE(G1 = expand_gasp(G, D, R, F), GEXPAND_TIME, G1, *cost);
+     free_cover(G);
+     EXECUTE(F = irred_gasp(F, D, G1), GIRRED_TIME, F, *cost);
+     return F;
+ }
+ 
+ 
+ /* super_gasp */
+ pcover super_gasp(F, D, R, cost)
+ pcover F, D, R;
+ cost_t *cost;
+ {
+     pcover G, G1;
+ 
+     EXECUTE(G = reduce_gasp(F, D), GREDUCE_TIME, G, *cost);
+     EXECUTE(G1 = all_primes(G, R), GEXPAND_TIME, G1, *cost);
+     free_cover(G);
+     EXEC(G = sf_dupl(sf_append(F, G1)), "NEWPRIMES", G);
+     EXECUTE(F = irredundant(G, D), IRRED_TIME, F, *cost);
+     return F;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/getopt.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/getopt.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/getopt.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,47 ----
+ #include "port.h"
+ /*  File   : getopt.c
+     Author : Henry Spencer, University of Toronto
+     Updated: 28 April 1984
+     Purpose: get option letter from argv.
+ */
+ #define	NullS	((char *) 0)
+ 
+ char	*optarg;	/* Global argument pointer. */
+ int	optind = 0;	/* Global argv index. */
+ 
+ int getopt(argc, argv, optstring)
+     int argc;
+     char *argv[];
+     char *optstring;
+     {
+ 	register int c;
+ 	register char *place;
+ 	static char *scan = NullS;	/* Private scan pointer. */
+ 
+ 	optarg = NullS;
+ 
+ 	if (scan == NullS || *scan == '\0') {
+ 	    if (optind == 0) optind++;
+ 	    if (optind >= argc) return EOF;
+ 	    place = argv[optind];
+ 	    if (place[0] != '-' || place[1] == '\0') return EOF;
+ 	    optind++;
+ 	    if (place[1] == '-' && place[2] == '\0') return EOF;
+ 	    scan = place+1;
+ 	}
+ 
+ 	c = *scan++;
+ 	place = strchr(optstring, c);
+ 	if (place == NullS || c == ':') {
+ 	    fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
+ 	    return '?';
+ 	}
+ 	if (*++place == ':') {
+ 	    if (*scan != '\0') {
+ 		optarg = scan, scan = NullS;
+ 	    } else {
+ 		optarg = argv[optind], optind++;
+ 	    }
+ 	}
+ 	return c;
+     }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/gimpel.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/gimpel.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/gimpel.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,97 ----
+ #include "mincov_int.h"
+ 
+ 
+ /*
+  *  check for:
+  *
+  *		c1	c2	rest
+  *		--      --      ---
+  *		 1	 1	0 0 0 0		<-- primary row
+  *		 1	 0	S1		<-- secondary row
+  *		 0       1	T1
+  *		 0       1	T2
+  *		 0       1	Tn
+  *		 0       0      R
+  */
+ 
+ int
+ gimpel_reduce(A, select, weight, lb, bound, depth, stats, best)
+ sm_matrix *A;
+ solution_t *select;
+ int *weight;
+ int lb;
+ int bound;
+ int depth;
+ stats_t *stats;
+ solution_t **best;
+ {
+     register sm_row *prow, *save_sec;
+     register sm_col *c1, *c2;
+     register sm_element *p, *p1;
+     int c1_col_num, c2_col_num, primary_row_num, secondary_row_num;
+     int reduce_it; 
+ 
+     reduce_it = 0;
+     for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 	if (prow->length == 2) {
+ 	    c1 = sm_get_col(A, prow->first_col->col_num);
+ 	    c2 = sm_get_col(A, prow->last_col->col_num);
+ 	    if (c1->length == 2) {
+ 		reduce_it = 1;
+ 	    } else if (c2->length == 2) {
+ 		c1 = sm_get_col(A, prow->last_col->col_num);
+ 		c2 = sm_get_col(A, prow->first_col->col_num);
+ 		reduce_it = 1;
+ 	    }
+ 	    if (reduce_it) {
+ 		primary_row_num = prow->row_num;
+ 		secondary_row_num = c1->first_row->row_num;
+ 		if (secondary_row_num == primary_row_num) {
+ 		    secondary_row_num = c1->last_row->row_num;
+ 		}
+ 		break;
+ 	    }
+ 	}
+     }
+ 
+     if (reduce_it) {
+ 	c1_col_num = c1->col_num;
+ 	c2_col_num = c2->col_num;
+ 	save_sec = sm_row_dup(sm_get_row(A, secondary_row_num));
+ 	sm_row_remove(save_sec, c1_col_num);
+ 
+ 	for(p = c2->first_row; p != 0; p = p->next_row) {
+ 	    if (p->row_num != primary_row_num) {
+ 		/* merge rows S1 and T */
+ 		for(p1 = save_sec->first_col; p1 != 0; p1 = p1->next_col) {
+ 		    (void) sm_insert(A, p->row_num, p1->col_num);
+ 		}
+ 	    }
+ 	}
+ 
+ 	sm_delcol(A, c1_col_num);
+ 	sm_delcol(A, c2_col_num);
+ 	sm_delrow(A, primary_row_num);
+ 	sm_delrow(A, secondary_row_num);
+ 
+ 	stats->gimpel_count++;
+ 	stats->gimpel++;
+ 	*best = sm_mincov(A, select, weight, lb-1, bound-1, depth, stats);
+ 	stats->gimpel--;
+ 
+ 	if (*best != NIL(solution_t)) {
+ 	    /* is secondary row covered ? */
+ 	    if (sm_row_intersects(save_sec, (*best)->row)) {
+ 		/* yes, actually select c2 */
+ 		solution_add(*best, weight, c2_col_num);
+ 	    } else {
+ 		solution_add(*best, weight, c1_col_num);
+ 	    }
+ 	}
+ 
+ 	sm_row_free(save_sec);
+ 	return 1;
+     } else {
+ 	return 0;
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/globals.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/globals.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/globals.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,67 ----
+ #include "espresso.h"
+ 
+ /*
+  *    Global Variable Declarations
+  */
+ 
+ unsigned int debug;              /* debug parameter */
+ bool verbose_debug;              /* -v:  whether to print a lot */
+ char *total_name[TIME_COUNT];    /* basic function names */
+ long total_time[TIME_COUNT];     /* time spent in basic fcts */
+ int total_calls[TIME_COUNT];     /* # calls to each fct */
+ 
+ bool echo_comments;		 /* turned off by -eat option */
+ bool echo_unknown_commands;	 /* always true ?? */
+ bool force_irredundant;          /* -nirr command line option */
+ bool skip_make_sparse;
+ bool kiss;                       /* -kiss command line option */
+ bool pos;                        /* -pos command line option */
+ bool print_solution;             /* -x command line option */
+ bool recompute_onset;            /* -onset command line option */
+ bool remove_essential;           /* -ness command line option */
+ bool single_expand;              /* -fast command line option */
+ bool summary;                    /* -s command line option */
+ bool trace;                      /* -t command line option */
+ bool unwrap_onset;               /* -nunwrap command line option */
+ bool use_random_order;		 /* -random command line option */
+ bool use_super_gasp;		 /* -strong command line option */
+ char *filename;			 /* filename PLA was read from */
+ 
+ struct pla_types_struct pla_types[] = {
+     "-f", F_type,
+     "-r", R_type,
+     "-d", D_type,
+     "-fd", FD_type,
+     "-fr", FR_type,
+     "-dr", DR_type,
+     "-fdr", FDR_type,
+     "-fc", F_type | CONSTRAINTS_type,
+     "-rc", R_type | CONSTRAINTS_type,
+     "-dc", D_type | CONSTRAINTS_type,
+     "-fdc", FD_type | CONSTRAINTS_type,
+     "-frc", FR_type | CONSTRAINTS_type,
+     "-drc", DR_type | CONSTRAINTS_type,
+     "-fdrc", FDR_type | CONSTRAINTS_type,
+     "-pleasure", PLEASURE_type,
+     "-eqn", EQNTOTT_type,
+     "-eqntott", EQNTOTT_type,
+     "-kiss", KISS_type,
+     "-cons", CONSTRAINTS_type,
+     "-scons", SYMBOLIC_CONSTRAINTS_type,
+     0, 0
+ };
+ 
+ 
+ struct cube_struct cube, temp_cube_save;
+ struct cdata_struct cdata, temp_cdata_save;
+ 
+ int bit_count[256] = {
+   0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,
+   1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+   1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+   2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+   1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,
+   2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+   2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,
+   3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8
+ };


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/hack.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/hack.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/hack.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,632 ----
+ #include "espresso.h"
+ 
+ map_dcset(PLA)
+ pPLA PLA;
+ {
+     int var, i;
+     pcover Tplus, Tminus, Tplusbar, Tminusbar;
+     pcover newf, term1, term2, dcset, dcsetbar;
+     pcube cplus, cminus, last, p;
+ 
+     if (PLA->label == NIL(char *) || PLA->label[0] == NIL(char))
+ 	return;
+ 
+     /* try to find a binary variable named "DONT_CARE" */
+     var = -1;
+     for(i = 0; i < cube.num_binary_vars * 2; i++) {
+ 	if (strncmp(PLA->label[i], "DONT_CARE", 9) == 0 ||
+ 	  strncmp(PLA->label[i], "DONTCARE", 8) == 0 ||
+ 	  strncmp(PLA->label[i], "dont_care", 9) == 0 ||
+ 	  strncmp(PLA->label[i], "dontcare", 8) == 0) {
+ 	    var = i/2;
+ 	    break;
+ 	}
+     }
+     if (var == -1) {
+ 	return;
+     }
+ 
+     /* form the cofactor cubes for the don't-care variable */
+     cplus = set_save(cube.fullset);
+     cminus = set_save(cube.fullset);
+     set_remove(cplus, var*2);
+     set_remove(cminus, var*2 + 1);
+ 
+     /* form the don't-care set */
+     EXEC(simp_comp(cofactor(cube1list(PLA->F), cplus), &Tplus, &Tplusbar),
+ 	"simpcomp+", Tplus);
+     EXEC(simp_comp(cofactor(cube1list(PLA->F), cminus), &Tminus, &Tminusbar),
+ 	"simpcomp-", Tminus);
+     EXEC(term1 = cv_intersect(Tplus, Tminusbar), "term1    ", term1);
+     EXEC(term2 = cv_intersect(Tminus, Tplusbar), "term2    ", term2);
+     EXEC(dcset = sf_union(term1, term2), "union     ", dcset);
+     EXEC(simp_comp(cube1list(dcset), &PLA->D, &dcsetbar), "simplify", PLA->D);
+     EXEC(newf = cv_intersect(PLA->F, dcsetbar), "separate  ", PLA->F);
+     free_cover(PLA->F);
+     PLA->F = newf;
+     free_cover(Tplus);
+     free_cover(Tminus);
+     free_cover(Tplusbar);
+     free_cover(Tminusbar);
+     free_cover(dcsetbar);
+ 
+     /* remove any cubes dependent on the DONT_CARE variable */
+     (void) sf_active(PLA->F);
+     foreach_set(PLA->F, last, p) {
+ 	if (! is_in_set(p, var*2) || ! is_in_set(p, var*2+1)) {
+ 	    RESET(p, ACTIVE);
+ 	}
+     }
+     PLA->F = sf_inactive(PLA->F);
+ 
+     /* resize the cube and delete the don't-care variable */
+     setdown_cube();
+     for(i = 2*var+2; i < cube.size; i++) {
+ 	PLA->label[i-2] = PLA->label[i];
+     }
+     for(i = var+1; i < cube.num_vars; i++) {
+ 	cube.part_size[i-1] = cube.part_size[i];
+     }
+     cube.num_binary_vars--;
+     cube.num_vars--;
+     cube_setup();
+     PLA->F = sf_delc(PLA->F, 2*var, 2*var+1);
+     PLA->D = sf_delc(PLA->D, 2*var, 2*var+1);
+ }
+ 
+ map_output_symbolic(PLA)
+ pPLA PLA;
+ {
+     pset_family newF, newD;
+     pset compress;
+     symbolic_t *p1;
+     symbolic_list_t *p2;
+     int i, bit, tot_size, base, old_size;
+ 
+     /* Remove the DC-set from the ON-set (is this necessary ??) */
+     if (PLA->D->count > 0) {
+ 	sf_free(PLA->F);
+ 	PLA->F = complement(cube2list(PLA->D, PLA->R));
+     }
+ 
+     /* tot_size = width added for all symbolic variables */
+     tot_size = 0;
+     for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ 	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ 	    if (p2->pos<0 || p2->pos>=cube.part_size[cube.output]) {
+ 		fatal("symbolic-output index out of range");
+ /*	    } else if (p2->variable != cube.output) {
+ 		fatal("symbolic-output label must be an output");*/
+ 	    }
+ 	}
+ 	tot_size += 1 << p1->symbolic_list_length;
+     }
+ 
+     /* adjust the indices to skip over new outputs */
+     for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ 	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ 	    p2->pos += tot_size;
+ 	}
+     }
+ 
+     /* resize the cube structure -- add enough for the one-hot outputs */
+     old_size = cube.size;
+     cube.part_size[cube.output] += tot_size;
+     setdown_cube();
+     cube_setup();
+ 
+     /* insert space in the output part for the one-hot output */
+     base = cube.first_part[cube.output];
+     PLA->F = sf_addcol(PLA->F, base, tot_size);
+     PLA->D = sf_addcol(PLA->D, base, tot_size);
+     PLA->R = sf_addcol(PLA->R, base, tot_size);
+ 
+     /* do the real work */
+     for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ 	newF = new_cover(100);
+ 	newD = new_cover(100);
+ 	find_inputs(NIL(set_family_t), PLA, p1->symbolic_list, base, 0,
+ 			    &newF, &newD);
+ /*
+  *  Not sure what this means
+ 	find_dc_inputs(PLA, p1->symbolic_list,
+ 			    base, 1 << p1->symbolic_list_length, &newF, &newD);
+  */
+ 	free_cover(PLA->F);
+ 	PLA->F = newF;
+ /*
+  *  retain OLD DC-set -- but we've lost the don't-care arc information
+  *  (it defaults to branch to the zero state)
+ 	free_cover(PLA->D);
+ 	PLA->D = newD;
+  */
+ 	free_cover(newD);
+ 	base += 1 << p1->symbolic_list_length;
+     }
+ 
+     /* delete the old outputs, and resize the cube */
+     compress = set_full(newF->sf_size);
+     for(p1=PLA->symbolic_output; p1!=NIL(symbolic_t); p1=p1->next) {
+ 	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ 	    bit = cube.first_part[cube.output] + p2->pos;
+ 	    set_remove(compress, bit);
+ 	}
+     }
+     cube.part_size[cube.output] -= newF->sf_size - set_ord(compress);
+     setdown_cube();
+     cube_setup();
+     PLA->F = sf_compress(PLA->F, compress);
+     PLA->D = sf_compress(PLA->D, compress);
+     if (cube.size != PLA->F->sf_size) fatal("error");
+ 
+     /* Quick minimization */
+     PLA->F = sf_contain(PLA->F);
+     PLA->D = sf_contain(PLA->D);
+     for(i = 0; i < cube.num_vars; i++) {
+ 	PLA->F = d1merge(PLA->F, i);
+ 	PLA->D = d1merge(PLA->D, i);
+     }
+     PLA->F = sf_contain(PLA->F);
+     PLA->D = sf_contain(PLA->D);
+ 
+     free_cover(PLA->R);
+     PLA->R = new_cover(0);
+ 
+     symbolic_hack_labels(PLA, PLA->symbolic_output,
+ 			    compress, cube.size, old_size, tot_size);
+     set_free(compress);
+ }
+ 
+ 
+ find_inputs(A, PLA, list, base, value, newF, newD)
+ pcover A;
+ pPLA PLA;
+ symbolic_list_t *list;
+ int base, value;
+ pcover *newF, *newD;
+ {
+     pcover S, S1;
+     register pset last, p;
+ 
+     /*
+      *  A represents th 'input' values for which the outputs assume
+      *  the integer value 'value
+      */
+     if (list == NIL(symbolic_list_t)) {
+ 	/*
+ 	 *  Simulate these inputs against the on-set; then, insert into the
+ 	 *  new on-set a 1 in the proper position
+ 	 */
+ 	S = cv_intersect(A, PLA->F);
+ 	foreach_set(S, last, p) {
+ 	    set_insert(p, base + value);
+ 	}
+ 	*newF = sf_append(*newF, S);
+ 
+ 	/*
+ 	 *  'simulate' these inputs against the don't-care set
+ 	S = cv_intersect(A, PLA->D);
+ 	*newD = sf_append(*newD, S);
+ 	 */
+ 
+     } else {
+ 	/* intersect and recur with the OFF-set */
+ 	S = cof_output(PLA->R, cube.first_part[cube.output] + list->pos);
+ 	if (A != NIL(set_family_t)) {
+ 	    S1 = cv_intersect(A, S);
+ 	    free_cover(S);
+ 	    S = S1;
+ 	}
+ 	find_inputs(S, PLA, list->next, base, value*2, newF, newD);
+ 	free_cover(S);
+ 
+ 	/* intersect and recur with the ON-set */
+ 	S = cof_output(PLA->F, cube.first_part[cube.output] + list->pos);
+ 	if (A != NIL(set_family_t)) {
+ 	    S1 = cv_intersect(A, S);
+ 	    free_cover(S);
+ 	    S = S1;
+ 	}
+ 	find_inputs(S, PLA, list->next, base, value*2 + 1, newF, newD);
+ 	free_cover(S);
+     }
+ }
+ 
+ 
+ #if 0
+ find_dc_inputs(PLA, list, base, maxval, newF, newD)
+ pPLA PLA;
+ symbolic_list_t *list;
+ int base, maxval;
+ pcover *newF, *newD;
+ {
+     pcover A, S, S1;
+     symbolic_list_t *p2;
+     register pset p, last;
+     register int i;
+ 
+     /* painfully find the points for which the symbolic output is dc */
+     A = NIL(set_family_t);
+     for(p2=list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ 	S = cof_output(PLA->D, cube.first_part[cube.output] + p2->pos);
+ 	if (A == NIL(set_family_t)) {
+ 	    A = S;
+ 	} else {
+ 	    S1 = cv_intersect(A, S);
+ 	    free_cover(S);
+ 	    free_cover(A);
+ 	    A = S1;
+ 	}
+     }
+ 
+     S = cv_intersect(A, PLA->F);
+     *newF = sf_append(*newF, S);
+ 
+     S = cv_intersect(A, PLA->D);
+     foreach_set(S, last, p) {
+ 	for(i = base; i < base + maxval; i++) {
+ 	    set_insert(p, i);
+ 	}
+     }
+     *newD = sf_append(*newD, S);
+     free_cover(A);
+ }
+ #endif
+ 
+ map_symbolic(PLA)
+ pPLA PLA;
+ {
+     symbolic_t *p1;
+     symbolic_list_t *p2;
+     int var, base, num_vars, num_binary_vars, *new_part_size;
+     int new_size, size_added, num_deleted_vars, num_added_vars, newvar;
+     pset compress;
+ 
+     /* Verify legal values are in the symbolic lists */
+     for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ 	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ 	    if (p2->variable  < 0 || p2->variable >= cube.num_binary_vars) {
+ 		fatal(".symbolic requires binary variables");
+ 	    }
+ 	}
+     }
+ 
+     /*
+      *  size_added = width added for all symbolic variables
+      *  num_deleted_vars = # binary variables to be deleted
+      *  num_added_vars = # new mv variables
+      *  compress = a cube which will be used to compress the set families
+      */
+     size_added = 0;
+     num_added_vars = 0;
+     for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ 	size_added += 1 << p1->symbolic_list_length;
+ 	num_added_vars++;
+     }
+     compress = set_full(PLA->F->sf_size + size_added);
+     for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ 	for(p2=p1->symbolic_list; p2!=NIL(symbolic_list_t); p2=p2->next) {
+ 	    set_remove(compress, p2->variable*2);
+ 	    set_remove(compress, p2->variable*2+1);
+ 	}
+     }
+     num_deleted_vars = ((PLA->F->sf_size + size_added) - set_ord(compress))/2;
+ 
+     /* compute the new cube constants */
+     num_vars = cube.num_vars - num_deleted_vars + num_added_vars;
+     num_binary_vars = cube.num_binary_vars - num_deleted_vars;
+     new_size = cube.size - num_deleted_vars*2 + size_added;
+     new_part_size = ALLOC(int, num_vars);
+     new_part_size[num_vars-1] = cube.part_size[cube.num_vars-1];
+     for(var = cube.num_binary_vars; var < cube.num_vars-1; var++) {
+ 	new_part_size[var-num_deleted_vars] = cube.part_size[var];
+     }
+ 
+     /* re-size the covers, opening room for the new mv variables */
+     base = cube.first_part[cube.output];
+     PLA->F = sf_addcol(PLA->F, base, size_added);
+     PLA->D = sf_addcol(PLA->D, base, size_added);
+     PLA->R = sf_addcol(PLA->R, base, size_added);
+ 
+     /* compute the values for the new mv variables */
+     newvar = (cube.num_vars - 1) - num_deleted_vars;
+     for(p1 = PLA->symbolic; p1 != NIL(symbolic_t); p1 = p1->next) {
+ 	PLA->F = map_symbolic_cover(PLA->F, p1->symbolic_list, base);
+ 	PLA->D = map_symbolic_cover(PLA->D, p1->symbolic_list, base);
+ 	PLA->R = map_symbolic_cover(PLA->R, p1->symbolic_list, base);
+ 	base += 1 << p1->symbolic_list_length;
+ 	new_part_size[newvar++] = 1 << p1->symbolic_list_length;
+     }
+ 
+     /* delete the binary variables which disappear */
+     PLA->F = sf_compress(PLA->F, compress);
+     PLA->D = sf_compress(PLA->D, compress);
+     PLA->R = sf_compress(PLA->R, compress);
+ 
+     symbolic_hack_labels(PLA, PLA->symbolic, compress,
+ 		new_size, cube.size, size_added);
+     setdown_cube();
+     FREE(cube.part_size);
+     cube.num_vars = num_vars;
+     cube.num_binary_vars = num_binary_vars;
+     cube.part_size = new_part_size;
+     cube_setup();
+     set_free(compress);
+ }
+ 
+ 
+ pcover map_symbolic_cover(T, list, base)
+ pcover T;
+ symbolic_list_t *list;
+ int base;
+ {
+     pset last, p;
+     foreach_set(T, last, p) {
+ 	form_bitvector(p, base, 0, list);
+     }
+     return T;
+ }
+ 
+ 
+ form_bitvector(p, base, value, list)
+ pset p;			/* old cube, looking at binary variables */
+ int base;		/* where in mv cube the new variable starts */
+ int value;		/* current value for this recursion */
+ symbolic_list_t *list;	/* current place in the symbolic list */
+ {
+     if (list == NIL(symbolic_list_t)) {
+ 	set_insert(p, base + value);
+     } else {
+ 	switch(GETINPUT(p, list->variable)) {
+ 	    case ZERO:
+ 		form_bitvector(p, base, value*2, list->next);
+ 		break;
+ 	    case ONE:
+ 		form_bitvector(p, base, value*2+1, list->next);
+ 		break;
+ 	    case TWO:
+ 		form_bitvector(p, base, value*2, list->next);
+ 		form_bitvector(p, base, value*2+1, list->next);
+ 		break;
+ 	    default:
+ 		fatal("bad cube in form_bitvector");
+ 	}
+     }
+ }
+ 
+ 
+ symbolic_hack_labels(PLA, list, compress, new_size, old_size, size_added)
+ pPLA PLA;
+ symbolic_t *list;
+ pset compress;
+ int new_size, old_size, size_added;
+ {
+     int i, base;
+     char **oldlabel;
+     symbolic_t *p1;
+     symbolic_label_t *p3;
+ 
+     /* hack with the labels */
+     if ((oldlabel = PLA->label) == NIL(char *))
+ 	return;
+     PLA->label = ALLOC(char *, new_size);
+     for(i = 0; i < new_size; i++) {
+ 	PLA->label[i] = NIL(char);
+     }
+ 
+     /* copy the binary variable labels and unchanged mv variable labels */
+     base = 0;
+     for(i = 0; i < cube.first_part[cube.output]; i++) {
+ 	if (is_in_set(compress, i)) {
+ 	    PLA->label[base++] = oldlabel[i];
+ 	} else {
+ 	    if (oldlabel[i] != NIL(char)) {
+ 		FREE(oldlabel[i]);
+ 	    }
+ 	}
+     }
+ 
+     /* add the user-defined labels for the symbolic outputs */
+     for(p1 = list; p1 != NIL(symbolic_t); p1 = p1->next) {
+ 	p3 = p1->symbolic_label;
+ 	for(i = 0; i < (1 << p1->symbolic_list_length); i++) {
+ 	    if (p3 == NIL(symbolic_label_t)) {
+ 		PLA->label[base+i] = ALLOC(char, 10);
+ 		(void) sprintf(PLA->label[base+i], "X%d", i);
+ 	    } else {
+ 		PLA->label[base+i] = p3->label;
+ 		p3 = p3->next;
+ 	    }
+ 	}
+ 	base += 1 << p1->symbolic_list_length;
+     }
+ 
+     /* copy the labels for the binary outputs which remain */
+     for(i = cube.first_part[cube.output]; i < old_size; i++) {
+ 	if (is_in_set(compress, i + size_added)) {
+ 	    PLA->label[base++] = oldlabel[i];
+ 	} else {
+ 	    if (oldlabel[i] != NIL(char)) {
+ 		FREE(oldlabel[i]);
+ 	    }
+ 	}
+     }
+     FREE(oldlabel);
+ }
+ 
+ static pcover fsm_simplify(F)
+ pcover F;
+ {
+     pcover D, R;
+     D = new_cover(0);
+     R = complement(cube1list(F));
+     F = espresso(F, D, R);
+     free_cover(D);
+     free_cover(R);
+     return F;
+ }
+ 
+ 
+ disassemble_fsm(PLA, verbose_mode)
+ pPLA PLA;
+ int verbose_mode;
+ {
+     int nin, nstates, nout;
+     int before, after, present_state, next_state, i, j;
+     pcube next_state_mask, present_state_mask, state_mask, p, p1, last;
+     pcover go_nowhere, F, tF;
+ 
+     /* We make the DISGUSTING assumption that the first 'n' outputs have
+      *  been created by .symbolic-output, and represent a one-hot encoding
+      * of the next state.  'n' is the size of the second-to-last multiple-
+      * valued variable (i.e., before the outputs
+      */
+ 
+     if (cube.num_vars - cube.num_binary_vars != 2) {
+ 	fprintf(stderr,
+ 	"use .symbolic and .symbolic-output to specify\n");
+ 	fprintf(stderr,
+ 	"the present state and next state field information\n");
+ 	fatal("disassemble_pla: need two multiple-valued variables\n");
+     }
+ 
+     nin = cube.num_binary_vars;
+     nstates = cube.part_size[cube.num_binary_vars];
+     nout = cube.part_size[cube.num_vars - 1];
+     if (nout < nstates) {
+ 	fprintf(stderr,
+ 	    "use .symbolic and .symbolic-output to specify\n");
+ 	fprintf(stderr,
+ 	    "the present state and next state field information\n");
+ 	fatal("disassemble_pla: # outputs < # states\n");
+     }
+ 
+ 
+     present_state = cube.first_part[cube.num_binary_vars];
+     present_state_mask = new_cube();
+     for(i = 0; i < nstates; i++) {
+ 	set_insert(present_state_mask, i + present_state);
+     }
+ 
+     next_state = cube.first_part[cube.num_binary_vars+1];
+     next_state_mask = new_cube();
+     for(i = 0; i < nstates; i++) {
+ 	set_insert(next_state_mask, i + next_state);
+     }
+ 
+     state_mask = set_or(new_cube(), next_state_mask, present_state_mask);
+ 
+     F = new_cover(10);
+ 
+ 
+     /*
+      *  check for arcs which go from ANY state to state #i
+      */
+     for(i = 0; i < nstates; i++) {
+ 	tF = new_cover(10);
+ 	foreach_set(PLA->F, last, p) {
+ 	    if (setp_implies(present_state_mask, p)) { /* from any state ! */
+ 		if (is_in_set(p, next_state + i)) {
+ 		    tF = sf_addset(tF, p);
+ 		}
+ 	    }
+ 	}
+ 	before = tF->count;
+ 	if (before > 0) {
+ 	    tF = fsm_simplify(tF);
+ 	    /* don't allow the next state to disappear ... */
+ 	    foreach_set(tF, last, p) {
+ 		set_insert(p, next_state + i);
+ 	    }
+ 	    after = tF->count;
+ 	    F = sf_append(F, tF);
+ 	    if (verbose_mode) {
+ 		printf("# state EVERY to %d, before=%d after=%d\n",
+ 			i, before, after);
+ 	    }
+ 	}
+     }
+ 
+ 
+     /*
+      *  some 'arcs' may NOT have a next state -- handle these
+      *  we must unravel the present state part
+      */
+     go_nowhere = new_cover(10);
+     foreach_set(PLA->F, last, p) {
+ 	if (setp_disjoint(p, next_state_mask)) { /* no next state !! */
+ 	    go_nowhere = sf_addset(go_nowhere, p);
+ 	}
+     }
+     before = go_nowhere->count;
+     go_nowhere = unravel_range(go_nowhere,
+ 				cube.num_binary_vars, cube.num_binary_vars);
+     after = go_nowhere->count;
+     F = sf_append(F, go_nowhere);
+     if (verbose_mode) {
+ 	printf("# state ANY to NOWHERE, before=%d after=%d\n", before, after);
+     }
+ 
+ 
+     /*
+      *  minimize cover for all arcs from state #i to state #j
+      */
+     for(i = 0; i < nstates; i++) {
+ 	for(j = 0; j < nstates; j++) {
+ 	    tF = new_cover(10);
+ 	    foreach_set(PLA->F, last, p) {
+ 		/* not EVERY state */
+ 		if (! setp_implies(present_state_mask, p)) {
+ 		    if (is_in_set(p, present_state + i)) {
+ 			if (is_in_set(p, next_state + j)) {
+ 			    p1 = set_save(p);
+ 			    set_diff(p1, p1, state_mask);
+ 			    set_insert(p1, present_state + i);
+ 			    set_insert(p1, next_state + j);
+ 			    tF = sf_addset(tF, p1);
+ 			    set_free(p1);
+ 			}
+ 		    }
+ 		}
+ 	    }
+ 	    before = tF->count;
+ 	    if (before > 0) {
+ 		tF = fsm_simplify(tF);
+ 		/* don't allow the next state to disappear ... */
+ 		foreach_set(tF, last, p) {
+ 		    set_insert(p, next_state + j);
+ 		}
+ 		after = tF->count;
+ 		F = sf_append(F, tF);
+ 		if (verbose_mode) {
+ 		    printf("# state %d to %d, before=%d after=%d\n",
+ 			    i, j, before, after);
+ 		}
+ 	    }
+ 	}
+     }
+ 
+ 
+     free_cube(state_mask);
+     free_cube(present_state_mask);
+     free_cube(next_state_mask);
+ 
+     free_cover(PLA->F);
+     PLA->F = F;
+     free_cover(PLA->D);
+     PLA->D = new_cover(0);
+ 
+     setdown_cube();
+     FREE(cube.part_size);
+     cube.num_binary_vars = nin;
+     cube.num_vars = nin + 3;
+     cube.part_size = ALLOC(int, cube.num_vars);
+     cube.part_size[cube.num_binary_vars] = nstates;
+     cube.part_size[cube.num_binary_vars+1] = nstates;
+     cube.part_size[cube.num_binary_vars+2] = nout - nstates;
+     cube_setup();
+ 
+     foreach_set(PLA->F, last, p) {
+ 	kiss_print_cube(stdout, PLA, p, "~1");
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/indep.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/indep.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/indep.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,125 ----
+ #include "mincov_int.h"
+ 
+ static sm_matrix *build_intersection_matrix();
+ 
+ 
+ #if 0
+ /*
+  *  verify that all rows in 'indep' are actually independent !
+  */
+ static int 
+ verify_indep_set(A, indep)
+ sm_matrix *A;
+ sm_row *indep;
+ {
+     register sm_row *prow, *prow1;
+     register sm_element *p, *p1;
+ 
+     for(p = indep->first_col; p != 0; p = p->next_col) {
+ 	prow = sm_get_row(A, p->col_num);
+ 	for(p1 = p->next_col; p1 != 0; p1 = p1->next_col) {
+ 	    prow1 = sm_get_row(A, p1->col_num);
+ 	    if (sm_row_intersects(prow, prow1)) {
+ 		return 0;
+ 	    }
+ 	}
+     }
+     return 1;
+ }
+ #endif
+ 
+ solution_t * 
+ sm_maximal_independent_set(A, weight)
+ sm_matrix *A;
+ int *weight;
+ {
+     register sm_row *best_row, *prow;
+     register sm_element *p;
+     int least_weight;
+     sm_row *save;
+     sm_matrix *B;
+     solution_t *indep;
+ 
+     indep = solution_alloc();
+     B = build_intersection_matrix(A);
+ 
+     while (B->nrows > 0) {
+ 	/*  Find the row which is disjoint from a maximum number of rows */
+ 	best_row = B->first_row;
+ 	for(prow = B->first_row->next_row; prow != 0; prow = prow->next_row) {
+ 	    if (prow->length < best_row->length) {
+ 		best_row = prow;
+ 	    }
+ 	}
+ 
+ 	/* Find which element in this row has least weight */
+ 	if (weight == NIL(int)) {
+ 	    least_weight = 1;
+ 	} else {
+ 	    prow = sm_get_row(A, best_row->row_num);
+ 	    least_weight = weight[prow->first_col->col_num];
+ 	    for(p = prow->first_col->next_col; p != 0; p = p->next_col) {
+ 		if (weight[p->col_num] < least_weight) {
+ 		    least_weight = weight[p->col_num];
+ 		}
+ 	    }
+ 	}
+ 	indep->cost += least_weight;
+ 	(void) sm_row_insert(indep->row, best_row->row_num);
+ 
+ 	/*  Discard the rows which intersect this row */
+ 	save = sm_row_dup(best_row);
+ 	for(p = save->first_col; p != 0; p = p->next_col) {
+ 	    sm_delrow(B, p->col_num);
+ 	    sm_delcol(B, p->col_num);
+ 	}
+ 	sm_row_free(save);
+     }
+ 
+     sm_free(B);
+ 
+ /*
+     if (! verify_indep_set(A, indep->row)) {
+ 	fail("sm_maximal_independent_set: row set is not independent");
+     }
+ */
+     return indep;
+ }
+ 
+ static sm_matrix *
+ build_intersection_matrix(A)
+ sm_matrix *A;
+ {
+     register sm_row *prow, *prow1;
+     register sm_element *p, *p1;
+     register sm_col *pcol;
+     sm_matrix *B;
+ 
+     /* Build row-intersection matrix */
+     B = sm_alloc();
+     for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 
+ 	/* Clear flags on all rows we can reach from row 'prow' */
+ 	for(p = prow->first_col; p != 0; p = p->next_col) {
+ 	    pcol = sm_get_col(A, p->col_num);
+ 	    for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+ 		prow1 = sm_get_row(A, p1->row_num);
+ 		prow1->flag = 0;
+ 	    }
+ 	}
+ 
+ 	/* Now record which rows can be reached */
+ 	for(p = prow->first_col; p != 0; p = p->next_col) {
+ 	    pcol = sm_get_col(A, p->col_num);
+ 	    for(p1 = pcol->first_row; p1 != 0; p1 = p1->next_row) {
+ 		prow1 = sm_get_row(A, p1->row_num);
+ 		if (! prow1->flag) {
+ 		    prow1->flag = 1;
+ 		    (void) sm_insert(B, prow->row_num, prow1->row_num);
+ 		}
+ 	    }
+ 	}
+     }
+ 
+     return B;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/irred.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/irred.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/irred.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,431 ----
+ #include "espresso.h"
+ 
+ static void fcube_is_covered();
+ static void ftautology();
+ static bool ftaut_special_cases();
+ 
+ 
+ static int Rp_current;
+ 
+ /*
+  *   irredundant -- Return a minimal subset of F
+  */
+ 
+ pcover
+ irredundant(F, D)
+ pcover F, D;
+ {
+     mark_irredundant(F, D);
+     return sf_inactive(F);
+ }
+ 
+ 
+ /*
+  *   mark_irredundant -- find redundant cubes, and mark them "INACTIVE"
+  */
+ 
+ void
+ mark_irredundant(F, D)
+ pcover F, D;
+ {
+     pcover E, Rt, Rp;
+     pset p, p1, last;
+     sm_matrix *table;
+     sm_row *cover;
+     sm_element *pe;
+ 
+     /* extract a minimum cover */
+     irred_split_cover(F, D, &E, &Rt, &Rp);
+     table = irred_derive_table(D, E, Rp);
+     cover = sm_minimum_cover(table, NIL(int), /* heuristic */ 1, /* debug */ 0);
+ 
+     /* mark the cubes for the result */
+     foreach_set(F, last, p) {
+ 	RESET(p, ACTIVE);
+ 	RESET(p, RELESSEN);
+     }
+     foreach_set(E, last, p) {
+ 	p1 = GETSET(F, SIZE(p));
+ 	assert(setp_equal(p1, p));
+ 	SET(p1, ACTIVE);
+ 	SET(p1, RELESSEN);		/* for essen(), mark as rel. ess. */
+     }
+     sm_foreach_row_element(cover, pe) {
+ 	p1 = GETSET(F, pe->col_num);
+ 	SET(p1, ACTIVE);
+     }
+ 
+     if (debug & IRRED) {
+ 	printf("# IRRED: F=%d E=%d R=%d Rt=%d Rp=%d Rc=%d Final=%d Bound=%d\n",
+ 	    F->count, E->count, Rt->count+Rp->count, Rt->count, Rp->count,
+ 	    cover->length, E->count + cover->length, 0);
+     }
+ 
+     free_cover(E);
+     free_cover(Rt);
+     free_cover(Rp);
+     sm_free(table);
+     sm_row_free(cover);
+ }
+ 
+ /*
+  *  irred_split_cover -- find E, Rt, and Rp from the cover F, D
+  *
+  *	E  -- relatively essential cubes
+  *	Rt  -- totally redundant cubes
+  *	Rp  -- partially redundant cubes
+  */
+ 
+ void
+ irred_split_cover(F, D, E, Rt, Rp)
+ pcover F, D;
+ pcover *E, *Rt, *Rp;
+ {
+     register pcube p, last;
+     register int index;
+     pcover R;
+     pcube *FD, *ED;
+ 
+     /* number the cubes of F -- these numbers track into E, Rp, Rt, etc. */
+     index = 0;
+     foreach_set(F, last, p) {
+ 	PUTSIZE(p, index);
+ 	index++;
+     }
+ 
+     *E = new_cover(10);
+     *Rt = new_cover(10);
+     *Rp = new_cover(10);
+     R = new_cover(10);
+ 
+     /* Split F into E and R */
+     FD = cube2list(F, D);
+     foreach_set(F, last, p) {
+ 	if (cube_is_covered(FD, p)) {
+ 	    R = sf_addset(R, p);
+ 	} else {
+ 	    *E = sf_addset(*E, p);
+ 	}
+ 	if (debug & IRRED1) {
+ 	    (void) printf("IRRED1: zr=%d ze=%d to-go=%d time=%s\n",
+ 		R->count, (*E)->count, F->count - (R->count + (*E)->count),
+ 		print_time(ptime()));
+ 	}
+     }
+     free_cubelist(FD);
+ 
+     /* Split R into Rt and Rp */
+     ED = cube2list(*E, D);
+     foreach_set(R, last, p) {
+ 	if (cube_is_covered(ED, p)) {
+ 	    *Rt = sf_addset(*Rt, p);
+ 	} else {
+ 	    *Rp = sf_addset(*Rp, p);
+ 	}
+ 	if (debug & IRRED1) {
+ 	    (void) printf("IRRED1: zr=%d zrt=%d to-go=%d time=%s\n",
+ 		(*Rp)->count, (*Rt)->count,
+ 		R->count - ((*Rp)->count +(*Rt)->count), print_time(ptime()));
+ 	}
+     }
+     free_cubelist(ED);
+ 
+     free_cover(R);
+ }
+ 
+ /*
+  *  irred_derive_table -- given the covers D, E and the set of
+  *  partially redundant primes Rp, build a covering table showing
+  *  possible selections of primes to cover Rp.
+  */
+ 
+ sm_matrix *
+ irred_derive_table(D, E, Rp)
+ pcover D, E, Rp;
+ {
+     register pcube last, p, *list;
+     sm_matrix *table;
+     int size_last_dominance, i;
+ 
+     /* Mark each cube in DE as not part of the redundant set */
+     foreach_set(D, last, p) {
+ 	RESET(p, REDUND);
+     }
+     foreach_set(E, last, p) {
+ 	RESET(p, REDUND);
+     }
+ 
+     /* Mark each cube in Rp as partially redundant */
+     foreach_set(Rp, last, p) {
+ 	SET(p, REDUND);             /* belongs to redundant set */
+     }
+ 
+     /* For each cube in Rp, find ways to cover its minterms */
+     list = cube3list(D, E, Rp);
+     table = sm_alloc();
+     size_last_dominance = 0;
+     i = 0;
+     foreach_set(Rp, last, p) {
+ 	Rp_current = SIZE(p);
+ 	fcube_is_covered(list, p, table);
+ 	RESET(p, REDUND);	/* can now consider this cube redundant */
+ 	if (debug & IRRED1) {
+ 	    (void) printf("IRRED1: %d of %d to-go=%d, table=%dx%d time=%s\n",
+ 		i, Rp->count, Rp->count - i,
+ 		table->nrows, table->ncols, print_time(ptime()));
+ 	}
+ 	/* try to keep memory limits down by reducing table as we go along */
+ 	if (table->nrows - size_last_dominance > 1000) {
+ 	    (void) sm_row_dominance(table);
+ 	    size_last_dominance = table->nrows;
+ 	    if (debug & IRRED1) {
+ 		(void) printf("IRRED1: delete redundant rows, now %dx%d\n",
+ 		    table->nrows, table->ncols);
+ 	    }
+ 	}
+ 	i++;
+     }
+     free_cubelist(list);
+ 
+     return table;
+ }
+ 
+ /* cube_is_covered -- determine if a cubelist "covers" a single cube */
+ bool
+ cube_is_covered(T, c)
+ pcube *T, c;
+ {
+     return tautology(cofactor(T,c));
+ }
+ 
+ 
+ 
+ /* tautology -- answer the tautology question for T */
+ bool
+ tautology(T)
+ pcube *T;         /* T will be disposed of */
+ {
+     register pcube cl, cr;
+     register int best, result;
+     static int taut_level = 0;
+ 
+     if (debug & TAUT) {
+ 	debug_print(T, "TAUTOLOGY", taut_level++);
+     }
+ 
+     if ((result = taut_special_cases(T)) == MAYBE) {
+ 	cl = new_cube();
+ 	cr = new_cube();
+ 	best = binate_split_select(T, cl, cr, TAUT);
+ 	result = tautology(scofactor(T, cl, best)) &&
+ 		 tautology(scofactor(T, cr, best));
+ 	free_cubelist(T);
+ 	free_cube(cl);
+ 	free_cube(cr);
+     }
+ 
+     if (debug & TAUT) {
+ 	printf("exit TAUTOLOGY[%d]: %s\n", --taut_level, print_bool(result));
+     }
+     return result;
+ }
+ 
+ /*
+  *  taut_special_cases -- check special cases for tautology
+  */
+ 
+ bool
+ taut_special_cases(T)
+ pcube *T;			/* will be disposed if answer is determined */
+ {
+     register pcube *T1, *Tsave, p, ceil=cube.temp[0], temp=cube.temp[1];
+     pcube *A, *B;
+     int var;
+ 
+     /* Check for a row of all 1's which implies tautology */
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	if (full_row(p, T[0])) {
+ 	    free_cubelist(T);
+ 	    return TRUE;
+ 	}
+     }
+ 
+     /* Check for a column of all 0's which implies no tautology */
+ start:
+     INLINEset_copy(ceil, T[0]);
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	INLINEset_or(ceil, ceil, p);
+     }
+     if (! setp_equal(ceil, cube.fullset)) {
+ 	free_cubelist(T);
+ 	return FALSE;
+     }
+ 
+     /* Collect column counts, determine unate variables, etc. */
+     massive_count(T);
+ 
+     /* If function is unate (and no row of all 1's), then no tautology */
+     if (cdata.vars_unate == cdata.vars_active) {
+ 	free_cubelist(T);
+ 	return FALSE;
+ 
+     /* If active in a single variable (and no column of 0's) then tautology */
+     } else if (cdata.vars_active == 1) {
+ 	free_cubelist(T);
+ 	return TRUE;
+ 
+     /* Check for unate variables, and reduce cover if there are any */
+     } else if (cdata.vars_unate != 0) {
+ 	/* Form a cube "ceil" with full variables in the unate variables */
+ 	(void) set_copy(ceil, cube.emptyset);
+ 	for(var = 0; var < cube.num_vars; var++) {
+ 	    if (cdata.is_unate[var]) {
+ 		INLINEset_or(ceil, ceil, cube.var_mask[var]);
+ 	    }
+ 	}
+ 
+ 	/* Save only those cubes that are "full" in all unate variables */
+ 	for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+ 	    if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+ 		*Tsave++ = p;
+ 	    }
+ 	}
+ 	*Tsave++ = NULL;
+ 	T[1] = (pcube) Tsave;
+ 
+ 	if (debug & TAUT) {
+ 	    printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+ 		cdata.vars_unate, CUBELISTSIZE(T));
+ 	}
+ 	goto start;
+ 
+     /* Check for component reduction */
+     } else if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T) / 2) {
+ 	if (cubelist_partition(T, &A, &B, debug & TAUT) == 0) {
+ 	    return MAYBE;
+ 	} else {
+ 	    free_cubelist(T);
+ 	    if (tautology(A)) {
+ 		free_cubelist(B);
+ 		return TRUE;
+ 	    } else {
+ 		return tautology(B);
+ 	    }
+ 	}
+     }
+ 
+     /* We tried as hard as we could, but must recurse from here on */
+     return MAYBE;
+ }
+ 
+ /* fcube_is_covered -- determine exactly how a cubelist "covers" a cube */
+ static void
+ fcube_is_covered(T, c, table)
+ pcube *T, c;
+ sm_matrix *table;
+ {
+     ftautology(cofactor(T,c), table);
+ }
+ 
+ 
+ /* ftautology -- find ways to make a tautology */
+ static void
+ ftautology(T, table)
+ pcube *T;         	/* T will be disposed of */
+ sm_matrix *table;
+ {
+     register pcube cl, cr;
+     register int best;
+     static int ftaut_level = 0;
+ 
+     if (debug & TAUT) {
+ 	debug_print(T, "FIND_TAUTOLOGY", ftaut_level++);
+     }
+ 
+     if (ftaut_special_cases(T, table) == MAYBE) {
+ 	cl = new_cube();
+ 	cr = new_cube();
+ 	best = binate_split_select(T, cl, cr, TAUT);
+ 
+ 	ftautology(scofactor(T, cl, best), table);
+ 	ftautology(scofactor(T, cr, best), table);
+ 
+ 	free_cubelist(T);
+ 	free_cube(cl);
+ 	free_cube(cr);
+     }
+ 
+     if (debug & TAUT) {
+ 	(void) printf("exit FIND_TAUTOLOGY[%d]: table is %d by %d\n",
+ 	    --ftaut_level, table->nrows, table->ncols);
+     }
+ }
+ 
+ static bool
+ ftaut_special_cases(T, table)
+ pcube *T;                 /* will be disposed if answer is determined */
+ sm_matrix *table;
+ {
+     register pcube *T1, *Tsave, p, temp = cube.temp[0], ceil = cube.temp[1];
+     int var, rownum;
+ 
+     /* Check for a row of all 1's in the essential cubes */
+     for(T1 = T+2; (p = *T1++) != 0; ) {
+ 	if (! TESTP(p, REDUND)) {
+ 	    if (full_row(p, T[0])) {
+ 		/* subspace is covered by essentials -- no new rows for table */
+ 		free_cubelist(T);
+ 		return TRUE;
+ 	    }
+ 	}
+     }
+ 
+     /* Collect column counts, determine unate variables, etc. */
+ start:
+     massive_count(T);
+ 
+     /* If function is unate, find the rows of all 1's */
+     if (cdata.vars_unate == cdata.vars_active) {
+ 	/* find which nonessentials cover this subspace */
+ 	rownum = table->last_row ? table->last_row->row_num+1 : 0;
+ 	(void) sm_insert(table, rownum, Rp_current);
+ 	for(T1 = T+2; (p = *T1++) != 0; ) {
+ 	    if (TESTP(p, REDUND)) {
+ 		/* See if a redundant cube covers this leaf */
+ 		if (full_row(p, T[0])) {
+ 		    (void) sm_insert(table, rownum, (int) SIZE(p));
+ 		}
+ 	    }
+ 	}
+ 	free_cubelist(T);
+ 	return TRUE;
+ 
+     /* Perform unate reduction if there are any unate variables */
+     } else if (cdata.vars_unate != 0) {
+ 	/* Form a cube "ceil" with full variables in the unate variables */
+ 	(void) set_copy(ceil, cube.emptyset);
+ 	for(var = 0; var < cube.num_vars; var++) {
+ 	    if (cdata.is_unate[var]) {
+ 		INLINEset_or(ceil, ceil, cube.var_mask[var]);
+ 	    }
+ 	}
+ 
+ 	/* Save only those cubes that are "full" in all unate variables */
+ 	for(Tsave = T1 = T+2; (p = *T1++) != 0; ) {
+ 	    if (setp_implies(ceil, set_or(temp, p, T[0]))) {
+ 		*Tsave++ = p;
+ 	    }
+ 	}
+ 	*Tsave++ = 0;
+ 	T[1] = (pcube) Tsave;
+ 
+ 	if (debug & TAUT) {
+ 	    printf("UNATE_REDUCTION: %d unate variables, reduced to %d\n",
+ 		cdata.vars_unate, CUBELISTSIZE(T));
+ 	}
+ 	goto start;
+     }
+ 
+     /* Not much we can do about it */
+     return MAYBE;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/main.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/main.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/main.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,743 ----
+ /*
+  *  Main driver for espresso
+  *
+  *  Old style -do xxx, -out xxx, etc. are still supported.
+  */
+ 
+ #include "espresso.h"
+ #include "main.h"		/* table definitions for options */
+ 
+ static FILE *last_fp;
+ static int input_type = FD_type;
+ 
+ main(argc, argv)
+ int argc;
+ char *argv[];
+ {
+     int i, j, first, last, strategy, out_type, option;
+     pPLA PLA, PLA1;
+     pcover F, Fold, Dold;
+     pset last1, p;
+     cost_t cost;
+     bool error, exact_cover;
+     long start;
+     extern char *optarg;
+     extern int optind;
+     
+ #ifdef BWGC
+ 	{
+ 	    extern gc_init();
+ 	    gc_init();
+ 	}
+ #endif BWGC
+ 
+     start = ptime();
+ 
+     error = FALSE;
+     init_runtime();
+ #ifdef RANDOM
+     srandom(314973);
+ #endif
+ 
+     option = 0;			/* default -D: ESPRESSO */
+     out_type = F_type;		/* default -o: default is ON-set only */
+     debug = 0;			/* default -d: no debugging info */
+     verbose_debug = FALSE;	/* default -v: not verbose */
+     print_solution = TRUE;	/* default -x: print the solution (!) */
+     summary = FALSE;		/* default -s: no summary */
+     trace = FALSE;		/* default -t: no trace information */
+     strategy = 0;		/* default -S: strategy number */
+     first = -1;			/* default -R: select range */
+     last = -1;
+     remove_essential = TRUE;	/* default -e: */
+     force_irredundant = TRUE;
+     unwrap_onset = TRUE;
+     single_expand = FALSE;
+     pos = FALSE;
+     recompute_onset = FALSE;
+     use_super_gasp = FALSE;
+     use_random_order = FALSE;
+     kiss = FALSE;
+     echo_comments = TRUE;
+     echo_unknown_commands = TRUE;
+     exact_cover = FALSE;	/* for -qm option, the default */
+ 
+     backward_compatibility_hack(&argc, argv, &option, &out_type);
+ 
+ 
+     /* parse command line options*/
+     while ((i = getopt(argc, argv, "D:S:de:o:r:stv:x")) != EOF) {
+ 	switch(i) {
+ 	    case 'D':		/* -Dcommand invokes a subcommand */
+ 		for(j = 0; option_table[j].name != 0; j++) {
+ 		    if (strcmp(optarg, option_table[j].name) == 0) {
+ 			option = j;
+ 			break;
+ 		    }
+ 		}
+ 		if (option_table[j].name == 0) {
+ 		    fprintf(stderr, "%s: bad subcommand \"%s\"\n",
+ 			argv[0], optarg);
+ 		    exit(1);
+ 		}
+ 		break;
+ 
+ 	    case 'o':		/* -ooutput selects and output option */
+ 		for(j = 0; pla_types[j].key != 0; j++) {
+ 		    if (strcmp(optarg, pla_types[j].key+1) == 0) {
+ 			out_type = pla_types[j].value;
+ 			break;
+ 		    }
+ 		}
+ 		if (pla_types[j].key == 0) {
+ 		    fprintf(stderr, "%s: bad output type \"%s\"\n",
+ 			argv[0], optarg);
+ 		    exit(1);
+ 		}
+ 		break;
+ 
+ 	    case 'e':		/* -eespresso selects an option for espresso */
+ 		for(j = 0; esp_opt_table[j].name != 0; j++) {
+ 		    if (strcmp(optarg, esp_opt_table[j].name) == 0) {
+ 			*(esp_opt_table[j].variable) = esp_opt_table[j].value;
+ 			break;
+ 		    }
+ 		}
+ 		if (esp_opt_table[j].name == 0) {
+ 		    fprintf(stderr, "%s: bad espresso option \"%s\"\n",
+ 			argv[0], optarg);
+ 		    exit(1);
+ 		}
+ 		break;
+ 
+ 	    case 'd':		/* -d turns on (softly) all debug switches */
+ 		debug = debug_table[0].value;
+ 		trace = TRUE;
+ 		summary = TRUE;
+ 		break;
+ 
+ 	    case 'v':		/* -vdebug invokes a debug option */
+ 		verbose_debug = TRUE;
+ 		for(j = 0; debug_table[j].name != 0; j++) {
+ 		    if (strcmp(optarg, debug_table[j].name) == 0) {
+ 			debug |= debug_table[j].value;
+ 			break;
+ 		    }
+ 		}
+ 		if (debug_table[j].name == 0) {
+ 		    fprintf(stderr, "%s: bad debug type \"%s\"\n",
+ 			argv[0], optarg);
+ 		    exit(1);
+ 		}
+ 		break;
+ 
+ 	    case 't':
+ 		trace = TRUE;
+ 		break;
+ 
+ 	    case 's':
+ 		summary = TRUE;
+ 		break;
+ 
+ 	    case 'x':		/* -x suppress printing of results */
+ 		print_solution = FALSE;
+ 		break;
+ 
+ 	    case 'S':		/* -S sets a strategy for several cmds */
+ 		strategy = atoi(optarg);
+ 		break;
+ 
+ 	    case 'r':		/* -r selects range (outputs or vars) */
+ 		if (sscanf(optarg, "%d-%d", &first, &last) < 2) {
+ 		    fprintf(stderr, "%s: bad output range \"%s\"\n",
+ 			argv[0], optarg);
+ 		    exit(1);
+ 		}
+ 		break;
+ 
+ 	    default:
+ 		usage();
+ 		exit(1);
+ 	}
+     }
+ 
+     /* provide version information and summaries */
+     if (summary || trace) {
+ 	/* echo command line and arguments */
+ 	printf("#");
+ 	for(i = 0; i < argc; i++) {
+ 	    printf(" %s", argv[i]);
+ 	}
+ 	printf("\n");
+ 	printf("# %s\n", VERSION);
+     }
+ 
+     /* the remaining arguments are argv[optind ... argc-1] */
+     PLA = PLA1 = NIL(PLA_t);
+     switch(option_table[option].num_plas) {
+ 	case 2:
+ 	    if (optind+2 < argc) fatal("trailing arguments on command line");
+ 	    getPLA(optind++, argc, argv, option, &PLA, out_type);
+ 	    getPLA(optind++, argc, argv, option, &PLA1, out_type);
+ 	    break;
+ 	case 1:
+ 	    if (optind+1 < argc) fatal("trailing arguments on command line");
+ 	    getPLA(optind++, argc, argv, option, &PLA, out_type);
+ 	    break;
+     }
+     if (optind < argc) fatal("trailing arguments on command line");
+ 
+     if (summary || trace) {
+ 	if (PLA != NIL(PLA_t)) PLA_summary(PLA);
+ 	if (PLA1 != NIL(PLA_t)) PLA_summary(PLA1);
+     }
+ 
+ /*
+  *  Now a case-statement to decide what to do
+  */
+ 
+     switch(option_table[option].key) {
+ 
+ 
+ /******************** Espresso operations ********************/
+ 
+     case KEY_ESPRESSO:
+ 	Fold = sf_save(PLA->F);
+ 	PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+ 	EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+ 	if (error) {
+ 	    print_solution = FALSE;
+ 	    PLA->F = Fold;
+ 	    (void) check_consistency(PLA);
+ 	} else {
+ 	    free_cover(Fold);
+ 	}
+ 	break;
+ 
+     case KEY_MANY_ESPRESSO: {
+ 	int pla_type;
+ 	do {
+ 	    EXEC(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO   ",PLA->F);
+ 	    if (print_solution) {
+ 		fprint_pla(stdout, PLA, out_type);
+ 		(void) fflush(stdout);
+ 	    }
+ 	    pla_type = PLA->pla_type;
+ 	    free_PLA(PLA);
+ 	    setdown_cube();
+ 	    FREE(cube.part_size);
+ 	} while (read_pla(last_fp, TRUE, TRUE, pla_type, &PLA) != EOF);
+ 	exit(0);
+     }
+ 
+     case KEY_simplify:
+ 	EXEC(PLA->F = simplify(cube1list(PLA->F)), "SIMPLIFY  ", PLA->F);
+ 	break;
+ 
+     case KEY_so:	        /* minimize all functions as single-output */
+ 	if (strategy < 0 || strategy > 1) {
+ 	    strategy = 0;
+ 	}
+ 	so_espresso(PLA, strategy);
+ 	break;
+ 
+     case KEY_so_both:		/* minimize all functions as single-output */
+ 	if (strategy < 0 || strategy > 1) {
+ 	    strategy = 0;
+ 	}
+ 	so_both_espresso(PLA, strategy);
+ 	break;
+ 
+     case KEY_expand:            /* execute expand */
+ 	EXECUTE(PLA->F=expand(PLA->F,PLA->R,FALSE),EXPAND_TIME, PLA->F, cost);
+ 	break;
+ 
+     case KEY_irred:             /* extract minimal irredundant subset */
+ 	EXECUTE(PLA->F = irredundant(PLA->F, PLA->D), IRRED_TIME, PLA->F, cost);
+ 	break;
+ 
+     case KEY_reduce:            /* perform reduction */
+ 	EXECUTE(PLA->F = reduce(PLA->F, PLA->D), REDUCE_TIME, PLA->F, cost);
+ 	break;
+ 
+     case KEY_essen:             /* check for essential primes */
+ 	foreach_set(PLA->F, last1, p) {
+ 	    SET(p, RELESSEN);
+ 	    RESET(p, NONESSEN);
+ 	}
+ 	EXECUTE(F = essential(&(PLA->F), &(PLA->D)), ESSEN_TIME, PLA->F, cost);
+ 	free_cover(F);
+ 	break;
+ 
+     case KEY_super_gasp:
+ 	PLA->F = super_gasp(PLA->F, PLA->D, PLA->R, &cost);
+ 	break;
+ 
+     case KEY_gasp:
+ 	PLA->F = last_gasp(PLA->F, PLA->D, PLA->R, &cost);
+ 	break;
+ 
+     case KEY_make_sparse:       /* make_sparse step of Espresso */
+ 	PLA->F = make_sparse(PLA->F, PLA->D, PLA->R);
+ 	break;
+ 
+     case KEY_exact:
+ 	exact_cover = TRUE;
+ 
+     case KEY_qm:
+ 	Fold = sf_save(PLA->F);
+ 	PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, exact_cover);
+ 	EXECUTE(error=verify(PLA->F,Fold,PLA->D), VERIFY_TIME, PLA->F, cost);
+ 	if (error) {
+ 	    print_solution = FALSE;
+ 	    PLA->F = Fold;
+ 	    (void) check_consistency(PLA);
+ 	}
+ 	free_cover(Fold);
+ 	break;
+ 
+     case KEY_primes:            /* generate all prime implicants */
+ 	EXEC(PLA->F = primes_consensus(cube2list(PLA->F, PLA->D)), 
+ 						    "PRIMES     ", PLA->F);
+ 	break;
+ 
+     case KEY_map:               /* print out a Karnaugh map of function */
+ 	map(PLA->F);
+ 	print_solution = FALSE;
+ 	break;
+ 
+ 
+ 
+ /******************** Output phase and bit pairing ********************/
+ 
+     case KEY_opo:               /* sasao output phase assignment */
+ 	phase_assignment(PLA, strategy);
+ 	break;
+ 
+     case KEY_opoall:		/* try all phase assignments (!) */
+ 	if (first < 0 || first >= cube.part_size[cube.output]) {
+ 	    first = 0;
+ 	}
+ 	if (last < 0 || last >= cube.part_size[cube.output]) {
+ 	    last = cube.part_size[cube.output] - 1;
+ 	}
+ 	opoall(PLA, first, last, strategy);
+ 	break;
+ 
+     case KEY_pair:              /* find an optimal pairing */
+ 	find_optimal_pairing(PLA, strategy);
+ 	break;
+ 
+     case KEY_pairall:		/* try all pairings !! */
+ 	pair_all(PLA, strategy);
+ 	break;
+ 
+ 
+ 
+ /******************** Simple cover operations ********************/
+ 
+     case KEY_echo:				/* echo the PLA */
+ 	break;
+ 
+     case KEY_taut:				/* tautology check */
+ 	printf("ON-set is%sa tautology\n",
+ 	    tautology(cube1list(PLA->F)) ? " " : " not ");
+ 	print_solution = FALSE;
+ 	break;
+ 
+     case KEY_contain:				/* single cube containment */
+ 	PLA->F = sf_contain(PLA->F);
+ 	break;
+ 
+     case KEY_intersect:				/* cover intersection */
+ 	PLA->F = cv_intersect(PLA->F, PLA1->F);
+ 	break;
+ 
+     case KEY_union:				/* cover union */
+ 	PLA->F = sf_union(PLA->F, PLA1->F);
+ 	break;
+ 
+     case KEY_disjoint:				/* make cover disjoint */
+ 	PLA->F = make_disjoint(PLA->F);
+ 	break;
+ 
+     case KEY_dsharp:				/* cover disjoint-sharp */
+ 	PLA->F = cv_dsharp(PLA->F, PLA1->F);
+ 	break;
+ 
+     case KEY_sharp:				/* cover sharp */
+ 	PLA->F = cv_sharp(PLA->F, PLA1->F);
+ 	break;
+ 
+     case KEY_lexsort:				/* lexical sort order */
+ 	PLA->F = lex_sort(PLA->F);
+ 	break;
+ 
+     case KEY_stats:				/* print info on size */
+ 	if (! summary) PLA_summary(PLA);
+ 	print_solution = FALSE;
+ 	break;
+ 
+     case KEY_minterms:				/* explode into minterms */
+ 	if (first < 0 || first >= cube.num_vars) {
+ 	    first = 0;
+ 	}
+ 	if (last < 0 || last >= cube.num_vars) {
+ 	    last = cube.num_vars - 1;
+ 	}
+ 	PLA->F = sf_dupl(unravel_range(PLA->F, first, last));
+ 	break;
+ 
+     case KEY_d1merge:				/* distance-1 merge */
+ 	if (first < 0 || first >= cube.num_vars) {
+ 	    first = 0;
+ 	}
+ 	if (last < 0 || last >= cube.num_vars) {
+ 	    last = cube.num_vars - 1;
+ 	}
+ 	for(i = first; i <= last; i++) {
+ 	    PLA->F = d1merge(PLA->F, i);
+ 	}
+ 	break;
+ 
+     case KEY_d1merge_in:		/* distance-1 merge inputs only */
+ 	for(i = 0; i < cube.num_binary_vars; i++) {
+ 	    PLA->F = d1merge(PLA->F, i);
+ 	}
+ 	break;
+ 
+     case KEY_PLA_verify:		/* check two PLAs for equivalence */
+ 	EXECUTE(error = PLA_verify(PLA, PLA1), VERIFY_TIME, PLA->F, cost);
+ 	if (error) {
+ 	    printf("PLA comparison failed; the PLA's are not equivalent\n");
+ 	    exit(1);
+ 	} else {
+ 	    printf("PLA's compared equal\n");
+ 	    exit(0);
+ 	}
+ 	break;	/* silly */
+ 
+     case KEY_verify:			/* check two covers for equivalence */
+ 	Fold = PLA->F;	Dold = PLA->D;	F = PLA1->F;
+ 	EXECUTE(error=verify(F, Fold, Dold), VERIFY_TIME, PLA->F, cost);
+ 	if (error) {
+ 	    printf("PLA comparison failed; the PLA's are not equivalent\n");
+ 	    exit(1);
+ 	} else {
+ 	    printf("PLA's compared equal\n");
+ 	    exit(0);
+ 	}	
+ 	break;	/* silly */
+ 
+     case KEY_check:			/* check consistency */
+ 	(void) check_consistency(PLA);
+ 	print_solution = FALSE;
+ 	break;
+ 
+     case KEY_mapdc:			/* compute don't care set */
+ 	map_dcset(PLA);
+ 	out_type = FD_type;
+ 	break;
+ 
+     case KEY_equiv:
+ 	find_equiv_outputs(PLA);
+ 	print_solution = FALSE;
+ 	break;
+ 
+     case KEY_separate:			/* remove PLA->D from PLA->F */
+ 	PLA->F = complement(cube2list(PLA->D, PLA->R));
+ 	break;
+ 
+     case KEY_xor: {
+ 	pcover T1 = cv_intersect(PLA->F, PLA1->R);
+ 	pcover T2 = cv_intersect(PLA1->F, PLA->R);
+ 	free_cover(PLA->F);
+ 	PLA->F = sf_contain(sf_join(T1, T2));
+ 	free_cover(T1);
+ 	free_cover(T2);
+ 	break;
+     }
+ 
+     case KEY_fsm: {
+ 	disassemble_fsm(PLA, summary);
+ 	print_solution = FALSE;
+ 	break;
+     }
+ 
+     case KEY_test: {
+ 	pcover T, E;
+ 	T = sf_join(PLA->D, PLA->R);
+ 	E = new_cover(10);
+ 	sf_free(PLA->F);
+ 	EXECUTE(PLA->F = complement(cube1list(T)), COMPL_TIME, PLA->F, cost);
+ 	EXECUTE(PLA->F = expand(PLA->F, T, FALSE), EXPAND_TIME, PLA->F, cost);
+ 	EXECUTE(PLA->F = irredundant(PLA->F, E), IRRED_TIME, PLA->F, cost);
+ 	sf_free(T);
+ 	T = sf_join(PLA->F, PLA->R);
+ 	EXECUTE(PLA->D = expand(PLA->D, T, FALSE), EXPAND_TIME, PLA->D, cost);
+ 	EXECUTE(PLA->D = irredundant(PLA->D, E), IRRED_TIME, PLA->D, cost);
+ 	sf_free(T);
+ 	sf_free(E);
+ 	break;
+     }
+ 
+ 
+     }
+ 
+     /* Print a runtime summary if trace mode enabled */
+     if (trace) {
+ 	runtime();
+     }
+ 
+     /* Print total runtime */
+     if (summary || trace) {
+ 	print_trace(PLA->F, option_table[option].name, ptime()-start);
+     }
+ 
+     /* Output the solution */
+     if (print_solution) {
+ 	EXECUTE(fprint_pla(stdout, PLA, out_type), WRITE_TIME, PLA->F, cost);
+     }
+ 
+     /* Crash and burn if there was a verify error */
+     if (error) {
+ 	fatal("cover verification failed");
+     }
+ 
+     /* cleanup all used memory */
+     free_PLA(PLA);
+     FREE(cube.part_size);
+     setdown_cube();             /* free the cube/cdata structure data */
+     sf_cleanup();               /* free unused set structures */
+     sm_cleanup();               /* sparse matrix cleanup */
+ 
+     exit(0);
+ }
+ 
+ 
+ getPLA(opt, argc, argv, option, PLA, out_type)
+ int opt;
+ int argc;
+ char *argv[];
+ int option;
+ pPLA *PLA;
+ int out_type;
+ {
+     FILE *fp;
+     int needs_dcset, needs_offset;
+     char *fname;
+ 
+     if (opt >= argc) {
+ 	fp = stdin;
+ 	fname = "(stdin)";
+     } else {
+ 	fname = argv[opt];
+ 	if (strcmp(fname, "-") == 0) {
+ 	    fp = stdin;
+ 	} else if ((fp = fopen(argv[opt], "r")) == NULL) {
+ 	    fprintf(stderr, "%s: Unable to open %s\n", argv[0], fname);
+ 	    exit(1);
+ 	}
+     }
+     if (option_table[option].key == KEY_echo) {
+ 	needs_dcset = (out_type & D_type) != 0;
+ 	needs_offset = (out_type & R_type) != 0;
+     } else {
+ 	needs_dcset = option_table[option].needs_dcset;
+ 	needs_offset = option_table[option].needs_offset;
+     }
+ 
+     if (read_pla(fp, needs_dcset, needs_offset, input_type, PLA) == EOF) {
+ 	fprintf(stderr, "%s: Unable to find PLA on file %s\n", argv[0], fname);
+ 	exit(1);
+     }
+     (*PLA)->filename = util_strsav(fname);
+     filename = (*PLA)->filename;
+ /*    (void) fclose(fp);*/
+ /* hackto support -Dmany */
+     last_fp = fp;
+ }
+ 
+ 
+ runtime()
+ {
+     int i;
+     long total = 1, temp;
+ 
+     for(i = 0; i < TIME_COUNT; i++) {
+ 	total += total_time[i];
+     }
+     for(i = 0; i < TIME_COUNT; i++) {
+ 	if (total_calls[i] != 0) {
+ 	    temp = 100 * total_time[i];
+ 	    printf("# %s\t%2d call(s) for %s (%2ld.%01ld%%)\n",
+ 		total_name[i], total_calls[i], print_time(total_time[i]),
+ 		    temp/total, (10 * (temp%total)) / total);
+ 	}
+     }
+ }
+ 
+ 
+ init_runtime()
+ {
+     total_name[READ_TIME] =     "READ       ";
+     total_name[WRITE_TIME] =    "WRITE      ";
+     total_name[COMPL_TIME] =    "COMPL      ";
+     total_name[REDUCE_TIME] =   "REDUCE     ";
+     total_name[EXPAND_TIME] =   "EXPAND     ";
+     total_name[ESSEN_TIME] =    "ESSEN      ";
+     total_name[IRRED_TIME] =    "IRRED      ";
+     total_name[GREDUCE_TIME] =  "REDUCE_GASP";
+     total_name[GEXPAND_TIME] =  "EXPAND_GASP";
+     total_name[GIRRED_TIME] =   "IRRED_GASP ";
+     total_name[MV_REDUCE_TIME] ="MV_REDUCE  ";
+     total_name[RAISE_IN_TIME] = "RAISE_IN   ";
+     total_name[VERIFY_TIME] =   "VERIFY     ";
+     total_name[PRIMES_TIME] =   "PRIMES     ";
+     total_name[MINCOV_TIME] =   "MINCOV     ";
+ }
+ 
+ 
+ subcommands()
+ {
+     int i, col;
+     printf("                ");
+     col = 16;
+     for(i = 0; option_table[i].name != 0; i++) {
+ 	if ((col + strlen(option_table[i].name) + 1) > 76) {
+ 	    printf(",\n                ");
+ 	    col = 16;
+ 	} else if (i != 0) {
+ 	    printf(", ");
+ 	}
+ 	printf("%s", option_table[i].name);
+ 	col += strlen(option_table[i].name) + 2;
+     }
+     printf("\n");
+ }
+ 
+ 
+ usage()
+ {
+     printf("%s\n\n", VERSION);
+     printf("SYNOPSIS: espresso [options] [file]\n\n");
+     printf("  -d        Enable debugging\n");
+     printf("  -e[opt]   Select espresso option:\n");
+     printf("                fast, ness, nirr, nunwrap, onset, pos, strong,\n");
+     printf("                eat, eatdots, kiss, random\n");
+     printf("  -o[type]  Select output format:\n");
+     printf("                f, fd, fr, fdr, pleasure, eqntott, kiss, cons\n");
+     printf("  -rn-m     Select range for subcommands:\n");
+     printf("                d1merge: first and last variables (0 ... m-1)\n");
+     printf("                minterms: first and last variables (0 ... m-1)\n");
+     printf("                opoall: first and last outputs (0 ... m-1)\n");
+     printf("  -s        Provide short execution summary\n");
+     printf("  -t        Provide longer execution trace\n");
+     printf("  -x        Suppress printing of solution\n");
+     printf("  -v[type]  Verbose debugging detail (-v '' for all)\n");
+     printf("  -D[cmd]   Execute subcommand 'cmd':\n");
+     subcommands();
+     printf("  -Sn       Select strategy for subcommands:\n");
+     printf("                opo: bit2=exact bit1=repeated bit0=skip sparse\n");
+     printf("                opoall: 0=minimize, 1=exact\n");
+     printf("                pair: 0=algebraic, 1=strongd, 2=espresso, 3=exact\n");
+     printf("                pairall: 0=minimize, 1=exact, 2=opo\n");
+     printf("                so_espresso: 0=minimize, 1=exact\n");
+     printf("                so_both: 0=minimize, 1=exact\n");
+ }
+ 
+ /*
+  *  Hack for backward compatibility (ACK! )
+  */
+ 
+ backward_compatibility_hack(argc, argv, option, out_type)
+ int *argc;
+ char **argv;
+ int *option;
+ int *out_type;
+ {
+     int i, j;
+ 
+     /* Scan the argument list for something to do (default is ESPRESSO) */
+     *option = 0;
+     for(i = 1; i < (*argc)-1; i++) {
+ 	if (strcmp(argv[i], "-do") == 0) {
+ 	    for(j = 0; option_table[j].name != 0; j++)
+ 		if (strcmp(argv[i+1], option_table[j].name) == 0) {
+ 		    *option = j;
+ 		    delete_arg(argc, argv, i+1);
+ 		    delete_arg(argc, argv, i);
+ 		    break;
+ 		}
+ 	    if (option_table[j].name == 0) {
+ 		fprintf(stderr,
+ 		 "espresso: bad keyword \"%s\" following -do\n",argv[i+1]);
+ 		exit(1);
+ 	    }
+ 	    break;
+ 	}
+     }
+ 
+     for(i = 1; i < (*argc)-1; i++) {
+ 	if (strcmp(argv[i], "-out") == 0) {
+ 	    for(j = 0; pla_types[j].key != 0; j++)
+ 		if (strcmp(pla_types[j].key+1, argv[i+1]) == 0) {
+ 		    *out_type = pla_types[j].value;
+ 		    delete_arg(argc, argv, i+1);
+ 		    delete_arg(argc, argv, i);
+ 		    break;
+ 		}
+ 	    if (pla_types[j].key == 0) {
+ 		fprintf(stderr,
+ 		   "espresso: bad keyword \"%s\" following -out\n",argv[i+1]);
+ 		exit(1);
+ 	    }
+ 	    break;
+ 	}
+     }
+ 
+     for(i = 1; i < (*argc); i++) {
+ 	if (argv[i][0] == '-') {
+ 	    for(j = 0; esp_opt_table[j].name != 0; j++) {
+ 		if (strcmp(argv[i]+1, esp_opt_table[j].name) == 0) {
+ 		    delete_arg(argc, argv, i);
+ 		    *(esp_opt_table[j].variable) = esp_opt_table[j].value;
+ 		    break;
+ 		}
+ 	    }
+ 	}
+     }
+ 
+     if (check_arg(argc, argv, "-fdr")) input_type = FDR_type;
+     if (check_arg(argc, argv, "-fr")) input_type = FR_type;
+     if (check_arg(argc, argv, "-f")) input_type = F_type;
+ }
+ 
+ 
+ /* delete_arg -- delete an argument from the argument list */
+ delete_arg(argc, argv, num)
+ int *argc, num;
+ register char *argv[];
+ {
+     register int i;
+     (*argc)--;
+     for(i = num; i < *argc; i++) {
+ 	argv[i] = argv[i+1];
+     }
+ }
+ 
+ 
+ /* check_arg -- scan argv for an argument, and return TRUE if found */
+ bool check_arg(argc, argv, s)
+ int *argc;
+ register char *argv[], *s;
+ {
+     register int i;
+     for(i = 1; i < *argc; i++) {
+ 	if (strcmp(argv[i], s) == 0) {
+ 	    delete_arg(argc, argv, i);
+ 	    return TRUE;
+ 	}
+     }
+     return FALSE;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/main.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/main.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/main.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,113 ----
+ enum keys {
+     KEY_ESPRESSO, KEY_PLA_verify, KEY_check, KEY_contain, KEY_d1merge,
+     KEY_disjoint, KEY_dsharp, KEY_echo, KEY_essen, KEY_exact, KEY_expand,
+     KEY_gasp, KEY_intersect, KEY_irred, KEY_lexsort, KEY_make_sparse,
+     KEY_map, KEY_mapdc, KEY_minterms, KEY_opo, KEY_opoall,
+     KEY_pair, KEY_pairall, KEY_primes, KEY_qm, KEY_reduce, KEY_sharp,
+     KEY_simplify, KEY_so, KEY_so_both, KEY_stats, KEY_super_gasp, KEY_taut,
+     KEY_test, KEY_equiv, KEY_union, KEY_verify, KEY_MANY_ESPRESSO,
+     KEY_separate, KEY_xor, KEY_d1merge_in, KEY_fsm,
+     KEY_unknown
+ };
+ 
+ /* Lookup table for program options */
+ struct {
+     char *name;
+     enum keys key;
+     int num_plas;
+     bool needs_offset;
+     bool needs_dcset;
+ } option_table [] = {
+     /* ways to minimize functions */
+     "ESPRESSO", KEY_ESPRESSO, 1, TRUE, TRUE,    /* must be first */
+     "many", KEY_MANY_ESPRESSO, 1, TRUE, TRUE,
+     "exact", KEY_exact, 1, TRUE, TRUE,
+     "qm", KEY_qm, 1, TRUE, TRUE,
+     "single_output", KEY_so, 1, TRUE, TRUE,
+     "so", KEY_so, 1, TRUE, TRUE,
+     "so_both", KEY_so_both, 1, TRUE, TRUE,
+     "simplify", KEY_simplify, 1, FALSE, FALSE,
+     "echo", KEY_echo, 1, FALSE, FALSE,
+ 
+     /* output phase assignment and assignment of inputs to two-bit decoders */
+     "opo", KEY_opo, 1, TRUE, TRUE,
+     "opoall", KEY_opoall, 1, TRUE, TRUE,
+     "pair", KEY_pair, 1, TRUE, TRUE,
+     "pairall", KEY_pairall, 1, TRUE, TRUE,
+ 
+     /* Ways to check covers */
+     "check", KEY_check, 1, TRUE, TRUE,
+     "stats", KEY_stats, 1, FALSE, FALSE,
+     "verify", KEY_verify, 2, FALSE, TRUE,
+     "PLAverify", KEY_PLA_verify, 2, FALSE, TRUE,
+ 
+     /* hacks */
+     "equiv", KEY_equiv, 1, TRUE, TRUE,
+     "map", KEY_map, 1, FALSE, FALSE,
+     "mapdc", KEY_mapdc, 1, FALSE, FALSE,
+     "fsm", KEY_fsm, 1, FALSE, TRUE,
+ 
+     /* the basic boolean operations on covers */
+     "contain", KEY_contain, 1, FALSE, FALSE,
+     "d1merge", KEY_d1merge, 1, FALSE, FALSE,
+     "d1merge_in", KEY_d1merge_in, 1, FALSE, FALSE,
+     "disjoint", KEY_disjoint, 1, TRUE, FALSE,
+     "dsharp", KEY_dsharp, 2, FALSE, FALSE,
+     "intersect", KEY_intersect, 2, FALSE, FALSE,
+     "minterms", KEY_minterms, 1, FALSE, FALSE,
+     "primes", KEY_primes, 1, FALSE, TRUE,
+     "separate", KEY_separate, 1, TRUE, TRUE,
+     "sharp", KEY_sharp, 2, FALSE, FALSE,
+     "union", KEY_union, 2, FALSE, FALSE,
+     "xor", KEY_xor, 2, TRUE, TRUE,
+ 
+     /* debugging only -- call each step of the espresso algorithm */
+     "essen", KEY_essen, 1, FALSE, TRUE,
+     "expand", KEY_expand, 1, TRUE, FALSE,
+     "gasp", KEY_gasp, 1, TRUE, TRUE,
+     "irred", KEY_irred, 1, FALSE, TRUE,
+     "make_sparse", KEY_make_sparse, 1, TRUE, TRUE,
+     "reduce", KEY_reduce, 1, FALSE, TRUE,
+     "taut", KEY_taut, 1, FALSE, FALSE,
+     "super_gasp", KEY_super_gasp, 1, TRUE, TRUE,
+     "lexsort", KEY_lexsort, 1, FALSE, FALSE,
+     "test", KEY_test, 1, TRUE, TRUE,
+     0, KEY_unknown, 0, FALSE, FALSE             /* must be last */
+ };
+ 
+ 
+ struct {
+     char *name;
+     int value;
+ } debug_table[] = {
+     "", EXPAND + ESSEN + IRRED + REDUCE + SPARSE + GASP + SHARP + MINCOV,
+     "compl",   COMPL,  "essen",       ESSEN,
+     "expand",  EXPAND, "expand1",     EXPAND1|EXPAND,
+     "irred",   IRRED,  "irred1",      IRRED1|IRRED,
+     "reduce",  REDUCE, "reduce1",     REDUCE1|REDUCE,
+     "mincov",  MINCOV, "mincov1",     MINCOV1|MINCOV,
+     "sparse",  SPARSE, "sharp",       SHARP,
+     "taut",    TAUT,   "gasp",        GASP,
+     "exact",   EXACT,
+     0,
+ };
+ 
+ 
+ struct {
+     char *name;
+     int *variable;
+     int value;
+ } esp_opt_table[] = {
+     "eat", &echo_comments, FALSE,
+     "eatdots", &echo_unknown_commands, FALSE,
+     "fast", &single_expand, TRUE,
+     "kiss", &kiss, TRUE,
+     "ness", &remove_essential, FALSE,
+     "nirr", &force_irredundant, FALSE,
+     "nunwrap", &unwrap_onset, FALSE,
+     "onset", &recompute_onset, TRUE,
+     "pos", &pos, TRUE,
+     "random", &use_random_order, TRUE,
+     "strong", &use_super_gasp, TRUE,
+     0,
+ };


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/map.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/map.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/map.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,106 ----
+ #include "espresso.h"
+ 
+ static pcube Gcube;
+ static pset Gminterm;
+ 
+ pset minterms(T)
+ pcover T;
+ {
+     int size, var;
+     register pcube last;
+ 
+     size = 1;
+     for(var = 0; var < cube.num_vars; var++)
+ 	size *= cube.part_size[var];
+     Gminterm = set_new(size);
+ 
+     foreach_set(T, last, Gcube)
+ 	explode(cube.num_vars-1, 0);
+ 
+     return Gminterm;
+ }
+ 
+ 
+ void explode(var, z)
+ int var, z;
+ {
+     int i, last = cube.last_part[var];
+     for(i=cube.first_part[var], z *= cube.part_size[var]; i<=last; i++, z++)
+ 	if (is_in_set(Gcube, i))
+ 	    if (var == 0)
+ 		set_insert(Gminterm, z);
+ 	    else
+ 		explode(var-1, z);
+ }
+ 
+ 
+ static int mapindex[16][16] = {
+      0,  1,  3,  2,   16, 17, 19, 18,      80, 81, 83, 82,   64, 65, 67, 66,
+      4,  5,  7,  6,   20, 21, 23, 22,      84, 85, 87, 86,   68, 69, 71, 70,
+     12, 13, 15, 14,   28, 29, 31, 30,      92, 93, 95, 94,   76, 77, 79, 78,
+      8,  9, 11, 10,   24, 25, 27, 26,      88, 89, 91, 90,   72, 73, 75, 74,
+ 
+     32, 33, 35, 34,   48, 49, 51, 50,     112,113,115,114,   96, 97, 99, 98,
+     36, 37, 39, 38,   52, 53, 55, 54,     116,117,119,118,  100,101,103,102,
+     44, 45, 47, 46,   60, 61, 63, 62,     124,125,127,126,  108,109,111,110,
+     40, 41, 43, 42,   56, 57, 59, 58,     120,121,123,122,  104,105,107,106,
+ 
+ 
+    160,161,163,162,  176,177,179,178,     240,241,243,242,  224,225,227,226,
+    164,165,167,166,  180,181,183,182,     244,245,247,246,  228,229,231,230,
+    172,173,175,174,  188,189,191,190,     252,253,255,254,  236,237,239,238,
+    168,169,171,170,  184,185,187,186,     248,249,251,250,  232,233,235,234,
+ 
+    128,129,131,130,  144,145,147,146,     208,209,211,210,  192,193,195,194,
+    132,133,135,134,  148,149,151,150,     212,213,215,214,  196,197,199,198,
+    140,141,143,142,  156,157,159,158,     220,221,223,222,  204,205,207,206,
+    136,137,139,138,  152,153,155,154,     216,217,219,218,  200,201,203,202
+ };
+ 
+ #define POWER2(n) (1 << n)
+ void map(T)
+ pcover T;
+ {
+     int j, k, l, other_input_offset, output_offset, outnum, ind;
+     int largest_input_ind,  numout;
+     char c;
+     pset m;
+     bool some_output;
+ 
+     m = minterms(T);
+     largest_input_ind = POWER2(cube.num_binary_vars);
+     numout = cube.part_size[cube.num_vars-1];
+ 
+     for(outnum = 0; outnum < numout; outnum++) {
+ 	output_offset = outnum * largest_input_ind;
+ 	printf("\n\nOutput space # %d\n", outnum);
+ 	for(l = 0; l <= MAX(cube.num_binary_vars - 8, 0); l++) {
+ 	    other_input_offset = l * 256;
+ 	    for(k = 0; k < 16; k++) {
+ 		some_output = FALSE;
+ 		for(j = 0; j < 16; j++) {
+ 		    ind = mapindex[k][j] + other_input_offset;
+ 		    if (ind < largest_input_ind) {
+ 			c = is_in_set(m, ind+output_offset) ? '1' : '.';
+ 			putchar(c);
+ 			some_output = TRUE;
+ 		    }
+ 		    if ((j+1)%4 == 0)
+ 			putchar(' ');
+ 		    if ((j+1)%8 == 0)
+ 			printf("  ");
+ 		}
+ 		if (some_output)
+ 		    putchar('\n');
+ 		if ((k+1)%4 == 0) {
+ 		    if (k != 15 && mapindex[k+1][0] >= largest_input_ind)
+ 			break;
+ 		    putchar('\n');
+ 		}
+ 		if ((k+1)%8 == 0)
+ 		    putchar('\n');
+ 	    }
+ 	}
+     }
+     set_free(m);
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/matrix.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/matrix.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/matrix.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,565 ----
+ #include "port.h"
+ #include "sparse_int.h"
+ 
+ /*
+  *  free-lists are only used if 'FAST_AND_LOOSE' is set; this is because
+  *  we lose the debugging capability of libmm_t which trashes objects when
+  *  they are free'd.  However, FAST_AND_LOOSE is much faster if matrices
+  *  are created and freed frequently.
+  */
+ 
+ #ifdef FAST_AND_LOOSE
+ sm_element *sm_element_freelist;
+ sm_row *sm_row_freelist;
+ sm_col *sm_col_freelist;
+ #endif
+ 
+ 
+ sm_matrix *
+ sm_alloc()
+ {
+     register sm_matrix *A;
+ 
+     A = ALLOC(sm_matrix, 1);
+     A->rows = NIL(sm_row *);
+     A->cols = NIL(sm_col *);
+     A->nrows = A->ncols = 0;
+     A->rows_size = A->cols_size = 0;
+     A->first_row = A->last_row = NIL(sm_row);
+     A->first_col = A->last_col = NIL(sm_col);
+     A->user_word = NIL(char);		/* for our user ... */
+     return A;
+ }
+ 
+ 
+ sm_matrix *
+ sm_alloc_size(row, col)
+ int row, col;
+ {
+     register sm_matrix *A;
+ 
+     A = sm_alloc();
+     sm_resize(A, row, col);
+     return A;
+ }
+ 
+ 
+ void
+ sm_free(A)
+ sm_matrix *A;
+ {
+ #ifdef FAST_AND_LOOSE
+     register sm_row *prow;
+ 
+     if (A->first_row != 0) {
+ 	for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 	    /* add the elements to the free list of elements */
+ 	    prow->last_col->next_col = sm_element_freelist;
+ 	    sm_element_freelist = prow->first_col;
+ 	}
+ 
+ 	/* Add the linked list of rows to the row-free-list */
+ 	A->last_row->next_row = sm_row_freelist;
+ 	sm_row_freelist = A->first_row;
+ 
+ 	/* Add the linked list of cols to the col-free-list */
+ 	A->last_col->next_col = sm_col_freelist;
+ 	sm_col_freelist = A->first_col;
+     }
+ #else
+     register sm_row *prow, *pnext_row;
+     register sm_col *pcol, *pnext_col;
+ 
+     for(prow = A->first_row; prow != 0; prow = pnext_row) {
+ 	pnext_row = prow->next_row;
+ 	sm_row_free(prow);
+     }
+     for(pcol = A->first_col; pcol != 0; pcol = pnext_col) {
+ 	pnext_col = pcol->next_col;
+ 	pcol->first_row = pcol->last_row = NIL(sm_element);
+ 	sm_col_free(pcol);
+     }
+ #endif
+ 
+     /* Free the arrays to map row/col numbers into pointers */
+     FREE(A->rows);
+     FREE(A->cols);
+     FREE(A);
+ }
+ 
+ 
+ sm_matrix *
+ sm_dup(A)
+ sm_matrix *A; 
+ {
+     register sm_row *prow;
+     register sm_element *p;
+     register sm_matrix *B;
+ 
+     B = sm_alloc();
+     if (A->last_row != 0) {
+ 	sm_resize(B, A->last_row->row_num, A->last_col->col_num);
+ 	for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 	    for(p = prow->first_col; p != 0; p = p->next_col) {
+ 		(void) sm_insert(B, p->row_num, p->col_num);
+ 	    }
+ 	}
+     }
+     return B;
+ }
+ 
+ 
+ void 
+ sm_resize(A, row, col)
+ register sm_matrix *A;
+ int row, col;
+ {
+     register int i, new_size;
+ 
+     if (row >= A->rows_size) {
+ 	new_size = MAX(A->rows_size*2, row+1);
+ 	A->rows = REALLOC(sm_row *, A->rows, new_size);
+ 	for(i = A->rows_size; i < new_size; i++) {
+ 	    A->rows[i] = NIL(sm_row);
+ 	}
+ 	A->rows_size = new_size;
+     }
+ 
+     if (col >= A->cols_size) {
+ 	new_size = MAX(A->cols_size*2, col+1);
+ 	A->cols = REALLOC(sm_col *, A->cols, new_size);
+ 	for(i = A->cols_size; i < new_size; i++) {
+ 	    A->cols[i] = NIL(sm_col);
+ 	}
+ 	A->cols_size = new_size;
+     }
+ }
+ 
+ 
+ /*  
+  *  insert -- insert a value into the matrix
+  */
+ sm_element *
+ sm_insert(A, row, col)
+ register sm_matrix *A;
+ register int row, col;
+ {
+     register sm_row *prow;
+     register sm_col *pcol;
+     register sm_element *element;
+     sm_element *save_element;
+ 
+     if (row >= A->rows_size || col >= A->cols_size) {
+ 	sm_resize(A, row, col);
+     }
+ 
+     prow = A->rows[row];
+     if (prow == NIL(sm_row)) {
+ 	prow = A->rows[row] = sm_row_alloc();
+ 	prow->row_num = row;
+ 	sorted_insert(sm_row, A->first_row, A->last_row, A->nrows, 
+ 			next_row, prev_row, row_num, row, prow);
+     }
+ 
+     pcol = A->cols[col];
+     if (pcol == NIL(sm_col)) {
+ 	pcol = A->cols[col] = sm_col_alloc();
+ 	pcol->col_num = col;
+ 	sorted_insert(sm_col, A->first_col, A->last_col, A->ncols, 
+ 			next_col, prev_col, col_num, col, pcol);
+     }
+ 
+     /* get a new item, save its address */
+     sm_element_alloc(element);
+     save_element = element;
+ 
+     /* insert it into the row list */
+     sorted_insert(sm_element, prow->first_col, prow->last_col, 
+ 		prow->length, next_col, prev_col, col_num, col, element);
+ 
+     /* if it was used, also insert it into the column list */
+     if (element == save_element) {
+ 	sorted_insert(sm_element, pcol->first_row, pcol->last_row, 
+ 		pcol->length, next_row, prev_row, row_num, row, element);
+     } else {
+ 	/* otherwise, it was already in matrix -- free element we allocated */
+ 	sm_element_free(save_element);
+     }
+     return element;
+ }
+ 
+ 
+ sm_element *
+ sm_find(A, rownum, colnum)
+ sm_matrix *A;
+ int rownum, colnum;
+ {
+     sm_row *prow;
+     sm_col *pcol;
+ 
+     prow = sm_get_row(A, rownum);
+     if (prow == NIL(sm_row)) {
+ 	return NIL(sm_element);
+     } else {
+ 	pcol = sm_get_col(A, colnum);
+ 	if (pcol == NIL(sm_col)) {
+ 	    return NIL(sm_element);
+ 	}
+ 	if (prow->length < pcol->length) {
+ 	    return sm_row_find(prow, colnum);
+ 	} else {
+ 	    return sm_col_find(pcol, rownum);
+ 	}
+     }
+ }
+ 
+ 
+ void
+ sm_remove(A, rownum, colnum)
+ sm_matrix *A;
+ int rownum, colnum;
+ {
+     sm_remove_element(A, sm_find(A, rownum, colnum));
+ }
+ 
+ 
+ 
+ void
+ sm_remove_element(A, p)
+ register sm_matrix *A; 
+ register sm_element *p;
+ {
+     register sm_row *prow;
+     register sm_col *pcol;
+ 
+     if (p == 0) return;
+ 
+     /* Unlink the element from its row */
+     prow = sm_get_row(A, p->row_num);
+     dll_unlink(p, prow->first_col, prow->last_col, 
+ 			next_col, prev_col, prow->length);
+ 
+     /* if no more elements in the row, discard the row header */
+     if (prow->first_col == NIL(sm_element)) {
+ 	sm_delrow(A, p->row_num);
+     }
+ 
+     /* Unlink the element from its column */
+     pcol = sm_get_col(A, p->col_num);
+     dll_unlink(p, pcol->first_row, pcol->last_row, 
+ 			next_row, prev_row, pcol->length);
+ 
+     /* if no more elements in the column, discard the column header */
+     if (pcol->first_row == NIL(sm_element)) {
+ 	sm_delcol(A, p->col_num);
+     }
+ 
+     sm_element_free(p);
+ }
+ 
+ void 
+ sm_delrow(A, i)
+ sm_matrix *A;
+ int i;
+ {
+     register sm_element *p, *pnext;
+     sm_col *pcol;
+     sm_row *prow;
+ 
+     prow = sm_get_row(A, i);
+     if (prow != NIL(sm_row)) {
+ 	/* walk across the row */
+ 	for(p = prow->first_col; p != 0; p = pnext) {
+ 	    pnext = p->next_col;
+ 
+ 	    /* unlink the item from the column (and delete it) */
+ 	    pcol = sm_get_col(A, p->col_num);
+ 	    sm_col_remove_element(pcol, p);
+ 
+ 	    /* discard the column if it is now empty */
+ 	    if (pcol->first_row == NIL(sm_element)) {
+ 		sm_delcol(A, pcol->col_num);
+ 	    }
+ 	}
+ 
+ 	/* discard the row -- we already threw away the elements */ 
+ 	A->rows[i] = NIL(sm_row);
+ 	dll_unlink(prow, A->first_row, A->last_row, 
+ 				next_row, prev_row, A->nrows);
+ 	prow->first_col = prow->last_col = NIL(sm_element);
+ 	sm_row_free(prow);
+     }
+ }
+ 
+ void 
+ sm_delcol(A, i)
+ sm_matrix *A;
+ int i;
+ {
+     register sm_element *p, *pnext;
+     sm_row *prow;
+     sm_col *pcol;
+ 
+     pcol = sm_get_col(A, i);
+     if (pcol != NIL(sm_col)) {
+ 	/* walk down the column */
+ 	for(p = pcol->first_row; p != 0; p = pnext) {
+ 	    pnext = p->next_row;
+ 
+ 	    /* unlink the element from the row (and delete it) */
+ 	    prow = sm_get_row(A, p->row_num);
+ 	    sm_row_remove_element(prow, p);
+ 
+ 	    /* discard the row if it is now empty */
+ 	    if (prow->first_col == NIL(sm_element)) {
+ 		sm_delrow(A, prow->row_num);
+ 	    }
+ 	}
+ 
+ 	/* discard the column -- we already threw away the elements */ 
+ 	A->cols[i] = NIL(sm_col);
+ 	dll_unlink(pcol, A->first_col, A->last_col, 
+ 			    next_col, prev_col, A->ncols);
+ 	pcol->first_row = pcol->last_row = NIL(sm_element);
+ 	sm_col_free(pcol);
+     }
+ }
+ 
+ void
+ sm_copy_row(dest, dest_row, prow)
+ register sm_matrix *dest;
+ int dest_row;
+ sm_row *prow;
+ {
+     register sm_element *p;
+ 
+     for(p = prow->first_col; p != 0; p = p->next_col) {
+ 	(void) sm_insert(dest, dest_row, p->col_num);
+     }
+ }
+ 
+ 
+ void
+ sm_copy_col(dest, dest_col, pcol)
+ register sm_matrix *dest;
+ int dest_col;
+ sm_col *pcol;
+ {
+     register sm_element *p;
+ 
+     for(p = pcol->first_row; p != 0; p = p->next_row) {
+ 	(void) sm_insert(dest, dest_col, p->row_num);
+     }
+ }
+ 
+ 
+ sm_row *
+ sm_longest_row(A)
+ sm_matrix *A;
+ {
+     register sm_row *large_row, *prow;
+     register int max_length;
+ 
+     max_length = 0;
+     large_row = NIL(sm_row);
+     for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 	if (prow->length > max_length) {
+ 	    max_length = prow->length;
+ 	    large_row = prow;
+ 	}
+     }
+     return large_row;
+ }
+ 
+ 
+ sm_col *
+ sm_longest_col(A)
+ sm_matrix *A;
+ {
+     register sm_col *large_col, *pcol;
+     register int max_length;
+ 
+     max_length = 0;
+     large_col = NIL(sm_col);
+     for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ 	if (pcol->length > max_length) {
+ 	    max_length = pcol->length;
+ 	    large_col = pcol;
+ 	}
+     }
+     return large_col;
+ }
+ 
+ int
+ sm_num_elements(A)
+ sm_matrix *A;
+ {
+     register sm_row *prow;
+     register int num;
+ 
+     num = 0;
+     sm_foreach_row(A, prow) {
+ 	num += prow->length;
+     }
+     return num;
+ }
+ 
+ int 
+ sm_read(fp, A)
+ FILE *fp;
+ sm_matrix **A;
+ {
+     int i, j, err;
+ 
+     *A = sm_alloc();
+     while (! feof(fp)) {
+ 	err = fscanf(fp, "%d %d", &i, &j);
+ 	if (err == EOF) {
+ 	    return 1;
+ 	} else if (err != 2) {
+ 	    return 0;
+ 	}
+ 	(void) sm_insert(*A, i, j);
+     }
+     return 1;
+ }
+ 
+ 
+ int 
+ sm_read_compressed(fp, A)
+ FILE *fp;
+ sm_matrix **A;
+ {
+     int i, j, k, nrows, ncols;
+     unsigned long x;
+ 
+     *A = sm_alloc();
+     if (fscanf(fp, "%d %d", &nrows, &ncols) != 2) {
+ 	return 0;
+     }
+     sm_resize(*A, nrows, ncols);
+ 
+     for(i = 0; i < nrows; i++) {
+ 	if (fscanf(fp, "%lx", &x) != 1) {
+ 	    return 0;
+ 	}
+ 	for(j = 0; j < ncols; j += 32) {
+ 	    if (fscanf(fp, "%lx", &x) != 1) {
+ 		return 0;
+ 	    }
+ 	    for(k = j; x != 0; x >>= 1, k++) {
+ 		if (x & 1) {
+ 		    (void) sm_insert(*A, i, k);
+ 		}
+ 	    }
+ 	}
+     }
+     return 1;
+ }
+ 
+ 
+ void 
+ sm_write(fp, A)
+ FILE *fp;
+ sm_matrix *A;
+ {
+     register sm_row *prow;
+     register sm_element *p;
+ 
+     for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 	for(p = prow->first_col; p != 0; p = p->next_col) {
+ 	    (void) fprintf(fp, "%d %d\n", p->row_num, p->col_num);
+ 	}
+     }
+ }
+ 
+ void 
+ sm_print(fp, A)
+ FILE *fp;
+ sm_matrix *A;
+ {
+     register sm_row *prow;
+     register sm_col *pcol;
+     int c;
+ 
+     if (A->last_col->col_num >= 100) {
+ 	(void) fprintf(fp, "    ");
+ 	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ 	    (void) fprintf(fp, "%d", (pcol->col_num / 100)%10);
+ 	}
+ 	putc('\n', fp);
+     }
+ 
+     if (A->last_col->col_num >= 10) {
+ 	(void) fprintf(fp, "    ");
+ 	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ 	    (void) fprintf(fp, "%d", (pcol->col_num / 10)%10);
+ 	}
+ 	putc('\n', fp);
+     }
+ 
+     (void) fprintf(fp, "    ");
+     for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ 	(void) fprintf(fp, "%d", pcol->col_num % 10);
+     }
+     putc('\n', fp);
+ 
+     (void) fprintf(fp, "    ");
+     for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ 	(void) fprintf(fp, "-");
+     }
+     putc('\n', fp);
+ 
+     for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 	(void) fprintf(fp, "%3d:", prow->row_num);
+ 
+ 	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ 	    c = sm_row_find(prow, pcol->col_num) ? '1' : '.';
+ 	    putc(c, fp);
+ 	}
+ 	putc('\n', fp);
+     }
+ }
+ 
+ 
+ void 
+ sm_dump(A, s, max)
+ sm_matrix *A;
+ char *s;
+ int max;
+ {
+     FILE *fp = stdout;
+ 
+     (void) fprintf(fp, "%s %d rows by %d cols\n", s, A->nrows, A->ncols);
+     if (A->nrows < max) {
+ 	sm_print(fp, A);
+     }
+ }
+ 
+ void
+ sm_cleanup()
+ {
+ #ifdef FAST_AND_LOOSE
+     register sm_element *p, *pnext;
+     register sm_row *prow, *pnextrow;
+     register sm_col *pcol, *pnextcol;
+ 
+     for(p = sm_element_freelist; p != 0; p = pnext) {
+ 	pnext = p->next_col;
+ 	FREE(p);
+     }
+     sm_element_freelist = 0;
+ 
+     for(prow = sm_row_freelist; prow != 0; prow = pnextrow) {
+ 	pnextrow = prow->next_row;
+ 	FREE(prow);
+     }
+     sm_row_freelist = 0;
+ 
+     for(pcol = sm_col_freelist; pcol != 0; pcol = pnextcol) {
+ 	pnextcol = pcol->next_col;
+ 	FREE(pcol);
+     }
+     sm_col_freelist = 0;
+ #endif
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/mincov.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/mincov.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/mincov.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,369 ----
+ #include "mincov_int.h"
+ 
+ /*
+  *  mincov.c
+  */
+ 
+ #define USE_GIMPEL
+ #define USE_INDEP_SET
+ 
+ extern int select_column();
+ extern void select_essential();
+ extern int verify_cover();
+ 
+ #define fail(why) {\
+     (void) fprintf(stderr, "Fatal error: file %s, line %d\n%s\n",\
+ 	__FILE__, __LINE__, why);\
+     (void) fflush(stdout);\
+     abort();\
+ }
+ 
+ sm_row *
+ sm_minimum_cover(A, weight, heuristic, debug_level)
+ sm_matrix *A;
+ int *weight;
+ int heuristic;		/* set to 1 for a heuristic covering */
+ int debug_level;	/* how deep in the recursion to provide info */
+ {
+     stats_t stats;
+     solution_t *best, *select;
+     sm_row *prow, *sol;
+     sm_col *pcol;
+     sm_matrix *dup_A;
+     int nelem, bound;
+     double sparsity;
+ 
+     /* Avoid sillyness */
+     if (A->nrows <= 0) {
+ 	return sm_row_alloc();		/* easy to cover */
+     }
+ 
+     /* Initialize debugging structure */
+     stats.start_time = util_cpu_time();
+     stats.debug = debug_level > 0;
+     stats.max_print_depth = debug_level;
+     stats.max_depth = -1;
+     stats.nodes = 0;
+     stats.component = stats.comp_count = 0;
+     stats.gimpel = stats.gimpel_count = 0;
+     stats.no_branching = heuristic != 0;
+     stats.lower_bound = -1;
+ 
+     /* Check the matrix sparsity */
+     nelem = 0;
+     sm_foreach_row(A, prow) {
+ 	nelem += prow->length;
+     }
+     sparsity = (double) nelem / (double) (A->nrows * A->ncols);
+ 
+     /* Determine an upper bound on the solution */
+     bound = 1;
+     sm_foreach_col(A, pcol) {
+ 	bound += WEIGHT(weight, pcol->col_num);
+     }
+ 
+     /* Perform the covering */
+     select = solution_alloc();
+     dup_A = sm_dup(A);
+     best = sm_mincov(dup_A, select, weight, 0, bound, 0, &stats);
+     sm_free(dup_A);
+     solution_free(select);
+ 
+     if (stats.debug) {
+ 	if (stats.no_branching) {
+ 	    (void) printf("**** heuristic covering ...\n");
+ 	    (void) printf("lower bound = %d\n", stats.lower_bound);
+ 	}
+ 	(void) printf("matrix     = %d by %d with %d elements (%4.3f%%)\n",
+ 		A->nrows, A->ncols, nelem, sparsity * 100.0);
+ 	(void) printf("cover size = %d elements\n", best->row->length);
+ 	(void) printf("cover cost = %d\n", best->cost);
+ 	(void) printf("time       = %s\n", 
+ 			util_print_time(util_cpu_time() - stats.start_time));
+ 	(void) printf("components = %d\n", stats.comp_count);
+ 	(void) printf("gimpel     = %d\n", stats.gimpel_count);
+ 	(void) printf("nodes      = %d\n", stats.nodes);
+ 	(void) printf("max_depth  = %d\n", stats.max_depth);
+     }
+ 
+     sol = sm_row_dup(best->row);
+     if (! verify_cover(A, sol)) {
+ 	fail("mincov: internal error -- cover verification failed\n");
+     }
+     solution_free(best);
+     return sol;
+ }
+ 
+ /*
+  *  Find the best cover for 'A' (given that 'select' already selected);
+  *
+  *    - abort search if a solution cannot be found which beats 'bound'
+  *
+  *    - if any solution meets 'lower_bound', then it is the optimum solution
+  *      and can be returned without further work.
+  */
+ 
+ solution_t * 
+ sm_mincov(A, select, weight, lb, bound, depth, stats)
+ sm_matrix *A;
+ solution_t *select;
+ int *weight;
+ int lb;
+ int bound;
+ int depth;
+ stats_t *stats;
+ {
+     sm_matrix *A1, *A2, *L, *R;
+     sm_element *p;
+     solution_t *select1, *select2, *best, *best1, *best2, *indep;
+     int pick, lb_new, debug;
+ 
+     /* Start out with some debugging information */
+     stats->nodes++;
+     if (depth > stats->max_depth) stats->max_depth = depth;
+     debug = stats->debug && (depth <= stats->max_print_depth);
+ 
+     /* Apply row dominance, column dominance, and select essentials */
+     select_essential(A, select, weight, bound);
+     if (select->cost >= bound) {
+ 	return NIL(solution_t);
+     }
+ 
+     /* See if gimpel's reduction technique applies ... */
+ #ifdef USE_GIMPEL
+     if ( weight == NIL(int)) {	/* hack until we fix it */
+ 	if (gimpel_reduce(A, select, weight, lb, bound, depth, stats, &best)) {
+ 	    return best;
+ 	}
+     }
+ #endif
+ 
+ #ifdef USE_INDEP_SET
+     /* Determine bound from here to final solution using independent-set */
+     indep = sm_maximal_independent_set(A, weight);
+ 
+     /* make sure the lower bound is monotonically increasing */
+     lb_new = MAX(select->cost + indep->cost, lb);
+     pick = select_column(A, weight, indep);
+     solution_free(indep);
+ #else
+     lb_new = select->cost + (A->nrows > 0);
+     pick = select_column(A, weight, NIL(solution_t));
+ #endif
+ 
+     if (depth == 0) {
+ 	stats->lower_bound = lb_new + stats->gimpel;
+     }
+ 
+     if (debug) {
+         (void) printf("ABSMIN[%2d]%s", depth, stats->component ? "*" : " ");
+         (void) printf(" %3dx%3d sel=%3d bnd=%3d lb=%3d %12s ",
+             A->nrows, A->ncols, select->cost + stats->gimpel, 
+ 	    bound + stats->gimpel, lb_new + stats->gimpel, 
+ 	    util_print_time(util_cpu_time()-stats->start_time));
+     }
+ 
+     /* Check for bounding based on no better solution possible */
+     if (lb_new >= bound) {
+ 	if (debug) (void) printf("bounded\n");
+ 	best = NIL(solution_t);
+ 
+ 
+     /* Check for new best solution */
+     } else if (A->nrows == 0) {
+ 	best = solution_dup(select);
+ 	if (debug) (void) printf("BEST\n");
+ 	if (stats->debug && stats->component == 0) {
+             (void) printf("new 'best' solution %d at level %d (time is %s)\n", 
+ 		best->cost + stats->gimpel, depth, 
+ 		util_print_time(util_cpu_time() - stats->start_time));
+         }
+ 
+ 
+     /* Check for a partition of the problem */
+     } else if (sm_block_partition(A, &L, &R)) {
+ 	/* Make L the smaller problem */
+ 	if (L->ncols > R->ncols) {
+ 	    A1 = L;
+ 	    L = R;
+ 	    R = A1;
+ 	}
+ 	if (debug) (void) printf("comp %d %d\n", L->nrows, R->nrows);
+ 	stats->comp_count++;
+ 
+ 	/* Solve problem for L */
+ 	select1 = solution_alloc();
+ 	stats->component++;
+ 	best1 = sm_mincov(L, select1, weight, 0, 
+ 				    bound-select->cost, depth+1, stats);
+ 	stats->component--;
+ 	solution_free(select1);
+ 	sm_free(L);
+ 
+ 	/* Add best solution to the selected set */
+ 	if (best1 == NIL(solution_t)) {
+ 	    best = NIL(solution_t);
+ 	} else {
+ 	    for(p = best1->row->first_col; p != 0; p = p->next_col) {
+ 		solution_add(select, weight, p->col_num);
+ 	    }
+ 	    solution_free(best1);
+ 
+ 	    /* recur for the remaining block */
+ 	    best = sm_mincov(R, select, weight, lb_new, bound, depth+1, stats);
+ 	}
+ 	sm_free(R);
+ 
+     /* We've tried as hard as possible, but now we must split and recur */
+     } else {
+ 	if (debug) (void) printf("pick=%d\n", pick);
+ 
+         /* Assume we choose this column to be in the covering set */
+ 	A1 = sm_dup(A);
+ 	select1 = solution_dup(select);
+ 	solution_accept(select1, A1, weight, pick);
+         best1 = sm_mincov(A1, select1, weight, lb_new, bound, depth+1, stats);
+ 	solution_free(select1);
+ 	sm_free(A1);
+ 
+ 	/* Update the upper bound if we found a better solution */
+ 	if (best1 != NIL(solution_t) && bound > best1->cost) {
+ 	    bound = best1->cost;
+ 	}
+ 
+ 	/* See if this is a heuristic covering (no branching) */
+ 	if (stats->no_branching) {
+ 	    return best1;
+ 	}
+ 
+ 	/* Check for reaching lower bound -- if so, don't actually branch */
+ 	if (best1 != NIL(solution_t) && best1->cost == lb_new) {
+ 	    return best1;
+ 	}
+ 
+         /* Now assume we cannot have that column */
+ 	A2 = sm_dup(A);
+ 	select2 = solution_dup(select);
+ 	solution_reject(select2, A2, weight, pick);
+         best2 = sm_mincov(A2, select2, weight, lb_new, bound, depth+1, stats);
+ 	solution_free(select2);
+ 	sm_free(A2);
+ 
+ 	best = solution_choose_best(best1, best2);
+     }
+ 
+     return best;
+ }
+ 
+ static int 
+ select_column(A, weight, indep)
+ sm_matrix *A;
+ int *weight;
+ solution_t *indep;
+ {
+     register sm_col *pcol;
+     register sm_row *prow, *indep_cols;
+     register sm_element *p, *p1;
+     double w, best;
+     int best_col;
+ 
+     indep_cols = sm_row_alloc();
+     if (indep != NIL(solution_t)) {
+ 	/* Find which columns are in the independent sets */
+ 	for(p = indep->row->first_col; p != 0; p = p->next_col) {
+ 	    prow = sm_get_row(A, p->col_num);
+ 	    for(p1 = prow->first_col; p1 != 0; p1 = p1->next_col) {
+ 		(void) sm_row_insert(indep_cols, p1->col_num);
+ 	    }
+ 	}
+     } else {
+ 	/* select out of all columns */
+ 	sm_foreach_col(A, pcol) {
+ 	    (void) sm_row_insert(indep_cols, pcol->col_num);
+ 	}
+     }
+ 
+     /* Find the best column */
+     best_col = -1;
+     best = -1;
+ 
+     /* Consider only columns which are in some independent row */
+     sm_foreach_row_element(indep_cols, p1) {
+ 	pcol = sm_get_col(A, p1->col_num);
+ 
+ 	/* Compute the total 'value' of all things covered by the column */
+ 	w = 0.0;
+ 	for(p = pcol->first_row; p != 0; p = p->next_row) {
+ 	    prow = sm_get_row(A, p->row_num);
+ 	    w += 1.0 / ((double) prow->length - 1.0);
+ 	}
+ 
+ 	/* divide this by the relative cost of choosing this column */
+ 	w = w / (double) WEIGHT(weight, pcol->col_num);
+ 
+ 	/* maximize this ratio */
+ 	if (w  > best) {
+ 	    best_col = pcol->col_num;
+ 	    best = w;
+ 	}
+     }
+ 
+     sm_row_free(indep_cols);
+     return best_col;
+ }
+ 
+ static void 
+ select_essential(A, select, weight, bound)
+ sm_matrix *A;
+ solution_t *select;
+ int *weight;
+ int bound;			/* must beat this solution */
+ {
+     register sm_element *p;
+     register sm_row *prow, *essen;
+     int delcols, delrows, essen_count;
+ 
+     do {
+ 	/*  Check for dominated columns  */
+ 	delcols = sm_col_dominance(A, weight);
+ 
+ 	/*  Find the rows with only 1 element (the essentials) */
+ 	essen = sm_row_alloc();
+ 	sm_foreach_row(A, prow) {
+ 	    if (prow->length == 1) {
+ 		(void) sm_row_insert(essen, prow->first_col->col_num);
+ 	    }
+ 	}
+ 
+ 	/* Select all of the elements */
+ 	sm_foreach_row_element(essen, p) {
+ 	    solution_accept(select, A, weight, p->col_num);
+ 	    /* Make sure solution still looks good */
+ 	    if (select->cost >= bound) {
+ 		sm_row_free(essen);
+ 		return;
+ 	    }
+ 	}
+ 	essen_count = essen->length;
+ 	sm_row_free(essen);
+ 
+ 	/*  Check for dominated rows  */
+ 	delrows = sm_row_dominance(A);
+ 
+     } while (delcols > 0 || delrows > 0 || essen_count > 0);
+ }
+ 
+ static int 
+ verify_cover(A, cover)
+ sm_matrix *A;
+ sm_row *cover;
+ {
+     sm_row *prow;
+ 
+     sm_foreach_row(A, prow) {
+ 	if (! sm_row_intersects(prow, cover)) {
+ 	    return 0;
+ 	}
+     }
+     return 1;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/mincov.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/mincov.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/mincov.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,2 ----
+ /* exported */
+ extern sm_row *sm_minimum_cover();


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/mincov_int.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/mincov_int.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/mincov_int.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,44 ----
+ #include "port.h"
+ #include "utility.h"
+ #include "sparse.h"
+ #include "mincov.h"
+ 
+ 
+ typedef struct stats_struct stats_t;
+ struct stats_struct {
+     int debug;			/* 1 if debugging is enabled */
+     int max_print_depth;	/* dump stats for levels up to this level */
+     int max_depth;		/* deepest the recursion has gone */
+     int nodes;			/* total nodes visited */
+     int component;		/* currently solving a component */
+     int comp_count;		/* number of components detected */
+     int gimpel_count;		/* number of times Gimpel reduction applied */
+     int gimpel;			/* currently inside Gimpel reduction */
+     long start_time;		/* cpu time when the covering started */
+     int no_branching;
+     int lower_bound;
+ };
+ 
+ 
+ 
+ typedef struct solution_struct solution_t;
+ struct solution_struct {
+     sm_row *row;
+     int cost;
+ };
+ 
+ 
+ extern solution_t *solution_alloc();
+ extern void solution_free();
+ extern solution_t *solution_dup();
+ extern void solution_accept();
+ extern void solution_reject();
+ extern void solution_add();
+ extern solution_t *solution_choose_best();
+ 
+ extern solution_t *sm_maximal_independent_set();
+ extern solution_t *sm_mincov();
+ extern int gimpel_reduce();
+ 
+ 
+ #define WEIGHT(weight, col)	(weight == NIL(int) ? 1 : weight[col])


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/opo.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/opo.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/opo.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,615 ----
+ #include "espresso.h"
+ 
+ /*
+  *   Phase assignment technique (T. Sasao):
+  *
+  *      1. create a function with 2*m outputs which implements the
+  *      original function and its complement for each output
+  *
+  *      2. minimize this function
+  *
+  *      3. choose the minimum number of prime implicants from the
+  *      result of step 2 which are needed to realize either a function
+  *      or its complement for each output
+  *
+  *  Step 3 is performed in a rather crude way -- by simply multiplying
+  *  out a large expression of the form:
+  *
+  *      I = (ab + cdef)(acd + bgh) ...
+  *
+  *  which is a product of m expressions where each expression has two
+  *  product terms -- one representing which primes are needed for the
+  *  function, and one representing which primes are needed for the
+  *  complement.  The largest product term resulting shows which primes
+  *  to keep to implement one function or the other for each output.
+  *  For problems with many outputs, this may grind to a
+  *  halt.
+  *
+  *  Untried: form complement of I and use unate_complement ...
+  *
+  *  I have unsuccessfully tried several modifications to the basic
+  *  algorithm.  The first is quite simple: use Sasao's technique, but
+  *  only commit to a single output at a time (rather than all
+  *  outputs).  The goal would be that the later minimizations can "take
+  *  into account" the partial assignment at each step.  This is
+  *  expensive (m+1 minimizations rather than 2), and the results are
+  *  discouraging.
+  *
+  *  The second modification is rather complicated.  The result from the
+  *  minimization in step 2 is guaranteed to be minimal.  Hence, for
+  *  each output, the set of primes with a 1 in that output are both
+  *  necessary and sufficient to implement the function.  Espresso
+  *  achieves the minimality using the routine MAKE_SPARSE.  The
+  *  modification is to prevent MAKE_SPARSE from running.  Hence, there
+  *  are potentially many subsets of the set of primes with a 1 in a
+  *  column which can be used to implement that output.  We use
+  *  IRREDUNDANT to enumerate all possible subsets and then proceed as
+  *  before.
+  */
+ 
+ static int opo_no_make_sparse;
+ static int opo_repeated;
+ static int opo_exact;
+ void minimize();
+ 
+ void phase_assignment(PLA, opo_strategy)
+ pPLA PLA;
+ int opo_strategy;
+ {
+     opo_no_make_sparse = opo_strategy % 2;
+     skip_make_sparse = opo_no_make_sparse;
+     opo_repeated = (opo_strategy / 2) % 2;
+     opo_exact = (opo_strategy / 4) % 2;
+ 
+     /* Determine a phase assignment */
+     if (PLA->phase != NULL) {
+ 	FREE(PLA->phase);
+     }
+ 
+     if (opo_repeated) {
+ 	PLA->phase = set_save(cube.fullset);
+ 	repeated_phase_assignment(PLA);
+     } else {
+ 	PLA->phase = find_phase(PLA, 0, (pcube) NULL);
+     }
+ 
+     /* Now minimize with this assignment */
+     skip_make_sparse = FALSE;
+     (void) set_phase(PLA);
+     minimize(PLA);
+ }
+ 
+ /*
+  *  repeated_phase_assignment -- an alternate strategy which commits
+  *  to a single phase assignment a step at a time.  Performs m + 1
+  *  minimizations !
+  */
+ void repeated_phase_assignment(PLA)
+ pPLA PLA;
+ {
+     int i;
+     pcube phase;
+ 
+     for(i = 0; i < cube.part_size[cube.output]; i++) {
+ 
+ 	/* Find best assignment for all undecided outputs */
+ 	phase = find_phase(PLA, i, PLA->phase);
+ 
+ 	/* Commit for only a single output ... */
+ 	if (! is_in_set(phase, cube.first_part[cube.output] + i)) {
+ 	    set_remove(PLA->phase, cube.first_part[cube.output] + i);
+ 	}
+ 
+ 	if (trace || summary) {
+ 	    printf("\nOPO loop for output #%d\n", i);
+ 	    printf("PLA->phase is %s\n", pc1(PLA->phase));
+ 	    printf("phase      is %s\n", pc1(phase));
+ 	}
+ 	set_free(phase);
+     }
+ }
+ 
+ 
+ /*
+  *  find_phase -- find a phase assignment for the PLA for all outputs starting
+  *  with output number first_output.
+  */
+ pcube find_phase(PLA, first_output, phase1)
+ pPLA PLA;
+ int first_output;
+ pcube phase1;
+ {
+     pcube phase;
+     pPLA PLA1;
+ 
+     phase = set_save(cube.fullset);
+ 
+     /* setup the double-phase characteristic function, resize the cube */
+     PLA1 = new_PLA();
+     PLA1->F = sf_save(PLA->F);
+     PLA1->R = sf_save(PLA->R);
+     PLA1->D = sf_save(PLA->D);
+     if (phase1 != NULL) {
+ 	PLA1->phase = set_save(phase1);
+ 	(void) set_phase(PLA1);
+     }
+     EXEC_S(output_phase_setup(PLA1, first_output), "OPO-SETUP ", PLA1->F);
+ 
+     /* minimize the double-phase function */
+     minimize(PLA1);
+ 
+     /* set the proper phases according to what gives a minimum solution */
+     EXEC_S(PLA1->F = opo(phase, PLA1->F, PLA1->D, PLA1->R, first_output),
+ 	    "OPO       ", PLA1->F);
+     free_PLA(PLA1);
+ 
+     /* set the cube structure to reflect the old size */
+     setdown_cube();
+     cube.part_size[cube.output] -=
+ 	(cube.part_size[cube.output] - first_output) / 2;
+     cube_setup();
+ 
+     return phase;
+ }
+ 
+ /*
+  *  opo -- multiply the expression out to determine a minimum subset of
+  *  primes.
+  */
+ 
+ /*ARGSUSED*/
+ pcover opo(phase, T, D, R, first_output)
+ pcube phase;
+ pcover T, D, R;
+ int first_output;
+ {
+     int offset, output, i, last_output, ind;
+     pset pdest, select, p, p1, last, last1, not_covered, tmp;
+     pset_family temp, T1, T2;
+ 
+     /* must select all primes for outputs [0 .. first_output-1] */
+     select = set_full(T->count);
+     for(output = 0; output < first_output; output++) {
+ 	ind = cube.first_part[cube.output] + output;
+ 	foreachi_set(T, i, p) {
+ 	    if (is_in_set(p, ind)) {
+ 		set_remove(select, i);
+ 	    }
+ 	}
+     }
+ 
+     /* Recursively perform the intersections */
+     offset = (cube.part_size[cube.output] - first_output) / 2;
+     last_output = first_output + offset - 1;
+     temp = opo_recur(T, D, select, offset, first_output, last_output);
+ 
+     /* largest set is on top -- select primes which are inferred from it */
+     pdest = temp->data;
+     T1 = new_cover(T->count);
+     foreachi_set(T, i, p) {
+ 	if (! is_in_set(pdest, i)) {
+ 	    T1 = sf_addset(T1, p);
+ 	}
+     }
+ 
+     set_free(select);
+     sf_free(temp);
+ 
+     /* finding phases is difficult -- see which functions are not covered */
+     T2 = complement(cube1list(T1));
+     not_covered = new_cube();
+     tmp = new_cube();
+     foreach_set(T, last, p) {
+ 	foreach_set(T2, last1, p1) {
+ 	    if (cdist0(p, p1)) {
+ 		(void) set_or(not_covered, not_covered, set_and(tmp, p, p1));
+ 	    }
+ 	}
+     }
+     free_cover(T);
+     free_cover(T2);
+     set_free(tmp);
+ 
+     /* Now reflect the phase choice in a single cube */
+     for(output = first_output; output <= last_output; output++) {
+ 	ind = cube.first_part[cube.output] + output;
+ 	if (is_in_set(not_covered, ind)) {
+ 	    if (is_in_set(not_covered, ind + offset)) {
+ 		fatal("error in output phase assignment");
+ 	    } else {
+ 		set_remove(phase, ind);
+ 	    }
+ 	}
+     }
+     set_free(not_covered);
+     return T1;
+ }
+ 
+ pset_family opo_recur(T, D, select, offset, first, last)
+ pcover T, D;
+ pcube select;
+ int offset, first, last;
+ {
+     static int level = 0;
+     int middle;
+     pset_family sl, sr, temp;
+ 
+     level++;
+     if (first == last) {
+ #if 0
+ 	if (opo_no_make_sparse) {
+ 	    temp = form_cover_table(T, D, select, first, first + offset);
+ 	} else {
+ 	    temp = opo_leaf(T, select, first, first + offset);
+ 	}
+ #else
+ 	temp = opo_leaf(T, select, first, first + offset);
+ #endif
+     } else {
+ 	middle = (first + last) / 2;
+ 	sl = opo_recur(T, D, select, offset, first, middle);
+ 	sr = opo_recur(T, D, select, offset, middle+1, last);
+ 	temp = unate_intersect(sl, sr, level == 1);
+ 	if (trace) {
+ 	    printf("# OPO[%d]: %4d = %4d x %4d, time = %s\n", level - 1,
+ 		temp->count, sl->count, sr->count, print_time(ptime()));
+ 	    (void) fflush(stdout);
+ 	}
+ 	free_cover(sl);
+ 	free_cover(sr);
+     }
+     level--;
+     return temp;
+ }
+ 
+ 
+ pset_family opo_leaf(T, select, out1, out2)
+ register pcover T;
+ pset select;
+ int out1, out2;
+ {
+     register pset_family temp;
+     register pset p, pdest;
+     register int i;
+ 
+     out1 += cube.first_part[cube.output];
+     out2 += cube.first_part[cube.output];
+ 
+     /* Allocate space for the result */
+     temp = sf_new(2, T->count);
+ 
+     /* Find which primes are needed for the ON-set of this fct */
+     pdest = GETSET(temp, temp->count++);
+     (void) set_copy(pdest, select);
+     foreachi_set(T, i, p) {
+ 	if (is_in_set(p, out1)) {
+ 	    set_remove(pdest, i);
+ 	}
+     }
+ 
+     /* Find which primes are needed for the OFF-set of this fct */
+     pdest = GETSET(temp, temp->count++);
+     (void) set_copy(pdest, select);
+     foreachi_set(T, i, p) {
+ 	if (is_in_set(p, out2)) {
+ 	    set_remove(pdest, i);
+ 	}
+     }
+ 
+     return temp;
+ }
+ 
+ #if 0
+ pset_family form_cover_table(F, D, select, f, fbar)
+ pcover F, D;
+ pset select;
+ int f, fbar;		/* indices of f and fbar in the output part */
+ {
+     register int i;
+     register pcube p;
+     pset_family f_table, fbar_table;
+ 
+     /* setup required for fcube_is_covered */
+     Rp_size = F->count;
+     Rp_start = set_new(Rp_size);
+     foreachi_set(F, i, p) {
+ 	PUTSIZE(p, i);
+     }
+     foreachi_set(D, i, p) {
+ 	RESET(p, REDUND);
+     }
+ 
+     f_table = find_covers(F, D, select, f);
+     fbar_table = find_covers(F, D, select, fbar);
+     f_table = sf_append(f_table, fbar_table);
+ 
+     set_free(Rp_start);
+     return f_table;
+ }
+ 
+ 
+ pset_family find_covers(F, D, select, n)
+ pcover F, D;
+ register pset select;
+ int n;
+ {
+     register pset p, last, new;
+     pcover F1;
+     pcube *Flist;
+     pset_family f_table, table;
+     int i;
+ 
+     n += cube.first_part[cube.output];
+ 
+     /* save cubes in this output, and remove the output variable */
+     F1 = new_cover(F->count);
+     foreach_set(F, last, p)
+ 	if (is_in_set(p, n)) {
+ 	    new = GETSET(F1, F1->count++);
+ 	    set_or(new, p, cube.var_mask[cube.output]);
+ 	    PUTSIZE(new, SIZE(p));
+ 	    SET(new, REDUND);
+ 	}
+ 
+     /* Find ways (sop form) to fail to cover output indexed by n */
+     Flist = cube2list(F1, D);
+     table = sf_new(10, Rp_size);
+     foreach_set(F1, last, p) {
+ 	set_fill(Rp_start, Rp_size);
+ 	set_remove(Rp_start, SIZE(p));
+ 	table = sf_append(table, fcube_is_covered(Flist, p));
+ 	RESET(p, REDUND);
+     }
+     set_fill(Rp_start, Rp_size);
+     foreach_set(table, last, p) {
+ 	set_diff(p, Rp_start, p);
+     }
+ 
+     /* complement this to get possible ways to cover the function */
+     for(i = 0; i < Rp_size; i++) {
+ 	if (! is_in_set(select, i)) {
+ 	    p = set_new(Rp_size);
+ 	    set_insert(p, i);
+ 	    table = sf_addset(table, p);
+ 	    set_free(p);
+ 	}
+     }
+     f_table = unate_compl(table);
+ 
+     /* what a pain, but we need bitwise complement of this */
+     set_fill(Rp_start, Rp_size);
+     foreach_set(f_table, last, p) {
+ 	set_diff(p, Rp_start, p);
+     }
+ 
+     free_cubelist(Flist);
+     sf_free(F1);
+     return f_table;
+ }
+ #endif
+ 
+ /*
+  *  Take a PLA (ON-set, OFF-set and DC-set) and create the
+  *  "double-phase characteristic function" which is merely a new
+  *  function which has twice as many outputs and realizes both the
+  *  function and the complement.
+  *
+  *  The cube structure is assumed to represent the PLA upon entering.
+  *  It will be modified to represent the double-phase function upon
+  *  exit.
+  *
+  *  Only the outputs numbered starting with "first_output" are
+  *  duplicated in the output part
+  */
+ 
+ output_phase_setup(PLA, first_output)
+ INOUT pPLA PLA;
+ int first_output;
+ {
+     pcover F, R, D;
+     pcube mask, mask1, last;
+     int first_part, offset;
+     bool save;
+     register pcube p, pr, pf;
+     register int i, last_part;
+ 
+     if (cube.output == -1)
+ 	fatal("output_phase_setup: must have an output");
+ 
+     F = PLA->F;
+     D = PLA->D;
+     R = PLA->R;
+     first_part = cube.first_part[cube.output] + first_output;
+     last_part = cube.last_part[cube.output];
+     offset = cube.part_size[cube.output] - first_output;
+ 
+     /* Change the output size, setup the cube structure */
+     setdown_cube();
+     cube.part_size[cube.output] += offset;
+     cube_setup();
+ 
+     /* Create a mask to select that part of the cube which isn't changing */
+     mask = set_save(cube.fullset);
+     for(i = first_part; i < cube.size; i++)
+ 	set_remove(mask, i);
+     mask1 = set_save(mask);
+     for(i = cube.first_part[cube.output]; i < first_part; i++) {
+ 	set_remove(mask1, i);
+     }
+ 
+     PLA->F = new_cover(F->count + R->count);
+     PLA->R = new_cover(F->count + R->count);
+     PLA->D = new_cover(D->count);
+ 
+     foreach_set(F, last, p) {
+ 	pf = GETSET(PLA->F, (PLA->F)->count++);
+ 	pr = GETSET(PLA->R, (PLA->R)->count++);
+ 	INLINEset_and(pf, mask, p);
+ 	INLINEset_and(pr, mask1, p);
+ 	for(i = first_part; i <= last_part; i++)
+ 	    if (is_in_set(p, i))
+ 		set_insert(pf, i);
+ 	save = FALSE;
+ 	for(i = first_part; i <= last_part; i++)
+ 	    if (is_in_set(p, i))
+ 		save = TRUE, set_insert(pr, i+offset);
+ 	if (! save) PLA->R->count--;
+     }
+ 
+     foreach_set(R, last, p) {
+ 	pf = GETSET(PLA->F, (PLA->F)->count++);
+ 	pr = GETSET(PLA->R, (PLA->R)->count++);
+ 	INLINEset_and(pf, mask1, p);
+ 	INLINEset_and(pr, mask, p);
+ 	save = FALSE;
+ 	for(i = first_part; i <= last_part; i++)
+ 	    if (is_in_set(p, i))
+ 		save = TRUE, set_insert(pf, i+offset);
+ 	if (! save) PLA->F->count--;
+ 	for(i = first_part; i <= last_part; i++)
+ 	    if (is_in_set(p, i))
+ 		set_insert(pr, i);
+     }
+ 
+     foreach_set(D, last, p) {
+ 	pf = GETSET(PLA->D, (PLA->D)->count++);
+ 	INLINEset_and(pf, mask, p);
+ 	for(i = first_part; i <= last_part; i++)
+ 	    if (is_in_set(p, i)) {
+ 		set_insert(pf, i);
+ 		set_insert(pf, i+offset);
+ 	    }
+     }
+ 
+     free_cover(F);
+     free_cover(D);
+     free_cover(R);
+     set_free(mask);
+     set_free(mask1);
+ }
+ 
+ /*
+  *  set_phase -- given a "cube" which describes which phases of the output
+  *  are to be implemented, compute the appropriate on-set and off-set
+  */
+ pPLA set_phase(PLA)
+ INOUT pPLA PLA;
+ {
+     pcover F1, R1;
+     register pcube last, p, outmask;
+     register pcube temp=cube.temp[0], phase=PLA->phase, phase1=cube.temp[1];
+ 
+     outmask = cube.var_mask[cube.num_vars - 1];
+     set_diff(phase1, outmask, phase);
+     set_or(phase1, set_diff(temp, cube.fullset, outmask), phase1);
+     F1 = new_cover((PLA->F)->count + (PLA->R)->count);
+     R1 = new_cover((PLA->F)->count + (PLA->R)->count);
+ 
+     foreach_set(PLA->F, last, p) {
+ 	if (! setp_disjoint(set_and(temp, p, phase), outmask))
+ 	    set_copy(GETSET(F1, F1->count++), temp);
+ 	if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+ 	    set_copy(GETSET(R1, R1->count++), temp);
+     }
+     foreach_set(PLA->R, last, p) {
+ 	if (! setp_disjoint(set_and(temp, p, phase), outmask))
+ 	    set_copy(GETSET(R1, R1->count++), temp);
+ 	if (! setp_disjoint(set_and(temp, p, phase1), outmask))
+ 	    set_copy(GETSET(F1, F1->count++), temp);
+     }
+     free_cover(PLA->F);
+     free_cover(PLA->R);
+     PLA->F = F1;
+     PLA->R = R1;
+     return PLA;
+ }
+ 
+ #define POW2(x)		(1 << (x))
+ 
+ void opoall(PLA, first_output, last_output, opo_strategy)
+ pPLA PLA;
+ int first_output, last_output;
+ int opo_strategy;
+ {
+     pcover F, D, R, best_F, best_D, best_R;
+     int i, j, ind, num;
+     pcube bestphase;
+ 
+     opo_exact = opo_strategy;
+ 
+     if (PLA->phase != NULL) {
+ 	set_free(PLA->phase);
+     }
+ 
+     bestphase = set_save(cube.fullset);
+     best_F = sf_save(PLA->F);
+     best_D = sf_save(PLA->D);
+     best_R = sf_save(PLA->R);
+ 
+     for(i = 0; i < POW2(last_output - first_output + 1); i++) {
+ 
+ 	/* save the initial PLA covers */
+ 	F = sf_save(PLA->F);
+ 	D = sf_save(PLA->D);
+ 	R = sf_save(PLA->R);
+ 
+ 	/* compute the phase cube for this iteration */
+ 	PLA->phase = set_save(cube.fullset);
+ 	num = i;
+ 	for(j = last_output; j >= first_output; j--) {
+ 	    if (num % 2 == 0) {
+ 		ind = cube.first_part[cube.output] + j;
+ 		set_remove(PLA->phase, ind);
+ 	    }
+ 	    num /= 2;
+ 	}
+ 
+ 	/* set the phase and minimize */
+ 	(void) set_phase(PLA);
+ 	printf("# phase is %s\n", pc1(PLA->phase));
+ 	summary = TRUE;
+ 	minimize(PLA);
+ 
+ 	/* see if this is the best so far */
+ 	if (PLA->F->count < best_F->count) {
+ 	    /* save new best solution */
+ 	    set_copy(bestphase, PLA->phase);
+ 	    sf_free(best_F);
+ 	    sf_free(best_D);
+ 	    sf_free(best_R);
+ 	    best_F = PLA->F;
+ 	    best_D = PLA->D;
+ 	    best_R = PLA->R;
+ 	} else {
+ 	    /* throw away the solution */
+ 	    free_cover(PLA->F);
+ 	    free_cover(PLA->D);
+ 	    free_cover(PLA->R);
+ 	}
+ 	set_free(PLA->phase);
+ 
+ 	/* restore the initial PLA covers */
+ 	PLA->F = F;
+ 	PLA->D = D;
+ 	PLA->R = R;
+     }
+ 
+     /* one more minimization to restore the best answer */
+     PLA->phase = bestphase;
+     sf_free(PLA->F);
+     sf_free(PLA->D);
+     sf_free(PLA->R);
+     PLA->F = best_F;
+     PLA->D = best_D;
+     PLA->R = best_R;
+ }
+ 
+ static void minimize(PLA)
+ pPLA PLA;
+ {
+     if (opo_exact) {
+ 	EXEC_S(PLA->F = minimize_exact(PLA->F,PLA->D,PLA->R,1), "EXACT", PLA->F);
+     } else {
+ 	EXEC_S(PLA->F = espresso(PLA->F, PLA->D, PLA->R), "ESPRESSO  ",PLA->F);
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/pair.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/pair.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/pair.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,666 ----
+ #include "espresso.h"
+ 
+ void set_pair(PLA)
+ pPLA PLA;
+ {
+     set_pair1(PLA, TRUE);
+ }
+ 
+ void set_pair1(PLA, adjust_labels)
+ pPLA PLA;
+ bool adjust_labels;
+ {
+     int i, var, *paired, newvar;
+     int old_num_vars, old_num_binary_vars, old_size, old_mv_start;
+     int *new_part_size, new_num_vars, new_num_binary_vars, new_mv_start;
+     ppair pair = PLA->pair;
+     char scratch[1000], **oldlabel, *var1, *var1bar, *var2, *var2bar;
+ 
+     if (adjust_labels)
+ 	makeup_labels(PLA);
+ 
+     /* Check the pair structure for valid entries and see which binary
+ 	variables are left unpaired
+     */
+     paired = ALLOC(bool, cube.num_binary_vars);
+     for(var = 0; var < cube.num_binary_vars; var++)
+ 	paired[var] = FALSE;
+     for(i = 0; i < pair->cnt; i++)
+ 	if ((pair->var1[i] > 0 && pair->var1[i] <= cube.num_binary_vars) &&
+ 	     (pair->var2[i] > 0 && pair->var2[i] <= cube.num_binary_vars)) {
+ 	    paired[pair->var1[i]-1] = TRUE;
+ 	    paired[pair->var2[i]-1] = TRUE;
+ 	} else
+ 	    fatal("can only pair binary-valued variables");
+ 
+     PLA->F = delvar(pairvar(PLA->F, pair), paired);
+     PLA->R = delvar(pairvar(PLA->R, pair), paired);
+     PLA->D = delvar(pairvar(PLA->D, pair), paired);
+ 
+     /* Now painfully adjust the cube size */
+     old_size = cube.size;
+     old_num_vars = cube.num_vars;
+     old_num_binary_vars = cube.num_binary_vars;
+     old_mv_start = cube.first_part[cube.num_binary_vars];
+     /* Create the new cube.part_size vector and setup the cube structure */
+     new_num_binary_vars = 0;
+     for(var = 0; var < old_num_binary_vars; var++)
+ 	new_num_binary_vars += (paired[var] == FALSE);
+     new_num_vars = new_num_binary_vars + pair->cnt;
+     new_num_vars += old_num_vars - old_num_binary_vars;
+     new_part_size = ALLOC(int, new_num_vars);
+     for(var = 0; var < pair->cnt; var++)
+ 	new_part_size[new_num_binary_vars + var] = 4;
+     for(var = 0; var < old_num_vars - old_num_binary_vars; var++)
+ 	new_part_size[new_num_binary_vars + pair->cnt + var] =
+ 	    cube.part_size[old_num_binary_vars + var];
+     setdown_cube();
+     FREE(cube.part_size);
+     cube.num_vars = new_num_vars;
+     cube.num_binary_vars = new_num_binary_vars;
+     cube.part_size = new_part_size;
+     cube_setup();
+ 
+     /* hack with the labels to get them correct */
+     if (adjust_labels) {
+ 	oldlabel = PLA->label;
+ 	PLA->label = ALLOC(char *, cube.size);
+ 	for(var = 0; var < pair->cnt; var++) {
+ 	    newvar = cube.num_binary_vars*2 + var*4;
+ 	    var1 = oldlabel[ (pair->var1[var]-1) * 2 + 1];
+ 	    var2 = oldlabel[ (pair->var2[var]-1) * 2 + 1];
+ 	    var1bar = oldlabel[ (pair->var1[var]-1) * 2];
+ 	    var2bar = oldlabel[ (pair->var2[var]-1) * 2];
+ 	    (void) sprintf(scratch, "%s+%s", var1bar, var2bar);
+ 	    PLA->label[newvar] = util_strsav(scratch);
+ 	    (void) sprintf(scratch, "%s+%s", var1bar, var2);
+ 	    PLA->label[newvar+1] = util_strsav(scratch);
+ 	    (void) sprintf(scratch, "%s+%s", var1, var2bar);
+ 	    PLA->label[newvar+2] = util_strsav(scratch);
+ 	    (void) sprintf(scratch, "%s+%s", var1, var2);
+ 	    PLA->label[newvar+3] = util_strsav(scratch);
+ 	}
+ 	/* Copy the old labels for the unpaired binary vars */
+ 	i = 0;
+ 	for(var = 0; var < old_num_binary_vars; var++) {
+ 	    if (paired[var] == FALSE) {
+ 		PLA->label[2*i] = oldlabel[2*var];
+ 		PLA->label[2*i+1] = oldlabel[2*var+1];
+ 		oldlabel[2*var] = oldlabel[2*var+1] = (char *) NULL;
+ 		i++;
+ 	    }
+ 	}
+ 	/* Copy the old labels for the remaining unpaired vars */
+ 	new_mv_start = cube.num_binary_vars*2 + pair->cnt*4;
+ 	for(i = old_mv_start; i < old_size; i++) {
+ 	    PLA->label[new_mv_start + i - old_mv_start] = oldlabel[i];
+ 	    oldlabel[i] = (char *) NULL;
+ 	}
+ 	/* free remaining entries in oldlabel */
+ 	for(i = 0; i < old_size; i++)
+ 	    if (oldlabel[i] != (char *) NULL)
+ 		FREE(oldlabel[i]);
+ 	FREE(oldlabel);
+     }
+ 
+     /* the paired variables should not be sparse (cf. mv_reduce/raise_in)*/
+     for(var = 0; var < pair->cnt; var++)
+ 	cube.sparse[cube.num_binary_vars + var] = 0;
+     FREE(paired);
+ }
+ 
+ pcover pairvar(A, pair)
+ pcover A;
+ ppair pair;
+ {
+     register pcube last, p;
+     register int val, p1, p2, b1, b0;
+     int insert_col, pairnum;
+ 
+     insert_col = cube.first_part[cube.num_vars - 1];
+ 
+     /* stretch the cover matrix to make room for the paired variables */
+     A = sf_delcol(A, insert_col, -4*pair->cnt);
+ 
+     /* compute the paired values */
+     foreach_set(A, last, p) {
+ 	for(pairnum = 0; pairnum < pair->cnt; pairnum++) {
+ 	    p1 = cube.first_part[pair->var1[pairnum] - 1];
+ 	    p2 = cube.first_part[pair->var2[pairnum] - 1];
+ 	    b1 = is_in_set(p, p2+1);
+ 	    b0 = is_in_set(p, p2);
+ 	    val = insert_col + pairnum * 4;
+ 	    if (/* a0 */ is_in_set(p, p1)) {
+ 		if (b0)
+ 		    set_insert(p, val + 3);
+ 		if (b1)
+ 		    set_insert(p, val + 2);
+ 	    }
+ 	    if (/* a1 */ is_in_set(p, p1+1)) {
+ 		if (b0)
+ 		    set_insert(p, val + 1);
+ 		if (b1)
+ 		    set_insert(p, val);
+ 	    }
+ 	}
+     }
+     return A;
+ }
+ 
+ 
+ /* delvar -- delete variables from A, minimize the number of column shifts */
+ pcover delvar(A, paired)
+ pcover A;
+ bool paired[];
+ {
+     bool run;
+     int first_run, run_length, var, offset = 0;
+ 
+     run = FALSE; run_length = 0;
+     for(var = 0; var < cube.num_binary_vars; var++)
+ 	if (paired[var])
+ 	    if (run)
+ 		run_length += cube.part_size[var];
+ 	    else {
+ 		run = TRUE;
+ 		first_run = cube.first_part[var];
+ 		run_length = cube.part_size[var];
+ 	    }
+ 	else
+ 	    if (run) {
+ 		A = sf_delcol(A, first_run-offset, run_length);
+ 		run = FALSE;
+ 		offset += run_length;
+ 	    }
+     if (run)
+ 	A = sf_delcol(A, first_run-offset, run_length);
+     return A;
+ }
+ 
+ /*
+     find_optimal_pairing -- find which binary variables should be paired
+     to maximally reduce the number of terms
+ 
+     This is essentially the technique outlined by T. Sasao in the
+     Trans. on Comp., Oct 1984.  We estimate the cost of pairing each
+     pair individually using 1 of 4 strategies: (1) algebraic division
+     of F by the pair (exactly T. Sasao technique); (2) strong division
+     of F by the paired variables (using REDUCE/EXPAND/ IRREDUNDANT from
+     espresso); (3) full minimization using espresso; (4) exact
+     minimization.  These are in order of both increasing accuracy and
+     increasing difficulty (!)
+ 
+     Once the n squared pairs have been evaluated, T. Sasao proposes a
+     graph covering of nodes by disjoint edges.  For now, I solve this
+     problem exhaustively (complexity = (n-1)*(n-3)*...*3*1 for n
+     variables when n is even).  Note that solving this problem exactly
+     is the same as evaluating the cost function for all possible
+     pairings.
+ 
+ 			       n       pairs
+ 
+ 			     1, 2           1
+ 			     3, 4           3
+ 			     5, 6          15
+ 			     7, 8         105
+ 			     9,10         945
+ 			    11,12      10,395
+ 			    13,14     135,135
+ 			    15,16   2,027,025
+ 			    17,18  34,459,425
+ 			    19,20 654,729,075
+ */
+ void find_optimal_pairing(PLA, strategy)
+ pPLA PLA;
+ int strategy;
+ {
+     int i, j, **cost_array;
+ 
+     cost_array = find_pairing_cost(PLA, strategy);
+ 
+     if (summary) {
+ 	printf("    ");
+ 	for(i = 0; i < cube.num_binary_vars; i++)
+ 	    printf("%3d ", i+1);
+ 	printf("\n");
+ 	for(i = 0; i < cube.num_binary_vars; i++) {
+ 	    printf("%3d ", i+1);
+ 	    for(j = 0; j < cube.num_binary_vars; j++)
+ 		printf("%3d ", cost_array[i][j]);
+ 	    printf("\n");
+ 	}
+     }
+ 
+     if (cube.num_binary_vars <= 14) {
+ 	PLA->pair = pair_best_cost(cost_array);
+     } else {
+ 	(void) greedy_best_cost(cost_array, &(PLA->pair));
+     }
+     printf("# ");
+     print_pair(PLA->pair);
+ 	
+     for(i = 0; i < cube.num_binary_vars; i++)
+ 	FREE(cost_array[i]);
+     FREE(cost_array);
+ 
+     set_pair(PLA);
+     EXEC_S(PLA->F=espresso(PLA->F,PLA->D,PLA->R),"ESPRESSO  ",PLA->F);
+ }
+ 
+ int **find_pairing_cost(PLA, strategy)
+ pPLA PLA;
+ int strategy;
+ {
+     int var1, var2, **cost_array;
+     int i, j, xnum_binary_vars, xnum_vars, *xpart_size, cost;
+     pcover T, Fsave, Dsave, Rsave;
+     pset mask;
+ /*    char *s;*/
+ 
+     /* data is returned in the cost array */
+     cost_array = ALLOC(int *, cube.num_binary_vars);
+     for(i = 0; i < cube.num_binary_vars; i++)
+ 	cost_array[i] = ALLOC(int, cube.num_binary_vars);
+     for(i = 0; i < cube.num_binary_vars; i++)
+ 	for(j = 0; j < cube.num_binary_vars; j++)
+ 	    cost_array[i][j] = 0;
+ 
+     /* Setup the pair structure for pairing variables together */
+     PLA->pair = pair_new(1);
+     PLA->pair->cnt = 1;
+ 
+     for(var1 = 0; var1 < cube.num_binary_vars-1; var1++) {
+ 	for(var2 = var1+1; var2 < cube.num_binary_vars; var2++) {
+ 	    /* if anything but simple strategy, perform setup */
+ 	    if (strategy > 0) {
+ 		/* save the original covers */
+ 		Fsave = sf_save(PLA->F);
+ 		Dsave = sf_save(PLA->D);
+ 		Rsave = sf_save(PLA->R);
+ 
+ 		/* save the original cube structure */
+ 		xnum_binary_vars = cube.num_binary_vars;
+ 		xnum_vars = cube.num_vars;
+ 		xpart_size = ALLOC(int, cube.num_vars);
+ 		for(i = 0; i < cube.num_vars; i++)
+ 		    xpart_size[i] = cube.part_size[i];
+ 
+ 		/* pair two variables together */
+ 		PLA->pair->var1[0] = var1 + 1;
+ 		PLA->pair->var2[0] = var2 + 1;
+ 		set_pair1(PLA, /* adjust_labels */ FALSE);
+ 	    }
+ 
+ 
+ 	    /* decide how to best estimate worth of this pairing */
+ 	    switch(strategy) {
+ 		case 3:
+ 		    /*s = "exact minimization";*/
+ 		    PLA->F = minimize_exact(PLA->F, PLA->D, PLA->R, 1);
+ 		    cost = Fsave->count - PLA->F->count;
+ 		    break;
+ 		case 2:
+ 		    /*s = "full minimization";*/
+ 		    PLA->F = espresso(PLA->F, PLA->D, PLA->R);
+ 		    cost = Fsave->count - PLA->F->count;
+ 		    break;
+ 		case 1:
+ 		    /*s = "strong division";*/
+ 		    PLA->F = reduce(PLA->F, PLA->D);
+ 		    PLA->F = expand(PLA->F, PLA->R, FALSE);
+ 		    PLA->F = irredundant(PLA->F, PLA->D);
+ 		    cost = Fsave->count - PLA->F->count;
+ 		    break;
+ 		case 0:
+ 		    /*s = "weak division";*/
+ 		    mask = new_cube();
+ 		    set_or(mask, cube.var_mask[var1], cube.var_mask[var2]);
+ 		    T = dist_merge(sf_save(PLA->F), mask);
+ 		    cost = PLA->F->count - T->count;
+ 		    sf_free(T);
+ 		    set_free(mask);
+ 	    }
+ 
+ 	    cost_array[var1][var2] = cost;
+ 
+ 	    if (strategy > 0) {
+ 		/* restore the original cube structure -- free the new ones */
+ 		setdown_cube();
+ 		FREE(cube.part_size);
+ 		cube.num_binary_vars = xnum_binary_vars;
+ 		cube.num_vars = xnum_vars;
+ 		cube.part_size = xpart_size;
+ 		cube_setup();
+ 
+ 		/* restore the original cover(s) -- free the new ones */
+ 		sf_free(PLA->F);
+ 		sf_free(PLA->D);
+ 		sf_free(PLA->R);
+ 		PLA->F = Fsave;
+ 		PLA->D = Dsave;
+ 		PLA->R = Rsave;
+ 	    }
+ 	}
+     }
+ 
+     pair_free(PLA->pair);
+     PLA->pair = NULL;
+     return cost_array;
+ }
+ 
+ static int best_cost;
+ static int **cost_array;
+ static ppair best_pair;
+ static pset best_phase;
+ static pPLA global_PLA;
+ static pcover best_F, best_D, best_R;
+ static int pair_minim_strategy;
+ 
+ 
+ print_pair(pair)
+ ppair pair;
+ {
+     int i;
+ 
+     printf("pair is");
+     for(i = 0; i < pair->cnt; i++)
+ 	printf (" (%d %d)", pair->var1[i], pair->var2[i]);
+     printf("\n");
+ }
+ 
+ 
+ int greedy_best_cost(cost_array_local, pair_p)
+ int **cost_array_local;
+ ppair *pair_p;
+ {
+     int i, j, besti, bestj, maxcost, total_cost;
+     pset cand;
+     ppair pair;
+ 
+     pair = pair_new(cube.num_binary_vars);
+     cand = set_full(cube.num_binary_vars);
+     total_cost = 0;
+ 
+     while (set_ord(cand) >= 2) {
+ 	maxcost = -1;
+ 	for(i = 0; i < cube.num_binary_vars; i++) {
+ 	    if (is_in_set(cand, i)) {
+ 		for(j = i+1; j < cube.num_binary_vars; j++) {
+ 		    if (is_in_set(cand, j)) {
+ 			if (cost_array_local[i][j] > maxcost) {
+ 			    maxcost = cost_array_local[i][j];
+ 			    besti = i;
+ 			    bestj = j;
+ 			}
+ 		    }
+ 		}
+ 	    }
+ 	}
+ 	pair->var1[pair->cnt] = besti+1;
+ 	pair->var2[pair->cnt] = bestj+1;
+ 	pair->cnt++;
+ 	set_remove(cand, besti);
+ 	set_remove(cand, bestj);
+ 	total_cost += maxcost;
+     }
+     set_free(cand);
+     *pair_p = pair;
+     return total_cost;
+ }
+ 
+ 
+ ppair pair_best_cost(cost_array_local)
+ int **cost_array_local;
+ {
+     ppair pair;
+     pset candidate;
+ 
+     best_cost = -1;
+     best_pair = NULL;
+     cost_array = cost_array_local;
+ 
+     pair = pair_new(cube.num_binary_vars);
+     candidate = set_full(cube.num_binary_vars);
+     generate_all_pairs(pair, cube.num_binary_vars, candidate, find_best_cost);
+     pair_free(pair);
+     set_free(candidate);
+     return best_pair;
+ }
+ 
+ 
+ int find_best_cost(pair)
+ register ppair pair;
+ {
+     register int i, cost;
+ 
+     cost = 0;
+     for(i = 0; i < pair->cnt; i++)
+ 	cost += cost_array[pair->var1[i]-1][pair->var2[i]-1];
+     if (cost > best_cost) {
+ 	best_cost = cost;
+ 	best_pair = pair_save(pair, pair->cnt);
+     }
+     if ((debug & MINCOV) && trace) {
+ 	printf("cost is %d ", cost);
+ 	print_pair(pair);
+     }
+ }
+ 
+ /*
+     pair_all: brute-force approach to try all possible pairings
+ 
+     pair_strategy is:
+ 	2) for espresso
+ 	3) for minimize_exact
+ 	4) for phase assignment
+ */
+ 
+ pair_all(PLA, pair_strategy)
+ pPLA PLA;
+ int pair_strategy;
+ {
+     ppair pair;
+     pset candidate;
+ 
+     global_PLA = PLA;
+     pair_minim_strategy = pair_strategy;
+     best_cost = PLA->F->count + 1;
+     best_pair = NULL;
+     best_phase = NULL;
+     best_F = best_D = best_R = NULL;
+     pair = pair_new(cube.num_binary_vars);
+     candidate = set_fill(set_new(cube.num_binary_vars), cube.num_binary_vars);
+ 
+     generate_all_pairs(pair, cube.num_binary_vars, candidate, minimize_pair);
+ 
+     pair_free(pair);
+     set_free(candidate);
+ 
+     PLA->pair = best_pair;
+     PLA->phase = best_phase;
+ /* not really necessary
+     if (phase != NULL)
+ 	(void) set_phase(PLA->phase);
+ */
+     set_pair(PLA);
+     printf("# ");
+     print_pair(PLA->pair);
+ 
+     sf_free(PLA->F);
+     sf_free(PLA->D);
+     sf_free(PLA->R);
+     PLA->F = best_F;
+     PLA->D = best_D;
+     PLA->R = best_R;
+ }
+ 
+ 
+ /*
+  *  minimize_pair -- called as each pair is generated
+  */
+ int minimize_pair(pair)
+ ppair pair;
+ {
+     pcover Fsave, Dsave, Rsave;
+     int i, xnum_binary_vars, xnum_vars, *xpart_size;
+ 
+     /* save the original covers */
+     Fsave = sf_save(global_PLA->F);
+     Dsave = sf_save(global_PLA->D);
+     Rsave = sf_save(global_PLA->R);
+ 
+     /* save the original cube structure */
+     xnum_binary_vars = cube.num_binary_vars;
+     xnum_vars = cube.num_vars;
+     xpart_size = ALLOC(int, cube.num_vars);
+     for(i = 0; i < cube.num_vars; i++)
+ 	xpart_size[i] = cube.part_size[i];
+ 
+     /* setup the paired variables */
+     global_PLA->pair = pair;
+     set_pair1(global_PLA, /* adjust_labels */ FALSE);
+ 
+     /* call the minimizer */
+     if (summary)
+ 	print_pair(pair);
+     switch(pair_minim_strategy) {
+ 	case 2:
+ 	    EXEC_S(phase_assignment(global_PLA,0), "OPO       ", global_PLA->F);
+ 	    if (summary)
+ 		printf("# phase is %s\n", pc1(global_PLA->phase));
+ 	    break;
+ 	case 1:
+ 	    EXEC_S(global_PLA->F = minimize_exact(global_PLA->F, global_PLA->D,
+ 		global_PLA->R, 1), "EXACT     ", global_PLA->F);
+ 	    break;
+ 	case 0:
+ 	    EXEC_S(global_PLA->F = espresso(global_PLA->F, global_PLA->D,
+ 		global_PLA->R), "ESPRESSO  ", global_PLA->F);
+ 	    break;
+ 	default:
+ 	    break;
+     }
+ 
+     /* see if we have a new best solution */
+     if (global_PLA->F->count < best_cost) {
+ 	best_cost = global_PLA->F->count;
+ 	best_pair = pair_save(pair, pair->cnt);
+ 	best_phase = global_PLA->phase!=NULL?set_save(global_PLA->phase):NULL;
+ 	if (best_F != NULL) sf_free(best_F);
+ 	if (best_D != NULL) sf_free(best_D);
+ 	if (best_R != NULL) sf_free(best_R);
+ 	best_F = sf_save(global_PLA->F);
+ 	best_D = sf_save(global_PLA->D);
+ 	best_R = sf_save(global_PLA->R);
+     }
+ 
+     /* restore the original cube structure -- free the new ones */
+     setdown_cube();
+     FREE(cube.part_size);
+     cube.num_binary_vars = xnum_binary_vars;
+     cube.num_vars = xnum_vars;
+     cube.part_size = xpart_size;
+     cube_setup();
+ 
+     /* restore the original cover(s) -- free the new ones */
+     sf_free(global_PLA->F);
+     sf_free(global_PLA->D);
+     sf_free(global_PLA->R);
+     global_PLA->F = Fsave;
+     global_PLA->D = Dsave;
+     global_PLA->R = Rsave;
+     global_PLA->pair = NULL;
+     global_PLA->phase = NULL;
+ }
+ 
+ generate_all_pairs(pair, n, candidate, action)
+ ppair pair;
+ int n;
+ pset candidate;
+ int (*action)();
+ {
+     int i, j;
+     pset recur_candidate;
+     ppair recur_pair;
+ 
+     if (set_ord(candidate) < 2) {
+ 	(*action)(pair);
+ 	return;
+     }
+ 
+     recur_pair = pair_save(pair, n);
+     recur_candidate = set_save(candidate);
+ 
+     /* Find first variable still in the candidate set */
+     for(i = 0; i < n; i++)
+ 	if (is_in_set(candidate, i))
+ 	    break;
+ 
+     /* Try all pairs of i with other variables */
+     for(j = i+1; j < n; j++)
+ 	if (is_in_set(candidate, j)) {
+ 	    /* pair (i j) -- remove from candidate set for future pairings */
+ 	    set_remove(recur_candidate, i);
+ 	    set_remove(recur_candidate, j);
+ 
+ 	    /* add to the pair array */
+ 	    recur_pair->var1[recur_pair->cnt] = i+1;
+ 	    recur_pair->var2[recur_pair->cnt] = j+1;
+ 	    recur_pair->cnt++;
+ 
+ 	    /* recur looking for the end ... */
+ 	    generate_all_pairs(recur_pair, n, recur_candidate, action);
+ 
+ 	    /* now break this pair, and restore candidate set */
+ 	    recur_pair->cnt--;
+ 	    set_insert(recur_candidate, i);
+ 	    set_insert(recur_candidate, j);
+ 	}
+ 
+     /* if odd, generate all pairs which do NOT include i */
+     if ((set_ord(candidate) % 2) == 1) {
+ 	set_remove(recur_candidate, i);
+ 	generate_all_pairs(recur_pair, n, recur_candidate, action);
+     }
+ 
+     pair_free(recur_pair);
+     set_free(recur_candidate);
+ }
+ 
+ ppair pair_new(n)
+ register int n;
+ {
+     register ppair pair1;
+ 
+     pair1 = ALLOC(pair_t, 1);
+     pair1->cnt = 0;
+     pair1->var1 = ALLOC(int, n);
+     pair1->var2 = ALLOC(int, n);
+     return pair1;
+ }
+ 
+ 
+ ppair pair_save(pair, n)
+ register ppair pair;
+ register int n;
+ {
+     register int k;
+     register ppair pair1;
+ 
+     pair1 = pair_new(n);
+     pair1->cnt = pair->cnt;
+     for(k = 0; k < pair->cnt; k++) {
+ 	pair1->var1[k] = pair->var1[k];
+ 	pair1->var2[k] = pair->var2[k];
+     }
+     return pair1;
+ }
+ 
+ 
+ int pair_free(pair)
+ register ppair pair;
+ {
+     FREE(pair->var1);
+     FREE(pair->var2);
+     FREE(pair);
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/part.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/part.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/part.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,112 ----
+ #include "mincov_int.h"
+ 
+ 
+ static void
+ copy_row(A, prow)
+ register sm_matrix *A;
+ register sm_row *prow;
+ {
+     register sm_element *p;
+ 
+     for(p = prow->first_col; p != 0; p = p->next_col) {
+ 	(void) sm_insert(A, p->row_num, p->col_num);
+     }
+ }
+ 
+ 
+ static int
+ visit_row(A, prow, rows_visited, cols_visited)
+ sm_matrix *A;
+ sm_row *prow;
+ int *rows_visited;
+ int *cols_visited;
+ {
+     sm_element *p;
+     sm_col *pcol;
+ 
+     if (! prow->flag) {
+ 	prow->flag = 1;
+ 	(*rows_visited)++;
+ 	if (*rows_visited == A->nrows) {
+ 	    return 1;
+ 	}
+ 	for(p = prow->first_col; p != 0; p = p->next_col) {
+ 	    pcol = sm_get_col(A, p->col_num);
+ 	    if (! pcol->flag) {
+ 		if (visit_col(A, pcol, rows_visited, cols_visited)) {
+ 		    return 1;
+ 		}
+ 	    }
+ 	}
+     }
+     return 0;
+ }
+ 
+ 
+ static int
+ visit_col(A, pcol, rows_visited, cols_visited)
+ sm_matrix *A;
+ sm_col *pcol;
+ int *rows_visited;
+ int *cols_visited;
+ {
+     sm_element *p;
+     sm_row *prow;
+ 
+     if (! pcol->flag) {
+ 	pcol->flag = 1;
+ 	(*cols_visited)++;
+ 	if (*cols_visited == A->ncols) {
+ 	    return 1;
+ 	}
+ 	for(p = pcol->first_row; p != 0; p = p->next_row) {
+ 	    prow = sm_get_row(A, p->row_num);
+ 	    if (! prow->flag) {
+ 		if (visit_row(A, prow, rows_visited, cols_visited)) {
+ 		    return 1;
+ 		}
+ 	    }
+ 	}
+     }
+     return 0;
+ }
+ 
+ int
+ sm_block_partition(A, L, R)
+ sm_matrix *A;
+ sm_matrix **L, **R;
+ {
+     int cols_visited, rows_visited;
+     register sm_row *prow;
+     register sm_col *pcol;
+ 
+     /* Avoid the trivial case */
+     if (A->nrows == 0) {
+ 	return 0;
+     }
+ 
+     /* Reset the visited flags for each row and column */
+     for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 	prow->flag = 0;
+     }
+     for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col) {
+ 	pcol->flag = 0;
+     }
+ 
+     cols_visited = rows_visited = 0;
+     if (visit_row(A, A->first_row, &rows_visited, &cols_visited)) {
+ 	/* we found all of the rows */
+ 	return 0;
+     } else {
+ 	*L = sm_alloc();
+ 	*R = sm_alloc();
+ 	for(prow = A->first_row; prow != 0; prow = prow->next_row) {
+ 	    if (prow->flag) {
+ 		copy_row(*L, prow);
+ 	    } else {
+ 		copy_row(*R, prow);
+ 	    }
+ 	}
+ 	return 1;
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/port.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/port.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/port.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,254 ----
+ #ifndef PORT_H
+ #define PORT_H
+ 
+ #ifdef SABER
+ #define volatile
+ #endif
+ 
+ #ifdef _IBMR2
+ #define _BSD
+ #ifndef _POSIX_SOURCE
+ #define _POSIX_SOURCE		/* Argh!  IBM strikes again */
+ #endif
+ #ifndef _ALL_SOURCE
+ #define _ALL_SOURCE		/* Argh!  IBM strikes again */
+ #endif
+ #ifndef _ANSI_C_SOURCE
+ #define _ANSI_C_SOURCE		/* Argh!  IBM strikes again */
+ #endif
+ #endif
+ 
+ /*
+  * int32 should be defined as the most economical sized integer capable of
+  * holding a 32 bit quantity
+  * int16 should be similarly defined
+  */
+ 
+ /* XXX hack */
+ #ifndef MACHDEP_INCLUDED
+ #define MACHDEP_INCLUDED
+ #ifdef vax
+ typedef int int32;
+ typedef short int16;
+ #else
+      /* Ansi-C promises that these definitions should always work */
+ typedef long int32;
+ typedef int int16;
+ #endif /* vax */
+ #endif /* MACHDEP_INCLUDED */
+ 
+ 
+ #ifndef __STDC__
+ #ifndef __DATE__
+ #ifdef CUR_DATE
+ #define __DATE__	CUR_DATE
+ #else
+ #define __DATE__	"unknown-date"
+ #endif /* CUR_DATE */
+ #endif /* __DATE__ */
+ 
+ #ifndef __TIME__
+ #ifdef CUR_TIME
+ #define __TIME__	CUR_TIME
+ #else
+ #define __TIME__	"unknown-time"
+ #endif /* CUR_TIME */
+ #endif /* __TIME__ */
+ #endif /* __STDC__ */
+ 
+ #ifdef sun386
+ #define PORTAR
+ #endif
+ 
+ #include <stdio.h>
+ #include <ctype.h>
+ #include <sys/types.h>
+ #undef HUGE
+ #include <math.h>
+ #include <signal.h>
+ 
+ #if defined(ultrix)  /* { */
+ #if defined(_SIZE_T_) /* { */
+ #define ultrix4
+ #else		     /* } else { */
+ #if defined(SIGLOST) /* { */
+ #define ultrix3
+ #else                /* } else { */
+ #define ultrix2
+ #endif               /* } */
+ #endif               /* } */
+ #endif               /* } */
+ 
+ #if defined(ultrix3) && defined(mips)
+ extern double rint();
+ extern double trunc();
+ #endif
+ 
+ #if defined(sun) && defined(FD_SETSIZE)
+ #define sunos4
+ #else
+ #define sunos3
+ #endif
+ 
+ #if defined(sequent) || defined(news800)
+ #define LACK_SYS5
+ #endif
+ 
+ #if defined(ultrix3) || defined(sunos4) || defined(_IBMR2)
+ #define SIGNAL_FN	void
+ #else
+ /* sequent, ultrix2, 4.3BSD (vax, hp), sunos3 */
+ #define SIGNAL_FN	int
+ #endif
+ 
+ /* Some systems have 'fixed' certain functions which used to be int */
+ #if defined(ultrix) || defined(SABER) || defined(hpux) || defined(aiws) || defined(apollo) || defined(__STDC__)
+ #define VOID_HACK void
+ #else
+ #define VOID_HACK int
+ #endif
+ 
+ #ifndef NULL
+ #define NULL 0
+ #endif /* NULL */
+ 
+ /*
+  * CHARBITS should be defined only if the compiler lacks "unsigned char".
+  * It should be a mask, e.g. 0377 for an 8-bit machine.
+  */
+ 
+ #ifndef CHARBITS
+ #	define	UNSCHAR(c)	((unsigned char)(c))
+ #else
+ #	define	UNSCHAR(c)	((c)&CHARBITS)
+ #endif
+ 
+ #define SIZET int
+ 
+ #ifdef __STDC__
+ #define CONST const
+ #define VOIDSTAR   void *
+ #else
+ #define CONST
+ #define VOIDSTAR   char *
+ #endif /* __STDC__ */
+ 
+ 
+ /* Some machines fail to define some functions in stdio.h */
+ #if !defined(__STDC__) && !defined(sprite)
+ extern FILE *popen(), *tmpfile();
+ extern int pclose();
+ #ifndef clearerr		/* is a macro on many machines, but not all */
+ extern VOID_HACK clearerr();
+ #endif /* clearerr */
+ #ifndef rewind
+ extern VOID_HACK rewind();
+ #endif /* rewind */
+ #endif /* __STDC__ */
+ 
+ 
+ /* most machines don't give us a header file for these */
+ #if defined(__STDC__) || defined(sprite)
+ #include <stdlib.h>
+ #else
+ #ifdef hpux
+ extern int abort();
+ extern void free(), exit(), perror();
+ #else
+ extern VOID_HACK abort(), free(), exit(), perror();
+ #endif /* hpux */
+ extern char *getenv();
+ #ifdef ultrix4
+ extern void *malloc(), *realloc(), *calloc();
+ #else
+ extern char *malloc(), *realloc(), *calloc();
+ #endif
+ #if defined(aiws) || defined(hpux)
+ extern int sprintf();
+ #else
+ extern char *sprintf();
+ #endif
+ extern int system();
+ extern double atof();
+ extern long atol();
+ extern int sscanf();
+ #endif /* __STDC__ */
+ 
+ 
+ /* some call it strings.h, some call it string.h; others, also have memory.h */
+ #if defined(__STDC__) || defined(sprite)
+ #include <string.h>
+ #else
+ /* ANSI C string.h -- 1/11/88 Draft Standard */
+ #if defined(ultrix4) || defined(hpux)
+ #include <strings.h>
+ #else
+ extern char *strcpy(), *strncpy(), *strcat(), *strncat(), *strerror();
+ extern char *strpbrk(), *strtok(), *strchr(), *strrchr(), *strstr();
+ extern int strcoll(), strxfrm(), strncmp(), strlen(), strspn(), strcspn();
+ extern char *memmove(), *memccpy(), *memchr(), *memcpy(), *memset();
+ extern int memcmp(), strcmp();
+ #endif /* ultrix4 */
+ #endif /* __STDC__ */
+ 
+ #ifdef lint
+ #undef putc			/* correct lint '_flsbuf' bug */
+ #endif /* lint */
+ 
+ /* a few extras */
+ #if defined(hpux)
+ extern VOID_HACK srand();
+ extern int rand();
+ #define random() rand()
+ #define srandom(a) srand(a)
+ #define bzero(a,b) memset(a, 0, b)
+ #else
+ extern VOID_HACK srandom();
+ extern long random();
+ #endif
+ 
+ /*
+ **  _std_h is defined in /usr/local/lib/g++-include/std.h  
+ */
+ #if ! defined(_std_h)
+ #if defined(ultrix3) || defined(ultrix4) ||  defined(hpux)
+ extern unsigned sleep();
+ #else
+ extern VOID_HACK sleep();
+ #endif
+ #endif  /* _std_h */
+ /* assertion macro */
+ 
+ #ifndef assert
+ #if defined(__STDC__) || defined(sprite)
+ #include <assert.h>
+ #else
+ #ifndef NDEBUG
+ #define assert(ex) {\
+     if (! (ex)) {\
+ 	(void) fprintf(stderr, "Assertion failed: file %s, line %d\n",\
+ 	    __FILE__, __LINE__);\
+ 	(void) fflush(stdout);\
+ 	abort();\
+     }\
+ }
+ #else
+ #define assert(ex) {;}
+ #endif
+ #endif
+ #endif
+ 
+ /* handle the various limits */
+ #if defined(__STDC__) || defined(POSIX)
+ #include <limits.h>
+ #else
+ #define USHRT_MAX	(~ (unsigned short int) 0)
+ #define UINT_MAX	(~ (unsigned int) 0)
+ #define ULONG_MAX	(~ (unsigned long int) 0)
+ #define SHRT_MAX	((short int) (USHRT_MAX >> 1))
+ #define INT_MAX		((int) (UINT_MAX >> 1))
+ #define LONG_MAX	((long int) (ULONG_MAX >> 1))
+ #endif
+ 
+ #endif /* PORT_H */
+ 


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/primes.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/primes.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/primes.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,161 ----
+ #include "espresso.h"
+ 
+ static bool primes_consensus_special_cases();
+ static pcover primes_consensus_merge();
+ static pcover and_with_cofactor(); 
+ 
+ 
+ /* primes_consensus -- generate primes using consensus */
+ pcover primes_consensus(T)
+ pcube *T;			/* T will be disposed of */
+ {
+     register pcube cl, cr;
+     register int best;
+     pcover Tnew, Tl, Tr;
+ 
+     if (primes_consensus_special_cases(T, &Tnew) == MAYBE) {
+ 	cl = new_cube();
+ 	cr = new_cube();
+ 	best = binate_split_select(T, cl, cr, COMPL);
+ 
+ 	Tl = primes_consensus(scofactor(T, cl, best));
+ 	Tr = primes_consensus(scofactor(T, cr, best));
+ 	Tnew = primes_consensus_merge(Tl, Tr, cl, cr);
+ 
+ 	free_cube(cl);
+ 	free_cube(cr);
+ 	free_cubelist(T);
+     }
+ 
+     return Tnew;
+ }
+ 
+ static bool 
+ primes_consensus_special_cases(T, Tnew)
+ pcube *T;			/* will be disposed if answer is determined */
+ pcover *Tnew;			/* returned only if answer determined */
+ {
+     register pcube *T1, p, ceil, cof=T[0];
+     pcube last;
+     pcover A;
+ 
+     /* Check for no cubes in the cover */
+     if (T[2] == NULL) {
+ 	*Tnew = new_cover(0);
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for only a single cube in the cover */
+     if (T[3] == NULL) {
+ 	*Tnew = sf_addset(new_cover(1), set_or(cof, cof, T[2]));
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for a row of all 1's (implies function is a tautology) */
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	if (full_row(p, cof)) {
+ 	    *Tnew = sf_addset(new_cover(1), cube.fullset);
+ 	    free_cubelist(T);
+ 	    return TRUE;
+ 	}
+     }
+ 
+     /* Check for a column of all 0's which can be factored out */
+     ceil = set_save(cof);
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	INLINEset_or(ceil, ceil, p);
+     }
+     if (! setp_equal(ceil, cube.fullset)) {
+ 	p = new_cube();
+ 	(void) set_diff(p, cube.fullset, ceil);
+ 	(void) set_or(cof, cof, p);
+ 	free_cube(p);
+ 
+ 	A = primes_consensus(T);
+ 	foreach_set(A, last, p) {
+ 	    INLINEset_and(p, p, ceil);
+ 	}
+ 	*Tnew = A;
+ 	set_free(ceil);
+ 	return TRUE;
+     }
+     set_free(ceil);
+ 
+     /* Collect column counts, determine unate variables, etc. */
+     massive_count(T);
+ 
+     /* If single active variable not factored out above, then tautology ! */
+     if (cdata.vars_active == 1) {
+ 	*Tnew = sf_addset(new_cover(1), cube.fullset);
+ 	free_cubelist(T);
+ 	return TRUE;
+ 
+     /* Check for unate cover */
+     } else if (cdata.vars_unate == cdata.vars_active) {
+ 	A = cubeunlist(T);
+ 	*Tnew = sf_contain(A);
+ 	free_cubelist(T);
+ 	return TRUE;
+ 
+     /* Not much we can do about it */
+     } else {
+ 	return MAYBE;
+     }
+ }
+ 
+ static pcover 
+ primes_consensus_merge(Tl, Tr, cl, cr)
+ pcover Tl, Tr;
+ pcube cl, cr;
+ {
+     register pcube pl, pr, lastl, lastr, pt;
+     pcover T, Tsave;
+ 
+     Tl = and_with_cofactor(Tl, cl);
+     Tr = and_with_cofactor(Tr, cr);
+ 
+     T = sf_new(500, Tl->sf_size);
+     pt = T->data;
+     Tsave = sf_contain(sf_join(Tl, Tr));
+ 
+     foreach_set(Tl, lastl, pl) {
+ 	foreach_set(Tr, lastr, pr) {
+ 	    if (cdist01(pl, pr) == 1) {
+ 		consensus(pt, pl, pr);
+ 		if (++T->count >= T->capacity) {
+ 		    Tsave = sf_union(Tsave, sf_contain(T));
+ 		    T = sf_new(500, Tl->sf_size);
+ 		    pt = T->data;
+ 		} else {
+ 		    pt += T->wsize;
+ 		}
+ 	    }
+ 	}
+     }
+     free_cover(Tl);
+     free_cover(Tr);
+ 
+     Tsave = sf_union(Tsave, sf_contain(T));
+     return Tsave;
+ }
+ 
+ 
+ static pcover
+ and_with_cofactor(A, cof)
+ pset_family A;
+ register pset cof;
+ {
+     register pset last, p;
+ 
+     foreach_set(A, last, p) {
+ 	INLINEset_and(p, p, cof);
+ 	if (cdist(p, cube.fullset) > 0) {
+ 	    RESET(p, ACTIVE);
+ 	} else {
+ 	    SET(p, ACTIVE);
+ 	}
+     }
+     return sf_inactive(A);
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/reduce.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/reduce.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/reduce.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,249 ----
+ /*
+     module: reduce.c
+     purpose: Perform the Espresso-II reduction step
+ 
+     Reduction is a technique used to explore larger regions of the
+     optimization space.  We replace each cube of F with a smaller
+     cube while still maintaining a cover of the same logic function.
+ */
+ 
+ #include "espresso.h"
+ 
+ static bool toggle = TRUE;
+ 
+ 
+ /*
+     reduce -- replace each cube in F with its reduction
+ 
+     The reduction of a cube is the smallest cube contained in the cube
+     which can replace the cube in the original cover without changing
+     the cover.  This is equivalent to the super cube of all of the
+     essential points in the cube.  This can be computed directly.
+ 
+     The problem is that the order in which the cubes are reduced can
+     greatly affect the final result.  We alternate between two ordering
+     strategies:
+ 
+ 	(1) Order the cubes in ascending order of distance from the
+ 	largest cube breaking ties by ordering cubes of equal distance
+ 	in descending order of size (sort_reduce)
+ 
+ 	(2) Order the cubes in descending order of the inner-product of
+ 	the cube and the column sums (mini_sort)
+ 
+     The real workhorse of this section is the routine SCCC which is
+     used to find the Smallest Cube Containing the Complement of a cover.
+     Reduction as proposed by Espresso-II takes a cube and computes its
+     maximal reduction as the intersection between the cube and the
+     smallest cube containing the complement of (F u D - {c}) cofactored
+     against c.
+ 
+     As usual, the unate-recursive paradigm is used to compute SCCC.
+     The SCCC of a unate cover is trivial to compute, and thus we perform
+     Shannon Cofactor expansion attempting to drive the cover to be unate
+     as fast as possible.
+ */
+ 
+ pcover reduce(F, D)
+ INOUT pcover F;
+ IN pcover D;
+ {
+     register pcube last, p, cunder, *FD;
+ 
+     /* Order the cubes */
+     if (use_random_order)
+ 	F = random_order(F);
+     else {
+ 	F = toggle ? sort_reduce(F) : mini_sort(F, descend);
+ 	toggle = ! toggle;
+     }
+ 
+     /* Try to reduce each cube */
+     FD = cube2list(F, D);
+     foreach_set(F, last, p) {
+ 	cunder = reduce_cube(FD, p);		/* reduce the cube */
+ 	if (setp_equal(cunder, p)) {            /* see if it actually did */
+ 	    SET(p, ACTIVE);	/* cube remains active */
+ 	    SET(p, PRIME);	/* cube remains prime ? */
+ 	} else {
+ 	    if (debug & REDUCE) {
+ 		printf("REDUCE: %s to %s %s\n",
+ 		    pc1(p), pc2(cunder), print_time(ptime()));
+ 	    }
+ 	    set_copy(p, cunder);                /* save reduced version */
+ 	    RESET(p, PRIME);                    /* cube is no longer prime */
+ 	    if (setp_empty(cunder))
+ 		RESET(p, ACTIVE);               /* if null, kill the cube */
+ 	    else
+ 		SET(p, ACTIVE);                 /* cube is active */
+ 	}
+ 	free_cube(cunder);
+     }
+     free_cubelist(FD);
+ 
+     /* Delete any cubes of F which reduced to the empty cube */
+     return sf_inactive(F);
+ }
+ 
+ /* reduce_cube -- find the maximal reduction of a cube */
+ pcube reduce_cube(FD, p)
+ IN pcube *FD, p;
+ {
+     pcube cunder;
+ 
+     cunder = sccc(cofactor(FD, p));
+     return set_and(cunder, cunder, p);
+ }
+ 
+ 
+ /* sccc -- find Smallest Cube Containing the Complement of a cover */
+ pcube sccc(T)
+ INOUT pcube *T;         /* T will be disposed of */
+ {
+     pcube r;
+     register pcube cl, cr;
+     register int best;
+     static int sccc_level = 0;
+ 
+     if (debug & REDUCE1) {
+ 	debug_print(T, "SCCC", sccc_level++);
+     }
+ 
+     if (sccc_special_cases(T, &r) == MAYBE) {
+ 	cl = new_cube();
+ 	cr = new_cube();
+ 	best = binate_split_select(T, cl, cr, REDUCE1);
+ 	r = sccc_merge(sccc(scofactor(T, cl, best)),
+ 		       sccc(scofactor(T, cr, best)), cl, cr);
+ 	free_cubelist(T);
+     }
+ 
+     if (debug & REDUCE1)
+ 	printf("SCCC[%d]: result is %s\n", --sccc_level, pc1(r));
+     return r;
+ }
+ 
+ 
+ pcube sccc_merge(left, right, cl, cr)
+ INOUT register pcube left, right;       /* will be disposed of ... */
+ INOUT register pcube cl, cr;            /* will be disposed of ... */
+ {
+     INLINEset_and(left, left, cl);
+     INLINEset_and(right, right, cr);
+     INLINEset_or(left, left, right);
+     free_cube(right);
+     free_cube(cl);
+     free_cube(cr);
+     return left;
+ }
+ 
+ 
+ /*
+     sccc_cube -- find the smallest cube containing the complement of a cube
+ 
+     By DeMorgan's law and the fact that the smallest cube containing a
+     cover is the "or" of the positional cubes, it is simple to see that
+     the SCCC is the universe if the cube has more than two active
+     variables.  If there is only a single active variable, then the
+     SCCC is merely the bitwise complement of the cube in that
+     variable.  A last special case is no active variables, in which
+     case the SCCC is empty.
+ 
+     This is "anded" with the incoming cube result.
+ */
+ pcube sccc_cube(result, p)
+ register pcube result, p;
+ {
+     register pcube temp=cube.temp[0], mask;
+     int var;
+ 
+     if ((var = cactive(p)) >= 0) {
+ 	mask = cube.var_mask[var];
+ 	INLINEset_xor(temp, p, mask);
+ 	INLINEset_and(result, result, temp);
+     }
+     return result;
+ }
+ 
+ /*
+  *   sccc_special_cases -- check the special cases for sccc
+  */
+ 
+ bool sccc_special_cases(T, result)
+ INOUT pcube *T;                 /* will be disposed if answer is determined */
+ OUT pcube *result;              /* returned only if answer determined */
+ {
+     register pcube *T1, p, temp = cube.temp[1], ceil, cof = T[0];
+     pcube *A, *B;
+ 
+     /* empty cover => complement is universe => SCCC is universe */
+     if (T[2] == NULL) {
+ 	*result = set_save(cube.fullset);
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* row of 1's => complement is empty => SCCC is empty */
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	if (full_row(p, cof)) {
+ 	    *result = new_cube();
+ 	    free_cubelist(T);
+ 	    return TRUE;
+ 	}
+     }
+ 
+     /* Collect column counts, determine unate variables, etc. */
+     massive_count(T);
+ 
+     /* If cover is unate (or single cube), apply simple rules to find SCCCU */
+     if (cdata.vars_unate == cdata.vars_active || T[3] == NULL) {
+ 	*result = set_save(cube.fullset);
+ 	for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	    (void) sccc_cube(*result, set_or(temp, p, cof));
+ 	}
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for column of 0's (which can be easily factored( */
+     ceil = set_save(cof);
+     for(T1 = T+2; (p = *T1++) != NULL; ) {
+ 	INLINEset_or(ceil, ceil, p);
+     }
+     if (! setp_equal(ceil, cube.fullset)) {
+ 	*result = sccc_cube(set_save(cube.fullset), ceil);
+ 	if (setp_equal(*result, cube.fullset)) {
+ 	    free_cube(ceil);
+ 	} else {
+ 	    *result = sccc_merge(sccc(cofactor(T,ceil)),
+ 			 set_save(cube.fullset), ceil, *result);
+ 	}
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+     free_cube(ceil);
+ 
+     /* Single active column at this point => tautology => SCCC is empty */
+     if (cdata.vars_active == 1) {
+ 	*result = new_cube();
+ 	free_cubelist(T);
+ 	return TRUE;
+     }
+ 
+     /* Check for components */
+     if (cdata.var_zeros[cdata.best] < CUBELISTSIZE(T)/2) {
+ 	if (cubelist_partition(T, &A, &B, debug & REDUCE1) == 0) {
+ 	    return MAYBE;
+ 	} else {
+ 	    free_cubelist(T);
+ 	    *result = sccc(A);
+ 	    ceil = sccc(B);
+ 	    (void) set_and(*result, *result, ceil);
+ 	    set_free(ceil);
+ 	    return TRUE;
+ 	}
+     }
+ 
+     /* Not much we can do about it */
+     return MAYBE;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/rows.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/rows.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/rows.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,305 ----
+ #include "port.h"
+ #include "sparse_int.h"
+ 
+ 
+ /*
+  *  allocate a new row vector 
+  */
+ sm_row *
+ sm_row_alloc()
+ {
+     register sm_row *prow;
+ 
+ #ifdef FAST_AND_LOOSE
+     if (sm_row_freelist == NIL(sm_row)) {
+ 	prow = ALLOC(sm_row, 1);
+     } else {
+ 	prow = sm_row_freelist;
+ 	sm_row_freelist = prow->next_row;
+     }
+ #else
+     prow = ALLOC(sm_row, 1);
+ #endif
+ 
+     prow->row_num = 0;
+     prow->length = 0;
+     prow->first_col = prow->last_col = NIL(sm_element);
+     prow->next_row = prow->prev_row = NIL(sm_row);
+     prow->flag = 0;
+     prow->user_word = NIL(char);		/* for our user ... */
+     return prow;
+ }
+ 
+ 
+ /*
+  *  free a row vector -- for FAST_AND_LOOSE, this is real cheap for rows;
+  *  however, freeing a column must still walk down the column discarding
+  *  the elements one-by-one; that is the only use for the extra '-DCOLS'
+  *  compile flag ...
+  */
+ void
+ sm_row_free(prow)
+ register sm_row *prow;
+ {
+ #if defined(FAST_AND_LOOSE) && ! defined(COLS)
+     if (prow->first_col != NIL(sm_element)) {
+ 	/* Add the linked list of row items to the free list */
+ 	prow->last_col->next_col = sm_element_freelist;
+ 	sm_element_freelist = prow->first_col;
+     }
+ 
+     /* Add the row to the free list of rows */
+     prow->next_row = sm_row_freelist;
+     sm_row_freelist = prow;
+ #else
+     register sm_element *p, *pnext;
+ 
+     for(p = prow->first_col; p != 0; p = pnext) {
+ 	pnext = p->next_col;
+ 	sm_element_free(p);
+     }
+     FREE(prow);
+ #endif
+ }
+ 
+ 
+ /*
+  *  duplicate an existing row
+  */
+ sm_row *
+ sm_row_dup(prow)
+ register sm_row *prow;
+ {
+     register sm_row *pnew;
+     register sm_element *p;
+ 
+     pnew = sm_row_alloc();
+     for(p = prow->first_col; p != 0; p = p->next_col) {
+ 	(void) sm_row_insert(pnew, p->col_num);
+     }
+     return pnew;
+ }
+ 
+ 
+ /*
+  *  insert an element into a row vector 
+  */
+ sm_element *
+ sm_row_insert(prow, col)
+ register sm_row *prow;
+ register int col;
+ {
+     register sm_element *test, *element;
+ 
+     /* get a new item, save its address */
+     sm_element_alloc(element);
+     test = element;
+     sorted_insert(sm_element, prow->first_col, prow->last_col, prow->length, 
+ 		    next_col, prev_col, col_num, col, test);
+ 
+     /* if item was not used, free it */
+     if (element != test) {
+ 	sm_element_free(element);
+     }
+ 
+     /* either way, return the current new value */
+     return test;
+ }
+ 
+ 
+ /*
+  *  remove an element from a row vector 
+  */
+ void
+ sm_row_remove(prow, col)
+ register sm_row *prow;
+ register int col;
+ {
+     register sm_element *p;
+ 
+     for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+ 	;
+     if (p != 0 && p->col_num == col) {
+ 	dll_unlink(p, prow->first_col, prow->last_col, 
+ 			    next_col, prev_col, prow->length);
+ 	sm_element_free(p);
+     }
+ }
+ 
+ 
+ /*
+  *  find an element (if it is in the row vector)
+  */
+ sm_element *
+ sm_row_find(prow, col)
+ sm_row *prow;
+ int col;
+ {
+     register sm_element *p;
+ 
+     for(p = prow->first_col; p != 0 && p->col_num < col; p = p->next_col)
+ 	;
+     if (p != 0 && p->col_num == col) {
+ 	return p;
+     } else {
+ 	return NIL(sm_element);
+     }
+ }
+ 
+ /*
+  *  return 1 if row p2 contains row p1; 0 otherwise
+  */
+ int 
+ sm_row_contains(p1, p2)
+ sm_row *p1, *p2;
+ {
+     register sm_element *q1, *q2;
+ 
+     q1 = p1->first_col;
+     q2 = p2->first_col;
+     while (q1 != 0) {
+ 	if (q2 == 0 || q1->col_num < q2->col_num) {
+ 	    return 0;
+ 	} else if (q1->col_num == q2->col_num) {
+ 	    q1 = q1->next_col;
+ 	    q2 = q2->next_col;
+ 	} else {
+ 	    q2 = q2->next_col;
+ 	}
+     }
+     return 1;
+ }
+ 
+ 
+ /*
+  *  return 1 if row p1 and row p2 share an element in common
+  */
+ int 
+ sm_row_intersects(p1, p2)
+ sm_row *p1, *p2;
+ {
+     register sm_element *q1, *q2;
+ 
+     q1 = p1->first_col;
+     q2 = p2->first_col;
+     if (q1 == 0 || q2 == 0) return 0;
+     for(;;) {
+ 	if (q1->col_num < q2->col_num) {
+ 	    if ((q1 = q1->next_col) == 0) {
+ 		return 0;
+ 	    }
+ 	} else if (q1->col_num > q2->col_num) {
+ 	    if ((q2 = q2->next_col) == 0) {
+ 		return 0;
+ 	    }
+ 	} else {
+ 	    return 1;
+ 	}
+     }
+ }
+ 
+ 
+ /*
+  *  compare two rows, lexical ordering
+  */
+ int 
+ sm_row_compare(p1, p2)
+ sm_row *p1, *p2;
+ {
+     register sm_element *q1, *q2;
+ 
+     q1 = p1->first_col;
+     q2 = p2->first_col;
+     while(q1 != 0 && q2 != 0) {
+ 	if (q1->col_num != q2->col_num) {
+ 	    return q1->col_num - q2->col_num;
+ 	}
+ 	q1 = q1->next_col;
+ 	q2 = q2->next_col;
+     }
+ 
+     if (q1 != 0) {
+ 	return 1;
+     } else if (q2 != 0) {
+ 	return -1;
+     } else {
+ 	return 0;
+     }
+ }
+ 
+ 
+ /*
+  *  return the intersection
+  */
+ sm_row *
+ sm_row_and(p1, p2)
+ sm_row *p1, *p2;
+ {
+     register sm_element *q1, *q2;
+     register sm_row *result;
+ 
+     result = sm_row_alloc();
+     q1 = p1->first_col;
+     q2 = p2->first_col;
+     if (q1 == 0 || q2 == 0) return result;
+     for(;;) {
+ 	if (q1->col_num < q2->col_num) {
+ 	    if ((q1 = q1->next_col) == 0) {
+ 		return result;
+ 	    }
+ 	} else if (q1->col_num > q2->col_num) {
+ 	    if ((q2 = q2->next_col) == 0) {
+ 		return result;
+ 	    }
+ 	} else {
+ 	    (void) sm_row_insert(result, q1->col_num);
+ 	    if ((q1 = q1->next_col) == 0) {
+ 		return result;
+ 	    }
+ 	    if ((q2 = q2->next_col) == 0) {
+ 		return result;
+ 	    }
+ 	}
+     }
+ }
+ 
+ int 
+ sm_row_hash(prow, modulus)
+ sm_row *prow;
+ int modulus;
+ {
+     register int sum;
+     register sm_element *p;
+ 
+     sum = 0;
+     for(p = prow->first_col; p != 0; p = p->next_col) {
+ 	sum = (sum*17 + p->col_num) % modulus;
+     }
+     return sum;
+ }
+ 
+ /*
+  *  remove an element from a row vector (given a pointer to the element) 
+  */
+ void
+ sm_row_remove_element(prow, p)
+ register sm_row *prow;
+ register sm_element *p;
+ {
+     dll_unlink(p, prow->first_col, prow->last_col, 
+ 			next_col, prev_col, prow->length);
+     sm_element_free(p);
+ }
+ 
+ 
+ void
+ sm_row_print(fp, prow)
+ FILE *fp;
+ sm_row *prow;
+ {
+     sm_element *p;
+ 
+     for(p = prow->first_col; p != 0; p = p->next_col) {
+ 	(void) fprintf(fp, " %d", p->col_num);
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/set.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/set.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/set.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,811 ----
+ /*
+  *   set.c -- routines for maniuplating sets and set families
+  */
+ 
+ /* LINTLIBRARY */
+ 
+ #include "espresso.h"
+ static pset_family set_family_garbage = NULL;
+ 
+ static int intcpy(d, s, n)
+ register unsigned int *d, *s;
+ register long n;
+ {
+     register int i;
+     for(i = 0; i < n; i++) {
+ 	*d++ = *s++;
+     }
+ }
+ 
+ 
+ /* bit_index -- find first bit (from LSB) in a word (MSB=bit n, LSB=bit 0) */
+ int bit_index(a)
+ register unsigned int a;
+ {
+     register int i;
+     if (a == 0)
+ 	return -1;
+     for(i = 0; (a & 1) == 0; a >>= 1, i++)
+ 	;
+     return i;
+ }
+ 
+ 
+ /* set_ord -- count number of elements in a set */
+ int set_ord(a)
+ register pset a;
+ {
+     register int i, sum = 0;
+     register unsigned int val;
+     for(i = LOOP(a); i > 0; i--)
+ 	if ((val = a[i]) != 0)
+ 	    sum += count_ones(val);
+     return sum;
+ }
+ 
+ /* set_dist -- distance between two sets (# elements in common) */
+ int set_dist(a, b)
+ register pset a, b;
+ {
+     register int i, sum = 0;
+     register unsigned int val;
+     for(i = LOOP(a); i > 0; i--)
+ 	if ((val = a[i] & b[i]) != 0)
+ 	    sum += count_ones(val);
+     return sum;
+ }
+ 
+ /* set_clear -- make "r" the empty set of "size" elements */
+ pset set_clear(r, size)
+ register pset r;
+ int size;
+ {
+     register int i = LOOPINIT(size);
+     *r = i; do r[i] = 0; while (--i > 0);
+     return r;
+ }
+ 
+ /* set_fill -- make "r" the universal set of "size" elements */
+ pset set_fill(r, size)
+ register pset r;
+ register int size;
+ {
+     register int i = LOOPINIT(size);
+     *r = i;
+     r[i] = ~ (unsigned) 0;
+     r[i] >>= i * BPI - size;
+     while (--i > 0)
+ 	r[i] = ~ (unsigned) 0;
+     return r;
+ }
+ 
+ /* set_copy -- copy set a into set r */
+ pset set_copy(r, a)
+ register pset r, a;
+ {
+     register int i = LOOPCOPY(a);
+     do r[i] = a[i]; while (--i >= 0);
+     return r;
+ }
+ 
+ /* set_and -- compute intersection of sets "a" and "b" */
+ pset set_and(r, a, b)
+ register pset r, a, b;
+ {
+     register int i = LOOP(a);
+     PUTLOOP(r,i); do r[i] = a[i] & b[i]; while (--i > 0);
+     return r;
+ }
+ 
+ /* set_or -- compute union of sets "a" and "b" */
+ pset set_or(r, a, b)
+ register pset r, a, b;
+ {
+     register int i = LOOP(a);
+     PUTLOOP(r,i); do r[i] = a[i] | b[i]; while (--i > 0);
+     return r;
+ }
+ 
+ /* set_diff -- compute difference of sets "a" and "b" */
+ pset set_diff(r, a, b)
+ register pset r, a, b;
+ {
+     register int i = LOOP(a);
+     PUTLOOP(r,i); do r[i] = a[i] & ~b[i]; while (--i > 0);
+     return r;
+ }
+ 
+ /* set_xor -- compute exclusive-or of sets "a" and "b" */
+ pset set_xor(r, a, b)
+ register pset r, a, b;
+ {
+     register int i = LOOP(a);
+ #ifdef IBM_WATC
+     PUTLOOP(r,i); do r[i] = (a[i]&~b[i]) | (~a[i]&b[i]); while (--i > 0);
+ #else
+     PUTLOOP(r,i); do r[i] = a[i] ^ b[i]; while (--i > 0);
+ #endif
+     return r;
+ }
+ 
+ /* set_merge -- compute "a" & "mask" | "b" & ~ "mask" */
+ pset set_merge(r, a, b, mask)
+ register pset r, a, b, mask;
+ {
+     register int i = LOOP(a);
+     PUTLOOP(r,i); do r[i] = (a[i]&mask[i]) | (b[i]&~mask[i]); while (--i > 0);
+     return r;
+ }
+ 
+ /* set_andp -- compute intersection of sets "a" and "b" , TRUE if nonempty */
+ bool set_andp(r, a, b)
+ register pset r, a, b;
+ {
+     register int i = LOOP(a);
+     register unsigned int x = 0;
+     PUTLOOP(r,i); do {r[i] = a[i] & b[i]; x |= r[i];} while (--i > 0);
+     return x != 0;
+ }
+ 
+ /* set_orp -- compute union of sets "a" and "b" , TRUE if nonempty */
+ bool set_orp(r, a, b)
+ register pset r, a, b;
+ {
+     register int i = LOOP(a);
+     register unsigned int x = 0;
+     PUTLOOP(r,i); do {r[i] = a[i] | b[i]; x |= r[i];} while (--i > 0);
+     return x != 0;
+ }
+ 
+ /* setp_empty -- check if the set "a" is empty */
+ bool setp_empty(a)
+ register pset a;
+ {
+     register int i = LOOP(a);
+     do if (a[i]) return FALSE; while (--i > 0);
+     return TRUE;
+ }
+ 
+ /* setp_full -- check if the set "a" is the full set of "size" elements */
+ bool setp_full(a, size)
+ register pset a;
+ register int size;
+ {
+     register int i = LOOP(a);
+     register unsigned int test;
+     test = ~ (unsigned) 0;
+     test >>= i * BPI - size;
+     if (a[i] != test)
+ 	return FALSE;
+     while (--i > 0)
+ 	if (a[i] != (~(unsigned) 0))
+ 	    return FALSE;
+     return TRUE;
+ }
+ 
+ /* setp_equal -- check if the set "a" equals set "b" */
+ bool setp_equal(a, b)
+ register pset a, b;
+ {
+     register int i = LOOP(a);
+     do if (a[i] != b[i]) return FALSE; while (--i > 0);
+     return TRUE;
+ }
+ 
+ /* setp_disjoint -- check if intersection of "a" and "b" is empty */
+ bool setp_disjoint(a, b)
+ register pset a, b;
+ {
+     register int i = LOOP(a);
+     do if (a[i] & b[i]) return FALSE; while (--i > 0);
+     return TRUE;
+ }
+ 
+ /* setp_implies -- check if "a" implies "b" ("b" contains "a") */
+ bool setp_implies(a, b)
+ register pset a, b;
+ {
+     register int i = LOOP(a);
+     do if (a[i] & ~b[i]) return FALSE; while (--i > 0);
+     return TRUE;
+ }
+ 
+ /* sf_or -- form the "or" of all sets in a set family */
+ pset sf_or(A)
+ pset_family A;
+ {
+     register pset or, last, p;
+ 
+     or = set_new(A->sf_size);
+     foreach_set(A, last, p)
+ 	INLINEset_or(or, or, p);
+     return or;
+ }
+ 
+ /* sf_and -- form the "and" of all sets in a set family */
+ pset sf_and(A)
+ pset_family A;
+ {
+     register pset and, last, p;
+ 
+     and = set_fill(set_new(A->sf_size), A->sf_size);
+     foreach_set(A, last, p)
+ 	INLINEset_and(and, and, p);
+     return and;
+ }
+ 
+ /* sf_active -- make all members of the set family active */
+ pset_family sf_active(A)
+ pset_family A;
+ {
+     register pset p, last;
+     foreach_set(A, last, p) {
+ 	SET(p, ACTIVE);
+     }
+     A->active_count = A->count;
+     return A;
+ }
+ 
+ 
+ /* sf_inactive -- remove all inactive cubes in a set family */
+ pset_family sf_inactive(A)
+ pset_family A;
+ {
+     register pset p, last, pdest;
+ 
+     pdest = A->data;
+     foreach_set(A, last, p) {
+ 	if (TESTP(p, ACTIVE)) {
+ 	    if (pdest != p) {
+ 		INLINEset_copy(pdest, p);
+ 	    }
+ 	    pdest += A->wsize;
+ 	} else {
+ 	    A->count--;
+ 	}
+     }
+     return A;
+ }
+ 
+ 
+ /* sf_copy -- copy a set family */
+ pset_family sf_copy(R, A)
+ pset_family R, A;
+ {
+     R->sf_size = A->sf_size;
+     R->wsize = A->wsize;
+ /*R->capacity = A->count;*/
+ /*R->data = REALLOC(unsigned int, R->data, (long) R->capacity * R->wsize);*/
+     R->count = A->count;
+     R->active_count = A->active_count;
+     intcpy(R->data, A->data, (long) A->wsize * A->count);
+     return R;
+ }
+ 
+ 
+ /* sf_join -- join A and B into a single set_family */
+ pset_family sf_join(A, B)
+ pset_family A, B;
+ {
+     pset_family R;
+     long asize = A->count * A->wsize;
+     long bsize = B->count * B->wsize;
+ 
+     if (A->sf_size != B->sf_size) fatal("sf_join: sf_size mismatch");
+     R = sf_new(A->count + B->count, A->sf_size);
+     R->count = A->count + B->count;
+     R->active_count = A->active_count + B->active_count;
+     intcpy(R->data, A->data, asize);
+     intcpy(R->data + asize, B->data, bsize);
+     return R;
+ }
+ 
+ 
+ /* sf_append -- append the sets of B to the end of A, and dispose of B */
+ pset_family sf_append(A, B)
+ pset_family A, B;
+ {
+     long asize = A->count * A->wsize;
+     long bsize = B->count * B->wsize;
+ 
+     if (A->sf_size != B->sf_size) fatal("sf_append: sf_size mismatch");
+     A->capacity = A->count + B->count;
+     A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+     intcpy(A->data + asize, B->data, bsize);
+     A->count += B->count;
+     A->active_count += B->active_count;
+     sf_free(B);
+     return A;
+ }
+ 
+ 
+ /* sf_new -- allocate "num" sets of "size" elements each */
+ pset_family sf_new(num, size)
+ int num, size;
+ {
+     pset_family A;
+     if (set_family_garbage == NULL) {
+ 	A = ALLOC(set_family_t, 1);
+     } else {
+ 	A = set_family_garbage;
+ 	set_family_garbage = A->next;
+     }
+     A->sf_size = size;
+     A->wsize = SET_SIZE(size);
+     A->capacity = num;
+     A->data = ALLOC(unsigned int, (long) A->capacity * A->wsize);
+     A->count = 0;
+     A->active_count = 0;
+     return A;
+ }
+ 
+ 
+ /* sf_save -- create a duplicate copy of a set family */
+ pset_family sf_save(A)
+ register pset_family A;
+ {
+     return sf_copy(sf_new(A->count, A->sf_size), A);
+ }
+ 
+ 
+ /* sf_free -- free the storage allocated for a set family */
+ void sf_free(A)
+ pset_family A;
+ {
+     FREE(A->data);
+     A->next = set_family_garbage;
+     set_family_garbage = A;
+ }
+ 
+ 
+ /* sf_cleanup -- free all of the set families from the garbage list */
+ void sf_cleanup()
+ {
+     register pset_family p, pnext;
+     for(p = set_family_garbage; p != (pset_family) NULL; p = pnext) {
+ 	pnext = p->next;
+ 	FREE(p);
+     }
+     set_family_garbage = (pset_family) NULL;
+ }
+ 
+ 
+ /* sf_addset -- add a set to the end of a set family */
+ pset_family sf_addset(A, s)
+ pset_family A;
+ pset s;
+ {
+     register pset p;
+ 
+     if (A->count >= A->capacity) {
+ 	A->capacity = A->capacity + A->capacity/2 + 1;
+ 	A->data = REALLOC(unsigned int, A->data, (long) A->capacity * A->wsize);
+     }
+     p = GETSET(A, A->count++);
+     INLINEset_copy(p, s);
+     return A;
+ }
+ 
+ /* sf_delset -- delete a set from a set family */
+ void sf_delset(A, i)
+ pset_family A;
+ int i;
+ {   (void) set_copy(GETSET(A,i), GETSET(A, --A->count));}
+ 
+ /* sf_print -- print a set_family as a set (list the element numbers) */
+ void sf_print(A)
+ pset_family A;
+ {
+     char *ps1();
+     register pset p;
+     register int i;
+     foreachi_set(A, i, p)
+ 	printf("A[%d] = %s\n", i, ps1(p));
+ }
+ 
+ /* sf_bm_print -- print a set_family as a bit-matrix */
+ void sf_bm_print(A)
+ pset_family A;
+ {
+     char *pbv1();
+     register pset p;
+     register int i;
+     foreachi_set(A, i, p)
+ 	printf("[%4d] %s\n", i, pbv1(p, A->sf_size));
+ }
+ 
+ 
+ /* sf_write -- output a set family in an unintelligable manner */
+ void sf_write(fp, A)
+ FILE *fp;
+ pset_family A;
+ {
+     register pset p, last;
+     fprintf(fp, "%d %d\n", A->count, A->sf_size);
+     foreach_set(A, last, p)
+ 	set_write(fp, p);
+     (void) fflush(fp);
+ }
+ 
+ 
+ /* sf_read -- read a set family written by sf_write */
+ pset_family sf_read(fp)
+ FILE *fp;
+ {
+     int i, j;
+     register pset p, last;
+     pset_family A;
+ 
+     (void) fscanf(fp, "%d %d\n", &i, &j);
+     A = sf_new(i, j);
+     A->count = i;
+     foreach_set(A, last, p) {
+ 	(void) fscanf(fp, "%x", p);
+ 	for(j = 1; j <= LOOP(p); j++)
+ 	    (void) fscanf(fp, "%x", p+j);
+     }
+     return A;
+ }
+ 
+ 
+ /* set_write -- output a set in an unintelligable manner */
+ void set_write(fp, a)
+ register FILE *fp;
+ register pset a;
+ {
+     register int n = LOOP(a), j;
+ 
+     for(j = 0; j <= n; j++) {
+ 	fprintf(fp, "%x ", a[j]);
+ 	if ((j+1) % 8 == 0 && j != n)
+ 	    fprintf(fp, "\n\t");
+     }
+     fprintf(fp, "\n");
+ }
+ 
+ 
+ /* sf_bm_read -- read a set family written by sf_bm_print (almost) */
+ pset_family sf_bm_read(fp)
+ FILE *fp;
+ {
+     int i, j, rows, cols;
+     register pset pdest;
+     pset_family A;
+ 
+     (void) fscanf(fp, "%d %d\n", &rows, &cols);
+     A = sf_new(rows, cols);
+     for(i = 0; i < rows; i++) {
+ 	pdest = GETSET(A, A->count++);
+ 	(void) set_clear(pdest, A->sf_size);
+ 	for(j = 0; j < cols; j++) {
+ 	    switch(getc(fp)) {
+ 		case '0':
+ 		    break;
+ 		case '1':
+ 		    set_insert(pdest, j);
+ 		    break;
+ 		default:
+ 		    fatal("Error reading set family");
+ 	    }
+ 	}
+ 	if (getc(fp) != '\n') {
+ 	    fatal("Error reading set family (at end of line)");
+ 	}
+     }
+     return A;
+ }
+ 
+ 
+ 
+ /* ps1 -- convert a set into a printable string */
+ #define largest_string 120
+ static char s1[largest_string];
+ char *ps1(a)
+ register pset a;
+ {
+     register int i, num, l, len = 0, n = NELEM(a);
+     char temp[20];
+     bool first = TRUE;
+ 
+     s1[len++] = '[';
+     for(i = 0; i < n; i++)
+ 	if (is_in_set(a,i)) {
+ 	    if (! first)
+ 		s1[len++] = ',';
+ 	    first = FALSE; num = i;
+ 	    /* Generate digits (reverse order) */
+ 	    l = 0; do temp[l++] = num % 10 + '0'; while ((num /= 10) > 0);
+ 	    /* Copy them back in correct order */
+ 	    do s1[len++] = temp[--l]; while (l > 0);
+ 	    if (len > largest_string-15) {
+ 		s1[len++] = '.'; s1[len++] = '.'; s1[len++] = '.';
+ 		break;
+ 	    }
+ 	}
+ 
+     s1[len++] = ']';
+     s1[len++] = '\0';
+     return s1;
+ }
+ 
+ /* pbv1 -- print bit-vector */
+ char *pbv1(s, n)
+ pset s;
+ int n;
+ {
+     register int i;
+     for(i = 0; i < n; i++)
+ 	s1[i] = is_in_set(s,i) ? '1' : '0';
+     s1[n] = '\0';
+     return s1;
+ }
+ 
+ 
+ /* set_adjcnt -- adjust the counts for a set by "weight" */
+ void
+ set_adjcnt(a, count, weight)
+ register pset a;
+ register int *count, weight;
+ {
+     register int i, base;
+     register unsigned int val;
+ 
+     for(i = LOOP(a); i > 0; ) {
+ 	for(val = a[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+ 	    if (val & 1) {
+ 		count[base] += weight;
+ 	    }
+ 	}
+     }
+ }
+ 
+ 
+ 
+ /* sf_count -- perform a column sum over a set family */
+ int *sf_count(A)
+ pset_family A;
+ {
+     register pset p, last;
+     register int i, base, *count;
+     register unsigned int val;
+ 
+     count = ALLOC(int, A->sf_size);
+     for(i = A->sf_size - 1; i >= 0; i--) {
+ 	count[i] = 0;
+     }
+ 
+     foreach_set(A, last, p) {
+ 	for(i = LOOP(p); i > 0; ) {
+ 	    for(val = p[i], base = --i << LOGBPI; val != 0; base++, val >>= 1) {
+ 		if (val & 1) {
+ 		    count[base]++;
+ 		}
+ 	    }
+ 	}
+     }
+     return count;
+ }
+ 
+ 
+ /* sf_count_restricted -- perform a column sum over a set family, restricting
+  * to only the columns which are in r; also, the columns are weighted by the
+  * number of elements which are in each row
+  */
+ int *sf_count_restricted(A, r)
+ pset_family A;
+ register pset r;
+ {
+     register pset p;
+     register int i, base, *count;
+     register unsigned int val;
+     int weight;
+     pset last;
+ 
+     count = ALLOC(int, A->sf_size);
+     for(i = A->sf_size - 1; i >= 0; i--) {
+ 	count[i] = 0;
+     }
+ 
+     /* Loop for each set */
+     foreach_set(A, last, p) {
+ 	weight = 1024 / (set_ord(p) - 1);
+ 	for(i = LOOP(p); i > 0; ) {
+ 	    for(val=p[i]&r[i], base= --i<<LOGBPI; val!=0; base++, val >>= 1) {
+ 		if (val & 1) {
+ 		    count[base] += weight;
+ 		}
+ 	    }
+ 	}
+     }
+     return count;
+ }
+ 
+ 
+ /*
+  *  sf_delc -- delete columns first ... last of A
+  */
+ pset_family sf_delc(A, first, last)
+ pset_family A;
+ int first, last;
+ {
+     return sf_delcol(A, first, last-first + 1);
+ }
+ 
+ 
+ /*
+  *  sf_addcol -- add columns to a set family; includes a quick check to see
+  *  if there is already enough room (and hence, can avoid copying)
+  */
+ pset_family sf_addcol(A, firstcol, n)
+ pset_family A;
+ int firstcol, n;
+ {
+     int maxsize;
+ 
+     /* Check if adding columns at the end ... */
+     if (firstcol == A->sf_size) {
+ 	/* If so, check if there is already enough room */
+ 	maxsize = BPI * LOOPINIT(A->sf_size);
+ 	if ((A->sf_size + n) <= maxsize) {
+ 	    A->sf_size += n;
+ 	    return A;
+ 	}
+     }
+     return sf_delcol(A, firstcol, -n);
+ }
+ 
+ /*
+  * sf_delcol -- add/delete columns to/from a set family
+  *
+  *  if n > 0 then n columns starting from firstcol are deleted if n < 0
+  *  then n blank columns are inserted starting at firstcol
+  *      (i.e., the first new column number is firstcol)
+  *
+  *  This is done by copying columns in the array which is a relatively
+  *  slow operation.
+  */
+ pset_family sf_delcol(A, firstcol, n)
+ pset_family A;
+ register int firstcol, n;
+ {
+     register pset p, last, pdest;
+     register int i;
+     pset_family B;
+ 
+     B = sf_new(A->count, A->sf_size - n);
+     foreach_set(A, last, p) {
+ 	pdest = GETSET(B, B->count++);
+ 	INLINEset_clear(pdest, B->sf_size);
+ 	for(i = 0; i < firstcol; i++)
+ 	    if (is_in_set(p, i))
+ 		set_insert(pdest, i);
+ 	for(i = n > 0 ? firstcol + n : firstcol; i < A->sf_size; i++)
+ 	    if (is_in_set(p, i))
+ 		set_insert(pdest, i - n);
+     }
+     sf_free(A);
+     return B;
+ }
+ 
+ 
+ /*
+  *  sf_copy_col -- copy column "srccol" from "src" to column "dstcol" of "dst"
+  */
+ pset_family sf_copy_col(dst, dstcol, src, srccol)
+ pset_family dst, src;
+ int dstcol, srccol;
+ {
+     register pset last, p, pdest;
+     register int word_test, word_set;
+     unsigned int bit_set, bit_test;
+ 
+     /* CHEAT! form these constants outside the loop */
+     word_test = WHICH_WORD(srccol);
+     bit_test = 1 << WHICH_BIT(srccol);
+     word_set = WHICH_WORD(dstcol);
+     bit_set = 1 << WHICH_BIT(dstcol);
+ 
+     pdest = dst->data;
+     foreach_set(src, last, p) {
+ 	if ((p[word_test] & bit_test) != 0)
+ 	    pdest[word_set] |= bit_set;
+ /*
+  *  equivalent code for this is ...
+  *	if (is_in_set(p, srccol)) set_insert(pdest, destcol);
+  */
+ 	pdest += dst->wsize;
+     }
+     return dst;
+ }
+ 
+ 
+ 
+ /*
+  *  sf_compress -- delete columns from a matrix
+  */
+ pset_family sf_compress(A, c)
+ pset_family A;			/* will be freed */
+ register pset c;
+ {
+     register pset p;
+     register int i, bcol;
+     pset_family B;
+ 
+     /* create a clean set family for the result */
+     B = sf_new(A->count, set_ord(c));
+     for(i = 0; i < A->count; i++) {
+ 	p = GETSET(B, B->count++);
+ 	INLINEset_clear(p, B->sf_size);
+     }
+ 
+     /* copy each column of A which has a 1 in c */
+     bcol = 0;
+     for(i = 0; i < A->sf_size; i++) {
+ 	if (is_in_set(c, i)) {
+ 	    (void) sf_copy_col(B, bcol++, A, i);
+ 	}
+     }
+     sf_free(A);
+     return B;
+ }
+ 
+ 
+ 
+ /*
+  *  sf_transpose -- transpose a bit matrix
+  *
+  *  There are trickier ways of doing this, but this works.
+  */
+ pset_family sf_transpose(A)
+ pset_family A;
+ {
+     pset_family B;
+     register pset p;
+     register int i, j;
+ 
+     B = sf_new(A->sf_size, A->count);
+     B->count = A->sf_size;
+     foreachi_set(B, i, p) {
+ 	INLINEset_clear(p, B->sf_size);
+     }
+     foreachi_set(A, i, p) {
+ 	for(j = 0; j < A->sf_size; j++) {
+ 	    if (is_in_set(p, j)) {
+ 		set_insert(GETSET(B, j), i);
+ 	    }
+ 	}
+     }
+     sf_free(A);
+     return B;
+ }
+ 
+ 
+ /*
+  *   sf_permute -- permute the columns of a set_family
+  *
+  *   permute is an array of integers containing column numbers of A which
+  *   are to be retained.
+  */
+ pset_family sf_permute(A, permute, npermute)
+ pset_family A;
+ register int *permute, npermute;
+ {
+     pset_family B;
+     register pset p, last, pdest;
+     register int j;
+ 
+     B = sf_new(A->count, npermute);
+     B->count = A->count;
+     foreach_set(B, last, p)
+ 	INLINEset_clear(p, npermute);
+ 
+     pdest = B->data;
+     foreach_set(A, last, p) {
+ 	for(j = 0; j < npermute; j++)
+ 	    if (is_in_set(p, permute[j]))
+ 		set_insert(pdest, j);
+ 	pdest += B->wsize;
+     }
+     sf_free(A);
+     return B;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/setc.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/setc.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/setc.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,474 ----
+ /*
+     setc.c -- massive bit-hacking for performing special "cube"-type
+     operations on a set
+ 
+     The basic trick used for binary valued variables is the following:
+ 
+     If a[w] and b[w] contain a full word of binary variables, then:
+ 
+      1) to get the full word of their intersection, we use
+ 
+ 	    x = a[w] & b[w];
+ 
+ 
+      2) to see if the intersection is null in any variables, we examine
+ 
+ 	    x = ~(x | x >> 1) & DISJOINT;
+ 
+ 	this will have a single 1 in each binary variable for which
+ 	the intersection is null.  In particular, if this is zero,
+ 	then there are no disjoint variables; or, if this is nonzero,
+ 	then there is at least one disjoint variable.  A "count_ones"
+ 	over x will tell in how many variables they have an null
+ 	intersection.
+ 
+ 
+      3) to get a mask which selects the disjoint variables, we use
+ 
+ 	    (x | x << 1)
+ 
+ 	this provides a selector which can be used to see where
+ 	they have an null intersection
+ 
+ 
+     cdist       return distance between two cubes
+     cdist0      return true if two cubes are distance 0 apart
+     cdist01     return distance, or 2 if distance exceeds 1
+     consensus   compute consensus of two cubes distance 1 apart
+     force_lower expand hack (for now), related to consensus
+ */
+ 
+ #include "espresso.h"
+ 
+ /* see if the cube has a full row of 1's (with respect to cof) */
+ bool full_row(p, cof)
+ IN register pcube p, cof;
+ {
+     register int i = LOOP(p);
+     do if ((p[i] | cof[i]) != cube.fullset[i]) return FALSE; while (--i > 0);
+     return TRUE;
+ }
+ 
+ /*
+     cdist0 -- return TRUE if a and b are distance 0 apart
+ */
+ 
+ bool cdist0(a, b)
+ register pcube a, b;
+ {
+  {  /* Check binary variables */
+     register int w, last; register unsigned int x;
+     if ((last = cube.inword) != -1) {
+ 
+ 	/* Check the partial word of binary variables */
+ 	x = a[last] & b[last];
+ 	if (~(x | x >> 1) & cube.inmask)
+ 	    return FALSE;               /* disjoint in some variable */
+ 
+ 	/* Check the full words of binary variables */
+ 	for(w = 1; w < last; w++) {
+ 	    x = a[w] & b[w];
+ 	    if (~(x | x >> 1) & DISJOINT)
+ 		return FALSE;           /* disjoint in some variable */
+ 	}
+     }
+  }
+ 
+  {  /* Check the multiple-valued variables */
+     register int w, var, last; register pcube mask;
+     for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ 	mask = cube.var_mask[var]; last = cube.last_word[var];
+ 	for(w = cube.first_word[var]; w <= last; w++)
+ 	    if (a[w] & b[w] & mask[w])
+ 		goto nextvar;
+ 	return FALSE;           /* disjoint in this variable */
+     nextvar: ;
+     }
+  }
+     return TRUE;
+ }
+ 
+ /*
+     cdist01 -- return the "distance" between two cubes (defined as the
+     number of null variables in their intersection).  If the distance
+     exceeds 1, the value 2 is returned.
+ */
+ 
+ int cdist01(a, b)
+ register pset a, b;
+ {
+     int dist = 0;
+ 
+  {  /* Check binary variables */
+     register int w, last; register unsigned int x;
+     if ((last = cube.inword) != -1) {
+ 
+ 	/* Check the partial word of binary variables */
+ 	x = a[last] & b[last];
+ 	if (x = ~ (x | x >> 1) & cube.inmask)
+ 	    if ((dist = count_ones(x)) > 1)
+ 		return 2;
+ 
+ 	/* Check the full words of binary variables */
+ 	for(w = 1; w < last; w++) {
+ 	    x = a[w] & b[w];
+ 	    if (x = ~ (x | x >> 1) & DISJOINT)
+ 		if (dist == 1 || (dist += count_ones(x)) > 1)
+ 		    return 2;
+ 	}
+     }
+  }
+ 
+  {  /* Check the multiple-valued variables */
+     register int w, var, last; register pcube mask;
+     for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ 	mask = cube.var_mask[var]; last = cube.last_word[var];
+ 	for(w = cube.first_word[var]; w <= last; w++)
+ 	    if (a[w] & b[w] & mask[w])
+ 		goto nextvar;
+ 	if (++dist > 1)
+ 	    return 2;
+     nextvar: ;
+     }
+  }
+     return dist;
+ }
+ 
+ /*
+     cdist -- return the "distance" between two cubes (defined as the
+     number of null variables in their intersection).
+ */
+ 
+ int cdist(a, b)
+ register pset a, b;
+ {
+     int dist = 0;
+ 
+  {  /* Check binary variables */
+     register int w, last; register unsigned int x;
+     if ((last = cube.inword) != -1) {
+ 
+ 	/* Check the partial word of binary variables */
+ 	x = a[last] & b[last];
+ 	if (x = ~ (x | x >> 1) & cube.inmask)
+ 	    dist = count_ones(x);
+ 
+ 	/* Check the full words of binary variables */
+ 	for(w = 1; w < last; w++) {
+ 	    x = a[w] & b[w];
+ 	    if (x = ~ (x | x >> 1) & DISJOINT)
+ 		dist += count_ones(x);
+ 	}
+     }
+  }
+ 
+  {  /* Check the multiple-valued variables */
+     register int w, var, last; register pcube mask;
+     for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ 	mask = cube.var_mask[var]; last = cube.last_word[var];
+ 	for(w = cube.first_word[var]; w <= last; w++)
+ 	    if (a[w] & b[w] & mask[w])
+ 		goto nextvar;
+ 	dist++;
+     nextvar: ;
+     }
+  }
+     return dist;
+ }
+ 
+ /*
+     force_lower -- Determine which variables of a do not intersect b.
+ */
+ 
+ pset force_lower(xlower, a, b)
+ INOUT pset xlower;
+ IN register pset a, b;
+ {
+ 
+  {  /* Check binary variables (if any) */
+     register int w, last; register unsigned int x;
+     if ((last = cube.inword) != -1) {
+ 
+ 	/* Check the partial word of binary variables */
+ 	x = a[last] & b[last];
+ 	if (x = ~(x | x >> 1) & cube.inmask)
+ 	    xlower[last] |= (x | (x << 1)) & a[last];
+ 
+ 	/* Check the full words of binary variables */
+ 	for(w = 1; w < last; w++) {
+ 	    x = a[w] & b[w];
+ 	    if (x = ~(x | x >> 1) & DISJOINT)
+ 		xlower[w] |= (x | (x << 1)) & a[w];
+ 	}
+     }
+  }
+ 
+  {  /* Check the multiple-valued variables */
+     register int w, var, last; register pcube mask;
+     for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ 	mask = cube.var_mask[var]; last = cube.last_word[var];
+ 	for(w = cube.first_word[var]; w <= last; w++)
+ 	    if (a[w] & b[w] & mask[w])
+ 		goto nextvar;
+ 	for(w = cube.first_word[var]; w <= last; w++)
+ 	    xlower[w] |= a[w] & mask[w];
+     nextvar: ;
+     }
+  }
+     return xlower;
+ }
+ 
+ /*
+     consensus -- multiple-valued consensus
+ 
+     Although this looks very messy, the idea is to compute for r the
+     "and" of the cubes a and b for each variable, unless the "and" is
+     null in a variable, in which case the "or" of a and b is computed
+     for this variable.
+ 
+     Because we don't check how many variables are null in the
+     intersection of a and b, the returned value for r really only
+     represents the consensus when a and b are distance 1 apart.
+ */
+ 
+ void consensus(r, a, b)
+ INOUT pcube r;
+ IN register pcube a, b;
+ {
+     INLINEset_clear(r, cube.size);
+ 
+  {  /* Check binary variables (if any) */
+     register int w, last; register unsigned int x;
+     if ((last = cube.inword) != -1) {
+ 
+ 	/* Check the partial word of binary variables */
+ 	r[last] = x = a[last] & b[last];
+ 	if (x = ~(x | x >> 1) & cube.inmask)
+ 	    r[last] |= (x | (x << 1)) & (a[last] | b[last]);
+ 
+ 	/* Check the full words of binary variables */
+ 	for(w = 1; w < last; w++) {
+ 	    r[w] = x = a[w] & b[w];
+ 	    if (x = ~(x | x >> 1) & DISJOINT)
+ 		r[w] |= (x | (x << 1)) & (a[w] | b[w]);
+ 	}
+     }
+  }
+ 
+ 
+  {  /* Check the multiple-valued variables */
+     bool empty; int var; unsigned int x;
+     register int w, last; register pcube mask;
+     for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ 	mask = cube.var_mask[var];
+ 	last = cube.last_word[var];
+ 	empty = TRUE;
+ 	for(w = cube.first_word[var]; w <= last; w++)
+ 	    if (x = a[w] & b[w] & mask[w])
+ 		empty = FALSE, r[w] |= x;
+ 	if (empty)
+ 	    for(w = cube.first_word[var]; w <= last; w++)
+ 		r[w] |= mask[w] & (a[w] | b[w]);
+     }
+  }
+ }
+ 
+ /*
+     cactive -- return the index of the single active variable in
+     the cube, or return -1 if there are none or more than 2.
+ */
+ 
+ int cactive(a)
+ register pcube a;
+ {
+     int active = -1, dist = 0, bit_index();
+ 
+  {  /* Check binary variables */
+     register int w, last;
+     register unsigned int x;
+     if ((last = cube.inword) != -1) {
+ 
+ 	/* Check the partial word of binary variables */
+ 	x = a[last];
+ 	if (x = ~ (x & x >> 1) & cube.inmask) {
+ 	    if ((dist = count_ones(x)) > 1)
+ 		return -1;		/* more than 2 active variables */
+ 	    active = (last-1)*(BPI/2) + bit_index(x) / 2;
+ 	}
+ 
+ 	/* Check the full words of binary variables */
+ 	for(w = 1; w < last; w++) {
+ 	    x = a[w];
+ 	    if (x = ~ (x & x >> 1) & DISJOINT) {
+ 		if ((dist += count_ones(x)) > 1)
+ 		    return -1;		/* more than 2 active variables */
+ 		active = (w-1)*(BPI/2) + bit_index(x) / 2;
+ 	    }
+ 	}
+     }
+  }
+ 
+  {  /* Check the multiple-valued variables */
+     register int w, var, last;
+     register pcube mask;
+     for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ 	mask = cube.var_mask[var];
+ 	last = cube.last_word[var];
+ 	for(w = cube.first_word[var]; w <= last; w++)
+ 	    if (mask[w] & ~ a[w]) {
+ 		if (++dist > 1)
+ 		    return -1;
+ 		active = var;
+ 		break;
+ 	    }
+     }
+  }
+  return active;
+ }
+ 
+ /*
+     ccommon -- return TRUE if a and b are share "active" variables
+     active variables include variables that are empty;
+ */
+ 
+ bool ccommon(a, b, cof)
+ register pcube a, b, cof;
+ {
+  {  /* Check binary variables */
+     int last;
+     register int w;
+     register unsigned int x, y;
+     if ((last = cube.inword) != -1) {
+ 
+ 	/* Check the partial word of binary variables */
+ 	x = a[last] | cof[last];
+ 	y = b[last] | cof[last];
+ 	if (~(x & x>>1) & ~(y & y>>1) & cube.inmask)
+ 	    return TRUE;
+ 
+ 	/* Check the full words of binary variables */
+ 	for(w = 1; w < last; w++) {
+ 	    x = a[w] | cof[w];
+ 	    y = b[w] | cof[w];
+ 	    if (~(x & x>>1) & ~(y & y>>1) & DISJOINT)
+ 		return TRUE;
+ 	}
+     }
+  }
+ 
+  {  /* Check the multiple-valued variables */
+     int var;
+     register int w, last;
+     register pcube mask;
+     for(var = cube.num_binary_vars; var < cube.num_vars; var++) {
+ 	mask = cube.var_mask[var]; last = cube.last_word[var];
+ 	/* Check for some part missing from a */
+ 	for(w = cube.first_word[var]; w <= last; w++)
+ 	    if (mask[w] & ~a[w] & ~cof[w]) {
+ 
+ 		/* If so, check for some part missing from b */
+ 		for(w = cube.first_word[var]; w <= last; w++)
+ 		    if (mask[w] & ~b[w] & ~cof[w])
+ 			return TRUE;            /* both active */
+ 		break;
+ 	    }
+     }
+  }
+     return FALSE;
+ }
+ 
+ /*
+     These routines compare two sets (cubes) for the qsort() routine and
+     return:
+ 
+ 	-1 if set a is to precede set b
+ 	 0 if set a and set b are equal
+ 	 1 if set a is to follow set b
+ 
+     Usually the SIZE field of the set is assumed to contain the size
+     of the set (which will save recomputing the set size during the
+     sort).  For distance-1 merging, the global variable cube.temp[0] is
+     a mask which mask's-out the merging variable.
+ */
+ 
+ /* descend -- comparison for descending sort on set size */
+ int descend(a, b)
+ pset *a, *b;
+ {
+     register pset a1 = *a, b1 = *b;
+     if (SIZE(a1) > SIZE(b1)) return -1;
+     else if (SIZE(a1) < SIZE(b1)) return 1;
+     else {
+ 	register int i = LOOP(a1);
+ 	do
+ 	    if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+ 	while (--i > 0);
+     }
+     return 0;
+ }
+ 
+ /* ascend -- comparison for ascending sort on set size */
+ int ascend(a, b)
+ pset *a, *b;
+ {
+     register pset a1 = *a, b1 = *b;
+     if (SIZE(a1) > SIZE(b1)) return 1;
+     else if (SIZE(a1) < SIZE(b1)) return -1;
+     else {
+ 	register int i = LOOP(a1);
+ 	do
+ 	    if (a1[i] > b1[i]) return 1; else if (a1[i] < b1[i]) return -1;
+ 	while (--i > 0);
+     }
+     return 0;
+ }
+ 
+ 
+ /* lex_order -- comparison for "lexical" ordering of cubes */
+ int lex_order(a, b)
+ pset *a, *b;
+ {
+     register pset a1 = *a, b1 = *b;
+     register int i = LOOP(a1);
+     do
+ 	if (a1[i] > b1[i]) return -1; else if (a1[i] < b1[i]) return 1;
+     while (--i > 0);
+     return 0;
+ }
+ 
+ 
+ /* d1_order -- comparison for distance-1 merge routine */
+ int d1_order(a, b)
+ pset *a, *b;
+ {
+     register pset a1 = *a, b1 = *b, c1 = cube.temp[0];
+     register int i = LOOP(a1);
+     register unsigned int x1, x2;
+     do
+ 	if ((x1 = a1[i] | c1[i]) > (x2 = b1[i] | c1[i])) return -1;
+ 	else if (x1 < x2) return 1;
+     while (--i > 0);
+     return 0;
+ }
+ 
+ 
+ /* desc1 -- comparison (without indirection) for descending sort */
+ /* also has effect of handling NULL pointers,and a NULL pointer has smallest
+ order */
+ int desc1(a, b)
+ register pset a, b;
+ {
+     if (a == (pset) NULL)
+ 	return (b == (pset) NULL) ? 0 : 1;
+     else if (b == (pset) NULL)
+ 	return -1;
+     if (SIZE(a) > SIZE(b)) return -1;
+     else if (SIZE(a) < SIZE(b)) return 1;
+     else {
+ 	register int i = LOOP(a);
+ 	do
+ 	    if (a[i] > b[i]) return -1; else if (a[i] < b[i]) return 1;
+ 	while (--i > 0);
+     }
+     return 0;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sharp.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sharp.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sharp.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,238 ----
+ /*
+     sharp.c -- perform sharp, disjoint sharp, and intersection
+ */
+ 
+ #include "espresso.h"
+ 
+ long start_time;
+ 
+ 
+ /* cv_sharp -- form the sharp product between two covers */
+ pcover cv_sharp(A, B)
+ pcover A, B;
+ {
+     pcube last, p;
+     pcover T;
+ 
+     T = new_cover(0);
+     foreach_set(A, last, p)
+ 	T = sf_union(T, cb_sharp(p, B));
+     return T;
+ }
+ 
+ 
+ /* cb_sharp -- form the sharp product between a cube and a cover */
+ pcover cb_sharp(c, T)
+ pcube c;
+ pcover T;
+ {
+     if (T->count == 0) {
+ 	T = sf_addset(new_cover(1), c);
+     } else {
+ 	start_time = ptime();
+ 	T = cb_recur_sharp(c, T, 0, T->count-1, 0);
+     }
+     return T;
+ }
+ 
+ 
+ /* recursive formulation to provide balanced merging */
+ pcover cb_recur_sharp(c, T, first, last, level)
+ pcube c;
+ pcover T;
+ int first, last, level;
+ {
+     pcover temp, left, right;
+     int middle;
+ 
+     if (first == last) {
+ 	temp = sharp(c, GETSET(T, first));
+     } else {
+ 	middle = (first + last) / 2;
+ 	left = cb_recur_sharp(c, T, first, middle, level+1);
+ 	right = cb_recur_sharp(c, T, middle+1, last, level+1);
+ 	temp = cv_intersect(left, right);
+ 	if ((debug & SHARP) && level < 4) {
+ 	    printf("# SHARP[%d]: %4d = %4d x %4d, time = %s\n",
+ 		level, temp->count, left->count, right->count,
+ 		print_time(ptime() - start_time));
+ 	    (void) fflush(stdout);
+ 	}
+ 	free_cover(left);
+ 	free_cover(right);
+     }
+     return temp;
+ }
+ 
+ 
+ /* sharp -- form the sharp product between two cubes */
+ pcover sharp(a, b)
+ pcube a, b;
+ {
+     register int var;
+     register pcube d=cube.temp[0], temp=cube.temp[1], temp1=cube.temp[2];
+     pcover r = new_cover(cube.num_vars);
+ 
+     if (cdist0(a, b)) {
+ 	set_diff(d, a, b);
+ 	for(var = 0; var < cube.num_vars; var++) {
+ 	    if (! setp_empty(set_and(temp, d, cube.var_mask[var]))) {
+ 		set_diff(temp1, a, cube.var_mask[var]);
+ 		set_or(GETSET(r, r->count++), temp, temp1);
+ 	    }
+ 	}
+     } else {
+ 	r = sf_addset(r, a);
+     }
+     return r;
+ }
+ 
+ pcover make_disjoint(A)
+ pcover A;
+ {
+     pcover R, new;
+     register pset last, p;
+ 
+     R = new_cover(0);
+     foreach_set(A, last, p) {
+ 	new = cb_dsharp(p, R);
+ 	R = sf_append(R, new);
+     }
+     return R;
+ }
+ 
+ 
+ /* cv_dsharp -- disjoint-sharp product between two covers */
+ pcover cv_dsharp(A, B)
+ pcover A, B;
+ {
+     register pcube last, p;
+     pcover T;
+ 
+     T = new_cover(0);
+     foreach_set(A, last, p) {
+ 	T = sf_union(T, cb_dsharp(p, B));
+     }
+     return T;
+ }
+ 
+ 
+ /* cb1_dsharp -- disjoint-sharp product between a cover and a cube */
+ pcover cb1_dsharp(T, c)
+ pcover T;
+ pcube c;
+ {
+     pcube last, p;
+     pcover R;
+ 
+     R = new_cover(T->count);
+     foreach_set(T, last, p) {
+ 	R = sf_union(R, dsharp(p, c));
+     }
+     return R;
+ }
+ 
+ 
+ /* cb_dsharp -- disjoint-sharp product between a cube and a cover */
+ pcover cb_dsharp(c, T)
+ pcube c;
+ pcover T;
+ {
+     pcube last, p;
+     pcover Y, Y1;
+ 
+     if (T->count == 0) {
+ 	Y = sf_addset(new_cover(1), c);
+     } else {
+ 	Y = new_cover(T->count);
+ 	set_copy(GETSET(Y,Y->count++), c);
+ 	foreach_set(T, last, p) {
+ 	    Y1 = cb1_dsharp(Y, p);
+ 	    free_cover(Y);
+ 	    Y = Y1;
+ 	}
+     }
+     return Y;
+ }
+ 
+ 
+ /* dsharp -- form the disjoint-sharp product between two cubes */
+ pcover dsharp(a, b)
+ pcube a, b;
+ {
+     register pcube mask, diff, and, temp, temp1 = cube.temp[0];
+     int var;
+     pcover r;
+ 
+     r = new_cover(cube.num_vars);
+ 
+     if (cdist0(a, b)) {
+ 	diff = set_diff(new_cube(), a, b);
+ 	and = set_and(new_cube(), a, b);
+ 	mask = new_cube();
+ 	for(var = 0; var < cube.num_vars; var++) {
+ 	    /* check if position var of "a and not b" is not empty */
+ 	    if (! setp_disjoint(diff, cube.var_mask[var])) {
+ 
+ 		/* coordinate var equals the difference between a and b */
+ 		temp = GETSET(r, r->count++);
+ 		(void) set_and(temp, diff, cube.var_mask[var]);
+ 
+ 		/* coordinates 0 ... var-1 equal the intersection */
+ 		INLINEset_and(temp1, and, mask);
+ 		INLINEset_or(temp, temp, temp1);
+ 
+ 		/* coordinates var+1 .. cube.num_vars equal a */
+ 		set_or(mask, mask, cube.var_mask[var]);
+ 		INLINEset_diff(temp1, a, mask);
+ 		INLINEset_or(temp, temp, temp1);
+ 	    }
+ 	}
+ 	free_cube(diff);
+ 	free_cube(and);
+ 	free_cube(mask);
+     } else {
+ 	r = sf_addset(r, a);
+     }
+     return r;
+ }
+ 
+ /* cv_intersect -- form the intersection of two covers */
+ 
+ #define MAGIC 500               /* save 500 cubes before containment */
+ 
+ pcover cv_intersect(A, B)
+ pcover A, B;
+ {
+     register pcube pi, pj, lasti, lastj, pt;
+     pcover T, Tsave = NULL;
+ 
+     /* How large should each temporary result cover be ? */
+     T = new_cover(MAGIC);
+     pt = T->data;
+ 
+     /* Form pairwise intersection of each cube of A with each cube of B */
+     foreach_set(A, lasti, pi) {
+ 	foreach_set(B, lastj, pj) {
+ 	    if (cdist0(pi, pj)) {
+ 		(void) set_and(pt, pi, pj);
+ 		if (++T->count >= T->capacity) {
+ 		    if (Tsave == NULL)
+ 			Tsave = sf_contain(T);
+ 		    else
+ 			Tsave = sf_union(Tsave, sf_contain(T));
+ 		    T = new_cover(MAGIC);
+ 		    pt = T->data;
+ 		} else
+ 		    pt += T->wsize;
+ 	    }
+ 	}
+     }
+ 
+ 
+     if (Tsave == NULL)
+ 	Tsave = sf_contain(T);
+     else
+ 	Tsave = sf_union(Tsave, sf_contain(T));
+     return Tsave;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sminterf.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sminterf.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sminterf.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,35 ----
+ #include "espresso.h"
+ 
+ 
+ pset
+ do_sm_minimum_cover(A)
+ pset_family A;
+ {
+     sm_matrix *M;
+     sm_row *sparse_cover;
+     sm_element *pe;
+     pset cover;
+     register int i, base, rownum;
+     register unsigned val;
+     register pset last, p;
+ 
+     M = sm_alloc();
+     rownum = 0;
+     foreach_set(A, last, p) {
+ 	foreach_set_element(p, i, val, base) {
+ 	    (void) sm_insert(M, rownum, base);
+ 	}
+ 	rownum++;
+     }
+ 
+     sparse_cover = sm_minimum_cover(M, NIL(int), 1, 0);
+     sm_free(M);
+ 
+     cover = set_new(A->sf_size);
+     sm_foreach_row_element(sparse_cover, pe) {
+ 	set_insert(cover, pe->col_num);
+     }
+     sm_row_free(sparse_cover);
+ 
+     return cover;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/solution.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/solution.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/solution.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,105 ----
+ #include "mincov_int.h"
+ 
+ 
+ solution_t *
+ solution_alloc()
+ {
+     solution_t *sol;
+ 
+     sol = ALLOC(solution_t, 1);
+     sol->cost = 0;
+     sol->row = sm_row_alloc();
+     return sol;
+ }
+ 
+ 
+ void
+ solution_free(sol)
+ solution_t *sol;
+ {
+     sm_row_free(sol->row);
+     FREE(sol);
+ }
+ 
+ 
+ solution_t *
+ solution_dup(sol)
+ solution_t *sol;
+ {
+     solution_t *new_sol;
+ 
+     new_sol = ALLOC(solution_t, 1);
+     new_sol->cost = sol->cost;
+     new_sol->row = sm_row_dup(sol->row);
+     return new_sol;
+ }
+ 
+ 
+ void 
+ solution_add(sol, weight, col)
+ solution_t *sol;
+ int *weight;
+ int col;
+ {
+     (void) sm_row_insert(sol->row, col);
+     sol->cost += WEIGHT(weight, col);
+ }
+ 
+ 
+ void 
+ solution_accept(sol, A, weight, col)
+ solution_t *sol;
+ sm_matrix *A;
+ int *weight;
+ int col;
+ {
+     register sm_element *p, *pnext;
+     sm_col *pcol;
+ 
+     solution_add(sol, weight, col);
+ 
+     /* delete rows covered by this column */
+     pcol = sm_get_col(A, col);
+     for(p = pcol->first_row; p != 0; p = pnext) {
+ 	pnext = p->next_row;		/* grab it before it disappears */
+ 	sm_delrow(A, p->row_num);
+     }
+ }
+ 
+ 
+ /* ARGSUSED */
+ void 
+ solution_reject(sol, A, weight, col)
+ solution_t *sol;
+ sm_matrix *A;
+ int *weight;
+ int col;
+ {
+     sm_delcol(A, col);
+ }
+ 
+ 
+ solution_t *
+ solution_choose_best(best1, best2)
+ solution_t *best1, *best2;
+ {
+     if (best1 != NIL(solution_t)) {
+ 	if (best2 != NIL(solution_t)) {
+ 	    if (best1->cost <= best2->cost) {
+ 		solution_free(best2);
+ 		return best1;
+ 	    } else {
+ 		solution_free(best1);
+ 		return best2;
+ 	    }
+ 	} else {
+ 	    return best1;
+ 	}
+     } else {
+ 	if (best2 != NIL(solution_t)) {
+ 	    return best2;
+ 	} else {
+ 	    return NIL(solution_t);
+ 	}
+     }
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sparse.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sparse.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sparse.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,137 ----
+ /*
+     module: sparse.c
+ 
+     make_sparse is a last-step cleanup to reduce the total number
+     of literals in the cover.
+ 
+     This is done by reducing the "sparse" variables (using a modified
+     version of irredundant rather than reduce), followed by expanding
+     the "dense" variables (using modified version of expand).
+ */
+ 
+ #include "espresso.h"
+ 
+ pcover make_sparse(F, D, R)
+ pcover F, D, R;
+ {
+     cost_t cost, best_cost;
+ 
+     cover_cost(F, &best_cost);
+ 
+     do {
+ 	EXECUTE(F = mv_reduce(F, D), MV_REDUCE_TIME, F, cost);
+ 	if (cost.total == best_cost.total)
+ 	    break;
+ 	copy_cost(&cost, &best_cost);
+ 
+ 	EXECUTE(F = expand(F, R, TRUE), RAISE_IN_TIME, F, cost);
+ 	if (cost.total == best_cost.total)
+ 	    break;
+ 	copy_cost(&cost, &best_cost);
+     } while (force_irredundant);
+ 
+     return F;
+ }
+ 
+ /*
+     mv_reduce -- perform an "optimal" reduction of the variables which
+     we desire to be sparse
+ 
+     This could be done using "reduce" and then saving just the desired
+     part of the reduction.  Instead, this version uses IRRED to find
+     which cubes of an output are redundant.  Note that this gets around
+     the cube-ordering problem.
+ 
+     In normal use, it is expected that the cover is irredundant and
+     hence no cubes will be reduced to the empty cube (however, this is
+     checked for and such cubes will be deleted)
+ */
+ 
+ pcover
+ mv_reduce(F, D)
+ pcover F, D;
+ {
+     register int i, var;
+     register pcube p, p1, last;
+     int index;
+     pcover F1, D1;
+     pcube *F_cube_table;
+ 
+     /* loop for each multiple-valued variable */
+     for(var = 0; var < cube.num_vars; var++) {
+ 
+ 	if (cube.sparse[var]) {
+ 
+ 	    /* loop for each part of the variable */
+ 	    for(i = cube.first_part[var]; i <= cube.last_part[var]; i++) {
+ 
+ 		/* remember mapping of F1 cubes back to F cubes */
+ 		F_cube_table = ALLOC(pcube, F->count);
+ 
+ 		/* 'cofactor' against part #i of variable #var */
+ 		F1 = new_cover(F->count);
+ 		foreach_set(F, last, p) {
+ 		    if (is_in_set(p, i)) {
+ 			F_cube_table[F1->count] = p;
+ 			p1 = GETSET(F1, F1->count++);
+ 			(void) set_diff(p1, p, cube.var_mask[var]);
+ 			set_insert(p1, i);
+ 		    }
+ 		}
+ 
+ 		/* 'cofactor' against part #i of variable #var */
+ 		/* not really necessary -- just more efficient ? */
+ 		D1 = new_cover(D->count);
+ 		foreach_set(D, last, p) {
+ 		    if (is_in_set(p, i)) {
+ 			p1 = GETSET(D1, D1->count++);
+ 			(void) set_diff(p1, p, cube.var_mask[var]);
+ 			set_insert(p1, i);
+ 		    }
+ 		}
+ 
+ 		mark_irredundant(F1, D1);
+ 
+ 		/* now remove part i from cubes which are redundant */
+ 		index = 0;
+ 		foreach_set(F1, last, p1) {
+ 		    if (! TESTP(p1, ACTIVE)) {
+ 			p = F_cube_table[index];
+ 
+ 			/*   don't reduce a variable which is full
+ 			 *   (unless it is the output variable)
+ 			 */
+ 			if (var == cube.num_vars-1 ||
+ 			     ! setp_implies(cube.var_mask[var], p)) {
+ 			    set_remove(p, i);
+ 			}
+ 			RESET(p, PRIME);
+ 		    }
+ 		    index++;
+ 		}
+ 
+ 		free_cover(F1);
+ 		free_cover(D1);
+ 		FREE(F_cube_table);
+ 	    }
+ 	}
+     }
+ 
+     /* Check if any cubes disappeared */
+     (void) sf_active(F);
+     for(var = 0; var < cube.num_vars; var++) {
+ 	if (cube.sparse[var]) {
+ 	    foreach_active_set(F, last, p) {
+ 		if (setp_disjoint(p, cube.var_mask[var])) {
+ 		    RESET(p, ACTIVE);
+ 		    F->active_count--;
+ 		}
+ 	    }
+ 	}
+     }
+ 
+     if (F->count != F->active_count) {
+ 	F = sf_inactive(F);
+     }
+     return F;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sparse.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sparse.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sparse.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,126 ----
+ #ifndef SPARSE_H
+ #define SPARSE_H
+ 
+ /*
+  *  sparse.h -- sparse matrix package header file
+  */
+ 
+ typedef struct sm_element_struct sm_element;
+ typedef struct sm_row_struct sm_row;
+ typedef struct sm_col_struct sm_col;
+ typedef struct sm_matrix_struct sm_matrix;
+ 
+ 
+ /*
+  *  sparse matrix element
+  */
+ struct sm_element_struct {
+     int row_num;		/* row number of this element */
+     int col_num;		/* column number of this element */
+     sm_element *next_row;	/* next row in this column */
+     sm_element *prev_row;	/* previous row in this column */
+     sm_element *next_col;	/* next column in this row */
+     sm_element *prev_col;	/* previous column in this row */
+     char *user_word;		/* user-defined word */
+ };
+ 
+ 
+ /*
+  *  row header
+  */
+ struct sm_row_struct {
+     int row_num;		/* the row number */
+     int length;			/* number of elements in this row */
+     int flag;			/* user-defined word */
+     sm_element *first_col;	/* first element in this row */
+     sm_element *last_col;	/* last element in this row */
+     sm_row *next_row;		/* next row (in sm_matrix linked list) */
+     sm_row *prev_row;		/* previous row (in sm_matrix linked list) */
+     char *user_word;		/* user-defined word */
+ };
+ 
+ 
+ /*
+  *  column header
+  */
+ struct sm_col_struct {
+     int col_num;		/* the column number */
+     int length;			/* number of elements in this column */
+     int flag;			/* user-defined word */
+     sm_element *first_row;	/* first element in this column */
+     sm_element *last_row;	/* last element in this column */
+     sm_col *next_col;		/* next column (in sm_matrix linked list) */
+     sm_col *prev_col;		/* prev column (in sm_matrix linked list) */
+     char *user_word;		/* user-defined word */
+ };
+ 
+ 
+ /*
+  *  A sparse matrix
+  */
+ struct sm_matrix_struct {
+     sm_row **rows;		/* pointer to row headers (by row #) */
+     int rows_size;		/* alloc'ed size of above array */
+     sm_col **cols;		/* pointer to column headers (by col #) */
+     int cols_size;		/* alloc'ed size of above array */
+     sm_row *first_row;		/* first row (linked list of all rows) */
+     sm_row *last_row;		/* last row (linked list of all rows) */
+     int nrows;			/* number of rows */
+     sm_col *first_col;		/* first column (linked list of columns) */
+     sm_col *last_col;		/* last column (linked list of columns) */
+     int ncols;			/* number of columns */
+     char *user_word;		/* user-defined word */
+ };
+ 
+ 
+ #define sm_get_col(A, colnum)	\
+     (((colnum) >= 0 && (colnum) < (A)->cols_size) ? \
+ 	(A)->cols[colnum] : (sm_col *) 0)
+ 
+ #define sm_get_row(A, rownum)	\
+     (((rownum) >= 0 && (rownum) < (A)->rows_size) ? \
+ 	(A)->rows[rownum] : (sm_row *) 0)
+ 
+ #define sm_foreach_row(A, prow)	\
+ 	for(prow = A->first_row; prow != 0; prow = prow->next_row)
+ 
+ #define sm_foreach_col(A, pcol)	\
+ 	for(pcol = A->first_col; pcol != 0; pcol = pcol->next_col)
+ 
+ #define sm_foreach_row_element(prow, p)	\
+ 	for(p = prow->first_col; p != 0; p = p->next_col)
+ 
+ #define sm_foreach_col_element(pcol, p)	\
+ 	for(p = pcol->first_row; p != 0; p = p->next_row)
+ 
+ #define sm_put(x, val) \
+ 	(x->user_word = (char *) val)
+ 
+ #define sm_get(type, x) \
+ 	((type) (x->user_word))
+ 
+ extern sm_matrix *sm_alloc(), *sm_alloc_size(), *sm_dup();
+ extern void sm_free(), sm_delrow(), sm_delcol(), sm_resize();
+ extern void sm_write(), sm_print(), sm_dump(), sm_cleanup();
+ extern void sm_copy_row(), sm_copy_col();
+ extern void sm_remove(), sm_remove_element();
+ extern sm_element *sm_insert(), *sm_find();
+ extern sm_row *sm_longest_row();
+ extern sm_col *sm_longest_col();
+ extern int sm_read(), sm_read_compressed();
+ 
+ extern sm_row *sm_row_alloc(), *sm_row_dup(), *sm_row_and();
+ extern void sm_row_free(), sm_row_remove(), sm_row_print();
+ extern sm_element *sm_row_insert(), *sm_row_find();
+ extern int sm_row_contains(), sm_row_intersects();
+ extern int sm_row_compare(), sm_row_hash();
+ 
+ extern sm_col *sm_col_alloc(), *sm_col_dup(), *sm_col_and();
+ extern void sm_col_free(), sm_col_remove(), sm_col_print();
+ extern sm_element *sm_col_insert(), *sm_col_find();
+ extern int sm_col_contains(), sm_col_intersects();
+ extern int sm_col_compare(), sm_col_hash();
+ 
+ extern int sm_row_dominance(), sm_col_dominance(), sm_block_partition();
+ 
+ #endif


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sparse_int.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sparse_int.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/sparse_int.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,110 ----
+ #include "port.h"
+ #include "utility.h"
+ #include "sparse.h"
+ 
+ 
+ 
+ /*
+  *  sorted, double-linked list insertion
+  *
+  *  type: object type
+  *
+  *  first, last: fields (in header) to head and tail of the list
+  *  count: field (in header) of length of the list
+  *
+  *  next, prev: fields (in object) to link next and previous objects
+  *  value: field (in object) which controls the order
+  *
+  *  newval: value field for new object
+  *  e: an object to use if insertion needed (set to actual value used)
+  */
+ 
+ #define sorted_insert(type, first, last, count, next, prev, value, newval, e) \
+     if (last == 0) { \
+ 	e->value = newval; \
+ 	first = e; \
+ 	last = e; \
+ 	e->next = 0; \
+ 	e->prev = 0; \
+ 	count++; \
+     } else if (last->value < newval) { \
+ 	e->value = newval; \
+ 	last->next = e; \
+ 	e->prev = last; \
+ 	last = e; \
+ 	e->next = 0; \
+ 	count++; \
+     } else if (first->value > newval) { \
+ 	e->value = newval; \
+ 	first->prev = e; \
+ 	e->next = first; \
+ 	first = e; \
+ 	e->prev = 0; \
+ 	count++; \
+     } else { \
+ 	type *p; \
+ 	for(p = first; p->value < newval; p = p->next) \
+ 	    ; \
+ 	if (p->value > newval) { \
+ 	    e->value = newval; \
+ 	    p = p->prev; \
+ 	    p->next->prev = e; \
+ 	    e->next = p->next; \
+ 	    p->next = e; \
+ 	    e->prev = p; \
+ 	    count++; \
+ 	} else { \
+ 	    e = p; \
+ 	} \
+     }
+ 
+ 
+ /*
+  *  double linked-list deletion
+  */
+ #define dll_unlink(p, first, last, next, prev, count) { \
+     if (p->prev == 0) { \
+ 	first = p->next; \
+     } else { \
+ 	p->prev->next = p->next; \
+     } \
+     if (p->next == 0) { \
+ 	last = p->prev; \
+     } else { \
+ 	p->next->prev = p->prev; \
+     } \
+     count--; \
+ }
+ 
+ 
+ #ifdef FAST_AND_LOOSE
+ extern sm_element *sm_element_freelist;
+ extern sm_row *sm_row_freelist;
+ extern sm_col *sm_col_freelist;
+ 
+ #define sm_element_alloc(newobj) \
+     if (sm_element_freelist == NIL(sm_element)) { \
+ 	newobj = ALLOC(sm_element, 1); \
+     } else { \
+ 	newobj = sm_element_freelist; \
+ 	sm_element_freelist = sm_element_freelist->next_col; \
+     } \
+     newobj->user_word = NIL(char); \
+ 
+ #define sm_element_free(e) \
+     (e->next_col = sm_element_freelist, sm_element_freelist = e)
+ 
+ #else
+ 
+ #define sm_element_alloc(newobj)	\
+     newobj = ALLOC(sm_element, 1);	\
+     newobj->user_word = NIL(char);
+ #define sm_element_free(e)		\
+     FREE(e)
+ #endif
+ 
+ 
+ extern void sm_row_remove_element();
+ extern void sm_col_remove_element();
+ 
+ /* LINTLIBRARY */


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/stdlib.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/stdlib.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/stdlib.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,38 ----
+ /* ANSI Compatible stdlib.h stub */
+ 
+ #ifndef __cplusplus
+ 
+ #include <sys/types.h>
+ 
+ #ifndef ultrix4
+ extern double atof(const char *);
+ extern int atoi(const char *);
+ extern long atol(const char *);
+ extern void abort(void);
+ extern void *calloc(size_t, size_t);
+ extern void exit(int);
+ extern void free(void *);
+ extern void *malloc(size_t);
+ extern void *realloc(void *, size_t);
+ extern char *getenv(const char *);
+ #else
+ extern double atof(const char *);
+ extern int atoi(char *);
+ extern long atol(char *);
+ extern void abort(void);
+ extern void *calloc(size_t, size_t);
+ extern void exit(int);
+ extern void free(void *);
+ extern void *malloc(size_t);
+ extern void *realloc(void *, size_t);
+ extern char *getenv(char *);
+ #endif
+ 
+ /* should be in stdio.h */
+ extern void perror(const char *);
+ 
+ #ifdef LINT
+ #undef putc
+ #endif
+ 
+ #endif


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/unate.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/unate.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/unate.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,432 ----
+ /*
+  *  unate.c -- routines for dealing with unate functions
+  */
+ 
+ #include "espresso.h"
+ 
+ static pset_family abs_covered();
+ static pset_family abs_covered_many();
+ static int abs_select_restricted();
+ 
+ pcover map_cover_to_unate(T)
+ pcube *T;
+ {
+     register unsigned int word_test, word_set, bit_test, bit_set;
+     register pcube p, pA;
+     pset_family A;
+     pcube *T1;
+     int ncol, i;
+ 
+     A = sf_new(CUBELISTSIZE(T), cdata.vars_unate);
+     A->count = CUBELISTSIZE(T);
+     foreachi_set(A, i, p) {
+ 	(void) set_clear(p, A->sf_size);
+     }
+     ncol = 0;
+ 
+     for(i = 0; i < cube.size; i++) {
+ 	if (cdata.part_zeros[i] > 0) {
+ 	    assert(ncol <= cdata.vars_unate);
+ 
+ 	    /* Copy a column from T to A */
+ 	    word_test = WHICH_WORD(i);
+ 	    bit_test = 1 << WHICH_BIT(i);
+ 	    word_set = WHICH_WORD(ncol);
+ 	    bit_set = 1 << WHICH_BIT(ncol);
+ 
+ 	    pA = A->data;
+ 	    for(T1 = T+2; (p = *T1++) != 0; ) {
+ 		if ((p[word_test] & bit_test) == 0) {
+ 		    pA[word_set] |= bit_set;
+ 		}
+ 		pA += A->wsize;
+ 	    }
+ 
+ 	    ncol++;
+ 	}
+     }
+ 
+     return A;
+ }
+ 
+ pcover map_unate_to_cover(A)
+ pset_family A;
+ {
+     register int i, ncol, lp;
+     register pcube p, pB;
+     int var, nunate, *unate;
+     pcube last;
+     pset_family B;
+ 
+     B = sf_new(A->count, cube.size);
+     B->count = A->count;
+ 
+     /* Find the unate variables */
+     unate = ALLOC(int, cube.num_vars);
+     nunate = 0;
+     for(var = 0; var < cube.num_vars; var++) {
+ 	if (cdata.is_unate[var]) {
+ 	    unate[nunate++] = var;
+ 	}
+     }
+ 
+     /* Loop for each set of A */
+     pB = B->data;
+     foreach_set(A, last, p) {
+ 
+ 	/* Initialize this set of B */
+ 	INLINEset_fill(pB, cube.size);
+ 
+ 	/* Now loop for the unate variables; if the part is in A,
+ 	 * then this variable of B should be a single 1 in the unate
+ 	 * part.
+ 	 */
+ 	for(ncol = 0; ncol < nunate; ncol++) {
+ 	    if (is_in_set(p, ncol)) {
+ 		lp = cube.last_part[unate[ncol]];
+ 		for(i = cube.first_part[unate[ncol]]; i <= lp; i++) {
+ 		    if (cdata.part_zeros[i] == 0) {
+ 			set_remove(pB, i);
+ 		    }
+ 		}
+ 	    }
+ 	}
+ 	pB += B->wsize;
+     }
+ 
+     FREE(unate);
+     return B;
+ }
+ 
+ /*
+  *  unate_compl
+  */
+ 
+ pset_family unate_compl(A)
+ pset_family A;
+ {
+     register pset p, last;
+ 
+     /* Make sure A is single-cube containment minimal */
+ /*    A = sf_rev_contain(A);*/
+ 
+     foreach_set(A, last, p) {
+ 	PUTSIZE(p, set_ord(p));
+     }
+ 
+     /* Recursively find the complement */
+     A = unate_complement(A);
+ 
+     /* Now, we can guarantee a minimal result by containing the result */
+     A = sf_rev_contain(A);
+     return A;
+ }
+ 
+ 
+ /*
+  *  Assume SIZE(p) records the size of each set
+  */
+ pset_family unate_complement(A)
+ pset_family A;			/* disposes of A */
+ {
+     pset_family Abar;
+     register pset p, p1, restrict;
+     register int i;
+     int max_i, min_set_ord, j;
+ 
+     /* Check for no sets in the matrix -- complement is the universe */
+     if (A->count == 0) {
+ 	sf_free(A);
+ 	Abar = sf_new(1, A->sf_size);
+ 	(void) set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+ 
+     /* Check for a single set in the maxtrix -- compute de Morgan complement */
+     } else if (A->count == 1) {
+ 	p = A->data;
+ 	Abar = sf_new(A->sf_size, A->sf_size);
+ 	for(i = 0; i < A->sf_size; i++) {
+ 	    if (is_in_set(p, i)) {
+ 		p1 = set_clear(GETSET(Abar, Abar->count++), A->sf_size);
+ 		set_insert(p1, i);
+ 	    }
+ 	}
+ 	sf_free(A);
+ 
+     } else {
+ 
+ 	/* Select splitting variable as the variable which belongs to a set
+ 	 * of the smallest size, and which has greatest column count
+ 	 */
+ 	restrict = set_new(A->sf_size);
+ 	min_set_ord = A->sf_size + 1;
+ 	foreachi_set(A, i, p) {
+ 	    if (SIZE(p) < min_set_ord) {
+ 		set_copy(restrict, p);
+ 		min_set_ord = SIZE(p);
+ 	    } else if (SIZE(p) == min_set_ord) {
+ 		set_or(restrict, restrict, p);
+ 	    }
+ 	}
+ 
+ 	/* Check for no data (shouldn't happen ?) */
+ 	if (min_set_ord == 0) {
+ 	    A->count = 0;
+ 	    Abar = A;
+ 
+ 	/* Check for "essential" columns */
+ 	} else if (min_set_ord == 1) {
+ 	    Abar = unate_complement(abs_covered_many(A, restrict));
+ 	    sf_free(A);
+ 	    foreachi_set(Abar, i, p) {
+ 		set_or(p, p, restrict);
+ 	    }
+ 
+ 	/* else, recur as usual */
+ 	} else {
+ 	    max_i = abs_select_restricted(A, restrict);
+ 
+ 	    /* Select those rows of A which are not covered by max_i,
+ 	     * recursively find all minimal covers of these rows, and
+ 	     * then add back in max_i
+ 	     */
+ 	    Abar = unate_complement(abs_covered(A, max_i));
+ 	    foreachi_set(Abar, i, p) {
+ 		set_insert(p, max_i);
+ 	    }
+ 
+ 	    /* Now recur on A with all zero's on column max_i */
+ 	    foreachi_set(A, i, p) {
+ 		if (is_in_set(p, max_i)) {
+ 		    set_remove(p, max_i);
+ 		    j = SIZE(p) - 1;
+ 		    PUTSIZE(p, j);
+ 		}
+ 	    }
+ 
+ 	    Abar = sf_append(Abar, unate_complement(A));
+ 	}
+ 	set_free(restrict);
+     }
+ 
+     return Abar;
+ }
+ 
+ pset_family exact_minimum_cover(T)
+ IN pset_family T;
+ {
+     register pset p, last, p1;
+     register int i, n;
+     int lev, lvl;
+     pset nlast;
+     pset_family temp;
+     long start = ptime();
+     struct {
+ 	pset_family sf;
+ 	int level;
+     } stack[32];                /* 32 suffices for 2 ** 32 cubes ! */
+ 
+     if (T->count <= 0)
+ 	return sf_new(1, T->sf_size);
+     for(n = T->count, lev = 0; n != 0; n >>= 1, lev++)   ;
+ 
+     /* A simple heuristic ordering */
+     T = lex_sort(sf_save(T));
+ 
+     /* Push a full set on the stack to get things started */
+     n = 1;
+     stack[0].sf = sf_new(1, T->sf_size);
+     stack[0].level = lev;
+     set_fill(GETSET(stack[0].sf, stack[0].sf->count++), T->sf_size);
+ 
+     nlast = GETSET(T, T->count - 1);
+     foreach_set(T, last, p) {
+ 
+ 	/* "unstack" the set into a family */
+ 	temp = sf_new(set_ord(p), T->sf_size);
+ 	for(i = 0; i < T->sf_size; i++)
+ 	    if (is_in_set(p, i)) {
+ 		p1 = set_fill(GETSET(temp, temp->count++), T->sf_size);
+ 		set_remove(p1, i);
+ 	    }
+ 	stack[n].sf = temp;
+ 	stack[n++].level = lev;
+ 
+ 	/* Pop the stack and perform (leveled) intersections */
+ 	while (n > 1 && (stack[n-1].level==stack[n-2].level || p == nlast)) {
+ 	    temp = unate_intersect(stack[n-1].sf, stack[n-2].sf, FALSE);
+ 	    lvl = MIN(stack[n-1].level, stack[n-2].level) - 1;
+ 	    if (debug & MINCOV && lvl < 10) {
+ 		printf("# EXACT_MINCOV[%d]: %4d = %4d x %4d, time = %s\n",
+ 		    lvl, temp->count, stack[n-1].sf->count,
+ 		    stack[n-2].sf->count, print_time(ptime() - start));
+ 		(void) fflush(stdout);
+ 	    }
+ 	    sf_free(stack[n-2].sf);
+ 	    sf_free(stack[n-1].sf);
+ 	    stack[n-2].sf = temp;
+ 	    stack[n-2].level = lvl;
+ 	    n--;
+ 	}
+     }
+ 
+     temp = stack[0].sf;
+     p1 = set_fill(set_new(T->sf_size), T->sf_size);
+     foreach_set(temp, last, p)
+ 	INLINEset_diff(p, p1, p);
+     set_free(p1);
+     if (debug & MINCOV1) {
+ 	printf("MINCOV: family of all minimal coverings is\n");
+ 	sf_print(temp);
+     }
+     sf_free(T);         /* this is the copy of T we made ... */
+     return temp;
+ }
+ 
+ /*
+  *  unate_intersect -- intersect two unate covers
+  *
+  *  If largest_only is TRUE, then only the largest cube(s) are returned
+  */
+ 
+ #define MAGIC 500               /* save 500 cubes before containment */
+ 
+ pset_family unate_intersect(A, B, largest_only)
+ pset_family A, B;
+ bool largest_only;
+ {
+     register pset pi, pj, lasti, lastj, pt;
+     pset_family T, Tsave;
+     bool save;
+     int maxord, ord;
+ 
+     /* How large should each temporary result cover be ? */
+     T = sf_new(MAGIC, A->sf_size);
+     Tsave = NULL;
+     maxord = 0;
+     pt = T->data;
+ 
+     /* Form pairwise intersection of each set of A with each cube of B */
+     foreach_set(A, lasti, pi) {
+ 
+ 	foreach_set(B, lastj, pj) {
+ 
+ 	    save = set_andp(pt, pi, pj);
+ 
+ 	    /* Check if we want the largest only */
+ 	    if (save && largest_only) {
+ 		if ((ord = set_ord(pt)) > maxord) {
+ 		    /* discard Tsave and T */
+ 		    if (Tsave != NULL) {
+ 			sf_free(Tsave);
+ 			Tsave = NULL;
+ 		    }
+ 		    pt = T->data;
+ 		    T->count = 0;
+ 		    /* Re-create pt (which was just thrown away) */
+ 		    (void) set_and(pt, pi, pj);
+ 		    maxord = ord;
+ 		} else if (ord < maxord) {
+ 		    save = FALSE;
+ 		}
+ 	    }
+ 
+ 	    if (save) {
+ 		if (++T->count >= T->capacity) {
+ 		    T = sf_contain(T);
+ 		    Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+ 		    T = sf_new(MAGIC, A->sf_size);
+ 		    pt = T->data;
+ 		} else {
+ 		    pt += T->wsize;
+ 		}
+ 	    }
+ 	}
+     }
+ 
+ 
+     /* Contain the final result and merge it into Tsave */
+     T = sf_contain(T);
+     Tsave = (Tsave == NULL) ? T : sf_union(Tsave, T);
+ 
+     return Tsave;
+ }
+ 
+ /*
+  *  abs_covered -- after selecting a new column for the selected set,
+  *  create a new matrix which is only those rows which are still uncovered
+  */
+ static pset_family
+ abs_covered(A, pick)
+ pset_family A;
+ register int pick;
+ {
+     register pset last, p, pdest;
+     register pset_family Aprime;
+ 
+     Aprime = sf_new(A->count, A->sf_size);
+     pdest = Aprime->data;
+     foreach_set(A, last, p)
+ 	if (! is_in_set(p, pick)) {
+ 	    INLINEset_copy(pdest, p);
+ 	    Aprime->count++;
+ 	    pdest += Aprime->wsize;
+ 	}
+     return Aprime;
+ }
+ 
+ 
+ /*
+  *  abs_covered_many -- after selecting many columns for ther selected set,
+  *  create a new matrix which is only those rows which are still uncovered
+  */
+ static pset_family
+ abs_covered_many(A, pick_set)
+ pset_family A;
+ register pset pick_set;
+ {
+     register pset last, p, pdest;
+     register pset_family Aprime;
+ 
+     Aprime = sf_new(A->count, A->sf_size);
+     pdest = Aprime->data;
+     foreach_set(A, last, p)
+ 	if (setp_disjoint(p, pick_set)) {
+ 	    INLINEset_copy(pdest, p);
+ 	    Aprime->count++;
+ 	    pdest += Aprime->wsize;
+ 	}
+     return Aprime;
+ }
+ 
+ 
+ /*
+  *  abs_select_restricted -- select the column of maximum column count which
+  *  also belongs to the set "restrict"; weight each column of a set as
+  *  1 / (set_ord(p) - 1).
+  */
+ static int
+ abs_select_restricted(A, restrict)
+ pset_family A;
+ pset restrict;
+ {
+     register int i, best_var, best_count, *count;
+ 
+     /* Sum the elements in these columns */
+     count = sf_count_restricted(A, restrict);
+ 
+     /* Find which variable has maximum weight */
+     best_var = -1;
+     best_count = 0;
+     for(i = 0; i < A->sf_size; i++) {
+ 	if (count[i] > best_count) {
+ 	    best_var = i;
+ 	    best_count = count[i];
+ 	}
+     }
+     FREE(count);
+ 
+     if (best_var == -1)
+ 	fatal("abs_select_restricted: should not have best_var == -1");
+ 
+     return best_var;
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/utility.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/utility.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/utility.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,141 ----
+ /* LINTLIBRARY */
+ #include "copyright.h"
+ #include "port.h"
+ #include "utility.h"
+ 
+ #ifdef IBM_WATC		/* IBM Waterloo-C compiler (same as bsd 4.2) */
+ #ifndef BSD
+ #define BSD
+ #endif
+ #ifndef void
+ #define void int
+ #endif
+ #endif
+ 
+ #ifdef ultrix
+ #ifndef BSD
+ #define BSD
+ #endif
+ #endif
+ 
+ #ifdef hpux
+ #ifndef UNIX50
+ #define UNIX50
+ #endif
+ #endif
+ 
+ #ifdef aiws
+ #ifndef UNIX10
+ #define UNIX10
+ #endif
+ #endif
+ 
+ #ifdef vms		/* VAX/C compiler -- times() with 100 HZ clock */
+ #ifndef UNIX100
+ #define UNIX100
+ #endif
+ #endif
+ 
+ /* default */
+ #if !defined(BSD) && !defined(UNIX10) && !defined(UNIX60) && !defined(UNIX100) && !defined(UNIX50)
+ #define BSD
+ #endif
+ 
+ #ifdef BSD
+ #include <sys/time.h>
+ #include <sys/resource.h>
+ #endif
+ 
+ #ifdef UNIX10
+ #include <sys/times.h>
+ #endif
+ 
+ #ifdef UNIX50
+ #include <sys/times.h>
+ #endif
+ 
+ #ifdef UNIX60
+ #include <sys/times.h>
+ #endif
+ 
+ #ifdef UNIX100
+ #include <sys/times.h>
+ #endif
+ 
+ 
+ /*
+  *   util_cpu_time -- return a long which represents the elapsed processor
+  *   time in milliseconds since some constant reference
+  */
+ long 
+ util_cpu_time()
+ {
+     long t = 0;
+ 
+ #ifdef BSD
+     struct rusage rusage;
+     (void) getrusage(RUSAGE_SELF, &rusage);
+     t = (long) rusage.ru_utime.tv_sec*1000 + rusage.ru_utime.tv_usec/1000;
+ #endif
+ 
+ #ifdef IBMPC
+     long ltime;
+     (void) time(&ltime);
+     t = ltime * 1000;
+ #endif
+ 
+ #ifdef UNIX10			/* times() with 10 Hz resolution */
+     struct tms buffer;
+     (void) times(&buffer);
+     t = buffer.tms_utime * 100;
+ #endif
+ 
+ #ifdef UNIX50			/* times() with 50 Hz resolution */
+     struct tms buffer;
+     times(&buffer);
+     t = buffer.tms_utime * 20;
+ #endif
+ 
+ #ifdef UNIX60			/* times() with 60 Hz resolution */
+     struct tms buffer;
+     times(&buffer);
+     t = buffer.tms_utime * 16.6667;
+ #endif
+ 
+ #ifdef UNIX100
+     struct tms buffer;		/* times() with 100 Hz resolution */
+     times(&buffer);
+     t = buffer.tms_utime * 10;
+ #endif
+ 
+     return t;
+ }
+ 
+ 
+ /*
+  *  util_print_time -- massage a long which represents a time interval in
+  *  milliseconds, into a string suitable for output 
+  *
+  *  Hack for IBM/PC -- avoids using floating point
+  */
+ 
+ char *
+ util_print_time(t)
+ long t;
+ {
+     static char s[40];
+ 
+     (void) sprintf(s, "%ld.%02ld sec", t/1000, (t%1000)/10);
+     return s;
+ }
+ 
+ 
+ /*
+  *  util_strsav -- save a copy of a string
+  */
+ char *
+ util_strsav(s)
+ char *s;
+ {
+     return strcpy(ALLOC(char, strlen(s)+1), s);
+ }


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/utility.h
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/utility.h:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/utility.h	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,80 ----
+ #ifndef UTILITY_H
+ #define UTILITY_H
+ 
+ /*
+  *  assumes the memory manager is libmm.a
+  *	- allows malloc(0) or realloc(obj, 0)
+  *	- catches out of memory (and calls MMout_of_memory())
+  *	- catch free(0) and realloc(0, size) in the macros
+  */
+ #define NIL(type)		((type *) 0)
+ 
+ #ifdef BWGC 
+ #define ALLOC(type, num)	\
+     ((type *) gc_malloc(sizeof(type) * ((num)==0?1:(num))))
+ #define REALLOC(type, obj, num)	\
+     (obj) ? ((type *) gc_realloc((char *) obj, sizeof(type) * ((num)==0?1:(num)))) : \
+ 	    ((type *) gc_malloc(sizeof(type) * ((num)==0?1:(num))))
+ #else
+ #define ALLOC(type, num)	\
+     ((type *) malloc(sizeof(type) * (num)))
+ #define REALLOC(type, obj, num)	\
+     (obj) ? ((type *) realloc((char *) obj, sizeof(type) * (num))) : \
+ 	    ((type *) malloc(sizeof(type) * (num)))
+ #endif BWGC
+ 
+ #ifdef IGNOREFREE
+ #define FREE(obj)		\
+     {};
+ #else
+ #define FREE(obj)		\
+     if ((obj)) { (void) free((char *) (obj)); (obj) = 0; }
+ #endif IGNOREFREE
+ 
+ #include "ansi.h"
+ 
+ EXTERN long  util_cpu_time
+ 	NULLARGS;
+ EXTERN char *util_path_search
+ 	ARGS((char *program));
+ EXTERN char *util_file_search
+ 	ARGS((char *file, char *path, char *mode));
+ EXTERN int   util_pipefork
+ 	ARGS((char **argv, FILE **toCommand, FILE **fromCommand, int *pid));
+ EXTERN int   util_csystem
+ 	ARGS((char *command));
+ EXTERN char *util_print_time
+ 	ARGS((long t));
+ EXTERN char *util_strsav
+ 	ARGS((char *ptr));
+ EXTERN char *util_tilde_expand
+ 	ARGS((char *filename));
+ EXTERN char *util_tilde_compress
+ 	ARGS((char *filename));
+ EXTERN void util_register_user
+ 	ARGS((char *user, char *directory));
+ 
+ #ifndef NIL_FN
+ #define NIL_FN(type) ((type (*)()) 0)
+ #endif /* NIL_FN */
+ 
+ #ifndef MAX
+ #define MAX(a,b)	((a) > (b) ? (a) : (b))
+ #endif /* MAX */
+ #ifndef MIN
+ #define MIN(a,b)	((a) < (b) ? (a) : (b))
+ #endif /* MIN */
+ #ifndef ABS
+ #define ABS(a)		((a) > 0 ? (a) : -(a))
+ #endif /* ABS */
+ 
+ 
+ #ifdef lint
+ #undef ALLOC			/* allow for lint -h flag */
+ #undef REALLOC
+ #define ALLOC(type, num)	(((type *) 0) + (num))
+ #define REALLOC(type, obj, num)	((obj) + (num))
+ #endif /* lint */
+ 
+ #endif
+ 


Index: llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/verify.c
diff -c /dev/null llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/verify.c:1.1.2.1
*** /dev/null	Mon Mar  1 17:59:21 2004
--- llvm/test/Programs/MultiSource/Benchmarks/MallocBench/espresso/verify.c	Mon Mar  1 17:59:10 2004
***************
*** 0 ****
--- 1,184 ----
+ /*
+  */
+ 
+ #include "espresso.h"
+ 
+ /*
+  *  verify -- check that all minterms of F are contained in (Fold u Dold)
+  *  and that all minterms of Fold are contained in (F u Dold).
+  */
+ bool verify(F, Fold, Dold)
+ pcover F, Fold, Dold;
+ {
+     pcube p, last, *FD;
+     bool verify_error = FALSE;
+ 
+     /* Make sure the function didn't grow too large */
+     FD = cube2list(Fold, Dold);
+     foreach_set(F, last, p)
+ 	if (! cube_is_covered(FD, p)) {
+ 	    printf("some minterm in F is not covered by Fold u Dold\n");
+ 	    verify_error = TRUE;
+ 	    if (verbose_debug) printf("%s\n", pc1(p)); else break;
+ 	}
+     free_cubelist(FD);
+ 
+     /* Make sure minimized function covers the original function */
+     FD = cube2list(F, Dold);
+     foreach_set(Fold, last, p)
+ 	if (! cube_is_covered(FD, p)) {
+ 	    printf("some minterm in Fold is not covered by F u Dold\n");
+ 	    verify_error = TRUE;
+ 	    if (verbose_debug) printf("%s\n", pc1(p)); else break;
+ 	}
+     free_cubelist(FD);
+ 
+     return verify_error;
+ }
+ 
+ 
+ 
+ /*
+  *  PLA_verify -- verify that two PLA's are identical
+  *
+  *  If names are given, row and column permutations are done to make
+  *  the comparison meaningful.
+  *
+  */
+ bool PLA_verify(PLA1, PLA2)
+ pPLA PLA1, PLA2;
+ {
+     /* Check if both have names given; if so, attempt to permute to
+      * match the names
+      */
+     if (PLA1->label != NULL && PLA1->label[0] != NULL &&
+ 	   PLA2->label != NULL && PLA2->label[0] != NULL) {
+ 	PLA_permute(PLA1, PLA2);
+     } else {
+ 	fprintf(stderr, "Warning: cannot permute columns without names\n");
+ 	return TRUE;
+     }
+ 
+     if (PLA1->F->sf_size != PLA2->F->sf_size) {
+ 	fprintf(stderr, "PLA_verify: PLA's are not the same size\n");
+ 	return TRUE;
+     }
+ 
+     return verify(PLA2->F, PLA1->F, PLA1->D);
+ }
+ 
+ 
+ 
+ /*
+  *  Permute the columns of PLA1 so that they match the order of PLA2
+  *  Discard any columns of PLA1 which are not in PLA2
+  *  Association is strictly by the names of the columns of the cover.
+  */
+ PLA_permute(PLA1, PLA2)
+ pPLA PLA1, PLA2;
+ {
+     register int i, j, *permute, npermute;
+     register char *labi;
+     char **label;
+ 
+     /* determine which columns of PLA1 to save, and place these in the list
+      * "permute"; the order in this list is the final output order
+      */
+     npermute = 0;
+     permute = ALLOC(int, PLA2->F->sf_size);
+     for(i = 0; i < PLA2->F->sf_size; i++) {
+ 	labi = PLA2->label[i];
+ 	for(j = 0; j < PLA1->F->sf_size; j++) {
+ 	    if (strcmp(labi, PLA1->label[j]) == 0) {
+ 		permute[npermute++] = j;
+ 		break;
+ 	    }
+ 	}
+     }
+ 
+     /* permute columns */
+     if (PLA1->F != NULL) {
+ 	PLA1->F = sf_permute(PLA1->F, permute, npermute);
+     }
+     if (PLA1->R != NULL) {
+ 	PLA1->R = sf_permute(PLA1->R, permute, npermute);
+     }
+     if (PLA1->D != NULL) {
+ 	PLA1->D = sf_permute(PLA1->D, permute, npermute);
+     }
+ 
+     /* permute the labels */
+     label = ALLOC(char *, cube.size);
+     for(i = 0; i < npermute; i++) {
+ 	label[i] = PLA1->label[permute[i]];
+     }
+     for(i = npermute; i < cube.size; i++) {
+ 	label[i] = NULL;
+     }
+     FREE(PLA1->label);
+     PLA1->label = label;
+ 
+     FREE(permute);
+ }
+ 
+ 
+ 
+ /*
+  *  check_consistency -- test that the ON-set, OFF-set and DC-set form
+  *  a partition of the boolean space.
+  */
+ bool check_consistency(PLA)
+ pPLA PLA;
+ {
+     bool verify_error = FALSE;
+     pcover T;
+ 
+     T = cv_intersect(PLA->F, PLA->D);
+     if (T->count == 0)
+ 	printf("ON-SET and DC-SET are disjoint\n");
+     else {
+ 	printf("Some minterm(s) belong to both the ON-SET and DC-SET !\n");
+ 	if (verbose_debug)
+ 	    cprint(T);
+ 	verify_error = TRUE;
+     }
+     (void) fflush(stdout);
+     free_cover(T);
+ 
+     T = cv_intersect(PLA->F, PLA->R);
+     if (T->count == 0)
+ 	printf("ON-SET and OFF-SET are disjoint\n");
+     else {
+ 	printf("Some minterm(s) belong to both the ON-SET and OFF-SET !\n");
+ 	if (verbose_debug)
+ 	    cprint(T);
+ 	verify_error = TRUE;
+     }
+     (void) fflush(stdout);
+     free_cover(T);
+ 
+     T = cv_intersect(PLA->D, PLA->R);
+     if (T->count == 0)
+ 	printf("DC-SET and OFF-SET are disjoint\n");
+     else {
+ 	printf("Some minterm(s) belong to both the OFF-SET and DC-SET !\n");
+ 	if (verbose_debug)
+ 	    cprint(T);
+ 	verify_error = TRUE;
+     }
+     (void) fflush(stdout);
+     free_cover(T);
+ 
+     if (tautology(cube3list(PLA->F, PLA->D, PLA->R)))
+ 	printf("Union of ON-SET, OFF-SET and DC-SET is the universe\n");
+     else {
+ 	T = complement(cube3list(PLA->F, PLA->D, PLA->R));
+ 	printf("There are minterms left unspecified !\n");
+ 	if (verbose_debug)
+ 	    cprint(T);
+ 	verify_error = TRUE;
+ 	free_cover(T);
+     }
+     (void) fflush(stdout);
+     return verify_error;
+ }





More information about the llvm-commits mailing list