📄 optimize.c
字号:
*/ ep->nodetype = en_compl; ep = optnode (ep); #endif /* LONGLONG_BOOTSTRAP */ } break; default: CANNOT_REACH_HERE (); } return ep; } break; case en_lt: case en_le: case en_gt: case en_ge: if (is_icon (ep->v.p[0])) { swap_nodes (ep); } ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; /* * constant expressions */ if ((is_icon (ep0) && is_icon (ep1)) || (is_fcon (ep0) && is_fcon (ep1))) { ep = dooper (ep); return ep; } if (is_unsigned_type (ep0->etp) && is_icon (ep1) && (ep1->v.u == Ox0UL)) { switch (ep->nodetype) { case en_lt: /* * a < 0 => 0 */ ep->v.i = 0L; ep->nodetype = en_icon; break; case en_le: /* * a <= 0 => a == 0 */ ep->nodetype = en_eq; ep = optnode (ep); break; case en_gt: /* * a > 0 => a != 0 */ ep->nodetype = en_ne; ep = optnode (ep); break; case en_ge: /* * a >= 1 => 1 */ ep->v.i = 1L; ep->nodetype = en_icon; break; default: CANNOT_REACH_HERE (); } } break; case en_lsh: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep0) && is_icon (ep1)) { ep = dooper (ep); return ep; } if (is_icon (ep1)) { if (ep1->v.i == 0L) { /* * a << 0 => a */ ep = optnode (ep0); return ep; } if (ep1->v.i >= (tp->size*8)) { /* * a << n => a, 0 */ ep1->v.i = 0; ep1->nodetype = en_icon; ep->nodetype = en_comma; ep = optnode (ep); return ep; } } break; case en_rsh: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep0) && is_icon (ep1)) { ep = dooper (ep); return ep; } if (is_icon (ep1)) { if (ep1->v.i == 0L) { /* * a >> 0 => a */ ep = optnode (ep0); return ep; } if ((ep1->v.i >= (tp->size*8)) && is_unsigned_type (tp)) { /* * a >> n => a, 0 (unsigned) */ ep1->v.i = 0; ep1->nodetype = en_icon; ep->nodetype = en_comma; ep = optnode (ep); return ep; } } break; case en_cond: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep0)) { if (ep0->v.i) { /* * 1 ? x, y => x */ ep = optnode (ep1->v.p[0]); } else { /* * 0 ? x, y => y */ ep = optnode (ep1->v.p[1]); } return ep; } break; case en_asadd: case en_assub: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep1)) { if (ep1->v.i == 0L) { /* * x += 0 => x */ ep = optnode (ep0->v.p[0]); return ep; } } break; case en_asand: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep1)) { if (ep1->v.i == 0L) { /* * x &= 0 => x = 0 */ ep->nodetype = en_assign; ep = optnode (ep); return ep; } #ifndef LONGLONG_BOOTSTRAP if (ep1->v.i == (IVAL) ~(UVAL) 0x0UL) { /* * x &= ~0 => x */ ep = optnode (ep0->v.p[0]); return ep; } #endif /* LONGLONG_BOOTSTRAP */ } break; case en_asor: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep1)) { if (ep1->v.i == 0L) { /* * x |= 0 => x */ ep = optnode (ep0->v.p[0]); return ep; } #ifndef LONGLONG_BOOTSTRAP if (ep1->v.i == (IVAL) ~(UVAL) 0x0UL) { /* * x |= ~0 => x = ~0 */ ep->nodetype = en_assign; ep = optnode (ep); return ep; } #endif /* LONGLONG_BOOTSTRAP */ } break; case en_asmul: case en_asmul2: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep1)) { if (ep1->v.i == 0L) { /* * x *= 0 => x = 0 */ ep->nodetype = en_assign; ep = optnode (ep); return ep; } if (ep1->v.i == 1L) { /* * x *= 1 => x */ ep = optnode (ep0->v.p[0]); return ep; } sc = (IVAL) pwrof2 (ep1->v.i); if (sc != (IVAL) -1) { /* * a *= (2**n) => a <<= n */ ep->v.p[1]->v.i = sc; ep->nodetype = en_aslsh; return optnode (ep); } } break; case en_comma: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep0)) { /* * constant, x => x */ ep = optnode (ep1); return ep; } break; case en_asrsh: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep1)) { if (ep1->v.i == 0L) { /* * x <<= 0 => x */ ep = optnode (ep0->v.p[0]); return ep; } if ((ep1->v.i > tp->size*8) && is_unsigned_type (tp)) { /* * x <<= n => x = 0 */ ep1->v.i = 0; ep->nodetype = en_assign; ep = optnode (ep); return ep; } } break; case en_aslsh: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep1)) { if (ep1->v.i == 0L) { /* * x <<= 0 => x */ ep = optnode (ep0->v.p[0]); return ep; } if (ep1->v.i >= (tp->size*8)) { /* * x <<= n => x = 0 */ ep1->v.i = 0; ep->nodetype = en_assign; ep = optnode (ep); return ep; } } break; case en_asxor: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep1)) { if (ep1->v.i == 0L) { /* * x ^= 0 => x */ ep = optnode (ep0->v.p[0]); return ep; }#ifndef LONGLONG_BOOTSTRAP if (ep1->v.i == (IVAL) ~(UVAL) 0x0UL) { /* * x ^= ~0 => ~x */ ep->nodetype = en_compl; ep = optnode (ep); return ep; }#endif /* LONGLONG_BOOTSTRAP */ } break; case en_asdiv: case en_asdiv2: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep1)) { if (ep1->v.i == 1L) { /* * x /= 1 => x */ ep = optnode (ep0->v.p[0]); return ep; } } break; case en_asmod: ep0 = ep->v.p[0]; ep1 = ep->v.p[1]; if (is_icon (ep1)) { if (is_unsigned_type (tp)) { sc = (IVAL) pwrof2 (ep1->v.i); if (sc != (IVAL) -1) { /* * x %= (y**2) => x &= (y-1) */ ep->v.p[1]->v.u = bitmask ((BITSIZE) sc); ep->nodetype = en_asand; return optnode (ep); } } } break; case en_fcall: case en_call:
case en_usercall: case en_list: case en_assign: case en_ref: case en_ainc: case en_adec: case en_deref: break; case en_fieldref: /* * If possible reduce bit-field references to ordinary * references as they are much more efficient */#ifdef CPU_DEFINED ep1 = simplify_fieldref (ep, tp_char, tp_uchar); if (ep1 == NIL_EXPR) { ep1 = simplify_fieldref (ep, tp_short, tp_ushort); if (ep1 == NIL_EXPR) { ep1 = simplify_fieldref (ep, tp_long, tp_ulong); } } return ep1 ? ep1 : ep;#else return ep;#endif default: break; } return ep;}EXPR *opt0 P1 (EXPR *, ep){ return walkexpr (ep, optnode);}/* * xfold() will remove constant nodes and return the values to the * calling routines. */static IVAL xfold P1 (EXPR *, ep){ IVAL i; if (ep == NIL_EXPR) { return 0L; } switch (ep->nodetype) { case en_icon: i = ep->v.i; ep->v.i = 0L; return i; case en_add: i = xfold (ep->v.p[0]) + xfold (ep->v.p[1]); return i; case en_sub: return xfold (ep->v.p[0]) - xfold (ep->v.p[1]); case en_mul: if (is_icon (ep->v.p[0])) { return xfold (ep->v.p[1]) * ep->v.p[0]->v.i; } else if (is_icon (ep->v.p[1])) { return xfold (ep->v.p[0]) * ep->v.p[1]->v.i; } /*lint -fallthrough */ case en_lsh: case en_rsh: case en_div: case en_mod: case en_asadd: case en_assub: case en_asmul: case en_asmul2: case en_asdiv: case en_asdiv2: case en_asmod: case en_and: case en_land: case en_or: case en_lor: case en_xor: case en_asand: case en_asor: case en_asxor: case en_comma: case en_list: case en_fcall: case en_call:
case en_usercall: case en_assign: case en_eq: case en_ne: case en_lt: case en_le: case en_gt: case en_ge: ep->v.p[1] = fold_const (ep->v.p[1]); /*lint -fallthrough */ case en_ref: case en_fieldref: case en_compl: case en_test: case en_not: case en_deref: case en_cast: ep->v.p[0] = fold_const (ep->v.p[0]); return 0L; case en_uminus: return -xfold (ep->v.p[0]); default: break; } return 0L;}/* * reorganise an expression for optimal constant grouping. */static EXPR *fold_const P1 (EXPR *, ep){ EXPR *ep1; IVAL i; if (ep == NIL_EXPR) { return ep; } switch (ep->nodetype) { case en_add: if (is_icon (ep->v.p[0])) { swap_nodes (ep); } if (is_icon (ep->v.p[1])) { ep->v.p[1]->v.i += xfold (ep->v.p[0]); return ep; } break; case en_sub: if (is_icon (ep->v.p[0])) { ep->v.p[0]->v.i -= xfold (ep->v.p[1]); return ep; } if (is_icon (ep->v.p[1])) { ep->v.p[1]->v.i -= xfold (ep->v.p[0]); return ep; } break; default: break; } i = xfold (ep); if (i != 0L) { /* * strip_icon() is in fact harmless here since this value is * just added to ep * * consider in 16-bit mode: * * int day, year; * day = 365 * (year - 1970); * * and look at the code, which is transformed to * * day = 365*year + 1846; * * which works if the multiplication returns the lower 16 bits * of the result correctly. */ i = strip_icon (i, ep->etp); ep1 = mk_icon (i, ep->etp); ep = mk_node (en_add, ep, ep1, ep->etp); } return ep;}/* * apply all constant optimizations. */EXPR *constantopt P1 (EXPR *, ep){ ep = fold_const (ep); return opt0 (ep);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -