Main Page | Class Hierarchy | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

dag.c

Go to the documentation of this file.
00001 #include "c.h"
00002 
00003 
00004 #define iscall(op) (generic(op) == CALL \
00005     || IR->mulops_calls \
00006     && (generic(op)==DIV||generic(op)==MOD||generic(op)==MUL) \
00007     && ( optype(op)==U  || optype(op)==I))
00008 static Node forest;
00009 static struct dag {
00010     struct node node;
00011     struct dag *hlink;
00012 } *buckets[16];
00013 int nodecount;
00014 static Tree firstarg;
00015 int assignargs = 1;
00016 int prunetemps = -1;
00017 static Node *tail;
00018 
00019 static int depth = 0;
00020 static Node replace(Node);
00021 static Node prune(Node);
00022 static Node asgnnode(Symbol, Node);
00023 static struct dag *dagnode(int, Node, Node, Symbol);
00024 static Symbol equated(Symbol);
00025 static void fixup(Node);
00026 static void labelnode(int);
00027 static void list(Node);
00028 static void kill(Symbol);
00029 static Node node(int, Node, Node, Symbol);
00030 static void printdag1(Node, int, int);
00031 static void printnode(Node, int, int);
00032 static void reset(void);
00033 static Node tmpnode(Node);
00034 static void typestab(Symbol, void *);
00035 static Node undag(Node);
00036 static Node visit(Node, int);
00037 static void unlist(void);
00038 void walk(Tree tp, int tlab, int flab) {
00039     listnodes(tp, tlab, flab);
00040     if (forest) {
00041         Node list = forest->link;
00042         forest->link = NULL;
00043         if (!IR->wants_dag)
00044             list = undag(list);
00045         code(Gen)->u.forest = list;
00046         forest = NULL;
00047     }
00048     reset();
00049     deallocate(STMT);
00050 }
00051 
00052 static Node node(int op, Node l, Node r, Symbol sym) {
00053     int i;
00054     struct dag *p;
00055 
00056     i = (opindex(op)^((unsigned long)sym>>2))&(NELEMS(buckets)-1);
00057     for (p = buckets[i]; p; p = p->hlink)
00058         if (p->node.op      == op && p->node.syms[0] == sym
00059         &&  p->node.kids[0] == l  && p->node.kids[1] == r)
00060             return &p->node;
00061     p = dagnode(op, l, r, sym);
00062     p->hlink = buckets[i];
00063     buckets[i] = p;
00064     ++nodecount;
00065     return &p->node;
00066 }
00067 static struct dag *dagnode(int op, Node l, Node r, Symbol sym) {
00068     struct dag *p;
00069 
00070     NEW0(p, FUNC);
00071     p->node.op = op;
00072     if ((p->node.kids[0] = l) != NULL)
00073         ++l->count;
00074     if ((p->node.kids[1] = r) != NULL)
00075         ++r->count;
00076     p->node.syms[0] = sym;
00077     return p;
00078 }
00079 Node newnode(int op, Node l, Node r, Symbol sym) {
00080     return &dagnode(op, l, r, sym)->node;
00081 }
00082 static void kill(Symbol p) {
00083     int i;
00084     struct dag **q;
00085 
00086     for (i = 0; i < NELEMS(buckets); i++)
00087         for (q = &buckets[i]; *q; )
00088             if (generic((*q)->node.op) == INDIR &&
00089                 (!isaddrop((*q)->node.kids[0]->op)
00090                  || (*q)->node.kids[0]->syms[0] == p)) {
00091                 *q = (*q)->hlink;
00092                 --nodecount;
00093             } else
00094                 q = &(*q)->hlink;
00095 }
00096 static void reset(void) {
00097     if (nodecount > 0)
00098         memset(buckets, 0, sizeof buckets);
00099     nodecount = 0;
00100 }
00101 Node listnodes(Tree tp, int tlab, int flab) {
00102     Node p = NULL, l, r;
00103     int op;
00104 
00105     assert(tlab || flab || tlab == 0 && flab == 0);
00106     if (tp == NULL)
00107         return NULL;
00108     if (tp->node)
00109         return tp->node;
00110     op = tp->op + sizeop(tp->type->size);
00111     switch (generic(tp->op)) {
00112     case AND:   { if (depth++ == 0) reset();
00113               if (flab) {
00114                 listnodes(tp->kids[0], 0, flab);
00115                 listnodes(tp->kids[1], 0, flab);
00116               } else {
00117                 listnodes(tp->kids[0], 0, flab = genlabel(1));
00118                 listnodes(tp->kids[1], tlab, 0);
00119                 labelnode(flab);
00120               }
00121               depth--; } break;
00122     case OR:    { if (depth++ == 0)
00123                 reset();
00124               if (tlab) {
00125                 listnodes(tp->kids[0], tlab, 0);
00126                 listnodes(tp->kids[1], tlab, 0);
00127               } else {
00128                 tlab = genlabel(1);
00129                 listnodes(tp->kids[0], tlab, 0);
00130                 listnodes(tp->kids[1], 0, flab);
00131                 labelnode(tlab);
00132               }
00133               depth--;
00134  } break;
00135     case NOT:   { return listnodes(tp->kids[0], flab, tlab); }
00136     case COND:  { Tree q = tp->kids[1];
00137               assert(tlab == 0 && flab == 0);
00138               if (tp->u.sym)
00139                 addlocal(tp->u.sym);
00140               flab = genlabel(2);
00141               listnodes(tp->kids[0], 0, flab);
00142               assert(q && q->op == RIGHT);
00143               reset();
00144               listnodes(q->kids[0], 0, 0);
00145               if (forest->op == LABEL+V) {
00146                 equatelab(forest->syms[0], findlabel(flab + 1));
00147                 unlist();
00148               }
00149               list(jump(flab + 1));
00150               labelnode(flab);
00151               listnodes(q->kids[1], 0, 0);
00152               if (forest->op == LABEL+V) {
00153                 equatelab(forest->syms[0], findlabel(flab + 1));
00154                 unlist();
00155               }
00156               labelnode(flab + 1);
00157 
00158               if (tp->u.sym)
00159                 p = listnodes(idtree(tp->u.sym), 0, 0); } break;
00160     case CNST:  { Type ty = unqual(tp->type);
00161               assert(ty->u.sym);
00162               if (tlab || flab) {
00163                 assert(ty == inttype);
00164                 if (tlab && tp->u.v.i != 0)
00165                     list(jump(tlab));
00166                 else if (flab && tp->u.v.i == 0)
00167                     list(jump(flab));
00168               }
00169               else if (ty->u.sym->addressed)
00170                 p = listnodes(cvtconst(tp), 0, 0);
00171               else
00172                 p = node(op, NULL, NULL, constant(ty, tp->u.v)); } break;
00173     case RIGHT: { if (   tp->kids[0] && tp->kids[1]
00174               &&  generic(tp->kids[1]->op) == ASGN
00175               && (generic(tp->kids[0]->op) == INDIR
00176               && tp->kids[0]->kids[0] == tp->kids[1]->kids[0]
00177               || (tp->kids[0]->op == FIELD
00178               &&  tp->kids[0] == tp->kids[1]->kids[0]))) {
00179                 assert(tlab == 0 && flab == 0);
00180             if (generic(tp->kids[0]->op) == INDIR) {
00181                 p = listnodes(tp->kids[0], 0, 0);
00182                 list(p);
00183                 listnodes(tp->kids[1], 0, 0);
00184             }
00185             else {
00186                 assert(generic(tp->kids[0]->kids[0]->op) == INDIR);
00187                 list(listnodes(tp->kids[0]->kids[0], 0, 0));
00188                 p = listnodes(tp->kids[0], 0, 0);
00189                 listnodes(tp->kids[1], 0, 0);
00190             }
00191               } else if (tp->kids[1]) {
00192                 listnodes(tp->kids[0], 0, 0);
00193                 p = listnodes(tp->kids[1], tlab, flab);
00194               } else
00195                 p = listnodes(tp->kids[0], tlab, flab); } break;
00196     case JUMP:  { assert(tlab == 0 && flab == 0);
00197               assert(tp->u.sym == 0);
00198               assert(tp->kids[0]);
00199               l = listnodes(tp->kids[0], 0, 0);
00200               list(newnode(JUMP+V, l, NULL, NULL));
00201               reset(); } break;
00202     case CALL:  { Tree save = firstarg;
00203               firstarg = NULL;
00204               assert(tlab == 0 && flab == 0);
00205               if (tp->op == CALL+B && !IR->wants_callb) {
00206                 Tree arg0 = tree(ARG+P, tp->kids[1]->type,
00207                 tp->kids[1], NULL);
00208             if (IR->left_to_right)
00209                 firstarg = arg0;
00210             l = listnodes(tp->kids[0], 0, 0);
00211             if (!IR->left_to_right || firstarg) {
00212                 firstarg = NULL;
00213                 listnodes(arg0, 0, 0);
00214             }
00215                 p = newnode(CALL+V, l, NULL, NULL);
00216               } else {
00217                 l = listnodes(tp->kids[0], 0, 0);
00218                 r = listnodes(tp->kids[1], 0, 0);
00219                 p = newnode(tp->op == CALL+B ? tp->op : op, l, r, NULL);
00220               }
00221               NEW0(p->syms[0], FUNC);
00222               assert(isptr(tp->kids[0]->type));
00223               assert(isfunc(tp->kids[0]->type->type));
00224               p->syms[0]->type = tp->kids[0]->type->type;
00225               list(p);
00226               reset();
00227               cfunc->u.f.ncalls++;
00228               firstarg = save;
00229  } break;
00230     case ARG:   { assert(tlab == 0 && flab == 0);
00231               if (IR->left_to_right)
00232                 listnodes(tp->kids[1], 0, 0);
00233               if (firstarg) {
00234                 Tree arg = firstarg;
00235                 firstarg = NULL;
00236                 listnodes(arg, 0, 0);
00237               }
00238               l = listnodes(tp->kids[0], 0, 0);
00239               list(newnode(tp->op == ARG+B ? tp->op : op, l, NULL, NULL));
00240               forest->syms[0] = intconst(tp->type->size);
00241               forest->syms[1] = intconst(tp->type->align);
00242               if (!IR->left_to_right)
00243                 listnodes(tp->kids[1], 0, 0); } break;
00244     case EQ:  case NE: case GT: case GE: case LE:
00245     case LT:    { assert(tp->u.sym == 0);
00246               assert(errcnt || tlab || flab);
00247               l = listnodes(tp->kids[0], 0, 0);
00248               r = listnodes(tp->kids[1], 0, 0);
00249               assert(errcnt || opkind(l->op) == opkind(r->op));
00250               assert(errcnt || optype(op) == optype(l->op));
00251               if (tlab)
00252                 assert(flab == 0),
00253                 list(newnode(generic(tp->op) + opkind(l->op), l, r, findlabel(tlab)));
00254               else if (flab) {
00255                 switch (generic(tp->op)) {
00256                 case EQ: op = NE; break;
00257                 case NE: op = EQ; break;
00258                 case GT: op = LE; break;
00259                 case LT: op = GE; break;
00260                 case GE: op = LT; break;
00261                 case LE: op = GT; break;
00262                 default: assert(0);
00263                 }
00264                 list(newnode(op + opkind(l->op), l, r, findlabel(flab)));
00265               }
00266               if (forest && forest->syms[0])
00267                 forest->syms[0]->ref++; } break;
00268     case ASGN:  { assert(tlab == 0 && flab == 0);
00269               if (tp->kids[0]->op == FIELD) {
00270                 Tree  x = tp->kids[0]->kids[0];
00271             Field f = tp->kids[0]->u.field;
00272             assert(generic(x->op) == INDIR);
00273             reset();
00274             l = listnodes(lvalue(x), 0, 0);
00275             if (fieldsize(f) < 8*f->type->size) {
00276                 unsigned int fmask = fieldmask(f);
00277                 unsigned int  mask = fmask<<fieldright(f);
00278                 Tree q = tp->kids[1];
00279                 if (q->op == CNST+I && q->u.v.i == 0
00280                 ||  q->op == CNST+U && q->u.v.u == 0)
00281                     q = bittree(BAND, x, cnsttree(unsignedtype, (unsigned long)~mask));
00282                 else if (q->op == CNST+I && (q->u.v.i&fmask) == fmask
00283                 ||       q->op == CNST+U && (q->u.v.u&fmask) == fmask)
00284                     q = bittree(BOR, x, cnsttree(unsignedtype, (unsigned long)mask));
00285                 else {
00286                     listnodes(q, 0, 0);
00287                     q = bittree(BOR,
00288                         bittree(BAND, rvalue(lvalue(x)),
00289                             cnsttree(unsignedtype, (unsigned long)~mask)),
00290                         bittree(BAND, shtree(LSH, cast(q, unsignedtype),
00291                             cnsttree(unsignedtype, (unsigned long)fieldright(f))),
00292                             cnsttree(unsignedtype, (unsigned long)mask)));
00293                 }
00294                 r = listnodes(q, 0, 0);
00295                 op = ASGN + ttob(q->type);
00296             } else {
00297                 r = listnodes(tp->kids[1], 0, 0);
00298                 op = ASGN + ttob(tp->kids[1]->type);
00299             }
00300               } else {
00301                 l = listnodes(tp->kids[0], 0, 0);
00302                 r = listnodes(tp->kids[1], 0, 0);
00303               }
00304               list(newnode(tp->op == ASGN+B ? tp->op : op, l, r, NULL));
00305               forest->syms[0] = intconst(tp->kids[1]->type->size);
00306               forest->syms[1] = intconst(tp->kids[1]->type->align);
00307               if (isaddrop(tp->kids[0]->op)
00308               && !tp->kids[0]->u.sym->computed)
00309                 kill(tp->kids[0]->u.sym);
00310               else
00311                 reset();
00312               p = listnodes(tp->kids[1], 0, 0); } break;
00313     case BOR: case BAND: case BXOR:
00314     case ADD: case SUB:  case RSH:
00315     case LSH:   { assert(tlab == 0 && flab == 0);
00316               l = listnodes(tp->kids[0], 0, 0);
00317               r = listnodes(tp->kids[1], 0, 0);
00318               p = node(op, l, r, NULL); } break;
00319     case DIV: case MUL:
00320     case MOD:   { assert(tlab == 0 && flab == 0);
00321               l = listnodes(tp->kids[0], 0, 0);
00322               r = listnodes(tp->kids[1], 0, 0);
00323               p = node(op, l, r, NULL);
00324               if (IR->mulops_calls && isint(tp->type)) {
00325                 list(p);
00326                 cfunc->u.f.ncalls++;
00327               } } break;
00328     case RET:   { assert(tlab == 0 && flab == 0);
00329               l = listnodes(tp->kids[0], 0, 0);
00330               list(newnode(op, l, NULL, NULL)); } break;
00331     case CVF: case CVI: case CVP:
00332     case CVU:   { assert(tlab == 0 && flab == 0);
00333               assert(optype(tp->kids[0]->op) != optype(tp->op) || tp->kids[0]->type->size != tp->type->size);
00334               l = listnodes(tp->kids[0], 0, 0);
00335               p = node(op, l, NULL, intconst(tp->kids[0]->type->size));
00336  } break;
00337     case BCOM:
00338     case NEG:   { assert(tlab == 0 && flab == 0);
00339               l = listnodes(tp->kids[0], 0, 0);
00340               p = node(op, l, NULL, NULL); } break;
00341     case INDIR: { Type ty = tp->kids[0]->type;
00342               assert(tlab == 0 && flab == 0);
00343               l = listnodes(tp->kids[0], 0, 0);
00344               if (isptr(ty))
00345                 ty = unqual(ty)->type;
00346               if (isvolatile(ty)
00347               || (isstruct(ty) && unqual(ty)->u.sym->u.s.vfields))
00348                 p = newnode(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL);
00349               else
00350                 p = node(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL); } break;
00351     case FIELD: { Tree q = tp->kids[0];
00352               if (tp->type == inttype) {
00353                 long n = fieldleft(tp->u.field);
00354                 q = shtree(RSH,
00355                     shtree(LSH, q, cnsttree(inttype, n)),
00356                     cnsttree(inttype, n + fieldright(tp->u.field)));
00357               } else if (fieldsize(tp->u.field) < 8*tp->u.field->type->size)
00358                 q = bittree(BAND,
00359                     shtree(RSH, q, cnsttree(inttype, (long)fieldright(tp->u.field))),
00360                     cnsttree(unsignedtype, (unsigned long)fieldmask(tp->u.field)));
00361               assert(tlab == 0 && flab == 0);
00362               p = listnodes(q, 0, 0); } break;
00363     case ADDRG:
00364     case ADDRF: { assert(tlab == 0 && flab == 0);
00365               p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u.sym);
00366  } break;
00367     case ADDRL: { assert(tlab == 0 && flab == 0);
00368               if (tp->u.sym->temporary)
00369                 addlocal(tp->u.sym);
00370               p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u.sym); } break;
00371     default:assert(0);
00372     }
00373     tp->node = p;
00374     return p;
00375 }
00376 static void list(Node p) {
00377     if (p && p->link == NULL) {
00378         if (forest) {
00379             p->link = forest->link;
00380             forest->link = p;
00381         } else
00382             p->link = p;
00383         forest = p;
00384     }
00385 }
00386 static void labelnode(int lab) {
00387     assert(lab);
00388     if (forest && forest->op == LABEL+V)
00389         equatelab(findlabel(lab), forest->syms[0]);
00390     else
00391         list(newnode(LABEL+V, NULL, NULL, findlabel(lab)));
00392     reset();
00393 }
00394 static void unlist(void) {
00395     Node p;
00396 
00397     assert(forest);
00398     assert(forest != forest->link);
00399     p = forest->link;
00400     while (p->link != forest)
00401         p = p->link;
00402     p->link = forest->link;
00403     forest = p;
00404 }
00405 Tree cvtconst(Tree p) {
00406     Symbol q = constant(p->type, p->u.v);
00407     Tree e;
00408 
00409     if (q->u.c.loc == NULL)
00410         q->u.c.loc = genident(STATIC, p->type, GLOBAL);
00411     if (isarray(p->type)) {
00412         e = simplify(ADDRG, atop(p->type), NULL, NULL);
00413         e->u.sym = q->u.c.loc;
00414     } else
00415         e = idtree(q->u.c.loc);
00416     return e;
00417 }
00418 void gencode(Symbol caller[], Symbol callee[]) {
00419     Code cp;
00420     Coordinate save;
00421 
00422     if (prunetemps == -1)
00423         prunetemps = !IR->wants_dag;
00424     save = src;
00425     if (assignargs) {
00426         int i;
00427         Symbol p, q;
00428         cp = codehead.next->next;
00429         codelist = codehead.next;
00430         for (i = 0; (p = callee[i]) != NULL
00431                  && (q = caller[i]) != NULL; i++)
00432             if (p->sclass != q->sclass || p->type != q->type)
00433                 walk(asgn(p, idtree(q)), 0, 0);
00434         codelist->next = cp;
00435         cp->prev = codelist;
00436     }
00437     if (glevel && IR->stabsym) {
00438         int i;
00439         Symbol p, q;
00440         for (i = 0; (p = callee[i]) != NULL
00441                  && (q = caller[i]) != NULL; i++) {
00442             (*IR->stabsym)(p);
00443             if (p->sclass != q->sclass || p->type != q->type)
00444                 (*IR->stabsym)(q);
00445         }
00446         swtoseg(CODE);
00447     }
00448     cp = codehead.next;
00449     for ( ; errcnt <= 0 && cp; cp = cp->next)
00450         switch (cp->kind) {
00451         case Address:  (*IR->address)(cp->u.addr.sym, cp->u.addr.base,
00452                     cp->u.addr.offset); break;
00453         case Blockbeg: {
00454                     Symbol *p = cp->u.block.locals;
00455                     (*IR->blockbeg)(&cp->u.block.x);
00456                     for ( ; *p; p++)
00457                         if ((*p)->ref != 0.0)
00458                             (*IR->local)(*p);
00459                         else if (glevel) (*IR->local)(*p);
00460                    }
00461  break;
00462         case Blockend: (*IR->blockend)(&cp->u.begin->u.block.x); break;
00463         case Defpoint: src = cp->u.point.src; break;
00464         case Gen: case Jump:
00465         case Label:    if (prunetemps)
00466                     cp->u.forest = prune(cp->u.forest);
00467                    fixup(cp->u.forest);
00468                    cp->u.forest = (*IR->gen)(cp->u.forest); break;
00469         case Local:    (*IR->local)(cp->u.var); break;
00470         case Switch:   break;
00471         default: assert(0);
00472         }
00473     src = save;
00474 }
00475 static void fixup(Node p) {
00476     for ( ; p; p = p->link)
00477         switch (generic(p->op)) {
00478         case JUMP:
00479             if (specific(p->kids[0]->op) == ADDRG+P)
00480                 p->kids[0]->syms[0] =
00481                     equated(p->kids[0]->syms[0]);
00482             break;
00483         case LABEL: assert(p->syms[0] == equated(p->syms[0])); break;
00484         case EQ: case GE: case GT: case LE: case LT: case NE:
00485             assert(p->syms[0]);
00486             p->syms[0] = equated(p->syms[0]);
00487         }
00488 }
00489 static Symbol equated(Symbol p) {
00490     { Symbol q; for (q = p->u.l.equatedto; q; q = q->u.l.equatedto) assert(p != q); }
00491     while (p->u.l.equatedto)
00492         p = p->u.l.equatedto;
00493     return p;
00494 }
00495 void emitcode(void) {
00496     Code cp;
00497     Coordinate save;
00498 
00499     save = src;
00500     cp = codehead.next;
00501     for ( ; errcnt <= 0 && cp; cp = cp->next)
00502         switch (cp->kind) {
00503         case Address: break;
00504         case Blockbeg: if (glevel && IR->stabblock) {
00505                     (*IR->stabblock)('{',  cp->u.block.level - LOCAL, cp->u.block.locals);
00506                     swtoseg(CODE);
00507                    }
00508  break;
00509         case Blockend: if (glevel && IR->stabblock) {
00510                     Code bp = cp->u.begin;
00511                     foreach(bp->u.block.identifiers, bp->u.block.level, typestab, NULL);
00512                     foreach(bp->u.block.types,       bp->u.block.level, typestab, NULL);
00513                     (*IR->stabblock)('}', bp->u.block.level - LOCAL, bp->u.block.locals);
00514                     swtoseg(CODE);
00515                    }
00516  break;
00517         case Defpoint: src = cp->u.point.src;
00518                    if (glevel > 0 && IR->stabline) {
00519                     (*IR->stabline)(&cp->u.point.src); swtoseg(CODE); } break;
00520         case Gen: case Jump:
00521         case Label:    if (cp->u.forest)
00522                     (*IR->emit)(cp->u.forest); break;
00523         case Local:    if (glevel && IR->stabsym) {
00524                     (*IR->stabsym)(cp->u.var);
00525                     swtoseg(CODE);
00526                    } break;
00527         case Switch:   {    int i;
00528                     defglobal(cp->u.swtch.table, LIT);
00529                     (*IR->defaddress)(equated(cp->u.swtch.labels[0]));
00530                     for (i = 1; i < cp->u.swtch.size; i++) {
00531                         long k = cp->u.swtch.values[i-1];
00532                         while (++k < cp->u.swtch.values[i])
00533                             assert(k < LONG_MAX),
00534                             (*IR->defaddress)(equated(cp->u.swtch.deflab));
00535                         (*IR->defaddress)(equated(cp->u.swtch.labels[i]));
00536                     }
00537                     swtoseg(CODE);
00538                    } break;
00539         default: assert(0);
00540         }
00541     src = save;
00542 }
00543 
00544 static Node undag(Node forest) {
00545     Node p;
00546 
00547     tail = &forest;
00548     for (p = forest; p; p = p->link)
00549         if (generic(p->op) == INDIR) {
00550             assert(p->count >= 1);
00551             visit(p, 1);
00552             if (p->syms[2]) {
00553                 assert(p->syms[2]->u.t.cse);
00554                 p->syms[2]->u.t.cse = NULL;
00555                 addlocal(p->syms[2]);
00556             }
00557         } else if (iscall(p->op) && p->count >= 1)
00558             visit(p, 1);
00559         else {
00560             assert(p->count == 0),
00561             visit(p, 1);
00562             *tail = p;
00563             tail = &p->link;
00564         }
00565     *tail = NULL;
00566     return forest;
00567 }
00568 static Node replace(Node p) {
00569     if (p && (  generic(p->op) == INDIR
00570          && generic(p->kids[0]->op) == ADDRL
00571          && p->kids[0]->syms[0]->temporary
00572          && p->kids[0]->syms[0]->u.t.replace)) {
00573         p = p->kids[0]->syms[0]->u.t.cse;
00574         if (generic(p->op) == INDIR && isaddrop(p->kids[0]->op))
00575             p = newnode(p->op, newnode(p->kids[0]->op, NULL, NULL,
00576                 p->kids[0]->syms[0]), NULL, NULL);
00577         else if (generic(p->op) == ADDRG)
00578             p = newnode(p->op, NULL, NULL, p->syms[0]);
00579         else
00580             assert(0);
00581         p->count = 1;
00582     } else if (p) {
00583         p->kids[0] = replace(p->kids[0]);
00584         p->kids[1] = replace(p->kids[1]);
00585     }
00586     return p;
00587 }
00588 static Node prune(Node forest) {
00589     Node p, *tail = &forest;
00590     int count = 0;
00591 
00592     for (p = forest; p; p = p->link) {
00593         if (count > 0) {
00594             p->kids[0] = replace(p->kids[0]);
00595             p->kids[1] = replace(p->kids[1]);
00596         }
00597         if ((  generic(p->op) == ASGN
00598             && generic(p->kids[0]->op) == ADDRL
00599             && p->kids[0]->syms[0]->temporary
00600             && p->kids[0]->syms[0]->u.t.cse == p->kids[1])) {
00601             Symbol tmp = p->kids[0]->syms[0];
00602             if (!tmp->defined)
00603                 (*IR->local)(tmp);
00604             tmp->defined = 1;
00605             if ((  generic(p->kids[1]->op) == INDIR
00606                 && isaddrop(p->kids[1]->kids[0]->op)
00607                 && p->kids[1]->kids[0]->syms[0]->sclass == REGISTER)
00608             || ((  generic(p->kids[1]->op) == INDIR
00609                 && isaddrop(p->kids[1]->kids[0]->op)) && tmp->sclass == AUTO)
00610             || (generic(p->kids[1]->op) == ADDRG && tmp->sclass == AUTO)) {
00611                 tmp->u.t.replace = 1;
00612                 count++;
00613                 continue;   /* and omit the assignment */
00614             }
00615         }
00616         /* keep the assignment and other roots */
00617         *tail = p;
00618         tail = &(*tail)->link;
00619     }
00620     assert(*tail == NULL);
00621     return forest;
00622 }
00623 static Node visit(Node p, int listed) {
00624     if (p)
00625         if (p->syms[2])
00626             p = tmpnode(p);
00627         else if (p->count <= 1 && !iscall(p->op)
00628         ||       p->count == 0 &&  iscall(p->op)) {
00629             p->kids[0] = visit(p->kids[0], 0);
00630             p->kids[1] = visit(p->kids[1], 0);
00631         }
00632 
00633         else if (specific(p->op) == ADDRL+P || specific(p->op) == ADDRF+P) {
00634             assert(!listed);
00635             p = newnode(p->op, NULL, NULL, p->syms[0]);
00636             p->count = 1;
00637         }
00638         else if (p->op == INDIR+B) {
00639             p = newnode(p->op, p->kids[0], NULL, NULL);
00640             p->count = 1;
00641             p->kids[0] = visit(p->kids[0], 0);
00642             p->kids[1] = visit(p->kids[1], 0);
00643         }
00644         else {
00645             p->kids[0] = visit(p->kids[0], 0);
00646             p->kids[1] = visit(p->kids[1], 0);
00647             p->syms[2] = temporary(REGISTER, btot(p->op, opsize(p->op)));
00648             assert(!p->syms[2]->defined);
00649             p->syms[2]->ref = 1;
00650             p->syms[2]->u.t.cse = p;
00651 
00652             *tail = asgnnode(p->syms[2], p);
00653             tail = &(*tail)->link;
00654             if (!listed)
00655                 p = tmpnode(p);
00656         };
00657     return p;
00658 }
00659 static Node tmpnode(Node p) {
00660     Symbol tmp = p->syms[2];
00661 
00662     assert(tmp);
00663     if (--p->count == 0)
00664         p->syms[2] = NULL;
00665     p = newnode(INDIR + ttob(tmp->type),
00666         newnode(ADDRL + ttob(voidptype), NULL, NULL, tmp), NULL, NULL);
00667     p->count = 1;
00668     return p;
00669 }
00670 static Node asgnnode(Symbol tmp, Node p) {
00671     p = newnode(ASGN + ttob(tmp->type),
00672         newnode(ADDRL + ttob(voidptype), NULL, NULL, tmp), p, NULL);
00673     p->syms[0] = intconst(tmp->type->size);
00674     p->syms[1] = intconst(tmp->type->align);
00675     return p;
00676 }
00677 /* printdag - print