📄 optimize.c
字号:
/*
* 68K/386 32-bit C compiler.
*
* copyright (c) 1997, David Lindauer
*
* This compiler is intended for educational use. It may not be used
* for profit without the express written consent of the author.
*
* It may be freely redistributed, as long as this notice remains intact
* and either the original sources or derived sources
* are distributed along with any executables derived from the originals.
*
* The author is not responsible for any damages that may arise from use
* of this software, either idirect or consequential.
*
* v1.35 March 1997
* David Lindauer, gclind01@starbase.spd.louisville.edu
*
* Credits to Mathew Brandt for original K&R C compiler
*
*/
/*
* this module combines constants at compile time. Integer constants
* will get combined slightly better than floating point ones
*/
#include <stdio.h>
#include "expr.h"
#include "c.h"
int maxinttype(ENODE *ep1, ENODE *ep2)
{
int type1=ep1->nodetype;
int type2 = ep2->nodetype;
if (type1 == en_lucon || type2 == en_lucon)
return en_lucon;
if (type1 == en_lcon || type2 == en_lcon)
return en_lcon;
if (type1 == en_iucon || type2 == en_iucon)
return en_iucon;
if (type1 == en_icon || type2 == en_icon)
return en_icon;
return en_ccon;
}
int maxfloattype(ENODE *ep1, ENODE *ep2)
{
int type1=ep1->nodetype;
int type2 = ep2->nodetype;
if (type1 == en_lrcon || type2 == en_lrcon)
return en_lrcon;
if (type1 == en_rcon || type2 == en_rcon)
return en_rcon;
return en_fcon;
}
int getmode(ENODE *ep1,ENODE *ep2)
/*
* get the constant mode of a pair of nodes
* 0 = Neither node is a constant
* 1 = icon,icon
* 2 = icon,rcon
* 3 = rcon,icon
* 4 = rcon,rcon
* 5 = icon,nothing
* 6 = rcon,nothing
* 7 = nothing,icon
* 8 = nothing,rcon
*/
{
int mode = 0;
if (isintconst(ep1->nodetype) )
if (ep2) {
if (isintconst(ep2->nodetype))
mode = 1;
else if (ep2->nodetype == en_rcon || ep2->nodetype == en_lrcon || ep2->nodetype == en_fcon)
mode = 2;
else mode = 5;
}
else
mode = 5;
else if (ep1->nodetype == en_rcon || ep1->nodetype == en_lrcon || ep1->nodetype == en_fcon)
if (ep2) {
if (isintconst(ep2->nodetype))
mode = 3;
else if (ep2->nodetype == en_rcon || ep2->nodetype == en_lrcon || ep2->nodetype == en_fcon)
mode = 4;
else mode = 6;
}
else
mode = 6;
else if (ep2)
if (isintconst(ep2->nodetype))
mode = 7;
else if (ep2->nodetype == en_rcon || ep2->nodetype == en_lrcon || ep2->nodetype == en_fcon)
mode = 8;
return(mode);
}
void dooper(ENODE ** node, int mode)
/*
* dooper will execute a constant operation in a node and
* modify the node to be the result of the operation.
* It will also cast integers to floating point values when
* necessary
*/
{ ENODE *ep,*ep1,*ep2;
ep = *node;
ep1 = ep->v.p[0];
ep2 = ep->v.p[1];
if (mode ==5) {
if (floatrecurse(ep2)) {
ep1->v.f = ep1->v.i;
ep1->nodetype = en_rcon;
}
return;
}
else if (mode == 7) {
if (floatrecurse(ep1)) {
ep2->v.f = ep2->v.i;
ep2->nodetype = en_rcon;
}
return;
}
else if (mode == 6 || mode == 8)
return;
else
switch( ep->nodetype ) {
case en_add:
switch (mode) {
case 1:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i + ep2->v.i;
break;
case 2:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.i + ep2->v.f;
break;
case 3:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.f + ep2->v.i;
break;
case 4:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.f + ep2->v.f;
break;
}
break;
case en_sub:
switch (mode) {
case 1:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i - ep2->v.i;
break;
case 2:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.i - ep2->v.f;
break;
case 3:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.f - ep2->v.i;
break;
case 4:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.f - ep2->v.f;
break;
}
break;
case en_pmul:
case en_umul:
case en_mul:
switch (mode) {
case 1:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i * ep2->v.i;
break;
case 2:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.i * ep2->v.f;
break;
case 3:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.f * ep2->v.i;
break;
case 4:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.f * ep2->v.f;
break;
}
break;
case en_pdiv:
case en_div:
case en_udiv:
switch (mode) {
case 1:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i / ep2->v.i;
break;
case 2:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.i / ep2->v.f;
break;
case 3:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.f / ep2->v.i;
break;
case 4:
ep->nodetype = maxfloattype(ep1,ep2);
ep->v.f = ep1->v.f / ep2->v.f;
break;
}
break;
case en_mod:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i % ep2->v.i;
break;
case en_lsh:
case en_alsh:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i << ep2->v.i;
break;
case en_rsh:
case en_arsh:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i >> ep2->v.i;
break;
case en_and:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i & ep2->v.i;
break;
case en_or:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i | ep2->v.i;
break;
case en_xor:
ep->nodetype = maxinttype(ep1,ep2);
ep->v.i = ep1->v.i ^ ep2->v.i;
break;
}
}
/*
* this stuff has been superceded by a lookup table
* I'll fix it eventually
*/
long pwrof2(int i)
/*
* return which power of two i is or -1.
*/
{ long p, q;
q = 2;
p = 1;
while( q > 0 )
{
if( q == i )
return p;
q <<= 1;
++p;
}
return -1;
}
long mod_mask(int i)
/*
* make a mod mask for a power of two.
*/
{ long m;
m = 0;
while( i-- )
m = (m << 1) | 1;
return m;
}
void opt0(ENODE ** node)
/*
* opt0 - delete useless expressions and combine constants.
*
* opt0 will delete expressions such as x + 0, x - 0, x * 0,
* x * 1, 0 / x, x / 1, x mod 0, etc from the tree pointed to
* by node and combine obvious constant operations. It cannot
* combine name and label constants but will combine icon type
* nodes.
*/
{ ENODE *ep;
int sc,mode,val;
double dval;
ep = *node;
if( ep == 0 )
return;
switch( (*node)->nodetype ) {
case en_b_ref:
case en_w_ref: /* optimize unary node */
case en_ub_ref:
case en_uw_ref: /* optimize unary node */
case en_l_ref:
case en_ul_ref:
case en_floatref: case en_doubleref: case en_longdoubleref:
case en_cb: case en_cub:
case en_cw: case en_cuw:
case en_cl: case en_cul:
case en_cf: case en_cd: case en_cp: case en_bits: case en_cld:
case en_ainc:
case en_adec:
case en_not:
case en_compl:
opt0( &((*node)->v.p[0]));
return;
case en_uminus:
opt0( &(ep->v.p[0]));
if( isintconst(ep->v.p[0]->nodetype))
{
ep->nodetype = ep->v.p[0]->nodetype;
ep->v.i = -ep->v.p[0]->v.i;
}
else if( ep->v.p[0]->nodetype == en_rcon || ep->v.p[0]->nodetype == en_fcon || ep->v.p[0]->nodetype == en_lrcon)
{
ep->nodetype = ep->v.p[0]->nodetype;
ep->v.i = -ep->v.p[0]->v.f;
}
return;
case en_add:
case en_sub:
opt0(&(ep->v.p[0]));
opt0(&(ep->v.p[1]));
mode = getmode(ep->v.p[0],ep->v.p[1]);
switch (mode) {
case 1: case 2: case 3: case 4:
dooper(node,mode);
break;
case 5:
if (ep->v.p[0]->v.i == 0) {
if (ep->nodetype == en_sub) {
*node = makenode(en_uminus,ep->v.p[1],0);
}
else *node = ep->v.p[1];
}
else dooper(node,mode);
break;
case 6:
if (ep->v.p[0]->v.f == 0) {
if (ep->nodetype == en_sub) {
*node = ep->v.p[1];
ep->v.p[1]->v.f = - ep->v.p[1]->v.f;
}
else *node = ep->v.p[1];
}
else dooper(node,mode);
break;
case 7:
if (ep->v.p[1]->v.i == 0) {
*node = ep->v.p[0];
}
else dooper(node,mode);
break;
case 8:
if (ep->v.p[1]->v.f == 0) {
*node = ep->v.p[0];
}
else dooper(node,mode);
break;
}
return;
case en_mul:
case en_umul:
case en_pmul:
case en_asmul: case en_asumul:
opt0(&(ep->v.p[0]));
opt0(&(ep->v.p[1]));
mode = getmode(ep->v.p[0],ep->v.p[1]);
switch(mode) {
case 1: case 2: case 3: case 4:
dooper(node,mode);
break;
case 5:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -