added floating point constant propagation

This commit is contained in:
bellard
2002-03-17 11:15:05 +00:00
parent 4226681d36
commit 22ce5f248a

78
tcc.c
View File

@ -2977,8 +2977,9 @@ void gen_opl(int op)
} }
} }
/* handle constant optimizations and various machine independant opt */ /* handle integer constant optimizations and various machine
void gen_opc(int op) independant opt */
void gen_opic(int op)
{ {
int fc, c1, c2, n; int fc, c1, c2, n;
SValue *v1, *v2; SValue *v1, *v2;
@ -3080,6 +3081,67 @@ void gen_opc(int op)
} }
} }
/* generate a floating point operation with constant propagation */
void gen_opif(int op)
{
int c1, c2;
SValue *v1, *v2;
long double f1, f2;
v1 = vtop - 1;
v2 = vtop;
/* currently, we cannot do computations with forward symbols */
c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
if (c1 && c2) {
if (v1->t == VT_FLOAT) {
f1 = v1->c.f;
f2 = v2->c.f;
} else if (v1->t == VT_DOUBLE) {
f1 = v1->c.d;
f2 = v2->c.d;
} else {
f1 = v1->c.ld;
f2 = v2->c.ld;
}
/* NOTE: we only do constant propagation if finite number (not
NaN or infinity) (ANSI spec) */
if (!finite(f1) || !finite(f2))
goto general_case;
switch(op) {
case '+': f1 += f2; break;
case '-': f1 -= f2; break;
case '*': f1 *= f2; break;
case '/':
if (f2 == 0.0) {
if (const_wanted)
error("division by zero in constant");
goto general_case;
}
f1 /= f2;
break;
/* XXX: also handles tests ? */
default:
goto general_case;
}
/* XXX: overflow test ? */
if (v1->t == VT_FLOAT) {
v1->c.f = f1;
} else if (v1->t == VT_DOUBLE) {
v1->c.d = f1;
} else {
v1->c.ld = f1;
}
vtop--;
} else {
general_case:
gen_opf(op);
}
}
int pointed_size(int t) int pointed_size(int t)
{ {
return type_size(pointed_type(t), &t); return type_size(pointed_type(t), &t);
@ -3127,7 +3189,7 @@ void gen_op(int op)
// check_pointer_types(vtop - 1, vtop); // check_pointer_types(vtop - 1, vtop);
/* XXX: check that types are compatible */ /* XXX: check that types are compatible */
u = pointed_size(t1); u = pointed_size(t1);
gen_opc(op); gen_opic(op);
/* set to integer type */ /* set to integer type */
vtop->t = VT_INT; vtop->t = VT_INT;
vpushi(u); vpushi(u);
@ -3160,9 +3222,9 @@ void gen_op(int op)
} else } else
#endif #endif
{ {
gen_opc(op); gen_opic(op);
} }
/* put again type if gen_opc() swaped operands */ /* put again type if gen_opic() swaped operands */
vtop->t = t1; vtop->t = t1;
} }
} else if (is_float(bt1) || is_float(bt2)) { } else if (is_float(bt1) || is_float(bt2)) {
@ -3223,11 +3285,11 @@ void gen_op(int op)
else else
gen_cast(t); gen_cast(t);
if (is_float(t)) if (is_float(t))
gen_opf(op); gen_opif(op);
else if ((t & VT_BTYPE) == VT_LLONG) else if ((t & VT_BTYPE) == VT_LLONG)
gen_opl(op); gen_opl(op);
else else
gen_opc(op); gen_opic(op);
if (op >= TOK_ULT && op <= TOK_GT) { if (op >= TOK_ULT && op <= TOK_GT) {
/* relationnal op: the result is an int */ /* relationnal op: the result is an int */
vtop->t = VT_INT; vtop->t = VT_INT;
@ -6314,7 +6376,7 @@ int launch_exe(int argc, char **argv)
void help(void) void help(void)
{ {
printf("tcc version 0.9.5 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n" printf("tcc version 0.9.6 - Tiny C Compiler - Copyright (C) 2001, 2002 Fabrice Bellard\n"
"usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n" "usage: tcc [-Idir] [-Dsym[=val]] [-Usym] [-llib] [-g] [-b]\n"
" [-i infile] infile [infile_args...]\n" " [-i infile] infile [infile_args...]\n"
"\n" "\n"