示例#1
0
/*
 * 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);
}
示例#2
0
/*
 * NAME:	optimize->expr()
 * DESCRIPTION:	optimize an expression
 */
static Uint opt_expr(node **m, bool pop)
{
    Uint d1, d2, i;
    node *n;
    node **oldside, *side;
    Uint olddepth;

    n = *m;
    switch (n->type) {
    case N_FLOAT:
    case N_GLOBAL:
    case N_INT:
    case N_LOCAL:
    case N_STR:
    case N_NIL:
	return !pop;

    case N_TOINT:
    case N_CAST:
	return opt_expr(&n->l.left, FALSE);

    case N_NEG:
    case N_UMIN:
	return max2(opt_expr(&n->l.left, FALSE), 2);

    case N_CATCH:
	oldside = side_start(&side, &olddepth);
	d1 = opt_expr(&n->l.left, TRUE);
	if (d1 == 0) {
	    n->l.left = (node *) NULL;
	}
	d1 = max2(d1, side_end(&n->l.left, side, oldside, olddepth));
	if (d1 == 0) {
	    *m = node_nil();
	    (*m)->line = n->line;
	    return !pop;
	}
	return d1;

    case N_TOFLOAT:
	if (n->l.left->mod != T_INT) {
	    return opt_expr(&n->l.left, FALSE);
	}
	/* fall through */
    case N_NOT:
    case N_TST:
	if (pop) {
	    *m = n->l.left;
	    return opt_expr(m, TRUE);
	}
	return opt_expr(&n->l.left, FALSE);

    case N_TOSTRING:
	if (pop && (n->l.left->mod == T_INT || n->l.left->mod == T_FLOAT)) {
	    *m = n->l.left;
	    return opt_expr(m, TRUE);
	}
	return opt_expr(&n->l.left, FALSE);

    case N_LVALUE:
	return opt_lvalue(n->l.left);

    case N_ADD_EQ_1:
    case N_ADD_EQ_1_INT:
    case N_ADD_EQ_1_FLOAT:
    case N_SUB_EQ_1:
    case N_SUB_EQ_1_INT:
    case N_SUB_EQ_1_FLOAT:
	return opt_lvalue(n->l.left) + 1;

    case N_MIN_MIN:
	if (pop) {
	    n->type = N_SUB_EQ_1;
	}
	return opt_lvalue(n->l.left) + 1;

    case N_MIN_MIN_INT:
	if (pop) {
	    n->type = N_SUB_EQ_1_INT;
	}
	return opt_lvalue(n->l.left) + 1;

    case N_MIN_MIN_FLOAT:
	if (pop) {
	    n->type = N_SUB_EQ_1_FLOAT;
	}
	return opt_lvalue(n->l.left) + 1;

    case N_PLUS_PLUS:
	if (pop) {
	    n->type = N_ADD_EQ_1;
	}
	return opt_lvalue(n->l.left) + 1;

    case N_PLUS_PLUS_INT:
	if (pop) {
	    n->type = N_ADD_EQ_1_INT;
	}
	return opt_lvalue(n->l.left) + 1;

    case N_PLUS_PLUS_FLOAT:
	if (pop) {
	    n->type = N_ADD_EQ_1_FLOAT;
	}
	return opt_lvalue(n->l.left) + 1;

    case N_FUNC:
	m = &n->l.left->r.right;
	n = *m;
	if (n == (node *) NULL) {
	    return 1;
	}

	d1 = 0;
	for (i = 0; n->type == N_PAIR; ) {
	    oldside = side_start(&side, &olddepth);
	    d2 = opt_expr(&n->l.left, FALSE);
	    d1 = max3(d1, i + d2,
		      i + side_end(&n->l.left, side, oldside, olddepth));
	    m = &n->r.right;
	    n = n->l.left;
	    i += (n->type == N_LVALUE ||
		  (n->type == N_COMMA && n->r.right->type == N_LVALUE)) ? 6 : 1;
	    n = *m;
	}
	if (n->type == N_SPREAD) {
	    m = &n->l.left;
	}
	oldside = side_start(&side, &olddepth);
	d2 = opt_expr(m, FALSE);
	d1 = max3(d1, i + d2, i + side_end(m, side, oldside, olddepth));
	n = *m;
	if (n->type == N_LVALUE ||
	    (n->type == N_COMMA && n->r.right->type == N_LVALUE)) {
	    d1 += 2;
	}
	return d1;

    case N_INSTANCEOF:
	return opt_expr(&n->l.left, FALSE) + 1;

    case N_GE:
    case N_GT:
    case N_LE:
    case N_LT:
	if (n->l.left->mod != n->r.right->mod) {
	    return max2(opt_expr(&n->l.left, FALSE),
			opt_expr(&n->r.right, FALSE) + 1);
	}
	/* fall through */
    case N_EQ:
    case N_NE:
	if (pop) {
	    d1 = opt_expr(&n->l.left, TRUE);
	    if (d1 == 0) {
		*m = n->r.right;
		return opt_expr(m, TRUE);
	    }
	    d2 = opt_expr(&n->r.right, TRUE);
	    if (d2 == 0) {
		*m = n->l.left;
		return d1;
	    }
	    n->type = N_COMMA;
	    side_add(m, d1);
	    return d2;
	}
	return opt_binop(m);

    case N_DIV_INT:
    case N_MOD_INT:
	if (n->r.right->type == N_INT && n->r.right->l.number == 0) {
	    d1 = opt_binop(m);
	    return (d1 == 1) ? !pop : d1;
	}
	/* fall through */
    case N_ADD_INT:
    case N_ADD_FLOAT:
    case N_AND_INT:
    case N_DIV_FLOAT:
    case N_EQ_INT:
    case N_EQ_FLOAT:
    case N_GE_INT:
    case N_GE_FLOAT:
    case N_GT_INT:
    case N_GT_FLOAT:
    case N_LE_INT:
    case N_LE_FLOAT:
    case N_LSHIFT_INT:
    case N_LT_INT:
    case N_LT_FLOAT:
    case N_MULT_INT:
    case N_MULT_FLOAT:
    case N_NE_INT:
    case N_NE_FLOAT:
    case N_OR_INT:
    case N_RSHIFT_INT:
    case N_SUB_INT:
    case N_SUB_FLOAT:
    case N_XOR_INT:
	if (pop) {
	    d1 = opt_expr(&n->l.left, TRUE);
	    if (d1 == 0) {
		*m = n->r.right;
		return opt_expr(m, TRUE);
	    }
	    d2 = opt_expr(&n->r.right, TRUE);
	    if (d2 == 0) {
		*m = n->l.left;
		return d1;
	    }
	    n->type = N_COMMA;
	    side_add(m, d1);
	    return d2;
	}
	/* fall through */
    case N_ADD:
    case N_AND:
    case N_DIV:
    case N_LSHIFT:
    case N_MOD:
    case N_MULT:
    case N_OR:
    case N_RSHIFT:
    case N_SUB:
    case N_SUM:
    case N_XOR:
	d1 = opt_binop(m);
	return (d1 == 1) ? !pop : d1;

    case N_INDEX:
	if (n->l.left->type == N_STR && n->r.right->type == N_INT) {
	    if (n->r.right->l.number < 0 ||
		n->r.right->l.number >= (long) n->l.left->l.string->len) {
		return 2;
	    }
	    node_toint(n, (Int) str_index(n->l.left->l.string,
					  (long) n->r.right->l.number));
	    return !pop;
	}
	if (n->l.left->type == N_FUNC && n->r.right->mod == T_INT) {
	    if (n->l.left->r.number == kd_status) {
		n->type = N_FUNC;
		if (n->l.left->l.left->r.right != (node *) NULL) {
		    /* status(obj)[i] */
		    n = n->l.left;
		    n->type = N_STR;
		    n->r.right = n->l.left;
		    n->l.string = n->l.left->l.string;
		    n = n->r.right;
		    n->type = N_PAIR;
		    n->l.left = n->r.right;
		    n->r.right = (*m)->r.right;
		    (*m)->r.number = ((long) KFCALL << 24) | KF_STATUSO_IDX;
		} else {
		    /* status()[i] */
		    n->l.left = n->l.left->l.left;
		    n->l.left->r.right = n->r.right;
		    n->r.number = ((long) KFCALL << 24) | KF_STATUS_IDX;
		}
		return opt_expr(m, pop);
	    }
	    if (n->l.left->r.number == kd_call_trace) {
		/* call_trace()[i] */
		n->type = N_FUNC;
		n->l.left = n->l.left->l.left;
		n->l.left->r.right = n->r.right;
		n->r.number = ((long) KFCALL << 24) | KF_CALLTR_IDX;
		return opt_expr(m, pop);
	    }
	}
	return max3(opt_expr(&n->l.left, FALSE),
		    opt_expr(&n->r.right, FALSE) + 1, 3);

    case N_ADD_EQ:
    case N_ADD_EQ_INT:
    case N_ADD_EQ_FLOAT:
    case N_AND_EQ:
    case N_AND_EQ_INT:
    case N_DIV_EQ:
    case N_DIV_EQ_INT:
    case N_DIV_EQ_FLOAT:
    case N_LSHIFT_EQ:
    case N_LSHIFT_EQ_INT:
    case N_MOD_EQ:
    case N_MOD_EQ_INT:
    case N_MULT_EQ:
    case N_MULT_EQ_INT:
    case N_MULT_EQ_FLOAT:
    case N_OR_EQ:
    case N_OR_EQ_INT:
    case N_RSHIFT_EQ:
    case N_RSHIFT_EQ_INT:
    case N_SUB_EQ:
    case N_SUB_EQ_INT:
    case N_SUB_EQ_FLOAT:
    case N_SUM_EQ:
    case N_XOR_EQ:
    case N_XOR_EQ_INT:
	return opt_asgnexp(m, pop);

    case N_ASSIGN:
	if (n->l.left->type == N_AGGR) {
	    d2 = 0;
	    for (n = n->l.left->l.left; n->type == N_PAIR; n = n->r.right) {
		d1 = opt_lvalue(n->l.left);
		d2 += 2 + ((d1 < 4) ? d1 : 4);
	    }
	    d1 = opt_lvalue(n);
	    d2 += 2 + ((d1 < 4) ? d1 : 4);
	    return d2 + max2(2, opt_expr(&(*m)->r.right, FALSE));
	} else {
	    d1 = opt_lvalue(n->l.left);
	    return max2(d1, ((d1 < 4) ? d1 : 4) + opt_expr(&n->r.right, FALSE));
	}

    case N_COMMA:
	side_add(m, opt_expr(&n->l.left, TRUE));
	return opt_expr(m, pop);

    case N_LAND:
	d1 = opt_cond(&n->l.left, FALSE);
	if (n->l.left->flags & F_CONST) {
	    if (!opt_ctest(n->l.left)) {
		/* false && x */
		*m = n->l.left;
		return !pop;
	    }
	    /* true && x */
	    n->type = N_TST;
	    n->l.left = n->r.right;
	    return opt_expr(m, pop);
	}

	oldside = side_start(&side, &olddepth);
	d2 = opt_cond(&n->r.right, pop);
	if (d2 == 0) {
	    n->r.right = (node *) NULL;
	}
	d2 = max2(d2, side_end(&n->r.right, side, oldside, olddepth));
	if (d2 == 0) {
	    *m = n->l.left;
	    return opt_expr(m, TRUE);
	}
	if (n->r.right->flags & F_CONST) {
	    if (pop) {
		*m = n->l.left;
		return opt_expr(m, TRUE);
	    }
	    if (!opt_ctest(n->r.right)) {
		/* x && false */
		n->type = N_COMMA;
		return opt_expr(m, FALSE);
	    }
	    /* x && true */
	    n->type = N_TST;
	    return d1;
	}
	if (n->r.right->type == N_COMMA) {
	    n = n->r.right;
	    if ((n->r.right->flags & F_CONST) && !opt_ctest(n->r.right)) {
		/* x && (y, false) --> (x && y, false) */
		(*m)->r.right = n->l.left;
		n->l.left = *m;
		*m = n;
		return opt_expr(m, pop);
	    }
	}
	return max2(d1, d2);

    case N_LOR:
	d1 = opt_cond(&n->l.left, FALSE);
	if (n->l.left->flags & F_CONST) {
	    if (opt_ctest(n->l.left)) {
		/* true || x */
		*m = n->l.left;
		return !pop;
	    }
	    /* false || x */
	    n->type = N_TST;
	    n->l.left = n->r.right;
	    return opt_expr(m, pop);
	}

	oldside = side_start(&side, &olddepth);
	d2 = opt_cond(&n->r.right, pop);
	if (d2 == 0) {
	    n->r.right = (node *) NULL;
	}
	d2 = max2(d2, side_end(&n->r.right, side, oldside, olddepth));
	if (d2 == 0) {
	    *m = n->l.left;
	    return opt_expr(m, TRUE);
	}
	if (n->r.right->flags & F_CONST) {
	    if (pop) {
		*m = n->l.left;
		return opt_expr(m, TRUE);
	    }
	    if (opt_ctest(n->r.right)) {
		/* x || true */
		n->type = N_COMMA;
		return opt_expr(m, FALSE);
	    }
	    /* x || false */
	    n->type = N_TST;
	    return d1;
	}
	if (n->r.right->type == N_COMMA) {
	    n = n->r.right;
	    if ((n->r.right->flags & F_CONST) && opt_ctest(n->r.right)) {
		/* x || (y, true) --> (x || y, true) */
		(*m)->r.right = n->l.left;
		n->l.left = *m;
		*m = n;
		return opt_expr(m, pop);
	    }
	}
	return max2(d1, d2);

    case N_QUEST:
	i = opt_cond(&n->l.left, FALSE);
	if (n->l.left->flags & F_CONST) {
	    if (opt_ctest(n->l.left)) {
		*m = n->r.right->l.left;
	    } else {
		*m = n->r.right->r.right;
	    }
	    return opt_expr(m, pop);
	}
	if (n->l.left->type == N_COMMA && (n->l.left->r.right->flags & F_CONST))
	{
	    side_add(&n->l.left, i);
	    if (opt_ctest(n->l.left)) {
		*m = n->r.right->l.left;
	    } else {
		*m = n->r.right->r.right;
	    }
	    return opt_expr(m, pop);
	}

	n = n->r.right;
	oldside = side_start(&side, &olddepth);
	d1 = opt_expr(&n->l.left, pop);
	if (d1 == 0) {
	    n->l.left = (node *) NULL;
	}
	d1 = max2(d1, side_end(&n->l.left, side, oldside, olddepth));
	if (d1 == 0) {
	    n->l.left = (node *) NULL;
	}
	oldside = side_start(&side, &olddepth);
	d2 = opt_expr(&n->r.right, pop);
	if (d2 == 0) {
	    n->r.right = (node *) NULL;
	}
	d2 = max2(d2, side_end(&n->r.right, side, oldside, olddepth));
	if (d2 == 0) {
	    n->r.right = (node *) NULL;
	}
	return max3(i, d1, d2);

    case N_RANGE:
	d1 = opt_expr(&n->l.left, FALSE);
	d2 = 1;
	if (n->r.right->l.left != (node *) NULL) {
	    d2 = opt_expr(&n->r.right->l.left, FALSE);
	    if ((n->l.left->mod == T_STRING || (n->l.left->mod & T_REF) != 0) &&
		n->r.right->l.left->type == N_INT &&
		n->r.right->l.left->l.number == 0) {
		/*
		 * str[0 .. x] or arr[0 .. x]
		 */
		n->r.right->l.left = (node *) NULL;
		d2 = 1;
	    } else {
		d1 = max2(d1, d2 + 1);
		d2 = 2;
	    }
	}
	if (n->r.right->r.right != (node *) NULL) {
	    d1 = max2(d1, d2 + opt_expr(&n->r.right->r.right, FALSE));
	}
	if (n->l.left->type == N_STR) {
	    long from, to;

	    if (n->r.right->l.left == (node *) NULL) {
		from = 0;
	    } else {
		if (n->r.right->l.left->type != N_INT) {
		    return d1;
		}
		from = n->r.right->l.left->l.number;
	    }
	    if (n->r.right->r.right == (node *) NULL) {
		to = n->l.left->l.string->len - 1;
	    } else {
		if (n->r.right->r.right->type != N_INT) {
		    return d1;
		}
		to = n->r.right->r.right->l.number;
	    }
	    if (from >= 0 && from <= to + 1 &&
		to < (long) n->l.left->l.string->len) {
		node_tostr(n, str_range(n->l.left->l.string, from, to));
		return !pop;
	    }
	    return d1;
	}
	return max2(d1, 3);

    case N_AGGR:
	if (n->mod == T_MAPPING) {
	    n = n->l.left;
	    if (n == (node *) NULL) {
		return 1;
	    }

	    d1 = 0;
	    for (i = 0; n->type == N_PAIR; i += 2) {
		oldside = side_start(&side, &olddepth);
		d2 = opt_expr(&n->l.left->l.left, FALSE);
		d1 = max3(d1, i + d2, i + side_end(&n->l.left->l.left,
						   side, oldside, olddepth));
		oldside = side_start(&side, &olddepth);
		d2 = opt_expr(&n->l.left->r.right, FALSE);
		d1 = max3(d1, i + 1 + d2,
			  i + 1 + side_end(&n->l.left->r.right, side, oldside,
					   olddepth));
		n = n->r.right;
	    }
	    oldside = side_start(&side, &olddepth);
	    d2 = opt_expr(&n->l.left, FALSE);
	    d1 = max3(d1, i + d2,
		      i + side_end(&n->l.left, side, oldside, olddepth));
	    oldside = side_start(&side, &olddepth);
	    d2 = opt_expr(&n->r.right, FALSE);
	    return max3(d1, i + 1 + d2,
			i + 1 + side_end(&n->r.right, side, oldside, olddepth));
	} else {
	    m = &n->l.left;
	    n = *m;
	    if (n == (node *) NULL) {
		return 1;
	    }

	    d1 = 0;
	    for (i = 0; n->type == N_PAIR; i++) {
		oldside = side_start(&side, &olddepth);
		d2 = opt_expr(&n->l.left, FALSE);
		d1 = max3(d1, i + d2,
			  i + side_end(&n->l.left, side, oldside, olddepth));
		m = &n->r.right;
		n = *m;
	    }
	    oldside = side_start(&side, &olddepth);
	    d2 = opt_expr(m, FALSE);
	    return max3(d1, i + d2, i + side_end(m, side, oldside, olddepth));
	}
    }

# ifdef DEBUG
    fatal("unknown expression type %d", n->type);
# endif
    return 0;
}
示例#3
0
/*
 * 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);
}