📄 c12.c
字号:
#/* * C compiler part 2 -- expression optimizer * */#include "c1.h"optim(atree)struct tnode *atree;{ struct { int intx[4]; }; register op, dope; int d1, d2; struct tnode *t; register struct tnode *tree; if ((tree=atree)==0) return(0); if ((op = tree->op)==0) return(tree); if (op==NAME && tree->class==AUTO) { tree->class = OFFS; tree->regno = 5; tree->offset = tree->nloc; } dope = opdope[op]; if ((dope&LEAF) != 0) { if (op==FCON && tree->fvalue.intx[1]==0 && tree->fvalue.intx[2]==0 && tree->fvalue.intx[3]==0) { tree->op = SFCON; tree->value = tree->fvalue.intx[0]; } return(tree); } if ((dope&BINARY) == 0) return(unoptim(tree)); /* is known to be binary */ if (tree->type==CHAR) tree->type = INT; switch(op) { /* * PDP-11 special: * generate new =&~ operator out of =& * by complementing the RHS. */ case ASAND: tree->op = ASANDN; tree->tr2 = tnode(COMPL, tree->tr2->type, tree->tr2); break; /* * On the PDP-11, int->ptr via multiplication * Longs are just truncated. */ case LTOP: tree->op = ITOP; tree->tr1 = unoptim(tnode(LTOI,INT,tree->tr1)); case ITOP: tree->op = TIMES; break; case MINUS: if ((t = isconstant(tree->tr2)) && (t->type!=UNSIGN || tree->type!=LONG)) { tree->op = PLUS; if (t->type==DOUBLE) /* PDP-11 FP representation */ t->value =^ 0100000; else t->value = -t->value; } break; } op = tree->op; dope = opdope[op]; if (dope&LVALUE && tree->tr1->op==FSEL) return(lvfield(tree)); if ((dope&COMMUTE)!=0) { d1 = tree->type; tree = acommute(tree); if (tree->op == op) tree->type = d1; /* * PDP-11 special: * replace a&b by a ANDN ~ b. * This will be undone when in * truth-value context. */ if (tree->op!=AND) return(tree); /* * long & pos-int is simpler */ if (tree->type==LONG && tree->tr2->op==ITOL && (tree->tr2->tr1->op==CON && tree->tr2->tr1->value>=0 || tree->tr2->tr1->type==UNSIGN)) { tree->type = UNSIGN; t = tree->tr2; tree->tr2 = tree->tr2->tr1; t->tr1 = tree; tree->tr1 = tnode(LTOI, UNSIGN, tree->tr1); return(optim(t)); } /* * Keep constants to the right */ if ((tree->tr1->op==ITOL && tree->tr1->tr1->op==CON) || tree->tr1->op==LCON) { t = tree->tr1; tree->tr1 = tree->tr2; tree->tr2 = t; } tree->op = ANDN; op = ANDN; tree->tr2 = tnode(COMPL, tree->tr2->type, tree->tr2); } again: tree->tr1 = optim(tree->tr1); tree->tr2 = optim(tree->tr2); if (tree->type == LONG) { t = lconst(tree->op, tree->tr1, tree->tr2); if (t) return(t); } if ((dope&RELAT) != 0) { if ((d1=degree(tree->tr1)) < (d2=degree(tree->tr2)) || d1==d2 && tree->tr1->op==NAME && tree->tr2->op!=NAME) { t = tree->tr1; tree->tr1 = tree->tr2; tree->tr2 = t; tree->op = maprel[op-EQUAL]; } if (tree->tr1->type==CHAR && tree->tr2->op==CON && (dcalc(tree->tr1, 0) <= 12 || tree->tr1->op==STAR) && tree->tr2->value <= 127 && tree->tr2->value >= 0) tree->tr2->type = CHAR; } d1 = max(degree(tree->tr1), islong(tree->type)); d2 = max(degree(tree->tr2), 0); switch (op) { /* * In assignment to fields, treat all-zero and all-1 specially. */ case FSELA: if (tree->tr2->op==CON && tree->tr2->value==0) { tree->op = ASAND; tree->tr2->value = ~tree->mask; return(optim(tree)); } if (tree->tr2->op==CON && tree->mask==tree->tr2->value) { tree->op = ASOR; return(optim(tree)); } case LTIMES: case LDIV: case LMOD: case LASTIMES: case LASDIV: case LASMOD: tree->degree = 10; break; case ANDN: if (isconstant(tree->tr2) && tree->tr2->value==0) { return(tree->tr1); } goto def; case CALL: tree->degree = 10; break; case QUEST: case COLON: tree->degree = max(d1, d2); break; case DIVIDE: case ASDIV: case ASTIMES: case PTOI: if (tree->tr2->op==CON && tree->tr2->value==1) return(tree->tr1); case MOD: case ASMOD: if (tree->tr1->type==UNSIGN && ispow2(tree)) return(pow2(tree)); if ((op==MOD||op==ASMOD) && tree->type==DOUBLE) { error("Floating %% not defined"); tree->type = INT; } case ULSH: case ASULSH: d1 =+ 2; d2 =+ 2; if (tree->type==LONG) return(hardlongs(tree)); goto constant; case LSHIFT: case RSHIFT: case ASRSH: case ASLSH: if (tree->tr2->op==CON && tree->tr2->value==0) { return(tree->tr1); } /* * PDP-11 special: turn right shifts into negative * left shifts */ if (tree->type == LONG) { d1++; d2++; } if (op==LSHIFT||op==ASLSH) goto constant; if (tree->tr2->op==CON && tree->tr2->value==1 && tree->tr1->type!=UNSIGN) goto constant; op =+ (LSHIFT-RSHIFT); tree->op = op; tree->tr2 = tnode(NEG, tree->type, tree->tr2); if (tree->tr1->type==UNSIGN) { if (tree->op==LSHIFT) tree->op = ULSH; else if (tree->op==ASLSH) tree->op = ASULSH; } goto again; constant: if (tree->tr1->op==CON && tree->tr2->op==CON) { const(op, &tree->tr1->value, tree->tr2->value); return(tree->tr1); } def: default: if (dope&RELAT) { if (tree->tr1->type==LONG) /* long relations are a mess */ d1 = 10; if (opdope[tree->tr1->op]&RELAT && tree->tr2->op==CON && tree->tr2->value==0) { tree = tree->tr1; switch(op) { case GREATEQ: return(&cone); case LESS: return(&czero); case LESSEQ: case EQUAL: tree->op = notrel[tree->op-EQUAL]; } return(tree); } } tree->degree = d1==d2? d1+islong(tree->type): max(d1, d2); break; } return(tree);}unoptim(atree)struct tnode *atree;{ struct { int intx[4]; }; register struct tnode *subtre, *tree; register int *p; double static fv; struct ftconst *fp; if ((tree=atree)==0) return(0); again: if (tree->op==AMPER && tree->tr1->op==STAR) { subtre = tree->tr1->tr1; subtre->type = tree->type; return(optim(subtre)); } subtre = tree->tr1 = optim(tree->tr1); switch (tree->op) { case ITOL: if (subtre->op==CON && subtre->type==INT && subtre->value<0) { subtre = getblk(sizeof(struct lconst)); subtre->op = LCON; subtre->type = LONG; subtre->lvalue = tree->tr1->value; return(subtre); } break; case FTOI: if (tree->type==UNSIGN) { tree->op = FTOL; tree->type = LONG; tree = tnode(LTOI, UNSIGN, tree); } break; case LTOF: if (subtre->op==LCON) { tree = getblk(sizeof(*fp)); tree->op = FCON; tree->type = DOUBLE; tree->value = isn++; tree->fvalue = subtre->lvalue; return(optim(tree)); } break; case ITOF: if (tree->tr1->type==UNSIGN) { tree->tr1 = tnode(ITOL, LONG, tree->tr1); tree->op = LTOF; tree = optim(tree); } if (subtre->op!=CON) break; fv = subtre->value; p = &fv; p++; if (*p++==0 && *p++==0 && *p++==0) { tree = getblk(sizeof(*fp)); tree->op = SFCON; tree->type = DOUBLE; tree->value = * (int *) &fv; tree->fvalue = fv; return(tree); } break; case ITOC: p = tree->tr1; /* * Sign-extend PDP-11 characters */ if (p->op==CON) { p->value = p->value << 8 >> 8; return(p); } else if (p->op==NAME) { p->type = CHAR; return(p); } break; case LTOI: p = tree->tr1; switch (p->op) { case LCON: p->op = CON; p->type = tree->type; p->value = p->lvalue; return(p); case NAME: p->offset =+ 2; p->type = tree->type; return(p); case STAR: p->type = tree->type; p->tr1->type = tree->type+PTR; p->tr1 = tnode(PLUS, tree->type, p->tr1, tconst(2, INT)); return(optim(p)); case ITOL: return(p->tr1); case PLUS: case MINUS: case AND: case ANDN: case OR: case EXOR: p->tr2 = tnode(LTOI, tree->type, p->tr2); case NEG: case COMPL: p->tr1 = tnode(LTOI, tree->type, p->tr1); p->type = tree->type; return(optim(p)); } break; case FSEL: tree->op = AND; tree->tr1 = tree->tr2->tr1; tree->tr2->tr1 = subtre; tree->tr2->op = RSHIFT; tree->tr1->value = (1 << tree->tr1->value) - 1; return(optim(tree)); case FSELR: tree->op = LSHIFT; tree->type = UNSIGN; tree->tr1 = tree->tr2; tree->tr1->op = AND; tree->tr2 = tree->tr2->tr2; tree->tr1->tr2 = subtre; tree->tr1->tr1->value = (1 << tree->tr1->tr1->value) -1; return(optim(tree)); case AMPER: if (subtre->op==STAR) return(subtre->tr1); if (subtre->op==NAME && subtre->class == OFFS) { p = tnode(PLUS, tree->type, subtre, tree); subtre->type = tree->type; tree->op = CON; tree->type = INT; tree->degree = 0; tree->value = subtre->offset; subtre->class = REG; subtre->nloc = subtre->regno; subtre->offset = 0; return(optim(p)); } break; case STAR: if (subtre->op==AMPER) { subtre->tr1->type = tree->type; return(subtre->tr1); } if (tree->type==STRUCT) break; if (subtre->op==NAME && subtre->class==REG) { subtre->type = tree->type; subtre->class = OFFS; subtre->regno = subtre->nloc; return(subtre); } p = subtre->tr1; if ((subtre->op==INCAFT||subtre->op==DECBEF)&&tree->type!=LONG && p->op==NAME && p->class==REG && p->type==subtre->type) { p->type = tree->type; p->op = subtre->op==INCAFT? AUTOI: AUTOD; return(p); } if (subtre->op==PLUS && p->op==NAME && p->class==REG) { if (subtre->tr2->op==CON) { p->offset =+ subtre->tr2->value; p->class = OFFS; p->type = tree->type; p->regno = p->nloc; return(p); } if (subtre->tr2->op==AMPER) { subtre = subtre->tr2->tr1; subtre->class =+ XOFFS-EXTERN; subtre->regno = p->nloc; subtre->type = tree->type; return(subtre); } } break; case EXCLA: if ((opdope[subtre->op]&RELAT)==0) break; tree = subtre; tree->op = notrel[tree->op-EQUAL]; break; case COMPL: if (tree->type==CHAR) tree->type = INT; if (tree->op == subtre->op) return(subtre->tr1); if (subtre->op==CON) { subtre->value = ~subtre->value; return(subtre); } if (subtre->op==LCON) { subtre->lvalue = ~subtre->lvalue; return(subtre); } if (subtre->op==ITOL) { if (subtre->tr1->op==CON) { tree = getblk(sizeof(struct lconst)); tree->op = LCON; tree->type = LONG; if (subtre->tr1->type==UNSIGN) tree->lvalue = ~(long)(unsigned)subtre->tr1->value; else tree->lvalue = ~subtre->tr1->value; return(tree); } if (subtre->tr1->type==UNSIGN) break; subtre->op = tree->op; subtre->type = subtre->tr1->type; tree->op = ITOL; tree->type = LONG; goto again; } case NEG: if (tree->type==CHAR) tree->type = INT; if (tree->op==subtre->op) return(subtre->tr1); if (subtre->op==CON) { subtre->value = -subtre->value; return(subtre); } if (subtre->op==LCON) { subtre->lvalue = -subtre->lvalue; return(subtre); } if (subtre->op==ITOL && subtre->tr1->op==CON) { tree = getblk(sizeof(struct lconst)); tree->op = LCON; tree->type = LONG; if (subtre->tr1->type==UNSIGN) tree->lvalue = -(long)(unsigned)subtre->tr1->value; else tree->lvalue = -subtre->tr1->value; return(tree); } /* * PDP-11 FP negation */ if (subtre->op==SFCON) { subtre->value =^ 0100000; subtre->fvalue.intx[0] =^ 0100000; return(subtre); } if (subtre->op==FCON) { subtre->fvalue.intx[0] =^ 0100000; return(subtre); } } if ((opdope[tree->op]&LEAF)==0) tree->degree = max(islong(tree->type), degree(subtre)); return(tree);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -