📄 simp.c
字号:
break;
if (r->op == CNST+U && (n = ispow2(r->u.v.u)) != 0)
return simplify(RSH+U, unsignedtype, l, consttree(n, inttype));
foldcnst(U,u,/,unsignedtype);
break;
case EQ+D:
case EQ+L:
cfoldcnst(D,d,==,inttype);
commute(r,l);
break;
case EQ+F:
cfoldcnst(F,f,==,inttype);
commute(r,l);
break;
case EQ+U:
cfoldcnst(U,u,==,inttype);
commute(r,l);
zerofield(EQ,U,u);
op = EQ+I;
break;
case GE+D: cfoldcnst(D,d,>=,inttype); break;
case GE+F: cfoldcnst(F,f,>=,inttype); break;
case GE+I: cfoldcnst(I,i,>=,inttype); break;
case GE+L: cfoldcnst(L,d,>=,inttype); break;
case GE+U:
geu(l,r,1); /* l >= 0 => (l,1) */
cfoldcnst(U,u,>=,inttype);
if (l->op == CNST+U && l->u.v.u == 0) /* 0 >= r => r == o */
return tree(EQ+I, ty, r, l);
break;
case GT+D: cfoldcnst(D,d, >,inttype); break;
case GT+L: cfoldcnst(L,d, >,inttype); break;
case GT+F: cfoldcnst(F,f, >,inttype); break;
case GT+I: cfoldcnst(I,i, >,inttype); break;
case GT+U:
geu(r,l,0); /* 0 > r => (r,0) */
cfoldcnst(U,u, >,inttype);
if (r->op == CNST+U && r->u.v.u == 0) /* l > 0 => l != 0 */
return tree(NE+I, ty, l, r);
break;
case LE+D: cfoldcnst(D,d,<=,inttype); break;
case LE+F: cfoldcnst(F,f,<=,inttype); break;
case LE+I: cfoldcnst(I,i,<=,inttype); break;
case LE+L: cfoldcnst(L,d, >,inttype); break;
case LE+U:
geu(r,l,1); /* 0 <= r => (r,1) */
cfoldcnst(U,u,<=,inttype);
if (r->op == CNST+U && r->u.v.u == 0) /* l <= 0 => l == 0 */
return tree(EQ+I, ty, l, r);
break;
case LSH+I:
identity(r,l,I,i,0);
if (l->op == CNST+I && r->op == CNST+I
&& r->u.v.i >= 0 && r->u.v.i < 8*l->type->size
&& mul((double)l->u.v.i, (double)(1<<r->u.v.i), (double)INT_MIN, (double)INT_MAX, needconst))
return consttree(l->u.v.i<<r->u.v.i, inttype);
if (r->op == CNST+I && (r->u.v.i >= 8*l->type->size || r->u.v.i < 0)) {
warning(StrTab[89], r->u.v.i);// <shift by %d is undefined\n>
break;
}
break;
case LSH+L:
case RSH+L:
if (r->op == CNST+I && (r->u.v.i >= 8*l->type->size || r->u.v.i < 0)) {
warning(StrTab[90], r->u.v.i);// <shift by %d is undefined\n>
}
break;
case LSH+U:
identity(r,l,I,i,0);
sfoldcnst(U,u,<<,unsignedtype);
if (r->op == CNST+I && (r->u.v.i >= 8*l->type->size || r->u.v.i < 0)) {
warning(StrTab[91], r->u.v.i);// <shift by %d is undefined\n>
break;
}
break;
case LT+D: cfoldcnst(D,d, <,inttype); break;
case LT+F: cfoldcnst(F,f, <,inttype); break;
case LT+I: cfoldcnst(I,i, <,inttype); break;
case LT+L: cfoldcnst(L,i, <,inttype); break;
case LT+U:
geu(l,r,0); /* l < 0 => (l,0) */
cfoldcnst(U,u, <,inttype);
if (l->op == CNST+U && l->u.v.u == 0) /* 0 < r => r != 0 */
return tree(NE+I, ty, r, l);
break;
case MOD+I:
if (r->op == CNST+I && r->u.v.i == 1) /* l%1 => (l,0) */
return tree(RIGHT, inttype, root(l), consttree(0, inttype));
if (r->op == CNST+I && r->u.v.i == 0)
break;
#ifdef mips
if (l->op == CNST+I && r->op == CNST+I && r->u.v.i == -1
&& !div((double)l->u.v.i, (double)r->u.v.i, (double)INT_MIN, (double)INT_MAX, 0))
break;
#endif
xfoldcnst(I,i,%,inttype,div,INT_MIN,INT_MAX,needconst);
break;
case MOD+L:
break;
case MOD+U:
if (r->op == CNST+U && ispow2(r->u.v.u)) /* l%2^n => l&(2^n-1) */
return bittree(BAND, l,
consttree(r->u.v.u - 1, unsignedtype));
if (r->op == CNST+U && r->u.v.u == 0)
break;
foldcnst(U,u,%,unsignedtype);
break;
case MUL+D:
xfoldcnst(D,d,*,doubletype,mul,-DBL_MAX,DBL_MAX,0);
commute(l,r);
break;
case MUL+L:
xfoldcnst(L,d,*,longlongtype,mul,-DBL_MAX,DBL_MAX,0);
commute(l,r);
break;
case MUL+F:
xfoldcnst(F,f,*,floattype,mul,-FLT_MAX,FLT_MAX,0);
commute(l,r);
break;
case MUL+I:
if ((r->op == CNST+U || r->op == CNST+I) && r->u.v.i == 1)
return l;
commute(l,r);
if (l->op == CNST+I && r->op == ADD+I && r->kids[1]->op == CNST+I)
/* c1*(x + c2) => c1*x + c1*c2 */
return simplify(ADD+I, inttype, simplify(MUL+I, inttype, l, r->kids[0]),
simplify(MUL+I, inttype, l, r->kids[1]));
if (l->op == CNST+I && r->op == SUB+I && r->kids[1]->op == CNST+I)
/* c1*(x - c2) => c1*x - c1*c2 */
return simplify(SUB+I, inttype, simplify(MUL+I, inttype, l, r->kids[0]),
simplify(MUL+I, inttype, l, r->kids[1]));
if (l->op == CNST+I && l->u.v.i > 0 && (n = ispow2(l->u.v.i)) != 0)
/* 2^n * r => r<<n */
return simplify(LSH+I, inttype, r, consttree(n, inttype));
xfoldcnst(I,i,*,inttype,mul,INT_MIN,INT_MAX,needconst);
break;
case NE+D:
foldcnst(D,d,!=,inttype);
commute(r,l);
break;
case NE+L:
foldcnst(L,d,!=,inttype);
commute(r,l);
break;
case NE+F:
cfoldcnst(F,f,!=,inttype);
commute(r,l);
break;
case NE+U:
cfoldcnst(U,u,!=,inttype);
commute(r,l);
zerofield(NE,U,u);
op = NE+I;
break;
case NEG+D:
ufoldcnst(D,(p = tree(CNST+D, doubletype, NULL, NULL), p->u.v.d = -l->u.v.d, p));
idempotent(NEG+D);
break;
case NEG+F:
ufoldcnst(F,(p = tree(CNST+F, floattype, NULL, NULL), p->u.v.f = -l->u.v.f, p));
idempotent(NEG+F);
break;
case NEG+I:
if (l->op == CNST+I) {
if (needconst && l->u.v.i == INT_MIN)
warning(StrTab[92]);// <overflow in constant expression\n>
if (needconst || l->u.v.i != INT_MIN)
return consttree(-l->u.v.i, inttype);
}
idempotent(NEG+I);
break;
case NEG+L:
idempotent(NEG+L);
break;
case NOT+I:
op = NOT;
ufoldcnst(I,consttree(!l->u.v.i, inttype));
break;
case RSH+I:
identity(r,l,I,i,0);
if (l->op == CNST+I && r->op == CNST+I
&& r->u.v.i >= 0 && r->u.v.i < 8*l->type->size) {
int n = l->u.v.i>>r->u.v.i;
if (l->u.v.i < 0)
n |= ~0<<(8*l->type->size - r->u.v.i);
return consttree(n, inttype);
}
if (r->op == CNST+I && (r->u.v.i >= 8*l->type->size || r->u.v.i < 0)) {
warning(StrTab[93], r->u.v.i);// <shift by %d is undefined\n>
break;
}
break;
case RSH+U:
identity(r,l,I,i,0);
sfoldcnst(U,u,>>,unsignedtype);
if (r->op == CNST+I && (r->u.v.i >= 8*l->type->size || r->u.v.i < 0)) {
warning(StrTab[94], r->u.v.i);// <shift by %d is undefined\n>
break;
}
break;
case SUB+D:
if (r->op == CNSTD &&
r->u.v.d == 0.0)
return l;
xfoldcnst(D,d,-,doubletype,sub,-DBL_MAX,DBL_MAX,0);
break;
case SUB+L:
if (r->op == CNSTD &&
r->u.v.d == 0.0)
return l;
xfoldcnst(D,d,-,longlongtype,sub,-DBL_MAX,DBL_MAX,0);
break;
case SUB+F:
xfoldcnst(F,f,-,floattype,sub,-FLT_MAX,FLT_MAX,0);
break;
case SUB+I:
if (r->op == CNSTU || r->op == CNSTI) {
if (r->u.v.i == 0)
return l;
}
xfoldcnst(I,i,-,inttype,sub,INT_MIN,INT_MAX,needconst);
break;
case SUB+U:
if (r->op == CNSTU || r->op == CNSTI) {
if (r->u.v.i == 0)
return l;
}
foldcnst(U,u,-,unsignedtype);
break;
case SUB+P:
if (l->op == CNST+P && r->op == CNST+P)
return consttree((char *)l->u.v.p - (char *)r->u.v.p, inttype);
if (r->op == CNST+I || r->op == CNST+U)
return simplify(ADD+P, ty, l,
consttree(r->op == CNST+I ? -r->u.v.i : -(int)r->u.v.u, inttype));
if (isaddrop(l->op) && r->op == ADD+I && r->kids[1]->op == CNST+I)
/* l - (x + c) => l-c - x */
return simplify(SUB+P, ty,
simplify(SUB+P, ty, l, r->kids[1]), r->kids[0]);
break;
default:assert(0);
}
return tree(op, ty, l, r);
}
static int add(double x,double y,double min,double max,int needconst)
{
int cond = x == 0 || y == 0
|| x < 0 && y < 0 && x >= min - y
|| x < 0 && y > 0
|| x > 0 && y < 0
|| x > 0 && y > 0 && x <= max - y;
if (!cond && needconst) {
warning(StrTab[95]);// <overflow in constant expression\n>
cond = 1;
}
return cond;
}
static Tree addrtree(Tree e,int n,Type ty)
{
Symbol p = e->u.sym, q;
NEW0(q, FUNC);
q->name = stringd(genlabel(1));
q->sclass = p->sclass;
q->scope = p->scope;
assert(isptr(ty) || isarray(ty));
q->type = isptr(ty) ? ty->type : ty;
q->temporary = p->temporary;
q->generated = p->generated;
q->addressed = p->addressed;
q->computed = 1;
q->assigned = 1;
q->defined = 1;
q->ref = (float)1.0;
q->firstuse = q->lastuse = StatementCount;
if (p->scope == GLOBAL
|| p->sclass == STATIC || p->sclass == EXTERN) {
if (p->sclass == AUTO)
q->sclass = STATIC;
(*IR->address)(q, p, n);
} else {
Code cp;
addlocal(p);
cp = code(Address);
cp->u.addr.sym = q;
cp->u.addr.base = p;
cp->u.addr.offset = n;
}
e = tree(e->op, ty, NULL, NULL);
e->u.sym = q;
q->x.ArraySymbol = p;
return e;
}
/* div - return 1 if min <= x/y <= max, 0 otherwise */
static int div(double x,double y,double min,double max,int needconst)
{
int cond;
if (x < 0) x = -x;
if (y < 0) y = -y;
cond = y != 0 && (y > 1 || x <= max*y);
if (!cond && y != 0 && needconst) {
warning(StrTab[96]);// <overflow in constant expression\n>
cond = 1;
}
return cond;
}
/* ispow2 - if u > 1 && u == 2^n, return n, otherwise return 0 */
int ispow2(unsigned u)
{
int n;
if (u > 1 && (u&(u-1)) == 0)
for (n = 0; u; u >>= 1, n++)
if (u&1)
return n;
return 0;
}
/* mul - return 1 if min <= x*y <= max, 0 otherwise */
static int mul(double x,double y,double min,double max,int needconst)
{
int cond = x > -1 && x <= 1 || y > -1 && y <= 1
|| x < 0 && y < 0 && -x <= max/-y
|| x < 0 && y > 0 && x >= min/y
|| x > 0 && y < 0 && x >= min/y
|| x > 0 && y > 0 && x <= max/y;
if (!cond && needconst) {
warning(StrTab[97]);// <overflow in constant expression\n>
cond = 1;
}
return cond;
}
/* sub - return 1 if min <= x-y <= max, 0 otherwise */
static int sub(double x,double y,double min,double max,int needconst)
{
return add(x, -y, min, max, needconst);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -