⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 optimize.c

📁 一款拥有一定历史的C语言编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * C compiler * ========== * * Copyright 1989, 1990, 1991 Christoph van Wuellen. * Credits to Matthew Brandt. * All commercial rights reserved. * * This compiler may be redistributed as long there is no * commercial interest. The compiler must not be redistributed * without its full sources. This notice must stay intact. * * History: * * 1989   starting an 68000 C compiler, starting with material *		  originally by M. Brandt * 1990   68000 C compiler further bug fixes *		  started i386 port (December) * 1991   i386 port finished (January) *		  further corrections in the front end and in the 68000 *		  code generator. *		  The next port will be a SPARC port *//*****************************************************************************/#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"/*********************************************** Static Function Definitions */static IVAL xfold P_ ((EXPR *));static EXPR *dooper P_ ((EXPR *));static EXPR *fold_const P_ ((EXPR *));/*****************************************************************************//* *	 This function handles the adjustment of integer constants upon *	 casts. It forces the constant into the range acceptable for *	 the given type. */static IVAL strip_icon P2 (IVAL, i, const TYP *, tp){    switch (tp->type) {    case bt_bool:	i = (IVAL) (i ? 1 : 0);	break;    case bt_charu:    case bt_uchar:		/* 0 .. 255 */	i &= (IVAL) 0xFFL;	break;    case bt_char:		/* -128 .. 127 */    case bt_schar:	i &= (IVAL) 0xFFUL;	if ((UVAL) i > 0x7FUL) {	    i -= (IVAL) 0x100UL;	}	break;    case bt_ushort:		/* 0 .. 65535 */    case bt_uint16:	i &= (IVAL) 0xFFFFL;	break;    case bt_short:		/* -32768 .. 32767 */    case bt_int16:	i &= (IVAL) 0xFFFFL;	if ((UVAL) i > 0x7FFFUL) {	    i -= (IVAL) 0x10000UL;	}	break;#ifdef LONGLONG_SUPPORT    case bt_uint32:    case bt_ulong:	i = (IVAL) ((UVAL) i & (UVAL) 0xFFFFFFFFUL);	break;    case bt_int32:    case bt_long:	i = (IVAL) ((UVAL) i & (UVAL) 0xFFFFFFFFUL);	if ((UVAL) i > 0x7FFFFFFFUL) {	    #ifdef LONGLONG_BOOTSTRAP	    i -= (IVAL) 0x40000000UL;	    i -= (IVAL) 0x40000000UL;	    i -= (IVAL) 0x40000000UL;	    i -= (IVAL) 0x40000000UL;	    #else	    i -= (IVAL) 0x100000000UL;#endif	/* LONGLONG_BOOTSTRAP */	}	break;#endif /* LONGLONG_SUPPORT */    default:	break;    }    return i;}/* *	 dooper() will execute a constant operation in a node and return *	 the node to be the result of the operation. */static EXPR *dooper P1 (EXPR *, ep){    EXPRTYPE type = ep->nodetype;    ep->nodetype = ep->v.p[0]->nodetype;    switch (ep->v.p[0]->nodetype) {#ifdef FLOAT_SUPPORT#ifndef FLOAT_BOOTSTRAP	RVAL    f;#endif	/* FLOAT_BOOTSTRAP */    case en_fcon:#ifndef FLOAT_BOOTSTRAP	FASSIGN (f, ep->v.p[0]->v.f);	switch (type) {	case en_uminus:	    FASSIGN (ep->v.f, f);	    FNEG (ep->v.f);	    break;	case en_test:	    ep->v.i = FTST (f) ? (IVAL) 1 : (IVAL) 0;	    ep->nodetype = en_icon;	    break;	case en_not:	    ep->v.i = FTST (f) ? (IVAL) 0 : (IVAL) 1;	    ep->nodetype = en_icon;	    break;	case en_cast:	    if (is_real_floating_type (ep->etp)) {		ep->v.f = f;	    } else if (is_bool (ep->etp)) {		ep->v.u = (UVAL) (f ? 1 : 0);		ep->nodetype = en_icon;	    } else {		FTOL (ep->v.i, f);		ep->v.i = strip_icon (ep->v.i, ep->etp);		ep->nodetype = en_icon;	    }	    break;	case en_add:	    FADD3 (ep->v.f, f, ep->v.p[1]->v.f);	    break;	case en_sub:	    FSUB3 (ep->v.f, f, ep->v.p[1]->v.f);	    break;	case en_mul:	    FMUL3 (ep->v.f, f, ep->v.p[1]->v.f);	    break;	case en_div:	    if (FTST (ep->v.p[1]->v.f)) {		FDIV3 (ep->v.f, f, ep->v.p[1]->v.f);	    } else {		ep->nodetype = en_div;	    }	    break;	case en_eq:	    ep->v.i = (IVAL) FEQ (f, ep->v.p[1]->v.f);	    ep->nodetype = en_icon;	    break;	case en_ne:	    ep->v.i = (IVAL) FNE (f, ep->v.p[1]->v.f);	    ep->nodetype = en_icon;	    break;	case en_land:	    ep->v.i = (IVAL) (FTST (f) && FTST (ep->v.p[1]->v.f));	    ep->nodetype = en_icon;	    break;	case en_lor:	    ep->v.i = (IVAL) (FTST (f) || FTST (ep->v.p[1]->v.f));	    ep->nodetype = en_icon;	    break;	case en_lt:	    ep->v.i = (IVAL) FLT (f, ep->v.p[1]->v.f);	    ep->nodetype = en_icon;	    break;	case en_le:	    ep->v.i = (IVAL) FLE (f, ep->v.p[1]->v.f);	    ep->nodetype = en_icon;	    break;	case en_gt:	    ep->v.i = (IVAL) FGT (f, ep->v.p[1]->v.f);	    ep->nodetype = en_icon;	    break;	case en_ge:	    ep->v.i = (IVAL) FGE (f, ep->v.p[1]->v.f);	    ep->nodetype = en_icon;	    break;	default:	    CANNOT_REACH_HERE ();	    break;	}	break;	#endif /* FLOAT_BOOTSTRAP */#endif /* FLOAT_SUPPORT */    case en_icon:	if (is_unsigned_type (ep->v.p[0]->etp)) {	    UVAL    u = ep->v.p[0]->v.u;	    switch (type) {	    case en_uminus:		/*		 *       unary minus on an unsigned is normally a mistake so we must		 *       fool the compiler into not giving a warning.		 */		ep->v.u = (UVAL) (-(IVAL) u);		break;	    case en_test:		ep->v.u = (u ? (UVAL) 1 : (UVAL) 0);		break;	    case en_not:		ep->v.u = (u ? (UVAL) 0 : (UVAL) 1);		break;	    case en_compl:		ep->v.u = (UVAL) strip_icon ((IVAL) ~u, ep->etp);		break;	    case en_cast:		if (is_bool (ep->etp)) {		    ep->v.u = (UVAL) (u ? 1 : 0);#ifdef FLOAT_SUPPORT		} else if (is_real_floating_type (ep->etp)) {		    ep->nodetype = en_fcon;		    UTOF (ep->v.f, u);		    break;#endif /* FLOAT_SUPPORT */		} else {		    ep->v.u = (UVAL) strip_icon ((IVAL) u, ep->etp);		}		break;	    case en_add:		ep->v.u = u + ep->v.p[1]->v.u;		break;	    case en_sub:		ep->v.u = u - ep->v.p[1]->v.u;		break;	    case en_mul:		ep->v.u = u * ep->v.p[1]->v.u;		break;	    case en_div:		if (ep->v.p[1]->v.u == (UVAL) 0) {		    ep->nodetype = en_div;		} else {		    ep->v.u = u / ep->v.p[1]->v.u;		}		break;	    case en_mod:		if (ep->v.p[1]->v.u == (UVAL) 0) {		    ep->nodetype = en_mod;		} else {		    ep->v.u = u % ep->v.p[1]->v.u;		}		break;	    case en_and:		ep->v.u = u & ep->v.p[1]->v.u;		break;	    case en_or:		ep->v.u = u | ep->v.p[1]->v.u;		break;	    case en_xor:		ep->v.u = u ^ ep->v.p[1]->v.u;		break;	    case en_eq:		ep->v.u = (UVAL) (u == ep->v.p[1]->v.u);		break;	    case en_ne:		ep->v.u = (UVAL) (u != ep->v.p[1]->v.u);		break;	    case en_land:		ep->v.u = (UVAL) (u && ep->v.p[1]->v.u);		break;	    case en_lor:		ep->v.u = (UVAL) (u || ep->v.p[1]->v.u);		break;	    case en_lt:		ep->v.u = (UVAL) (u < ep->v.p[1]->v.u);		break;	    case en_le:		ep->v.u = (UVAL) (u <= ep->v.p[1]->v.u);		break;	    case en_gt:		ep->v.u = (UVAL) (u > ep->v.p[1]->v.u);		break;	    case en_ge:		ep->v.u = (UVAL) (u >= ep->v.p[1]->v.u);		break;	    case en_lsh:		ep->v.u = u << ep->v.p[1]->v.u;		break;	    case en_rsh:		ep->v.u = u >> ep->v.p[1]->v.u;		break;	    default:		CANNOT_REACH_HERE ();		break;	    }	} else {	    IVAL    i = ep->v.p[0]->v.i;	    switch (type) {	    case en_uminus:		ep->v.i = -i;		break;	    case en_test:		ep->v.i = (i) ? (IVAL) 1 : (IVAL) 0;		break;	    case en_not:		ep->v.i = (i) ? (IVAL) 0 : (IVAL) 1;		break;	    case en_compl:		ep->v.i = strip_icon ((IVAL) (~(UVAL) i), ep->etp);		break;	    case en_cast:		if (is_bool (ep->etp)) {		    ep->v.u = (UVAL) (i ? 1 : 0);#ifdef FLOAT_SUPPORT		} else if (is_real_floating_type (ep->etp)) {		    ep->nodetype = en_fcon;		    LTOF (ep->v.f, i);		    break;#endif /* FLOAT_SUPPORT */		} else {		    ep->v.i = strip_icon (i, ep->etp);		}		break;	    case en_add:		ep->v.i = i + ep->v.p[1]->v.i;		break;	    case en_sub:		ep->v.i = i - ep->v.p[1]->v.i;		break;	    case en_mul:		ep->v.i = i * ep->v.p[1]->v.i;		break;	    case en_div:		if (ep->v.p[1]->v.i == (IVAL) 0) {		    ep->nodetype = en_div;		} else {		    ep->v.i = i / ep->v.p[1]->v.i;		}		break;	    case en_mod:		if (ep->v.p[1]->v.i == (IVAL) 0) {		    ep->nodetype = en_mod;		} else {		    ep->v.i = i % ep->v.p[1]->v.i;		}		break;	    case en_and:		ep->v.i = (IVAL) ((UVAL) i & (UVAL) ep->v.p[1]->v.i);		break;	    case en_or:		ep->v.i = (IVAL) ((UVAL) i | (UVAL) ep->v.p[1]->v.i);		break;	    case en_xor:		ep->v.i = (IVAL) ((UVAL) i ^ (UVAL) ep->v.p[1]->v.i);		break;	    case en_eq:		ep->v.i = (IVAL) (i == ep->v.p[1]->v.i);		break;	    case en_ne:		ep->v.i = (IVAL) (i != ep->v.p[1]->v.i);		break;	    case en_land:		ep->v.i = (IVAL) (i && ep->v.p[1]->v.i);		break;	    case en_lor:		ep->v.i = (IVAL) (i || ep->v.p[1]->v.i);		break;	    case en_lt:		ep->v.i = (IVAL) (i < ep->v.p[1]->v.i);		break;	    case en_le:		ep->v.i = (IVAL) (i <= ep->v.p[1]->v.i);		break;	    case en_gt:		ep->v.i = (IVAL) (i > ep->v.p[1]->v.i);		break;	    case en_ge:		ep->v.i = (IVAL) (i >= ep->v.p[1]->v.i);		break;	    case en_lsh:		ep->v.i = (IVAL) ((UVAL) i << ep->v.p[1]->v.i);		break;	    case en_rsh:		ep->v.i = (IVAL) (i >> ep->v.p[1]->v.i);		break;	    default:		CANNOT_REACH_HERE ();		break;	    }	}	break;    default:	CANNOT_REACH_HERE ();	break;    }    return ep;}/* *	 return which power of two i is or -1. */int pwrof2 P1 (IVAL, i){    int     p;    IVAL    q;    q = (IVAL) 1;    p = 0;    while (q > (IVAL) 0) {	if (q == i) {	    return p;	}	q <<= 1L;	++p;    }    return -1;}#ifdef CPU_DEFINED/* *	 This routine attempts to optimize bitfield references ... if *	 it makes a change it returns a pointer to the new node, *	 otherwise it returns NULL; */static EXPR *simplify_fieldref P3 (EXPR *, ep, TYP *, tp1, TYP *, tp2){    if (g_is_bigendian ()) {	if (ep->nodetype == en_fieldref) {	    SIZE    algn = alignment_of_type (tp1) * bits_in_sizeunit;	    if (((SIZE) ep->v.bit.offset % algn + (SIZE) ep->v.bit.width) <=		tp1->size * bits_in_sizeunit) {		SIZE    adjust = (SIZE) ep->v.bit.offset / algn;		ep->v.bit.offset -= (BITSIZE) (adjust * bits_in_sizeunit);		adjust = ep->etp->size - (tp1->size + adjust);		if (adjust != 0L) {		    ep->v.p[0] = opt0 (mk_node (en_add, ep->v.p[0],						mk_icon ((IVAL) adjust,							 tp_pointer),						ep->etp));		}		ep->etp = is_signed_type (ep->etp) ? tp1 : tp2;		if ((ep->v.bit.offset == (BITSIZE) 0) &&		    (ep->v.bit.width ==		     (BITSIZE) (tp1->size * bits_in_sizeunit))) {		    /*		     *            Fits exactly within the type so change to an		     *           ordinary reference as this is much more efficient		     */		    ep->nodetype = en_ref;		}	    }	}    }    return ep;}#endif /* CPU_DEFINED *//* *	 optnode() - delete useless expressions and combine constants. * *	 optnode will delete expressions such as *	  x + 0, *	  x - 0, *	  x * 0, *	  x * 1, *	  0 / x, *	  x / 1, *	  x mod 0, *	  etc from the tree pointed to by node and combine obvious *	 constant operations. It cannot combine name and label constants *	 but will combine icon type nodes. */static EXPR *optnode P1 (EXPR *, ep){    IVAL    val, sc;    EXPR   *ep0, *ep1, *ep2;    TYP    *tp = ep->etp;    switch (ep->nodetype) {    case en_uminus:	ep0 = ep->v.p[0];	if (ep0->nodetype == en_sub)	{	    /*	     *  -(a-b)  => b-a	     */	    ep1 = ep0->v.p[0];	    ep0->v.p[0] = ep0->v.p[1];	    ep0->v.p[1] = ep1;	    ep = optnode (ep0);	    return ep;	}	/*lint -fallthrough*/    case en_compl:	ep0 = ep->v.p[0];	if (ep0->nodetype == ep->nodetype) {	    /*	     *  -(-a)   => a	     *  ~(~a)   => a	     */	    ep = ep0->v.p[0];	    return optnode (ep);	}	switch (ep0->nodetype) {	case en_cond:	    	    /*	     *  -(a ? b : c)    =>  a ? -b : -c	     *  ~(a ? b : c)    =>  a ? ~b : ~c	     */ 	    ep1 = ep0->v.p[1];	    ep1->v.p[0] = mk_node (ep->nodetype, ep1->v.p[0], NIL_EXPR, tp);	    ep1->v.p[1] = mk_node (ep->nodetype, ep1->v.p[1], NIL_EXPR, tp);
	    ep = ep0;	    return optnode (ep);	default:	    if (is_icon (ep0) || is_fcon (ep0)) {		ep = dooper (ep);		return ep;	    }	}

⌨️ 快捷键说明

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