/* * 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); }