--- uae/src/gengenblitter.c 2018/04/24 16:38:58 1.1.1.1 +++ uae/src/gengenblitter.c 2018/04/24 16:48:35 1.1.1.3 @@ -1,11 +1,11 @@ - /* + /* * UAE - The Un*x Amiga Emulator - * + * * Optimized blitter minterm function generator - * + * * Copyright 1995,1996 Bernd Schmidt * Copyright 1996 Alessandro Bissacco - * + * * Overkill, n: cf. genblitter */ @@ -17,76 +17,27 @@ static void nop(int); -#if 0 -typedef struct alloc_hdr -{ - int size; - struct alloc_hdr *next, *prev; - void *from, *from2; -} *ahead; - -static struct alloc_hdr ah_top = { 0, &ah_top, &ah_top, 0, 0 }; - -int nbytesmalloced = 0; -int malloc_cnt = 0; - -static void *xmalloc(int sz) -{ - ahead mem = (ahead)malloc(sz + sizeof(struct alloc_hdr)); - mem->size = sz; - mem->next = &ah_top; - mem->prev = ah_top.prev; - ah_top.prev->next = mem; - ah_top.prev = mem; - - mem->from = __builtin_return_address(0); - mem->from2 = __builtin_return_address(1); - - malloc_cnt++; - nbytesmalloced += sz; - - return mem + 1; -} - -static void *xrealloc(void *mem, int sz) -{ - if (mem == NULL) - return xmalloc(sz); - else { - ahead m = (ahead)mem; - m--; - - nbytesmalloced += sz - m->size; - m->size = sz; - return ((ahead)realloc(m, sz + sizeof(struct alloc_hdr))) + 1; - } -} - -static void xfree(void *mem) -{ - ahead m = (ahead)mem; - - m--; - - m->next->prev = m->prev; - m->prev->next = m->next; - nbytesmalloced -= m->size; - malloc_cnt--; - free(m); -} -#else #define xmalloc malloc #define xfree free #define xrealloc realloc -#endif typedef struct tree_n { - enum tree_op { op_and, op_or, op_xor, op_not, op_a, op_b, op_c } op; + enum tree_op { op_and, op_or, op_xor, op_not, op_a, op_b, op_c, op_d, op_e, op_f } op; struct tree_n *left, *right; } *tree; -static struct tree_n TRA = { op_a, NULL, NULL }, TRB = { op_b, NULL, NULL }, TRC = { op_c, NULL, NULL }; -static tree tree_a = &TRA, tree_b = &TRB, tree_c = &TRC; +static struct tree_n TRA = { op_a, NULL, NULL }; +static struct tree_n TRB = { op_b, NULL, NULL }; +static struct tree_n TRC = { op_c, NULL, NULL }; +static struct tree_n TRD = { op_d, NULL, NULL }; +static struct tree_n TRE = { op_e, NULL, NULL }; +static struct tree_n TRF = { op_f, NULL, NULL }; +static tree tree_a = &TRA; +static tree tree_b = &TRB; +static tree tree_c = &TRC; +static tree tree_d = &TRD; +static tree tree_e = &TRE; +static tree tree_f = &TRF; typedef struct { tree *trees; @@ -94,30 +45,9 @@ typedef struct { int ntrees; } tree_vec; -static tree best_tree, main_tree; -static int best_cost = 65535; - -static void kill_tree(tree *t) -{ - if (*t != NULL && *t != tree_a && *t != tree_b && *t != tree_c) { - if ((*t)->left) kill_tree(&(*t)->left); - if ((*t)->right) kill_tree(&(*t)->right); - xfree(*t); - } - *t = NULL; -} - -static tree dup_tree(tree t) +STATIC_INLINE int issrc (tree t) { - if (t == NULL || t == tree_a || t == tree_b || t == tree_c) - return t; - else { - tree nt = (tree)xmalloc(sizeof(struct tree_n)); - nt->op = t->op; - nt->left = dup_tree(t->left); - nt->right = dup_tree(t->right); - return nt; - } + return t == tree_a || t == tree_b || t == tree_c || t == tree_d || t == tree_e || t == tree_f; } static tree new_op_tree(enum tree_op op, tree l, tree r) @@ -135,195 +65,79 @@ static tree new_op_tree(enum tree_op op, return t; } -static int tree_cst(tree t, int *nota, int *notb, int *notc) +static int opidx (tree t) { - switch(t->op) { + switch (t->op) { case op_a: + return 0; case op_b: + return 1; case op_c: + return 2; + case op_d: + return 3; + case op_e: + return 4; + case op_f: + return 5; + default: + return -1; + } +} + +static int tree_cst (tree t, unsigned int *src, unsigned int *notsrc) +{ + int idx = opidx (t); + if (idx >= 0) { + src[idx] = 1; return 0; + } + switch (t->op) { case op_not: - switch (t->left->op) { - case op_a: - if (*nota) - return 0; - *nota = 1; - return 4; - - case op_b: - if (*notb) - return 0; - *notb = 1; - return 4; - - case op_c: - if (*notc) - return 0; - *notc = 1; - return 4; -#if 0 - case op_not: - return tree_cst(t->left->left, nota, notb, notc); -#endif - default: - break; + idx = opidx (t->left); + if (idx >= 0) { + notsrc[idx] = 1; + return 3; } - return 3 + tree_cst(t->left, nota, notb, notc); + return 3 + tree_cst (t->left, src, notsrc); case op_and: case op_xor: case op_or: - return 3 + tree_cst(t->left, nota, notb, notc) + tree_cst(t->right, nota, notb, notc); - } - return 0; -} - -static int tree_cost(tree t) -{ - int a = 0,b = 0,c = 0; - - return tree_cst(t,&a,&b,&c); -} - -static int eval(tree t) -{ - int v = tree_cost(t); - if (v < best_cost) { - best_cost = v; - if (best_tree != NULL) - kill_tree(&best_tree); - best_tree = dup_tree(t); - } - return v; -} - -static int tree_equal(tree a, tree b) -{ - unsigned long mask = 0; - int i; - tree t2, t3; - - if (a == b) - return 1; - if (a->op != b->op) - return 0; - if (a->op == op_not) - return tree_equal(a->left, b->left); - - if (a->op != op_xor && a->op != op_or && a->op != op_and) - return 0; - - if (tree_equal(a->left, b->left)) - return tree_equal(a->right, b->right); - - for (i = 0, t2 = a; t2->op == a->op; t2 = t2->right, i++) - ; - for (t3 = b; t3->op == b->op; t3 = t3->right, i--) - ; - - if (i != 0) - return 0; - - t2 = a; - for (;;) { - tree ttmp; - tree t3; - - if (t2->op == a->op) - ttmp = t2->left; - else - ttmp = t2; - - t3 = b; - for (i = 0;; i++) { - tree ttmp2; - - if (t3->op == b->op) - ttmp2 = t3->left; - else - ttmp2 = t3; - - if ((mask & (1 << i)) == 0 && tree_equal(ttmp, ttmp2)) { - mask |= 1 << i; - break; - } - - if (t3->op != b->op) - return 0; - - t3 = t3->right; - } + return 4 + tree_cst (t->left, src, notsrc) + tree_cst (t->right, src, notsrc); - if (t2->op != a->op) - break; - - t2 = t2->right; + default: + abort (); } - return 1; -} - -static int tree_isnormal(tree t) -{ - if ((t->op == op_xor || t->op == op_and || t->op == op_or) - && t->left->op == t->op) - return 0; - return 1; } -static void normalize(tree *t) +static int tree_cost (tree t) { - if (*t == NULL) - return; + int i, cost; + unsigned int src[6], notsrc[6]; + memset (src, 0, sizeof src); + memset (notsrc, 0, sizeof notsrc); - if ((*t)->op == op_not && (*t)->left->op == op_not) { - tree t2 = (*t)->left->left; - xfree((*t)->left); - xfree(*t); - *t = t2; - } - - while (((*t)->op == op_xor || (*t)->op == op_and || (*t)->op == op_or) - && (*t)->left->op == (*t)->op) - { - tree tmp = (*t)->left->left; - (*t)->left->left = (*t)->left->right; - (*t)->left->right = (*t)->right; - (*t)->right = (*t)->left; - (*t)->left = tmp; - } - normalize(&(*t)->left); - normalize(&(*t)->right); + cost = tree_cst (t, src, notsrc); + for (i = 0; i < 6; i++) + if (src[i] && notsrc[i]) + cost++; + return cost; } -static void add_vec(tree_vec *tv, tree t) +static int add_vec(tree_vec *tv, tree t) { - if (!tree_isnormal(t)) + int i; +#if 0 + if (! tree_isnormal(t)) nop(2); - - if (tv == NULL) { - eval(t); - kill_tree(&t); - } else { - int i; - for (i = 0; i < tv->ntrees; i++) - if (tree_equal(tv->trees[i], t)) { - kill_tree(&t); - return; - } - - if (tv->ntrees == tv->space) { - tv->trees = (tree *)xrealloc(tv->trees, sizeof(tree)*(tv->space += 40)); - } - tv->trees[tv->ntrees++] = t; +#endif + if (tv->ntrees == tv->space) { + tv->trees = (tree *)xrealloc(tv->trees, sizeof(tree)*(tv->space += 40)); } -} + tv->trees[tv->ntrees++] = t; -static void kill_vec(tree_vec *tv) -{ - int i; - for (i = 0; i < tv->ntrees; i++) - kill_tree(tv->trees + i); - xfree(tv->trees); + return 1; } static void init_vec(tree_vec *tv) @@ -332,598 +146,234 @@ static void init_vec(tree_vec *tv) tv->trees = NULL; } -static void do_sprint_tree(char *s, tree *t) +static void do_sprint_tree (char *s, tree t) { - switch ((*t)->op) { + enum tree_op op = t->op; + switch (op) { case op_a: - strcat(s, "srca"); + strcat (s, "srca"); break; case op_b: - strcat(s, "srcb"); + strcat (s, "srcb"); break; case op_c: - strcat(s, "srcc"); + strcat (s, "srcc"); break; - - case op_and: - strcat(s, "("); - do_sprint_tree(s, &(*t)->left); - strcat(s, " & "); - while ((*t)->right->op == op_and) { - t = &(*t)->right; - do_sprint_tree(s, &(*t)->left); - strcat(s, " & "); - } - do_sprint_tree(s, &(*t)->right); - strcat(s, ")"); + case op_d: + strcat (s, "srcd"); break; - - case op_or: - strcat(s, "("); - do_sprint_tree(s, &(*t)->left); - strcat(s, " | "); - while ((*t)->right->op == op_or) { - t = &(*t)->right; - do_sprint_tree(s, &(*t)->left); - strcat(s, " | "); - } - do_sprint_tree(s, &(*t)->right); - strcat(s, ")"); + case op_e: + strcat (s, "srce"); break; - + case op_f: + strcat (s, "srcf"); + break; + + case op_and: + case op_or: case op_xor: - strcat(s, "("); - do_sprint_tree(s, &(*t)->left); - strcat(s, " ^ "); - while ((*t)->right->op == op_xor) { - t = &(*t)->right; - do_sprint_tree(s, &(*t)->left); - strcat(s, " ^ "); + { + + char *c = op == op_and ? " & " : op == op_or ? " | " : " ^ "; + strcat (s, "("); + do_sprint_tree (s, t->left); + strcat (s, c); + while (t->right->op == op) { + t = t->right; + do_sprint_tree (s, t->left); + strcat (s, c); + } + do_sprint_tree(s, t->right); + strcat (s, ")"); } - do_sprint_tree(s, &(*t)->right); - strcat(s, ")"); break; - + case op_not: - strcat(s, "~"); - do_sprint_tree(s,&(*t)->left); + strcat (s, "~"); + do_sprint_tree (s, t->left); break; } } -static void sprint_tree(char *s, tree t) -{ - tree tt = dup_tree(t); - *s = 0; - do_sprint_tree(s, &tt); - kill_tree(&tt); -} - -static int treecmp(tree a, tree b) -{ - if (b->op != a->op) - return 1; - - if (a == b) - return 0; - - if (a->op == op_not) - return treecmp(a->left, b->left); - - return 1; -} +static tree_vec size_trees[20]; -static int issrc(tree t) -{ - return t->op == op_a || t->op == op_b || t->op == op_c; -} +static struct tree_n bad_tree = { op_and, &bad_tree, &bad_tree }; -static void do_opt(tree, tree_vec *, int); -static void opt_xor(tree t, tree_vec *tv); -static void opt_distrib(tree t, tree_vec *tv); -static void opt_demorgan(tree t, tree_vec *tv); +static unsigned int used_mask[256]; +static tree best_trees[256]; +static unsigned int best_cost[256]; +static int n_unknown; -static void opt_not(tree_vec *tv_dst, tree_vec *tv_src) +static unsigned long which_fn (tree t) { - int i; - for (i = 0; i < tv_src->ntrees; i++) { - tree t = tv_src->trees[i]; - - add_vec(tv_dst, new_op_tree(op_not, dup_tree(t), NULL)); - } -} - -static void demorgan(tree t, tree_vec *tv) -{ - tree newt = NULL, t_l = NULL; - int neednot = 0; - - if (t->op == op_not && (t->left->op == op_and || t->left->op == op_or)) - t_l = dup_tree(t->left); - else if (t->op == op_and || t->op == op_or) - t_l = dup_tree(t), neednot = 1; - else - return; - - if (t_l->op == op_and) - t_l->op = op_or; - else - t_l->op = op_and; - - t_l->left = new_op_tree(op_not, t_l->left, NULL); - t_l->right = new_op_tree(op_not, t_l->right, NULL); - normalize(&t_l); - - if (neednot) { - tree_vec tv2; - int i; - - init_vec(&tv2); - opt_xor(t_l, &tv2); - opt_distrib(t_l, &tv2); - add_vec(&tv2, t_l); -#if 0 - for (i = 0; i < tv2.ntrees; i++) { - add_vec(tv, new_op_tree(op_not, dup_tree(tv2.trees[i]), NULL)); - } -#endif - opt_not(tv, &tv2); - kill_vec(&tv2); - } else { - opt_xor(t_l, tv); - opt_distrib(t_l, tv); - add_vec(tv, t_l); - } -} - -static void opt_xor(tree t, tree_vec *tv) -{ - tree_vec tv1, tv2; - tree tt1, tt2; - int i; - - enum tree_op top, sop; - tree t1, t2, t3; - int n1 = 0, n2 = 0, ok1 = 0, ok2 = 0; - - top = t->op; - if (top != op_or) - return; - - sop = t->left->op; - if (sop != op_and || t->right->op != sop) - return; - - if (t->left->left->op == op_not) { - n1 = 1; - t1 = t->left->left->left; - } else { - t1 = t->left->left; - } - - if (t->left->right->op == op_not) { - n2 = 1; - t2 = t->left->right->left; - } else { - t2 = t->left->right; - } - - if (t->right->left->op == op_not) { - if (n1 == 0 && tree_equal(t->right->left->left, t1)) - ok1++; - if (n2 == 0 && tree_equal(t->right->left->left, t2)) - ok2++; - } else { - if (n1 == 1 && tree_equal(t->right->left, t1)) - ok1++; - if (n2 == 1 && tree_equal(t->right->left, t2)) - ok2++; - } - - if (t->right->right->op == op_not) { - if (n1 == 0 && tree_equal(t->right->right->left, t1)) - ok1++; - if (n2 == 0 && tree_equal(t->right->right->left, t2)) - ok2++; - } else { - if (n1 == 1 && tree_equal(t->right->right, t1)) - ok1++; - if (n2 == 1 && tree_equal(t->right->right, t2)) - ok2++; - } - - if (ok1 != 1 || ok2 != 1) - return; - - t3 = new_op_tree(op_xor, dup_tree(t1), dup_tree(t2)); - if (n1 == n2) - t3 = new_op_tree(op_not, t3, NULL); - normalize(&t3); - add_vec(tv, t3); - - init_vec(&tv1); init_vec(&tv2); - tt1 = new_op_tree(op_not, dup_tree(t1), NULL); - tt2 = new_op_tree(op_not, dup_tree(t2), NULL); - - do_opt(tt1, &tv1, 0); do_opt(tt2, &tv2, 0); - kill_tree(&tt1); kill_tree(&tt2); - - for (i = 0; i < tv1.ntrees; i++) { - t3 = new_op_tree(op_xor, dup_tree(tv1.trees[i]), dup_tree(t2)); - if (n1 != n2) - t3 = new_op_tree(op_not, t3, NULL); - normalize(&t3); - add_vec(tv, t3); - } - - for (i = 0; i < tv2.ntrees; i++) { - t3 = new_op_tree(op_xor, dup_tree(t1), dup_tree(tv2.trees[i])); - if (n1 != n2) - t3 = new_op_tree(op_not, t3, NULL); - normalize(&t3); - add_vec(tv, t3); - } - - for (i = 0; i < tv1.ntrees; i++) { - int j; - - for (j = 0; j < tv2.ntrees; j++) { - t3 = new_op_tree(op_xor, dup_tree(tv1.trees[i]), dup_tree(tv2.trees[j])); - if (n1 == n2) - t3 = new_op_tree(op_not, t3, NULL); - normalize(&t3); - add_vec(tv, t3); - } + switch (t->op) { + case op_a: + return 0xf0; + case op_b: + return 0xcc; + case op_c: + return 0xaa; + case op_and: + return which_fn (t->left) & which_fn (t->right); + case op_or: + return which_fn (t->left) | which_fn (t->right); + case op_xor: + return which_fn (t->left) ^ which_fn (t->right); + case op_not: + return 0xFF & ~which_fn (t->left); + default: + abort (); } - - kill_vec(&tv1); kill_vec(&tv2); } -static tree opt_factor_tree(tree old, tree f, enum tree_op top, enum tree_op sop, - tree *remainder) +static unsigned long tree_used_mask (tree t) { - tree t1 = old; - tree t2 = NULL; - *remainder = NULL; - - for (;;) { - int found_factor = 0; - tree t3 = NULL; - tree t4; - - if (t1->op == top) - t4 = t1->left; - else - t4 = t1; - - if (t4->op != sop) { - if (*remainder == NULL) - *remainder = dup_tree(t4); - else - *remainder = new_op_tree(top, *remainder, dup_tree(t4)); - } else { - for (;;) { - tree t5; - - if (t4->op == sop) - t5 = t4->left; - else - t5 = t4; - - if (treecmp(t5, f) != 0) { - if (t3 == NULL) - t3 = dup_tree(t5); - else - t3 = new_op_tree(sop, t3, dup_tree(t5)); - } else - found_factor = 1; - - if (t4->op != sop) - break; - t4 = t4->right; - } - if (!found_factor) { - if (*remainder == NULL) - *remainder = t3; - else - *remainder = new_op_tree(top, *remainder, t3); - } else { - if (t2 == NULL) - t2 = t3; - else - t2 = new_op_tree(top, t2, t3); - } - } - - if (t1->op != top) - break; - - t1 = t1->right; - } - if (t2 == NULL || t2->op != top) { - if (*remainder != NULL) - kill_tree(remainder); - if (t2 != NULL) - kill_tree(&t2); - return NULL; + switch (t->op) { + case op_a: + return 1; + case op_b: + return 2; + case op_c: + return 4; + case op_and: + case op_or: + case op_xor: + return tree_used_mask (t->left) | tree_used_mask (t->right); + case op_not: + return tree_used_mask (t->left); + default: + abort (); } - return t2; } -static void opt_distrib(tree t, tree_vec *tv) +static void candidate (tree_vec *v, tree t) { - enum tree_op top, sop; - tree t1; - - top = t->op; - - if (top != op_and && top != op_or) - return; - - sop = t->left->op; - if ((top == op_and && sop != op_or) || (top == op_or && sop != op_and)) - return; -#if 0 - t1 = t->right; - for (;;) { - if (t1->op == sop) - break; - if (t1->op != top) - return; - if (t1->left->op != sop) - return; - t1 = t1->right; - } -#endif - - t1 = t->left; - for (;;) { - tree t3, t4, t5; - - if (t1->op == sop) - t3 = t1->left; - else - t3 = t1; - - t4 = opt_factor_tree(t, t3, top, sop, &t5); - if (t4 != NULL) { - tree_vec tv2; - int i; - - init_vec(&tv2); - normalize(&t4); - do_opt(t4, &tv2, 0); - kill_tree(&t4); - - for (i = 0; i < tv2.ntrees; i++) { - t4 = new_op_tree(sop, dup_tree(t3), dup_tree(tv2.trees[i])); - if (t5 != NULL) - t4 = new_op_tree(top, t4, dup_tree(t5)); - normalize(&t4); - if (t5 != NULL) { - demorgan(t4, tv); - opt_xor(t4, tv); - } - add_vec(tv, t4); - } - kill_vec(&tv2); - - if (t5 != NULL) - kill_tree(&t5); - } - if (t1->op != sop) - break; - t1 = t1->right; - } + unsigned long fn = which_fn (t); + unsigned int cost = tree_cost (t); + if (best_trees[fn] == 0) + n_unknown--; + if (cost < best_cost[fn]) + best_trees[fn] = t, best_cost[fn] = cost; + add_vec (v, t); } -struct perm_data { - int n; - int *a; - tree_vec *tvar; - tree_vec *tvparent; - enum tree_op op; - int neednot; - int didmorgan; -}; - -static void allperms(struct perm_data *pd, int p, - void (*f)(struct perm_data *)) +static void cand_and_not (tree_vec *v, tree t) { - if (p == pd->n) - f(pd); - else { - int i; - for (i = p; i < pd->n; i++) { - int tmp = pd->a[i]; - pd->a[i] = pd->a[p]; - pd->a[p] = tmp; - allperms(pd, p + 1, f); - tmp = pd->a[i]; - pd->a[i] = pd->a[p]; - pd->a[p] = tmp; - } - } - + candidate (v, t); + t = new_op_tree (op_not, t, 0); + candidate (v, t); } -static void optimize(tree_vec *tv, tree subt, enum tree_op top) +static void try_tree (tree_vec *v, tree t) { - tree_vec sub_tv; - int i; - - if (subt->op != top) { - add_vec(tv, dup_tree(subt)); + int fnl = which_fn (t->left); + int fnr = which_fn (t->right); + int fn = which_fn (t); + if (fn == fnl + || fn == fnr + || fn == 0 + || fn == 0xFF + || (tree_used_mask (t) & ~used_mask[fn]) != 0 + || best_cost[fn] + 6 < tree_cost (t)) + { + xfree (t); return; } - - init_vec(&sub_tv); - optimize(&sub_tv, subt->right, top); - - for (i = 0; i < sub_tv.ntrees; i++) { - tree t1 = new_op_tree(top, dup_tree(subt->left), dup_tree(sub_tv.trees[i])); - demorgan(t1, tv); - opt_xor(t1, tv); - opt_distrib(t1, tv); - add_vec(tv, t1); - } - kill_vec(&sub_tv); + cand_and_not (v, t); } -static void do_opt_perm_1(struct perm_data *pd, int i, tree rhs) +static void find_best_trees (void) { - int j = pd->a[i]; - int k; - - i++; - for (k = 0; k < pd->tvar[j].ntrees; k++) { - tree lhs; - - if (rhs == NULL) - lhs = dup_tree(pd->tvar[j].trees[k]); - else - lhs = new_op_tree(pd->op, dup_tree(pd->tvar[j].trees[k]), dup_tree(rhs)); - - if (i < pd->n) { - do_opt_perm_1(pd, i, lhs); - } else { - normalize(&lhs); - - if (pd->neednot) { - int i; - tree_vec tvs; - init_vec(&tvs); - - optimize(&tvs, lhs, lhs->op); -#if 0 - for (i = 0; i < tvs.ntrees; i++) - add_vec(pd->tvparent, new_op_tree(op_not, dup_tree(tvs.trees[i]), NULL)); -#endif - opt_not(pd->tvparent, &tvs); - kill_vec(&tvs); - } else - optimize(pd->tvparent, lhs, lhs->op); - } - - kill_tree(&lhs); - } - nop(j); -} - -void nop(int a) -{ -} - -static void do_opt_perm(struct perm_data *pd) -{ - do_opt_perm_1(pd, 0, NULL); -} - -static void do_opt(tree t, tree_vec *tv, int did_morgan) -{ -/* if (!did_morgan) - demorgan(t, tv); - opt_distrib(t, tv); - opt_xor(t, tv);*/ - - if ((t->op == op_and || t->op == op_or) - || (t->op == op_not - && (t->left->op == op_and || t->left->op == op_or))) - { - int i, j; - struct perm_data pd; - tree t2, t3; - int neednot = t->op == op_not; - - if (neednot) - t3 = t->left; - else - t3 = t; - - pd.didmorgan = did_morgan; - pd.op = t3->op; - pd.neednot = neednot; - pd.tvparent = tv; - pd.n = 2; - - t2 = t3->right; - while (t2->op == t3->op) { - pd.n++; - t2 = t2->right; - } - - pd.a = (int *)xmalloc(sizeof(int)*pd.n); - pd.tvar = (tree_vec *)xmalloc(sizeof(tree_vec)*pd.n); - for (i = 0; i < pd.n; i++) - pd.a[i] = i; - - t2 = t3; i = 0; - while (t2->op == t3->op) { - init_vec(pd.tvar + i); - do_opt(t2->left, pd.tvar + i, neednot && did_morgan); - t2 = t2->right; - i++; - } - init_vec(pd.tvar + i); - do_opt(t2, pd.tvar + i, 0); + int i, size, do_stop; + for (i = 0; i < 256; i++) { + best_trees[i] = i == 0 || i == 255 ? &bad_tree : 0; + best_cost[i] = 65535; + } + n_unknown = 254; + + init_vec (size_trees); + cand_and_not (size_trees, tree_a); + cand_and_not (size_trees, tree_b); + cand_and_not (size_trees, tree_c); + + do_stop = 0; + for (size = 2; ! do_stop && size < 20; size++) { + int split, last_split; + tree_vec *sv = size_trees + size - 1; + + if (n_unknown == 0) + do_stop = 1; + last_split = (size >> 1) + 1; + for (split = 1; split < last_split; split++) { + int szl = split; + int szr = size - split; + tree_vec *lv = size_trees + szl - 1; + tree_vec *rv = size_trees + szr - 1; + int i; - allperms(&pd, 0, do_opt_perm); - - for (i = 0; i < pd.n; i++) { - kill_vec(pd.tvar + i); + for (i = 0; i < lv->ntrees; i++) { + tree l = lv->trees[i]; + int j; + for (j = szl == szr ? i + 1 : 0; j < rv->ntrees; j++) { + tree r = rv->trees[j]; + + if (l->op != op_and || r->op != op_and) { + tree tmp = (l->op == op_and + ? new_op_tree (op_and, r, l) + : new_op_tree (op_and, l, r)); + try_tree (sv, tmp); + } + if (l->op != op_or || r->op != op_or) { + tree tmp = (l->op == op_or + ? new_op_tree (op_or, r, l) + : new_op_tree (op_or, l, r)); + try_tree (sv, tmp); + } + if (l->op != op_xor || r->op != op_xor) { + tree tmp = (l->op == op_xor + ? new_op_tree (op_xor, r, l) + : new_op_tree (op_xor, l, r)); + try_tree (sv, tmp); + } + } + } } - xfree(pd.tvar); - xfree(pd.a); - } else { - demorgan(t, tv); - opt_xor(t, tv); - opt_distrib(t, tv); - add_vec(tv, dup_tree(t)); + /* An additional pass doesn't seem to create better solutions + * (not that much of a surprise). */ + if (n_unknown == 0) + do_stop = 1; } } -static int bitset(int mt, int bit) +static int bitset (int mt, int bit) { return mt & (1 << bit); } -static char buffer[4096]; - -static int generate_expr(int minterm, int print) +static unsigned int generate_expr (int minterm) { - int result = 0; - int firstor = 1; int bits = 0; int i; - int expr_bit[8], expr_dc[8], nexp = 0; + int expr_dc[8], nexp = 0; int expr_used[8]; - tree t, t1 = NULL; - if (minterm == 0) { - if (print) - printf("0"); + if (minterm == 0 || minterm == 0xFF) return 0; - } - if (minterm == 0xFF) { - if (print) - printf("0xFFFFFFFF"); - return 0; - } - - for(i=0; i<8; i++) { - if (bitset(minterm, i) && !bitset(bits,i)) { + + for (i = 0; i < 8; i++) { + if (bitset (minterm, i) && !bitset (bits, i)) { int j; int dontcare = 0; int firstand = 1; int bitbucket[8], bitcount; - + bits |= 1<