added some optimalizations
This commit is contained in:
parent
9915ed4bc2
commit
2f0275ba3c
4 changed files with 51 additions and 19 deletions
|
@ -27,8 +27,13 @@ extern char *symbol2str();
|
|||
depending on the constancy of the operands.
|
||||
*/
|
||||
|
||||
#define commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
|
||||
/*
|
||||
* Although the relational operators are generally not commutative, we can
|
||||
* switch the arguments if the operator is adapted (e.g. < becomes >)
|
||||
*/
|
||||
#define non_commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 0)
|
||||
#define commutative_binop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
|
||||
#define non_commutative_relop(expp, oper, expr) mk_binop(expp, oper, expr, 1)
|
||||
|
||||
ch3bin(expp, oper, expr)
|
||||
register struct expr **expp;
|
||||
|
@ -182,7 +187,7 @@ ch3bin(expp, oper, expr)
|
|||
case EQUAL:
|
||||
case NOTEQUAL:
|
||||
relbalance(expp, oper, &expr);
|
||||
non_commutative_binop(expp, oper, expr);
|
||||
non_commutative_relop(expp, oper, expr);
|
||||
(*expp)->ex_type = int_type;
|
||||
break;
|
||||
|
||||
|
@ -301,6 +306,23 @@ pntminuspnt(expp, oper, expr)
|
|||
if (int_size != pointer_size) (*expp)->ex_flags |= EX_PTRDIFF;
|
||||
}
|
||||
|
||||
/*
|
||||
* The function arg_switched() returns the operator that should be used
|
||||
* when the arguments are switched. This is special for some relational
|
||||
* operators.
|
||||
*/
|
||||
int
|
||||
arg_switched(oper)
|
||||
{
|
||||
switch (oper) {
|
||||
case '<': return '>';
|
||||
case '>': return '<';
|
||||
case LESSEQ: return GREATEREQ;
|
||||
case GREATEREQ: return LESSEQ;
|
||||
default: return oper;
|
||||
}
|
||||
}
|
||||
|
||||
mk_binop(expp, oper, expr, commutative)
|
||||
struct expr **expp;
|
||||
register struct expr *expr;
|
||||
|
@ -315,14 +337,13 @@ mk_binop(expp, oper, expr, commutative)
|
|||
cstbin(expp, oper, expr);
|
||||
else if (is_fp_cst(expr) && is_fp_cst(ex))
|
||||
fltcstbin(expp, oper, expr);
|
||||
else {
|
||||
*expp = (commutative &&
|
||||
! (ex->ex_flags & EX_VOLATILE) &&
|
||||
( expr->ex_depth > ex->ex_depth ||
|
||||
(expr->ex_flags & EX_SIDEEFFECTS) ||
|
||||
is_cp_cst(ex)))
|
||||
? new_oper(ex->ex_type, expr, oper, ex)
|
||||
: new_oper(ex->ex_type, ex, oper, expr);
|
||||
else {
|
||||
*expp = (commutative
|
||||
&& !(ex->ex_flags & EX_VOLATILE)
|
||||
&& ( expr->ex_depth > ex->ex_depth
|
||||
|| is_cp_cst(ex)))
|
||||
? new_oper(ex->ex_type, expr, arg_switched(oper), ex)
|
||||
: new_oper(ex->ex_type, ex, oper, expr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -279,14 +279,14 @@ end_proc(fbytes)
|
|||
DfaEndFunction();
|
||||
#endif DATAFLOW
|
||||
C_df_ilb(return2_label);
|
||||
if (return_expr_occurred) C_asp(-func_size);
|
||||
if (return_expr_occurred && func_res_label == 0) {
|
||||
C_asp(-func_size);
|
||||
}
|
||||
C_df_ilb(return_label);
|
||||
prc_exit();
|
||||
#ifndef LINT
|
||||
if (return_expr_occurred) {
|
||||
if (func_res_label != 0) {
|
||||
C_lae_dlb(func_res_label, (arith)0);
|
||||
store_block(func_size, func_type->tp_align);
|
||||
C_lae_dlb(func_res_label, (arith)0);
|
||||
C_ret(pointer_size);
|
||||
}
|
||||
|
@ -347,6 +347,10 @@ do_return_expr(expr)
|
|||
*/
|
||||
ch3cast(&expr, RETURN, func_type);
|
||||
code_expr(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||
if (func_res_label != 0) {
|
||||
C_lae_dlb(func_res_label, (arith)0);
|
||||
store_block(func_size, func_type->tp_align);
|
||||
}
|
||||
C_bra(return_label);
|
||||
return_expr_occurred = 1;
|
||||
}
|
||||
|
|
|
@ -67,13 +67,13 @@ declaration
|
|||
short typedef yepp;
|
||||
makes all hope of writing a specific grammar for typedefs illusory.
|
||||
*/
|
||||
/* Accept a single declaration specifier. Then accept zero or more
|
||||
type-specifiers. There can be a conflict on both TYPE_IDENTIFIER
|
||||
and IDENTIFIER.
|
||||
/* Accept a single declaration specifier. Then accept zero or more
|
||||
declaration specifiers. There can be a conflict on both
|
||||
TYPE_IDENTIFIER and IDENTIFIER.
|
||||
The following rule is used:
|
||||
When we see a TYPE_IDENTIFIER, we accept it if no type-specifier
|
||||
was given, and it is not directly followed by an identifier.
|
||||
If no type-dpecifier was given, it is taken as the identifier being
|
||||
When we see a TYPE_IDENTIFIER, we accept it if no type-specifier was
|
||||
given, and it is not directly followed by an identifier. If a
|
||||
type-specifier was given, it is taken as the identifier being
|
||||
declared. If it is followed by an identifier, we assume that an
|
||||
error has been made, (e.g. unsigned typedeffed_int x;) and that
|
||||
this will be detected later on.
|
||||
|
|
|
@ -383,6 +383,13 @@ new_oper(tp, e1, oper, e2)
|
|||
expr->ex_flags = (e1_flags | e2->ex_flags)
|
||||
& ~(EX_PARENS | EX_READONLY | EX_VOLATILE );
|
||||
}
|
||||
/*
|
||||
* A function call should be evaluated first when possible. Just say
|
||||
* that the expression tree is very deep.
|
||||
*/
|
||||
if (oper == '(') {
|
||||
expr->ex_depth = 50;
|
||||
}
|
||||
op = &expr->ex_object.ex_oper;
|
||||
op->op_type = tp;
|
||||
op->op_oper = oper;
|
||||
|
|
Loading…
Reference in a new issue