optimize.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,806 行 · 第 1/3 页

C
1,806
字号
			return;		if ((*diffp)->val[A_REGNO] != val)			break;		diffp = &(*diffp)->jf;		at_top = 0;	}	samep = &(*diffp)->jf;	while (1) {		if (*samep == 0)			return;		if ((*samep)->jt != b->jt)			return;		if (!NS_MEMBER((*samep)->dom, b->id))			return;		if ((*samep)->val[A_REGNO] == val)			break;		/* XXX Need to check that there are no data dependencies		   between dp0 and dp1.  Currently, the code generator		   will not produce such dependencies. */		samep = &(*samep)->jf;	}#ifdef notdef	/* XXX This doesn't cover everything. */	for (i = 0; i < N_MEMWORDS; ++i)		if ((*samep)->val[i] != pred->val[i])			return;#endif	/* Pull up the node. */	pull = *samep;	*samep = pull->jf;	pull->jf = *diffp;		/*	 * At the top of the chain, each predecessor needs to point at the	 * pulled up node.  Inside the chain, there is only one predecessor	 * to worry about.	 */	if (at_top) {		for (plist = b->pred; plist; plist = plist->next) {			if (plist->blk->jt == b)				plist->blk->jt = pull;			else				plist->blk->jf = pull;		}	}	else		*diffp = pull;	done = 0;}	static voidand_pullup(b)	struct block *b;{	int val, at_top;	struct block *pull;	struct block **diffp, **samep;	struct blist *plist;	plist = b->pred;	if (plist == 0)		return;	/*	 * Make sure each predecessor loads the same value.	 */	val = plist->blk->val[A_REGNO];	for (plist = plist->next; plist; plist = plist->next)		if (val != plist->blk->val[A_REGNO])			return;	if (b->pred->blk->jt == b)		diffp = &b->pred->blk->jt;	else		diffp = &b->pred->blk->jf;	at_top = 1;	while (1) {		if (*diffp == 0)			return;		if ((*diffp)->jf != b->jf)			return;		if (!NS_MEMBER((*diffp)->dom, b->id))			return;		if ((*diffp)->val[A_REGNO] != val)			break;		diffp = &(*diffp)->jt;		at_top = 0;	}	samep = &(*diffp)->jt;	while (1) {		if (*samep == 0)			return;		if ((*samep)->jf != b->jf)			return;		if (!NS_MEMBER((*samep)->dom, b->id))			return;		if ((*samep)->val[A_REGNO] == val)			break;		/* XXX Need to check that there are no data dependencies		   between dp0 and dp1.  Currently, the code generator		   will not produce such dependencies. */		samep = &(*samep)->jt;	}#ifdef notdef	/* XXX This doesn't cover everything. */	for (i = 0; i < N_MEMWORDS; ++i)		if ((*samep)->val[i] != pred->val[i])			return;#endif	/* Pull up the node. */	pull = *samep;	*samep = pull->jt;	pull->jt = *diffp;		/*	 * At the top of the chain, each predecessor needs to point at the	 * pulled up node.  Inside the chain, there is only one predecessor	 * to worry about.	 */	if (at_top) {		for (plist = b->pred; plist; plist = plist->next) {			if (plist->blk->jt == b)				plist->blk->jt = pull;			else				plist->blk->jf = pull;		}	}	else		*diffp = pull;	done = 0;}static voidopt_blks(root, do_stmts)	struct block *root;{	int i, maxlevel;	struct block *p;	init_val();	maxlevel = root->level;	for (i = maxlevel; i >= 0; --i)		for (p = levels[i]; p; p = p->link)			opt_blk(p, do_stmts);	if (do_stmts)		/* 		 * No point trying to move branches; it can't possibly		 * make a difference at this point.		 */		return;	for (i = 1; i <= maxlevel; ++i) {		for (p = levels[i]; p; p = p->link) {			opt_j(p, 1);			opt_j(p, 0);		}	}	for (i = 1; i <= maxlevel; ++i)		for (p = levels[i]; p; p = p->link) {			or_pullup(p);			and_pullup(p);		}}static voidfind_pred(root)	struct block *root;{	int i;	struct block *b;	struct blist *list;	next_blist = blist_base;	for (i = 0; i < n_blocks; ++i)		blocks[i]->pred = 0;	/*	 * Traverse the graph, adding each node to the predecessor	 * list of its sucessors.  Skip the leaves (i.e. level 0).	 */	for (i = root->level; i > 0; --i) {		for (b = levels[i]; b; b = b->link) {			list = next_blist++;			list->blk = b;			list->next = b->jt->pred;			b->jt->pred = list;			list = next_blist++;			list->blk = b;			list->next = b->jf->pred;			b->jf->pred = list;		}	}}static voidopt_root(b)	struct block **b;{	while (BPF_ISJUMP((*b)->s.code) &&	       (*b)->jt == (*b)->jf) {		*b = (*b)->jt;	}}static voidopt_loop(root, do_stmts)	struct block *root;	int do_stmts;{	do {		done = 1;		find_levels(root);		find_dom(root);		find_closure(root);		find_pred(root);		find_ud(root);		opt_blks(root, do_stmts);	} while (!done);}/* * Optimize the filter code in its dag representation. */voidoptimize(rootp)	struct block **rootp;{	struct block *root;	root = *rootp;	opt_init(root);	opt_loop(root, 0);	opt_loop(root, 1);	intern_blocks(root);	opt_root(rootp);	opt_cleanup();}static voidmake_marks(p)	struct block *p;{	if (!isMarked(p)) {		Mark(p);		if (!BPF_ISLEAF(p->s.code)) {			make_marks(p->jt);			make_marks(p->jf);		}	}}/* * Mark code array such that isMarked(i) is true * only for nodes that are alive. */static voidmark_code(p)	struct block *p;{	cur_mark += 1;	make_marks(p);}/* * True iff the two stmt lists load the same value from the packet into * the accumulator. */static inteq_slist(x, y)	struct slist *x, *y;{	while (1) {		while (x && x->s.code == NopOp)			x = x->next;		while (y && y->s.code == NopOp)			y = y->next;		if (x == 0)			return y == 0;		if (y == 0)			return x == 0;		if (x->s.code != y->s.code ||		    x->s.k != y->s.k)			return 0;		x = x->next;		y = y->next;	}}static inline inteq_blk(b0, b1)	struct block *b0, *b1;{	if (b0->s.code == b1->s.code &&	    b0->s.k == b1->s.k &&	    b0->jt == b1->jt && b0->jf == b1->jf)		return eq_slist(b0->stmts, b1->stmts);	return 0;}static voidintern_blocks(root)	struct block *root;{	struct block *p;	int i, j;	int done; top:	done = 1;	for (i = 0; i < n_blocks; ++i)		blocks[i]->link = 0;	mark_code(root);	for (i = n_blocks - 1; --i >= 0; ) {		if (!isMarked(blocks[i]))			continue;		for (j = i + 1; j < n_blocks; ++j) {			if (!isMarked(blocks[j]))				continue;			if (eq_blk(blocks[i], blocks[j])) {				blocks[i]->link = blocks[j]->link ?					blocks[j]->link : blocks[j];				break;			}		}	}	for (i = 0; i < n_blocks; ++i) {		p = blocks[i];		if (p->jt == 0)			continue;		if (p->jt->link) {			done = 0;			p->jt = p->jt->link;		}		if (p->jf->link) {			done = 0;			p->jf = p->jf->link;		}	}	if (!done)		goto top;}static voidopt_cleanup(){	free((void *)vnode_base);	free((void *)vmap);	free((void *)blist_base);	free((void *)space);	free((void *)levels);	free((void *)blocks);}/* * Return the number of stmts in 's'. */static intslength(s)	struct slist *s;{	int n = 0;	for (; s; s = s->next)		if (s->s.code != NopOp)			++n;	return n;}/* * Return the number of nodes reachable by 'p'. * All nodes should be initially unmarked. */static intcount_blocks(p)	struct block *p;{	if (p == 0 || isMarked(p))		return 0;	Mark(p);	return count_blocks(p->jt) + count_blocks(p->jf) + 1;}	/* * Do a depth first search on the flow graph, numbering the * the basic blocks, and entering them into the 'blocks' array.` */static voidnumber_blks_r(p)	struct block *p;{	int n;	if (p == 0 || isMarked(p))		return;	Mark(p);	n = n_blocks++;	p->id = n;	blocks[n] = p;	number_blks_r(p->jt);	number_blks_r(p->jf);}/* * Return the number of stmts in the flowgraph reachable by 'p'. * The nodes should be unmarked before calling. */static intcount_stmts(p)	struct block *p;{	int n;	if (p == 0 || isMarked(p))		return 0;	Mark(p);	n = count_stmts(p->jt) + count_stmts(p->jf);	return slength(p->stmts) + n + 1;}/* * Allocate memory.  All allocation is done before optimization * is begun.  A linear bound on the size of all data structures is computed * from the total number of blocks and/or statements. */static voidopt_init(root)	struct block *root;{	u_long *p;	int i, n, max_stmts;	/*	 * First, count the blocks, so we can malloc an array to map	 * block number to block.  Then, put the blocks into the array.	 */	unMarkAll();	n = count_blocks(root);	blocks = (struct block **)malloc(n * sizeof(*blocks));	unMarkAll();	n_blocks = 0;	number_blks_r(root);	/*	 * The number of levels is bounded by the number of nodes.	 */	levels = (struct block **)malloc(n * sizeof(*levels));	ns_nwords = n / (8 * sizeof(u_long)) + 1;	space = (u_long *)malloc(2 * n * ns_nwords * sizeof(*space));	p = space;	all_dom_sets = p;	for (i = 0; i < n; ++i) {		blocks[i]->dom = p;		p += ns_nwords;	}	all_closure_sets = p;	for (i = 0; i < n; ++i) {		blocks[i]->closure = p;		p += ns_nwords;	}	/*	 * At most, we can have E = 2N predecessors. 	 * (E = num edges, N = num blocks)	 */	blist_base = (struct blist *)malloc(2 * n * sizeof(*blist_base));	max_stmts = 0;	for (i = 0; i < n; ++i)		max_stmts += slength(blocks[i]->stmts) + 1;	/*	 * We allocate at most 3 value numbers per statement,	 * so this is an upper bound on the number of valnodes	 * we'll need.	 */	maxval = 3 * max_stmts;	vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap));	vnode_base = (struct valnode *)malloc(maxval * sizeof(*vmap));}/* * Some pointers used to convert the basic block form of the code, * into the array form that BPF requires.  'fstart' will point to * the malloc'd array while 'ftail' is used during the recursive traversal. */static struct bpf_insn *fstart;static struct bpf_insn *ftail;#ifdef BDEBUGint bids[1000];#endifstatic voidconvert_code_r(p)	struct block *p;{	struct bpf_insn *dst;	struct slist *src;	int slen;	u_int off;	if (p == 0 || isMarked(p))		return;	Mark(p);	convert_code_r(p->jf);	convert_code_r(p->jt);	slen = slength(p->stmts);	dst = ftail -= slen + 1;	p->offset = dst - fstart;	for (src = p->stmts; src; src = src->next) {		if (src->s.code == NopOp)			continue;		dst->code = (u_short)src->s.code;		dst->k = src->s.k;		++dst;	}#ifdef BDEBUG	bids[dst - fstart] = p->id + 1;#endif	dst->code = (u_short)p->s.code;	dst->k = p->s.k;	if (p->jt) {		off = p->jt->offset - (p->offset + slen);		if (off >= 256) 			error("long jumps not supported");		dst->jt = off;		off = p->jf->offset - (p->offset + slen);		if (off >= 256) 			error("long jumps not supported");		dst->jf = off;	}}	/* * Convert flowgraph intermediate representation to the * BPF array representation.  Set *lenp to the number of instructions. */struct bpf_insn *icode_to_fcode(root, lenp)	struct block *root;	int *lenp;{	int n;	struct bpf_insn *fp;		unMarkAll();	n = *lenp = count_stmts(root);	fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);	bzero((char *)fp, sizeof(*fp) * n);	fstart = fp;	ftail = fp + n;	unMarkAll();	convert_code_r(root);	return fp;}#ifdef BDEBUGopt_dump(root)	struct block *root;{	struct bpf_program f;		f.bf_insns = icode_to_fcode(root, &f.bf_len);	bpf_dump(&f, 1);	putchar('\n');	free((char *)f.bf_insns);}#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?