Trailing-Edge
-
PDP-10 Archives
-
SRI_NIC_PERM_FS_1_19910112
-
c/old/kcc/ccfold.c
There are 6 other files named ccfold.c in the archive. Click here to see a list.
/* <KCC.CC>CCFOLD.C.16, 20-Jun-85 11:39:56, Edit by KRONJ */
/* Flush addition by zero */
/* <KCC.CC>CCFOLD.C.10, 10-Mar-85 10:12:12, Edit by KRONJ */
/* Change IDWEIGHT to be independant of memory allocation */
/* (Otherwise it comes out different with every EXE and makes */
/* it difficult to tell when there's a real compiler bug) */
/*
** ccfold - perform various minor optimizations on expression trees
** (C) 1981 K. Chen
*/
#include "cc.h"
/* -------------------------------------- */
/* fold expression Ref.[2] 5.E */
/* -------------------------------------- */
node fold(e)
node e;
{
node ifold();
if (e->nop == UNDEF) return NULL;
switch (tok[e->nop].ttype) {
case PRIMARY:
if (e->nop != DOT && e->nop != MEMBER) break;
e->left = fold(e->left);
break;
case ASOP:
case BINOP:
case BOOLOP:
e->left = fold(e->left);
e->right = fold(e->right);
return ifold(e);
case UNOP:
case BOOLUN:
e->left = fold(e->left);
return ifold(e);
case TERNARY:
e->left = fold(e->left);
e->right->left = fold(e->right->left);
e->right->right = fold(e->right->right);
return ifold(e);
}
return e;
}
/*
** Copy flags and such across from old top node
** Used when op has been folded out but we still want to keep its info
*/
static node
copyflag (new, old)
node new, old;
{
new->ntype = old->ntype;
new->nflag = old->nflag;
return new;
}
/* ---------------------------------- */
/* fold integer expressions */
/* ---------------------------------- */
static node
ifold(e)
node e;
{
int op;
node l, r;
int u,v;
if (e->left->nop != ICONST) {
if (e->nop==PLUS && e->right->nop==ICONST && e->right->niconst==0)
return copyflag (e->left, e);
return e;
}
l = e->left;
op = e->nop;
u = l->niconst;
switch (op) {
case NEG:
l->niconst = -u;
return copyflag (l, e);
case COMPL:
l->niconst = ~u;
return copyflag (l, e);
case NOT:
l->niconst = !u;
return copyflag (l, e);
case LOR:
if (u == 0) return copyflag (e->right, e);
l->niconst = 1; /* make sure 1 not just non-zero */
return copyflag (l, e);
case LAND:
return copyflag ((u? e->right : l), e);
case QUERY:
return copyflag ((u? e->right->left : e->right->right), e);
case PLUS:
if (u == 0) return copyflag (e->right, e); /* fold out add by zero */
}
r = e->right;
if (r->nop != ICONST) return e;
l->ntype = e->ntype; /* preserve coercions */
v = r->niconst;
switch (op) {
case PLUS:
u += v;
break;
case MINUS:
u -= v;
break;
case MPLY:
u *= v;
break;
case DIV:
u /= v;
break;
case MOD:
u %= v;
break;
case ANDT:
u &= v;
break;
case OR:
u |= v;
break;
case XORT:
u ^= v;
break;
case LSHFT:
u <<= v;
break;
case RSHFT:
u >>= v;
break;
case EQUAL:
u = u == v;
break;
case NEQ:
u = u != v;
break;
case LESS:
u = u < v;
break;
case GREAT:
u = u > v;
break;
case LEQ:
u = u <= v;
break;
case GEQ:
u = u >= v;
break;
default:
return e;
}
l->niconst = u;
return copyflag (l, e);
}
/* ---------------------------------------- */
/* commute tree to canonical form */
/* ---------------------------------------- */
#define HBAR 64 /* basic unit of complexity */
#define IDMASK (HBAR-1) /* mask for quantum fluctuations */
#define IDWEIGHT(s) (hash(s->sname)&IDMASK) /* to permute for common subs */
#define BWEIGHT (4*HBAR) /* weight for binary operator */
#define IWEIGHT 0 /* weight for integer */
#define SWEIGHT (2*HBAR) /* weight for string const */
#define MWEIGHT HBAR /* weight for struct member */
#define CWEIGHT (2*HBAR) /* weight for coercion, unary */
#define FWEIGHT (32*HBAR) /* weight for fun call - v expensive */
#define QWEIGHT (2*HBAR) /* weight for ternary */
optexpr(n)
struct NODE *n;
{
struct NODE *t;
int x, y;
/*
** Return a weight for the tree, and commute subtrees.
** This function has two purposes:
** - To rearrange commutative expressions so that the more
** expensive operation is performed first, so that fewer
** registers need be allocated at once and so that moves
** from memory are more likely to be folded into the ops.
** - To permute equivalent expressions to the same canonical
** form, so that common subexpression elimination may be
** more likely to find them.
*/
switch (n->nop) {
case UNDEF:
case ICONST:
return IWEIGHT;
case IDENT:
return IDWEIGHT(n->nid);
case SCONST:
return SWEIGHT;
case DOT:
case MEMBER:
return optexpr(n->left) + MWEIGHT;
case EXPRESS:
if (n->left == NULL) return optexpr(n->right);
return optexpr(n->left) + optexpr(n->right);
case COERCE:
return optexpr(n->left) + CWEIGHT;
case FNCALL:
return (n->right == NULL) ? FWEIGHT : optexpr(n->right)+FWEIGHT;
default:
switch (tok[n->nop].ttype) {
case BINOP:
x = optexpr(n->left);
y = optexpr(n->right);
if (y > x && (n->nop == PLUS || n->nop == MPLY)) {
t = n->left;
n->left = n->right;
n->right = t;
}
return x + y + BWEIGHT;
case ASOP:
case BOOLOP:
return optexpr(n->left) + optexpr(n->right) + BWEIGHT;
case UNOP:
case BOOLUN:
case COERCE:
return optexpr(n->left)+CWEIGHT;
case TERNARY:
x = optexpr(n->right->left);
y = optexpr(n->right->right);
if (y > x) x = y;
return optexpr(n->left) + x + QWEIGHT;
default:
return 0;
}
}
}