/* * NAME: optimize->ctest() * DESCRIPTION: test a constant expression */ static bool opt_ctest(node *n) { if (n->type != N_INT) { node_toint(n, (Int) (n->type != N_NIL && (n->type != T_FLOAT || !NFLT_ISZERO(n)))); } return (n->l.number != 0); }
/* * NAME: optimize->tst() * DESCRIPTION: optimize a tst operation */ static node *opt_tst(node *n) { node *m; switch (n->type) { case N_INT: n->l.number = (n->l.number != 0); return n; case N_FLOAT: node_toint(n, (Int) !NFLT_ISZERO(n)); return n; case N_STR: node_toint(n, (Int) TRUE); return n; case N_NIL: node_toint(n, (Int) FALSE); return n; case N_TST: case N_NOT: case N_LAND: case N_EQ: case N_EQ_INT: case N_EQ_FLOAT: case N_NE: case N_NE_INT: case N_NE_FLOAT: case N_GT: case N_GT_INT: case N_GT_FLOAT: case N_GE: case N_GE_INT: case N_GE_FLOAT: case N_LT: case N_LT_INT: case N_LT_FLOAT: case N_LE: case N_LE_INT: case N_LE_FLOAT: return n; case N_COMMA: n->mod = T_INT; n->r.right = opt_tst(n->r.right); return n; default: m = node_new(n->line); m->type = N_TST; m->mod = T_INT; m->l.left = n; return m; } }
/* * NAME: optimize->const() * DESCRIPTION: check if a condition is a constant */ static int opt_const(node *n) { if (n->type == N_COMMA) { n = n->r.right; } switch (n->type) { case N_INT: return (n->l.number != 0); case N_FLOAT: return (!NFLT_ISZERO(n)); case N_STR: return TRUE; case N_NIL: return FALSE; default: return -1; } }
/* * NAME: optimize->binop() * DESCRIPTION: optimize a binary operator expression */ static Uint opt_binop(node **m) { node *n, *t; Uint d1, d2, d; Float f1, f2; n = *m; if (n->type == N_ADD && n->r.right->type == N_ADD && n->l.left->mod == n->r.right->mod && (n->mod == T_STRING || (n->mod & T_REF) != 0)) { /* * a + (b + c) --> (a + b) + c * the order in which these are added won't affect the final result */ t = n->l.left; n->l.left = n->r.right; n->r.right = n->l.left->r.right; n->l.left->r.right = n->l.left->l.left; n->l.left->l.left = t; } d1 = opt_expr(&n->l.left, FALSE); d2 = opt_expr(&n->r.right, FALSE); if (n->type == N_SUM) { if (n->l.left->type == N_RANGE) { d1 = max2(d1, 3); } else if (n->l.left->type != N_SUM) { d1++; } if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); } else { d2++; } return d1 + d2; } if (n->type == N_ADD) { if (n->r.right->type == N_STR && (n->l.left->type == N_ADD || n->l.left->type == N_SUM) && n->l.left->r.right->type == N_STR) { /* (x + s1) + s2 */ node_tostr(n->r.right, str_add(n->l.left->r.right->l.string, n->r.right->l.string)); n->l.left = n->l.left->l.left; return d1; } if (n->l.left->mod == T_STRING || (n->l.left->mod & T_REF) != 0) { /* * see if the summand operator can be used */ switch (n->l.left->type) { case N_ADD: n->l.left->type = N_SUM; d1 += 2; /* SUM_SIMPLE on both sides */ if (n->l.left->l.left->type == N_RANGE) { d1++; } n->type = N_SUM; if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); /* at least 3 */ } else { d2++; /* add SUM_SIMPLE */ } return d1 + d2; case N_FUNC: if (n->l.left->r.number == kd_allocate || n->l.left->r.number == kd_allocate_int || n->l.left->r.number == kd_allocate_float) { t = n->l.left->l.left->r.right; if (t != (node *) NULL && t->type != N_PAIR && t->type != N_SPREAD && t->mod == T_INT) { d1++; /* add SUM_ALLOCATE */ n->type = N_SUM; if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); /* at least 3 */ } else { d2++; /* add SUM_SIMPLE */ } return d1 + d2; } } /* fall through */ default: if (n->r.right->type != N_RANGE && n->r.right->type != N_AGGR) { if (n->r.right->type != N_FUNC || (n->r.right->r.number != kd_allocate && n->r.right->r.number != kd_allocate_int && n->r.right->r.number != kd_allocate_float)) { break; } t = n->r.right->l.left->r.right; if (t == (node *) NULL || t->type == N_PAIR || t->type == N_SPREAD || t->mod != T_INT) { break; } } /* fall through */ case N_AGGR: d1++; /* add SUM_SIMPLE */ n->type = N_SUM; if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); /* at least 3 */ } else { d2++; /* add SUM_SIMPLE */ } return d1 + d2; case N_RANGE: d1 = max2(d1, 3); /* at least 3 */ /* fall through */ case N_SUM: n->type = N_SUM; if (n->r.right->type == N_RANGE) { d2 = max2(d2, 3); /* at least 3 */ } else { d2++; /* add SUM_SIMPLE */ } return d1 + d2; } } } if (n->l.left->flags & F_CONST) { if (n->r.right->flags & F_CONST) { /* c1 . c2 */ return opt_binconst(m); } switch (n->type) { case N_ADD: if (!T_ARITHMETIC(n->l.left->mod) || !T_ARITHMETIC(n->r.right->mod)) { break; } /* fall through */ case N_ADD_INT: case N_ADD_FLOAT: case N_AND: case N_AND_INT: case N_EQ: case N_EQ_INT: case N_EQ_FLOAT: case N_MULT: case N_MULT_INT: case N_MULT_FLOAT: case N_NE: case N_NE_INT: case N_NE_FLOAT: case N_OR: case N_OR_INT: case N_XOR: case N_XOR_INT: /* swap constant to the right */ t = n->l.left; n->l.left = n->r.right; n->r.right = t; d = d1; d1 = d2; d2 = d; break; } } d = max2(d1, d2 + 1); if ((n->r.right->type == N_INT && n->r.right->l.number == 0 && n->l.left->mod == T_INT) || (n->r.right->type == N_FLOAT && NFLT_ISZERO(n->r.right) && n->l.left->mod == T_FLOAT) || (n->r.right->type == nil_node && n->r.right->l.number == 0 && n->l.left->mod != T_MIXED && T_POINTER(n->l.left->mod))) { /* * int == 0, float == 0.0, ptr == nil */ switch (n->type) { case N_EQ: case N_EQ_INT: case N_EQ_FLOAT: *m = opt_not(n->l.left); return d1; case N_NE: case N_NE_INT: case N_NE_FLOAT: *m = opt_tst(n->l.left); return d1; } } if (T_ARITHMETIC(n->mod) && n->mod == n->l.left->mod && n->mod == n->r.right->mod) { if (n->r.right->flags & F_CONST) { /* x . c */ if ((n->type == n->l.left->type || (n->mod == T_INT && n->l.left->mod == T_INT && n->type == n->l.left->type + 1)) && (n->l.left->r.right->flags & F_CONST)) { /* (x . c1) . c2 */ switch (n->type) { case N_ADD_FLOAT: case N_SUB_FLOAT: NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.add(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; break; case N_ADD_INT: case N_SUB_INT: case N_LSHIFT_INT: case N_RSHIFT_INT: n->l.left->r.right->l.number += n->r.right->l.number; *m = n->l.left; d = d1; break; case N_AND_INT: n->l.left->r.right->l.number &= n->r.right->l.number; *m = n->l.left; d = d1; break; case N_DIV_FLOAT: case N_MULT_FLOAT: NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.mult(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; break; case N_DIV_INT: case N_MULT_INT: n->l.left->r.right->l.number *= n->r.right->l.number; *m = n->l.left; d = d1; break; case N_OR_INT: n->l.left->r.right->l.number |= n->r.right->l.number; *m = n->l.left; d = d1; break; case N_XOR_INT: n->l.left->r.right->l.number ^= n->r.right->l.number; *m = n->l.left; d = d1; break; } } else { switch (n->type) { case N_ADD_FLOAT: if (n->l.left->type == N_SUB_FLOAT) { if (n->l.left->l.left->type == N_FLOAT) { /* (c1 - x) + c2 */ NFLT_GET(n->l.left->l.left, f1); NFLT_GET(n->r.right, f2); f1.add(f2); NFLT_PUT(n->l.left->l.left, f1); *m = n->l.left; return d1; } if (n->l.left->r.right->type == N_FLOAT) { /* (x - c1) + c2 */ NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.sub(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; } } break; case N_ADD_INT: if (n->l.left->type == N_SUB || n->l.left->type == N_SUB_INT) { if (n->l.left->l.left->type == N_INT) { /* (c1 - x) + c2 */ n->l.left->l.left->l.number += n->r.right->l.number; *m = n->l.left; return d1; } if (n->l.left->r.right->type == N_INT) { /* (x - c1) + c2 */ n->l.left->r.right->l.number -= n->r.right->l.number; *m = n->l.left; d = d1; } } break; case N_DIV_FLOAT: if (n->l.left->type == N_MULT_FLOAT && n->l.left->r.right->type == N_FLOAT && !NFLT_ISZERO(n->r.right)) { /* (x * c1) / c2 */ NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.div(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; } break; case N_MULT_FLOAT: if (n->l.left->type == N_DIV_FLOAT) { if (n->l.left->l.left->type == N_FLOAT) { /* (c1 / x) * c2 */ NFLT_GET(n->l.left->l.left, f1); NFLT_GET(n->r.right, f2); f1.mult(f2); NFLT_PUT(n->l.left->l.left, f1); *m = n->l.left; return d1; } if (n->l.left->r.right->type == N_FLOAT && !NFLT_ISZERO(n->l.left->r.right)) { /* (x / c1) * c2 */ NFLT_GET(n->r.right, f1); NFLT_GET(n->l.left->r.right, f2); f1.div(f2); NFLT_PUT(n->r.right, f1); n->l.left = n->l.left->l.left; d = d1; } } break; case N_SUB_FLOAT: if (n->l.left->type == N_ADD_FLOAT && n->l.left->r.right->type == N_FLOAT) { /* (x + c1) - c2 */ NFLT_GET(n->l.left->r.right, f1); NFLT_GET(n->r.right, f2); f1.sub(f2); NFLT_PUT(n->l.left->r.right, f1); *m = n->l.left; d = d1; } break; case N_SUB_INT: if (n->l.left->type == N_ADD_INT && n->l.left->r.right->type == N_INT) { /* (x + c1) - c2 */ n->l.left->r.right->l.number -= n->r.right->l.number; *m = n->l.left; d = d1; } break; } } } else if (n->l.left->flags & F_CONST) { /* c . x */ switch (n->type) { case N_SUB_FLOAT: if (n->r.right->type == N_SUB_FLOAT) { if (n->r.right->l.left->type == N_FLOAT) { /* c1 - (c2 - x) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->l.left, f2); f1.sub(f2); n->type = N_ADD; n->l.left = n->r.right->r.right; n->r.right = n->r.right->l.left; NFLT_PUT(n->r.right, f1); d = d2; } else if (n->r.right->r.right->type == N_FLOAT) { /* c1 - (x - c2) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->r.right, f2); f1.add(f2); NFLT_PUT(n->l.left, f1); n->r.right = n->r.right->l.left; return d2 + 1; } } else if (n->r.right->type == N_ADD_FLOAT && n->r.right->r.right->type == N_FLOAT) { /* c1 - (x + c2) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->r.right, f2); f1.sub(f2); NFLT_PUT(n->l.left, f1); n->r.right = n->r.right->l.left; return d2 + 1; } break; case N_SUB_INT: if ((n->r.right->type == N_SUB || n->r.right->type == N_SUB_INT)) { if (n->r.right->l.left->type == N_INT) { /* c1 - (c2 - x) */ n->r.right->l.left->l.number -= n->l.left->l.number; n->type = n->r.right->type; n->l.left = n->r.right->r.right; n->r.right = n->r.right->l.left; d = d2; } else if (n->r.right->r.right->type == N_INT) { /* c1 - (x - c2) */ n->l.left->l.number += n->r.right->r.right->l.number; n->r.right->r.right = n->r.right->l.left; n->r.right->l.left = n->l.left; *m = n->r.right; return d2 + 1; } } else if (n->r.right->type == N_ADD_INT && n->r.right->r.right->type == N_INT) { /* c1 - (x + c2) */ n->l.left->l.number -= n->r.right->r.right->l.number; n->r.right = n->r.right->l.left; return d2 + 1; } break; case N_DIV_FLOAT: if (n->r.right->type == N_DIV_FLOAT) { if (n->r.right->l.left->type == N_FLOAT && !NFLT_ISZERO(n->r.right->l.left)) { /* c1 / (c2 / x) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->l.left, f2); f1.div(f2); n->type = N_MULT; n->l.left = n->r.right->r.right; n->r.right = n->r.right->l.left; NFLT_PUT(n->r.right, f1); d = d2; } else if (n->r.right->r.right->type == N_FLOAT) { /* c1 / (x / c2) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->r.right, f2); f1.mult(f2); NFLT_PUT(n->l.left, f1); n->r.right = n->r.right->l.left; return d2 + 1; } } else if (n->r.right->type == N_MULT_FLOAT && n->r.right->r.right->type == N_FLOAT && !NFLT_ISZERO(n->r.right->r.right)) { /* c1 / (x * c2) */ NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right->r.right, f2); f1.div(f2); NFLT_PUT(n->l.left, f1); n->r.right = n->r.right->l.left; return d2 + 1; } break; } } n = *m; if (T_ARITHMETIC(n->l.left->mod) && (n->r.right->flags & F_CONST)) { switch (n->type) { case N_ADD: case N_ADD_FLOAT: case N_SUB: case N_SUB_FLOAT: if (NFLT_ISZERO(n->r.right)) { *m = n->l.left; d = d1; } break; case N_ADD_INT: case N_SUB_INT: case N_LSHIFT_INT: case N_RSHIFT_INT: case N_XOR_INT: if (n->r.right->l.number == 0) { *m = n->l.left; d = d1; } break; case N_AND_INT: if (n->r.right->l.number == 0) { n->type = N_COMMA; return opt_expr(m, FALSE); } if (n->r.right->l.number == -1) { *m = n->l.left; d = d1; } break; case N_MULT: case N_MULT_FLOAT: if (NFLT_ISZERO(n->r.right)) { n->type = N_COMMA; return opt_expr(m, FALSE); } /* fall through */ case N_DIV: case N_DIV_FLOAT: if (NFLT_ISONE(n->r.right)) { *m = n->l.left; d = d1; } break; case N_MULT_INT: if (n->r.right->l.number == 0) { n->type = N_COMMA; return opt_expr(m, FALSE); } /* fall through */ case N_DIV_INT: if (n->r.right->l.number == 1) { *m = n->l.left; d = d1; } break; case N_MOD_INT: if (n->r.right->l.number == 1) { n->r.right->l.number = 0; n->type = N_COMMA; return opt_expr(m, FALSE); } break; case N_OR_INT: if (n->r.right->l.number == -1) { n->type = N_COMMA; return opt_expr(m, FALSE); } if (n->r.right->l.number == 0) { *m = n->l.left; d = d1; } break; } } } return d; }
/* * NAME: optimize->binconst() * DESCRIPTION: optimize a binary operator constant expression */ static Uint opt_binconst(node **m) { node *n; Float f1, f2; bool flag; n = *m; if (n->l.left->type != n->r.right->type) { if (n->type == N_EQ) { node_toint(n, (Int) FALSE); } else if (n->type == N_NE) { node_toint(n, (Int) TRUE); } else { return 2; /* runtime error expected */ } return 1; } switch (n->l.left->type) { case N_INT: switch (n->type) { case N_ADD_INT: n->l.left->l.number += n->r.right->l.number; break; case N_AND_INT: n->l.left->l.number &= n->r.right->l.number; break; case N_DIV_INT: if (n->r.right->l.number == 0) { return 2; /* runtime error: division by 0 */ } n->l.left->l.number /= n->r.right->l.number; break; case N_EQ_INT: n->l.left->l.number = (n->l.left->l.number == n->r.right->l.number); break; case N_GE_INT: n->l.left->l.number = (n->l.left->l.number >= n->r.right->l.number); break; case N_GT_INT: n->l.left->l.number = (n->l.left->l.number > n->r.right->l.number); break; case N_LE_INT: n->l.left->l.number = (n->l.left->l.number <= n->r.right->l.number); break; case N_LSHIFT_INT: n->l.left->l.number <<= n->r.right->l.number; break; case N_LT_INT: n->l.left->l.number = (n->l.left->l.number < n->r.right->l.number); break; case N_MOD_INT: if (n->r.right->l.number == 0) { return 2; /* runtime error: % 0 */ } n->l.left->l.number %= n->r.right->l.number; break; case N_MULT_INT: n->l.left->l.number *= n->r.right->l.number; break; case N_NE_INT: n->l.left->l.number = (n->l.left->l.number != n->r.right->l.number); break; case N_OR_INT: n->l.left->l.number |= n->r.right->l.number; break; case N_RSHIFT_INT: n->l.left->l.number >>= n->r.right->l.number; break; case N_SUB_INT: n->l.left->l.number -= n->r.right->l.number; break; case N_XOR_INT: n->l.left->l.number ^= n->r.right->l.number; break; default: return 2; /* runtime error expected */ } *m = n->l.left; (*m)->line = n->line; return 1; case N_FLOAT: NFLT_GET(n->l.left, f1); NFLT_GET(n->r.right, f2); switch (n->type) { case N_ADD: case N_ADD_FLOAT: f1.add(f2); break; case N_DIV: case N_DIV_FLOAT: if (NFLT_ISZERO(n->r.right)) { return 2; /* runtime error: division by 0.0 */ } f1.div(f2); break; case N_EQ: case N_EQ_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) == 0)); break; case N_GE: case N_GE_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) >= 0)); break; case N_GT: case N_GT_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) > 0)); break; case N_LE: case N_LE_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) <= 0)); break; case N_LT: case N_LT_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) < 0)); break; case N_MULT: case N_MULT_FLOAT: f1.mult(f2); break; case N_NE: case N_NE_FLOAT: node_toint(n->l.left, (Int) (f1.cmp(f2) != 0)); break; case N_SUB: case N_SUB_FLOAT: f1.sub(f2); break; default: return 2; /* runtime error expected */ } NFLT_PUT(n->l.left, f1); *m = n->l.left; (*m)->line = n->line; return 1; case N_STR: switch (n->type) { case N_ADD: node_tostr(n, str_add(n->l.left->l.string, n->r.right->l.string)); return 1; case N_EQ: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) == 0); break; case N_GE: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) >= 0); break; case N_GT: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) > 0); break; case N_LE: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) <= 0); break; case N_LT: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) < 0); break; case N_NE: flag = (str_cmp(n->l.left->l.string, n->r.right->l.string) != 0); break; default: return 2; /* runtime error expected */ } node_toint(n, (Int) flag); return 1; case N_NIL: switch (n->type) { case N_EQ: flag = TRUE; break; case N_NE: flag = FALSE; break; default: return 2; /* runtime error expected */ } node_toint(n, (Int) flag); return 1; } return 2; }
/* * NAME: optimize->asgnexp() * DESCRIPTION: optimize an assignment expression */ static Uint opt_asgnexp(node **m, bool pop) { node *n, *t; Uint d1, d2; n = *m; d2 = opt_expr(&n->r.right, FALSE); if ((n->r.right->type == N_INT || n->r.right->type == N_FLOAT) && n->l.left->mod == n->r.right->mod) { switch (n->type) { case N_ADD_EQ: case N_ADD_EQ_FLOAT: if (NFLT_ISZERO(n->r.right)) { *m = n->l.left; return opt_expr(m, pop); } if (NFLT_ISONE(n->r.right)) { n->type = N_ADD_EQ_1_FLOAT; return opt_lvalue(n->l.left) + 1; } if (NFLT_ISMONE(n->r.right)) { n->type = N_SUB_EQ_1_FLOAT; return opt_lvalue(n->l.left) + 1; } break; case N_ADD_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } if (n->r.right->l.number == 1) { n->type = N_ADD_EQ_1_INT; return opt_lvalue(n->l.left) + 1; } if (n->r.right->l.number == -1) { n->type = N_SUB_EQ_1_INT; return opt_lvalue(n->l.left) + 1; } break; case N_AND_EQ_INT: if (n->r.right->l.number == 0) { n->type = N_ASSIGN; return opt_expr(m, pop); } if (n->r.right->l.number == -1) { *m = n->l.left; return opt_expr(m, pop); } break; case N_MULT_EQ: case N_MULT_EQ_FLOAT: if (NFLT_ISZERO(n->r.right)) { n->type = N_ASSIGN; return opt_expr(m, pop); } /* fall through */ case N_DIV_EQ: case N_DIV_EQ_FLOAT: if (NFLT_ISONE(n->r.right)) { *m = n->l.left; return opt_expr(m, pop); } break; case N_MULT_EQ_INT: if (n->r.right->l.number == 0) { n->type = N_ASSIGN; return opt_expr(m, pop); } /* fall through */ case N_DIV_EQ_INT: if (n->r.right->l.number == 1) { *m = n->l.left; return opt_expr(m, pop); } break; case N_LSHIFT_EQ_INT: case N_RSHIFT_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } break; case N_MOD_EQ_INT: if (n->r.right->l.number == 1) { n->type = N_ASSIGN; n->r.right->l.number = 0; return opt_expr(m, pop); } break; case N_OR_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } if (n->r.right->l.number == -1) { n->type = N_ASSIGN; return opt_expr(m, pop); } break; case N_SUB_EQ: case N_SUB_EQ_FLOAT: if (NFLT_ISZERO(n->r.right)) { *m = n->l.left; return opt_expr(m, pop); } if (NFLT_ISONE(n->r.right)) { n->type = N_SUB_EQ_1_FLOAT; return opt_lvalue(n->l.left) + 1; } if (NFLT_ISMONE(n->r.right)) { n->type = N_ADD_EQ_1_FLOAT; return opt_lvalue(n->l.left) + 1; } break; case N_SUB_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } if (n->r.right->l.number == 1) { n->type = N_SUB_EQ_1_INT; return opt_lvalue(n->l.left) + 1; } if (n->r.right->l.number == -1) { n->type = N_ADD_EQ_1_INT; return opt_lvalue(n->l.left) + 1; } break; case N_XOR_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } break; } } d1 = opt_lvalue(n->l.left) + 1; if (n->type == N_SUM_EQ) { d1++; return max2(d1, ((d1 < 6) ? d1 : 6) + d2); } if (n->type == N_ADD_EQ && (n->mod == T_STRING || (n->mod & T_REF) != 0) && (n->r.right->mod == T_STRING || (n->r.right->mod & T_REF) != 0 || n->r.right->type == N_RANGE)) { /* * see if the summand operator can be used */ switch (n->r.right->type) { case N_ADD: n->r.right->type = N_SUM; d2 += 2; /* SUM_SIMPLE on both sides */ if (n->r.right->l.left->type == N_RANGE) { d1++; } n->type = N_SUM_EQ; d1++; /* add SUM_SIMPLE */ return max2(d1, ((d1 < 6) ? d1 : 6) + d2); case N_AGGR: d2++; /* add SUM_SIMPLE */ n->type = N_SUM_EQ; d1++; /* add SUM_SIMPLE */ return max2(d1, ((d1 < 6) ? d1 : 6) + d2); case N_RANGE: d2 = max2(d2, 3); /* at least 3 */ /* fall through */ case N_SUM: n->type = N_SUM_EQ; d1++; /* add SUM_SIMPLE */ return max2(d1, ((d1 < 6) ? d1 : 6) + d2); case N_FUNC: if (n->r.right->r.number == kd_allocate || n->r.right->r.number == kd_allocate_int || n->r.right->r.number == kd_allocate_float) { t = n->r.right->l.left->r.right; if (t != (node *) NULL && t->type != N_PAIR && t->type != N_SPREAD && t->mod == T_INT) { d2++; /* add SUM_ALLOCATE */ n->type = N_SUM_EQ; d1++; /* add SUM_SIMPLE */ return max2(d1, ((d1 < 6) ? d1 : 6) + d2); } } break; } } return max2(d1, ((d1 < 5) ? d1 : 5) + d2); }
/* * NAME: optimize->asgnexp() * DESCRIPTION: optimize an assignment expression */ static Uint opt_asgnexp(node **m, bool pop) { node *n; Uint d1, d2; n = *m; d2 = opt_expr(&n->r.right, FALSE); if ((n->r.right->type == N_INT || n->r.right->type == N_FLOAT) && n->l.left->mod == n->r.right->mod) { switch (n->type) { case N_ADD_EQ: if (NFLT_ISZERO(n->r.right)) { *m = n->l.left; return opt_expr(m, pop); } if (NFLT_ISONE(n->r.right)) { n->type = N_ADD_EQ_1; return opt_lvalue(n->l.left) + 1; } if (NFLT_ISMONE(n->r.right)) { n->type = N_SUB_EQ_1; return opt_lvalue(n->l.left) + 1; } break; case N_ADD_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } if (n->r.right->l.number == 1) { n->type = N_ADD_EQ_1_INT; return opt_lvalue(n->l.left) + 1; } if (n->r.right->l.number == -1) { n->type = N_SUB_EQ_1_INT; return opt_lvalue(n->l.left) + 1; } break; case N_AND_EQ_INT: if (n->r.right->l.number == 0) { n->type = N_ASSIGN; return opt_expr(m, pop); } if (n->r.right->l.number == -1) { *m = n->l.left; return opt_expr(m, pop); } break; case N_MULT_EQ: if (NFLT_ISZERO(n->r.right)) { n->type = N_ASSIGN; return opt_expr(m, pop); } /* fall through */ case N_DIV_EQ: if (NFLT_ISONE(n->r.right)) { *m = n->l.left; return opt_expr(m, pop); } break; case N_MULT_EQ_INT: if (n->r.right->l.number == 0) { n->type = N_ASSIGN; return opt_expr(m, pop); } /* fall through */ case N_DIV_EQ_INT: if (n->r.right->l.number == 1) { *m = n->l.left; return opt_expr(m, pop); } break; case N_LSHIFT_EQ_INT: case N_RSHIFT_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } break; case N_MOD_EQ_INT: if (n->r.right->l.number == 1) { n->type = N_ASSIGN; n->r.right->l.number = 0; return opt_expr(m, pop); } break; case N_OR_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } if (n->r.right->l.number == -1) { n->type = N_ASSIGN; return opt_expr(m, pop); } break; case N_SUB_EQ: if (NFLT_ISZERO(n->r.right)) { *m = n->l.left; return opt_expr(m, pop); } if (NFLT_ISONE(n->r.right)) { n->type = N_SUB_EQ_1; return opt_lvalue(n->l.left) + 1; } if (NFLT_ISMONE(n->r.right)) { n->type = N_ADD_EQ_1; return opt_lvalue(n->l.left) + 1; } break; case N_SUB_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } if (n->r.right->l.number == 1) { n->type = N_SUB_EQ_1_INT; return opt_lvalue(n->l.left) + 1; } if (n->r.right->l.number == -1) { n->type = N_ADD_EQ_1_INT; return opt_lvalue(n->l.left) + 1; } break; case N_XOR_EQ_INT: if (n->r.right->l.number == 0) { *m = n->l.left; return opt_expr(m, pop); } break; } } d1 = opt_lvalue(n->l.left) + 1; if (n->type == N_SUM_EQ) { d1++; return max2(d1, ((d1 < 5) ? d1 : 5) + d2); } if (n->type == N_ADD_EQ && (n->mod == T_STRING || (n->mod & T_REF) != 0) && (n->r.right->mod == T_STRING || (n->r.right->mod & T_REF) != 0 || n->r.right->type == N_RANGE)) { /* * see if the summand operator can be used */ switch (n->r.right->type) { case N_ADD: n->r.right->type = N_SUM; d2 += 2; /* (-2) on both sides */ if (n->r.right->l.left->type == N_RANGE) { d1++; } n->type = N_SUM_EQ; d1++; /* add (-2) */ return max2(d1, ((d1 < 5) ? d1 : 5) + d2); case N_AGGR: d2++; /* add (-2) */ n->type = N_SUM_EQ; d1++; /* add (-2) */ return max2(d1, ((d1 < 5) ? d1 : 5) + d2); case N_RANGE: d2 = max2(d2, 3); /* at least 3 */ /* fall through */ case N_SUM: n->type = N_SUM_EQ; d1++; /* add (-2) */ return max2(d1, ((d1 < 5) ? d1 : 5) + d2); } } return max2(d1, ((d1 < 4) ? d1 : 4) + d2); }