xref: /plan9/sys/src/cmd/spin/tl_cache.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
17dd7cddfSDavid du Colombier /***** tl_spin: tl_cache.c *****/
27dd7cddfSDavid du Colombier 
3312a1df1SDavid du Colombier /* Copyright (c) 1995-2003 by Lucent Technologies, Bell Laboratories.     */
47dd7cddfSDavid du Colombier /* All Rights Reserved.  This software is for educational purposes only.  */
5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6312a1df1SDavid du Colombier /* this code.  Permission is given to distribute this code provided that  */
7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged.  */
8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9312a1df1SDavid du Colombier /*             http://spinroot.com/                                       */
10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11312a1df1SDavid du Colombier 
127dd7cddfSDavid du Colombier /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
137dd7cddfSDavid du Colombier /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.   */
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier #include "tl.h"
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier typedef struct Cache {
187dd7cddfSDavid du Colombier 	Node *before;
197dd7cddfSDavid du Colombier 	Node *after;
207dd7cddfSDavid du Colombier 	int same;
217dd7cddfSDavid du Colombier 	struct Cache *nxt;
227dd7cddfSDavid du Colombier } Cache;
237dd7cddfSDavid du Colombier 
247dd7cddfSDavid du Colombier static Cache	*stored = (Cache *) 0;
257dd7cddfSDavid du Colombier static unsigned long	Caches, CacheHits;
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier static int	ismatch(Node *, Node *);
287dd7cddfSDavid du Colombier extern void fatal(char *, char *);
297dd7cddfSDavid du Colombier int	sameform(Node *, Node *);
307dd7cddfSDavid du Colombier 
31*00d97012SDavid du Colombier void
ini_cache(void)32*00d97012SDavid du Colombier ini_cache(void)
33*00d97012SDavid du Colombier {
34*00d97012SDavid du Colombier 	stored = (Cache *) 0;
35*00d97012SDavid du Colombier 	Caches = 0;
36*00d97012SDavid du Colombier 	CacheHits = 0;
37*00d97012SDavid du Colombier }
38*00d97012SDavid du Colombier 
39312a1df1SDavid du Colombier #if 0
407dd7cddfSDavid du Colombier void
417dd7cddfSDavid du Colombier cache_dump(void)
427dd7cddfSDavid du Colombier {	Cache *d; int nr=0;
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier 	printf("\nCACHE DUMP:\n");
457dd7cddfSDavid du Colombier 	for (d = stored; d; d = d->nxt, nr++)
467dd7cddfSDavid du Colombier 	{	if (d->same) continue;
477dd7cddfSDavid du Colombier 		printf("B%3d: ", nr); dump(d->before); printf("\n");
487dd7cddfSDavid du Colombier 		printf("A%3d: ", nr); dump(d->after); printf("\n");
497dd7cddfSDavid du Colombier 	}
507dd7cddfSDavid du Colombier 	printf("============\n");
517dd7cddfSDavid du Colombier }
52312a1df1SDavid du Colombier #endif
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier Node *
in_cache(Node * n)557dd7cddfSDavid du Colombier in_cache(Node *n)
567dd7cddfSDavid du Colombier {	Cache *d; int nr=0;
577dd7cddfSDavid du Colombier 
587dd7cddfSDavid du Colombier 	for (d = stored; d; d = d->nxt, nr++)
597dd7cddfSDavid du Colombier 		if (isequal(d->before, n))
607dd7cddfSDavid du Colombier 		{	CacheHits++;
617dd7cddfSDavid du Colombier 			if (d->same && ismatch(n, d->before)) return n;
627dd7cddfSDavid du Colombier 			return dupnode(d->after);
637dd7cddfSDavid du Colombier 		}
647dd7cddfSDavid du Colombier 	return ZN;
657dd7cddfSDavid du Colombier }
667dd7cddfSDavid du Colombier 
677dd7cddfSDavid du Colombier Node *
cached(Node * n)687dd7cddfSDavid du Colombier cached(Node *n)
697dd7cddfSDavid du Colombier {	Cache *d;
707dd7cddfSDavid du Colombier 	Node *m;
717dd7cddfSDavid du Colombier 
727dd7cddfSDavid du Colombier 	if (!n) return n;
73312a1df1SDavid du Colombier 	if ((m = in_cache(n)) != ZN)
747dd7cddfSDavid du Colombier 		return m;
757dd7cddfSDavid du Colombier 
767dd7cddfSDavid du Colombier 	Caches++;
777dd7cddfSDavid du Colombier 	d = (Cache *) tl_emalloc(sizeof(Cache));
787dd7cddfSDavid du Colombier 	d->before = dupnode(n);
797dd7cddfSDavid du Colombier 	d->after  = Canonical(n); /* n is released */
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier 	if (ismatch(d->before, d->after))
827dd7cddfSDavid du Colombier 	{	d->same = 1;
837dd7cddfSDavid du Colombier 		releasenode(1, d->after);
847dd7cddfSDavid du Colombier 		d->after = d->before;
857dd7cddfSDavid du Colombier 	}
867dd7cddfSDavid du Colombier 	d->nxt = stored;
877dd7cddfSDavid du Colombier 	stored = d;
887dd7cddfSDavid du Colombier 	return dupnode(d->after);
897dd7cddfSDavid du Colombier }
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier void
cache_stats(void)927dd7cddfSDavid du Colombier cache_stats(void)
937dd7cddfSDavid du Colombier {
947dd7cddfSDavid du Colombier 	printf("cache stores     : %9ld\n", Caches);
957dd7cddfSDavid du Colombier 	printf("cache hits       : %9ld\n", CacheHits);
967dd7cddfSDavid du Colombier }
977dd7cddfSDavid du Colombier 
987dd7cddfSDavid du Colombier void
releasenode(int all_levels,Node * n)997dd7cddfSDavid du Colombier releasenode(int all_levels, Node *n)
1007dd7cddfSDavid du Colombier {
1017dd7cddfSDavid du Colombier 	if (!n) return;
1027dd7cddfSDavid du Colombier 
1037dd7cddfSDavid du Colombier 	if (all_levels)
1047dd7cddfSDavid du Colombier 	{	releasenode(1, n->lft);
1057dd7cddfSDavid du Colombier 		n->lft = ZN;
1067dd7cddfSDavid du Colombier 		releasenode(1, n->rgt);
1077dd7cddfSDavid du Colombier 		n->rgt = ZN;
1087dd7cddfSDavid du Colombier 	}
1097dd7cddfSDavid du Colombier 	tfree((void *) n);
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier 
1127dd7cddfSDavid du Colombier Node *
tl_nn(int t,Node * ll,Node * rl)1137dd7cddfSDavid du Colombier tl_nn(int t, Node *ll, Node *rl)
1147dd7cddfSDavid du Colombier {	Node *n = (Node *) tl_emalloc(sizeof(Node));
1157dd7cddfSDavid du Colombier 
1167dd7cddfSDavid du Colombier 	n->ntyp = (short) t;
1177dd7cddfSDavid du Colombier 	n->lft  = ll;
1187dd7cddfSDavid du Colombier 	n->rgt  = rl;
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier 	return n;
1217dd7cddfSDavid du Colombier }
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier Node *
getnode(Node * p)1247dd7cddfSDavid du Colombier getnode(Node *p)
1257dd7cddfSDavid du Colombier {	Node *n;
1267dd7cddfSDavid du Colombier 
1277dd7cddfSDavid du Colombier 	if (!p) return p;
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier 	n =  (Node *) tl_emalloc(sizeof(Node));
1307dd7cddfSDavid du Colombier 	n->ntyp = p->ntyp;
1317dd7cddfSDavid du Colombier 	n->sym  = p->sym; /* same name */
1327dd7cddfSDavid du Colombier 	n->lft  = p->lft;
1337dd7cddfSDavid du Colombier 	n->rgt  = p->rgt;
1347dd7cddfSDavid du Colombier 
1357dd7cddfSDavid du Colombier 	return n;
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier Node *
dupnode(Node * n)1397dd7cddfSDavid du Colombier dupnode(Node *n)
1407dd7cddfSDavid du Colombier {	Node *d;
1417dd7cddfSDavid du Colombier 
1427dd7cddfSDavid du Colombier 	if (!n) return n;
1437dd7cddfSDavid du Colombier 	d = getnode(n);
1447dd7cddfSDavid du Colombier 	d->lft = dupnode(n->lft);
1457dd7cddfSDavid du Colombier 	d->rgt = dupnode(n->rgt);
1467dd7cddfSDavid du Colombier 	return d;
1477dd7cddfSDavid du Colombier }
1487dd7cddfSDavid du Colombier 
1497dd7cddfSDavid du Colombier int
one_lft(int ntyp,Node * x,Node * in)1507dd7cddfSDavid du Colombier one_lft(int ntyp, Node *x, Node *in)
1517dd7cddfSDavid du Colombier {
1527dd7cddfSDavid du Colombier 	if (!x)  return 1;
1537dd7cddfSDavid du Colombier 	if (!in) return 0;
1547dd7cddfSDavid du Colombier 
1557dd7cddfSDavid du Colombier 	if (sameform(x, in))
1567dd7cddfSDavid du Colombier 		return 1;
1577dd7cddfSDavid du Colombier 
1587dd7cddfSDavid du Colombier 	if (in->ntyp != ntyp)
1597dd7cddfSDavid du Colombier 		return 0;
1607dd7cddfSDavid du Colombier 
1617dd7cddfSDavid du Colombier 	if (one_lft(ntyp, x, in->lft))
1627dd7cddfSDavid du Colombier 		return 1;
1637dd7cddfSDavid du Colombier 
1647dd7cddfSDavid du Colombier 	return one_lft(ntyp, x, in->rgt);
1657dd7cddfSDavid du Colombier }
1667dd7cddfSDavid du Colombier 
1677dd7cddfSDavid du Colombier int
all_lfts(int ntyp,Node * from,Node * in)1687dd7cddfSDavid du Colombier all_lfts(int ntyp, Node *from, Node *in)
1697dd7cddfSDavid du Colombier {
1707dd7cddfSDavid du Colombier 	if (!from) return 1;
1717dd7cddfSDavid du Colombier 
1727dd7cddfSDavid du Colombier 	if (from->ntyp != ntyp)
1737dd7cddfSDavid du Colombier 		return one_lft(ntyp, from, in);
1747dd7cddfSDavid du Colombier 
1757dd7cddfSDavid du Colombier 	if (!one_lft(ntyp, from->lft, in))
1767dd7cddfSDavid du Colombier 		return 0;
1777dd7cddfSDavid du Colombier 
1787dd7cddfSDavid du Colombier 	return all_lfts(ntyp, from->rgt, in);
1797dd7cddfSDavid du Colombier }
1807dd7cddfSDavid du Colombier 
1817dd7cddfSDavid du Colombier int
sametrees(int ntyp,Node * a,Node * b)1827dd7cddfSDavid du Colombier sametrees(int ntyp, Node *a, Node *b)
1837dd7cddfSDavid du Colombier {	/* toplevel is an AND or OR */
1847dd7cddfSDavid du Colombier 	/* both trees are right-linked, but the leafs */
1857dd7cddfSDavid du Colombier 	/* can be in different places in the two trees */
1867dd7cddfSDavid du Colombier 
1877dd7cddfSDavid du Colombier 	if (!all_lfts(ntyp, a, b))
1887dd7cddfSDavid du Colombier 		return 0;
1897dd7cddfSDavid du Colombier 
1907dd7cddfSDavid du Colombier 	return all_lfts(ntyp, b, a);
1917dd7cddfSDavid du Colombier }
1927dd7cddfSDavid du Colombier 
1937dd7cddfSDavid du Colombier int	/* a better isequal() */
sameform(Node * a,Node * b)1947dd7cddfSDavid du Colombier sameform(Node *a, Node *b)
1957dd7cddfSDavid du Colombier {
1967dd7cddfSDavid du Colombier 	if (!a && !b) return 1;
1977dd7cddfSDavid du Colombier 	if (!a || !b) return 0;
1987dd7cddfSDavid du Colombier 	if (a->ntyp != b->ntyp) return 0;
1997dd7cddfSDavid du Colombier 
2007dd7cddfSDavid du Colombier 	if (a->sym
2017dd7cddfSDavid du Colombier 	&&  b->sym
2027dd7cddfSDavid du Colombier 	&&  strcmp(a->sym->name, b->sym->name) != 0)
2037dd7cddfSDavid du Colombier 		return 0;
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier 	switch (a->ntyp) {
2067dd7cddfSDavid du Colombier 	case TRUE:
2077dd7cddfSDavid du Colombier 	case FALSE:
2087dd7cddfSDavid du Colombier 		return 1;
2097dd7cddfSDavid du Colombier 	case PREDICATE:
2107dd7cddfSDavid du Colombier 		if (!a->sym || !b->sym) fatal("sameform...", (char *) 0);
2117dd7cddfSDavid du Colombier 		return !strcmp(a->sym->name, b->sym->name);
2127dd7cddfSDavid du Colombier 
2137dd7cddfSDavid du Colombier 	case NOT:
2147dd7cddfSDavid du Colombier #ifdef NXT
2157dd7cddfSDavid du Colombier 	case NEXT:
2167dd7cddfSDavid du Colombier #endif
2177dd7cddfSDavid du Colombier 		return sameform(a->lft, b->lft);
2187dd7cddfSDavid du Colombier 	case U_OPER:
2197dd7cddfSDavid du Colombier 	case V_OPER:
2207dd7cddfSDavid du Colombier 		if (!sameform(a->lft, b->lft))
2217dd7cddfSDavid du Colombier 			return 0;
2227dd7cddfSDavid du Colombier 		if (!sameform(a->rgt, b->rgt))
2237dd7cddfSDavid du Colombier 			return 0;
2247dd7cddfSDavid du Colombier 		return 1;
2257dd7cddfSDavid du Colombier 
2267dd7cddfSDavid du Colombier 	case AND:
2277dd7cddfSDavid du Colombier 	case OR:	/* the hard case */
2287dd7cddfSDavid du Colombier 		return sametrees(a->ntyp, a, b);
2297dd7cddfSDavid du Colombier 
2307dd7cddfSDavid du Colombier 	default:
2317dd7cddfSDavid du Colombier 		printf("type: %d\n", a->ntyp);
2327dd7cddfSDavid du Colombier 		fatal("cannot happen, sameform", (char *) 0);
2337dd7cddfSDavid du Colombier 	}
2347dd7cddfSDavid du Colombier 
2357dd7cddfSDavid du Colombier 	return 0;
2367dd7cddfSDavid du Colombier }
2377dd7cddfSDavid du Colombier 
2387dd7cddfSDavid du Colombier int
isequal(Node * a,Node * b)2397dd7cddfSDavid du Colombier isequal(Node *a, Node *b)
2407dd7cddfSDavid du Colombier {
2417dd7cddfSDavid du Colombier 	if (!a && !b)
2427dd7cddfSDavid du Colombier 		return 1;
2437dd7cddfSDavid du Colombier 
2447dd7cddfSDavid du Colombier 	if (!a || !b)
2457dd7cddfSDavid du Colombier 	{	if (!a)
2467dd7cddfSDavid du Colombier 		{	if (b->ntyp == TRUE)
2477dd7cddfSDavid du Colombier 				return 1;
2487dd7cddfSDavid du Colombier 		} else
2497dd7cddfSDavid du Colombier 		{	if (a->ntyp == TRUE)
2507dd7cddfSDavid du Colombier 				return 1;
2517dd7cddfSDavid du Colombier 		}
2527dd7cddfSDavid du Colombier 		return 0;
2537dd7cddfSDavid du Colombier 	}
2547dd7cddfSDavid du Colombier 	if (a->ntyp != b->ntyp)
2557dd7cddfSDavid du Colombier 		return 0;
2567dd7cddfSDavid du Colombier 
2577dd7cddfSDavid du Colombier 	if (a->sym
2587dd7cddfSDavid du Colombier 	&&  b->sym
2597dd7cddfSDavid du Colombier 	&&  strcmp(a->sym->name, b->sym->name) != 0)
2607dd7cddfSDavid du Colombier 		return 0;
2617dd7cddfSDavid du Colombier 
2627dd7cddfSDavid du Colombier 	if (isequal(a->lft, b->lft)
2637dd7cddfSDavid du Colombier 	&&  isequal(a->rgt, b->rgt))
2647dd7cddfSDavid du Colombier 		return 1;
2657dd7cddfSDavid du Colombier 
2667dd7cddfSDavid du Colombier 	return sameform(a, b);
2677dd7cddfSDavid du Colombier }
2687dd7cddfSDavid du Colombier 
2697dd7cddfSDavid du Colombier static int
ismatch(Node * a,Node * b)2707dd7cddfSDavid du Colombier ismatch(Node *a, Node *b)
2717dd7cddfSDavid du Colombier {
2727dd7cddfSDavid du Colombier 	if (!a && !b) return 1;
2737dd7cddfSDavid du Colombier 	if (!a || !b) return 0;
2747dd7cddfSDavid du Colombier 	if (a->ntyp != b->ntyp) return 0;
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier 	if (a->sym
2777dd7cddfSDavid du Colombier 	&&  b->sym
2787dd7cddfSDavid du Colombier 	&&  strcmp(a->sym->name, b->sym->name) != 0)
2797dd7cddfSDavid du Colombier 		return 0;
2807dd7cddfSDavid du Colombier 
2817dd7cddfSDavid du Colombier 	if (ismatch(a->lft, b->lft)
2827dd7cddfSDavid du Colombier 	&&  ismatch(a->rgt, b->rgt))
2837dd7cddfSDavid du Colombier 		return 1;
2847dd7cddfSDavid du Colombier 
2857dd7cddfSDavid du Colombier 	return 0;
2867dd7cddfSDavid du Colombier }
2877dd7cddfSDavid du Colombier 
2887dd7cddfSDavid du Colombier int
any_term(Node * srch,Node * in)2897dd7cddfSDavid du Colombier any_term(Node *srch, Node *in)
2907dd7cddfSDavid du Colombier {
2917dd7cddfSDavid du Colombier 	if (!in) return 0;
2927dd7cddfSDavid du Colombier 
2937dd7cddfSDavid du Colombier 	if (in->ntyp == AND)
2947dd7cddfSDavid du Colombier 		return	any_term(srch, in->lft) ||
2957dd7cddfSDavid du Colombier 			any_term(srch, in->rgt);
2967dd7cddfSDavid du Colombier 
2977dd7cddfSDavid du Colombier 	return isequal(in, srch);
2987dd7cddfSDavid du Colombier }
2997dd7cddfSDavid du Colombier 
3007dd7cddfSDavid du Colombier int
any_and(Node * srch,Node * in)3017dd7cddfSDavid du Colombier any_and(Node *srch, Node *in)
3027dd7cddfSDavid du Colombier {
3037dd7cddfSDavid du Colombier 	if (!in) return 0;
3047dd7cddfSDavid du Colombier 
3057dd7cddfSDavid du Colombier 	if (srch->ntyp == AND)
3067dd7cddfSDavid du Colombier 		return	any_and(srch->lft, in) &&
3077dd7cddfSDavid du Colombier 			any_and(srch->rgt, in);
3087dd7cddfSDavid du Colombier 
3097dd7cddfSDavid du Colombier 	return any_term(srch, in);
3107dd7cddfSDavid du Colombier }
3117dd7cddfSDavid du Colombier 
3127dd7cddfSDavid du Colombier int
any_lor(Node * srch,Node * in)3137dd7cddfSDavid du Colombier any_lor(Node *srch, Node *in)
3147dd7cddfSDavid du Colombier {
3157dd7cddfSDavid du Colombier 	if (!in) return 0;
3167dd7cddfSDavid du Colombier 
3177dd7cddfSDavid du Colombier 	if (in->ntyp == OR)
3187dd7cddfSDavid du Colombier 		return	any_lor(srch, in->lft) ||
3197dd7cddfSDavid du Colombier 			any_lor(srch, in->rgt);
3207dd7cddfSDavid du Colombier 
3217dd7cddfSDavid du Colombier 	return isequal(in, srch);
3227dd7cddfSDavid du Colombier }
3237dd7cddfSDavid du Colombier 
3247dd7cddfSDavid du Colombier int
anywhere(int tok,Node * srch,Node * in)3257dd7cddfSDavid du Colombier anywhere(int tok, Node *srch, Node *in)
3267dd7cddfSDavid du Colombier {
3277dd7cddfSDavid du Colombier 	if (!in) return 0;
3287dd7cddfSDavid du Colombier 
3297dd7cddfSDavid du Colombier 	switch (tok) {
3307dd7cddfSDavid du Colombier 	case AND:	return any_and(srch, in);
3317dd7cddfSDavid du Colombier 	case  OR:	return any_lor(srch, in);
3327dd7cddfSDavid du Colombier 	case   0:	return any_term(srch, in);
3337dd7cddfSDavid du Colombier 	}
3347dd7cddfSDavid du Colombier 	fatal("cannot happen, anywhere", (char *) 0);
3357dd7cddfSDavid du Colombier 	return 0;
3367dd7cddfSDavid du Colombier }
337