📄 optimize.c
字号:
/* * 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 + -