Main Page | Class Hierarchy | Alphabetical List | Compound List | File List | Compound Members | File Members

modify.C

Go to the documentation of this file.
00001 // modify.C
00002 
00003 /*
00004  * LEGO Object Modification Functions
00005  * by Bill Havanki
00006  *
00007  * 1/29/98 WAH:  Created file.
00008  * 4/9/98 WAH:   Added TailDuplicate (moved from IR).
00009  * 4/14/98 WAH:  TailDuplicate now picks op ids from proc, not module.
00010  * 4/22/98 WAH:  Updated calls to attrs copy constructor in TailDuplicate.
00011  */
00012 
00013 #include <stdio.h>
00014 #include <stdlib.h>
00015 #include "lego.H"
00016 #include "modify.H"
00017 #include "search.H"
00018 #include "addremove.H"
00019 #include "bitvector.H"
00020 
00021 #define YES 1
00022 #define NO 0
00023 
00024 // #define MODIFY_DEBUG
00025 #ifdef MODIFY_DEBUG
00026 #define derr(_s_)  cerr << _s_ 
00027 #define dprintf(s) fprintf s
00028 #define OUTF stderr
00029 #else
00030 #define derr(_s_) 
00031 #define dprintf(s)
00032 #endif // MODIFY_DEBUG
00033 
00034 // ========================================================================
00035 
00036 /*
00037  * AddWeightAttribute
00038  *   op = op to annotate
00039  *   returns: new attr attached to op
00040  *
00041  * Attaches a new attr to the op saying what the weight of its block
00042  * is.
00043  */
00044 static attrs *
00045 AddWeightAttribute (legoOp *op)
00046 {
00047   legoRegion *block;
00048   legoOprd *oprd;
00049   attrs *wtattr;
00050 
00051   block = (legoRegion *) op->GetParentBlockPtr();
00052   if (block == NULL) return NULL;
00053 
00054   oprd = new legoOprd;
00055   oprd->SetOprdType (OT_LITERAL_D);
00056   oprd->SetLiteralDouble (block->GetWeight());
00057 
00058   // Only update orig_wt for an op one time, as HBs may be in merged into 
00059   // other HBs. In this case we are only interested in the orig BB weight.
00060   if (FindLcAttribute( "orig_wt", op ) == NULL) {
00061     wtattr = AddLcAttribute ("orig_wt", oprd, op,
00062                              (legoProc *) FindParentRegionType (RT_PROC, op));
00063     return wtattr;
00064   }
00065   else {
00066     return NULL;
00067   }
00068 }
00069 
00070 // ========================================================================
00071 
00072 /*
00073  * RedirectEdge
00074  *   edge = edge to redirect
00075  *   end = which end of edge to redirect
00076  *   op = op to which edge is to be redirected
00077  *   returns: 1 for success, 0 for failure
00078  *
00079  * Changes the source or destination of edge to op. Passing EDGE_FROM
00080  * changes the source, EDGE_TO the destination.
00081  *
00082  * Warning: Arbitrary use of this function will not only affect program
00083  * behavior but could invalidate some profile information.
00084  */
00085 int
00086 RedirectEdge (opEdges *edge, int end, legoOp *op)
00087 {
00088   legoOp *oldop, *fromop, *toop;
00089   legoRegion *oldregion, *fromregion, *toregion;
00090   opList *opl;
00091 
00092   int from;
00093   double weight;
00094 
00095   if (edge == NULL || op == NULL ||
00096       (end != EDGE_FROM && end != EDGE_TO))
00097     {
00098       LegoNonFatal ("RedirectEdge", "Invalid argument: edge %p, end %d, "
00099                     "op %p.", edge, end, op);
00100       return 0;
00101     } // end if
00102   from = (end == EDGE_FROM);
00103 
00104   // Find the from and to components of the edge after the redirection
00105   // as well as the old (before).
00106   if (from)
00107     {
00108       toop = edge->GetToOpPtr();
00109       fromop = op;
00110       oldop = edge->GetFromOpPtr();
00111     } // end if
00112   else
00113     {
00114       fromop = edge->GetFromOpPtr();
00115       toop = op;
00116       oldop = edge->GetToOpPtr();
00117     } // end else
00118   fromregion = (legoRegion *) fromop->GetParentBlockPtr();
00119   toregion = (legoRegion *) toop->GetParentBlockPtr();
00120   oldregion = (legoRegion *) oldop->GetParentBlockPtr();
00121 
00122   // Remove the reference to from/toop from oldop, and add it to
00123   // to/fromop. First, though, save the weight!
00124   if (from)
00125     opl = oldop->GetOutListPtr();
00126   else
00127     opl = oldop->GetInListPtr();
00128   for ( ; opl != NULL; opl = opl->GetNextListPtr())
00129     if (opl->GetOpPtr() == (from ? toop : fromop)) break;
00130   if (opl != NULL) weight = opl->GetWeight();
00131   else weight = 0.0;
00132 
00133   // Now switch the references. Remove the old ref is fine. The new
00134   // ref should be added only if the op is a branch or C_MERGE!
00135   if (from)
00136     {
00137       opl = RemoveFromList (oldop->GetOutListPtr(), toop);
00138       oldop->SetOutListPtr (opl);
00139       if (IsBranchOp (fromop))
00140         {
00141           opl = AddToList (fromop->GetOutListPtr(), toop, 1, weight);
00142           fromop->SetOutListPtr (opl);
00143         } // end if
00144     } // end if
00145   else
00146     {
00147       opl = RemoveFromList (oldop->GetInListPtr(), fromop);
00148       oldop->SetInListPtr (opl);
00149       if (toop->GetOpcode() == C_MERGE)
00150         {
00151           opl = AddToList (toop->GetInListPtr(), fromop, 1, weight);
00152           toop->SetInListPtr (opl);
00153         } // end if
00154     } // end else
00155 
00156   // Now, change the reference to oldop in from/toop to refer
00157   // to to/fromop.
00158   if (from)
00159     opl = toop->GetInListPtr();
00160   else
00161     opl = fromop->GetOutListPtr();
00162   for ( ; opl != NULL; opl = opl->GetNextListPtr())
00163     if (opl->GetOpPtr() == oldop) break;
00164   if (opl != NULL)
00165     {
00166       opl->SetOpPtr ((from ? fromop : toop));
00167       opl->SetOpId (opl->GetOpPtr()->GetOpId());
00168     } // end if
00169 
00170   // Next, change the edge itself.
00171   if (from)
00172     {
00173       edge->SetFromOpPtr (fromop);
00174       edge->SetFromOpId (fromop->GetOpId());
00175     } // end if
00176   else
00177     {
00178       edge->SetToOpPtr (toop);
00179       edge->SetToOpId (toop->GetOpId());
00180     } // end else
00181 
00182   // Refresh everybody's edges.
00183   for ( ; oldregion->GetRegionType() != RT_PROC;
00184         oldregion = oldregion->GetParentPtr())
00185     oldregion->RefreshOpsAndEdges();
00186   for ( ; fromregion->GetRegionType() != RT_PROC;
00187         fromregion = fromregion->GetParentPtr())
00188     fromregion->RefreshOpsAndEdges();
00189   for ( ; toregion->GetRegionType() != RT_PROC;
00190         toregion = toregion->GetParentPtr())
00191     toregion->RefreshOpsAndEdges();
00192 
00193   return 1;
00194 } // end RedirectEdge
00195 
00196 // ========================================================================
00197 
00198 /*
00199  * GetNewEdgeMergeValue
00200  *   edge = edge to analyze
00201  *   proc = procedure of edge
00202  *   returns: correct second value for edge freq attribute
00203  *
00204  * Determines the proper second value for the edge's freq attribute:
00205  *   0 if a dummy branch
00206  *   1 if the taken edge of a conditional or unconditional
00207  *   0 if the not-taken edge of a conditional
00208  *   cc value if a jumptable
00209  */
00210 static int
00211 GetNewEdgeMergeValue (opEdges *edge, legoProc *proc)
00212 {
00213   int destblock;
00214   attrList *atl;
00215   legoOp *op;
00216 
00217   if (edge->GetFromOpPtr()->GetOpcode() == DUMMY_BR ||
00218       edge->GetFromOpPtr()->GetOpcode() == DUMMY_BRANCH)
00219     return 0;
00220 
00221   for (atl = edge->GetFromOpPtr()->GetOpAttrListPtr(); atl != NULL;
00222        atl = atl->GetNextListPtr())
00223     if (atl->GetAttrType() == ATTR_TBLNAME) break;
00224   if (atl != NULL)
00225     {
00226       jumpTable *jt;
00227       jumpList *jl;
00228 
00229       // Find cc value in jumptable (best guess).
00230       for (jt = proc->GetJumpDictionary(); jt != NULL;
00231            jt = jt->GetNextTablePtr())
00232         if (strcmp (jt->GetTableName(), atl->GetTableName()) == 0) break;
00233       if (jt == NULL) return 1;  // give up and return 1 for BRU
00234 
00235       for (jl = jt->GetJumpEntryPtr(); jl != NULL;
00236            jl = jl->GetNextListPtr())
00237         if (jl->GetOpId() == edge->GetToOpPtr()->GetOpId()) break;
00238       if (jl == NULL) return 1;
00239 
00240       if (jl->IsDefault()) return 1;
00241       else return jl->GetCcValue();
00242     } // end if
00243 
00244   // If branch takes to destination block, return 1, else 0.
00245   destblock = ((legoRegion *)(edge->GetToOpPtr()->GetParentBlockPtr()))
00246     ->GetRegionId();
00247   for (op = edge->GetFromOpPtr(); op != NULL; op = op->GetPrevLink())
00248     if (op->GetOpcode() == PBRR) break;
00249   if (op == NULL) return 1;  // give up and assume taken
00250 
00251   if (op->GetSrcOprdPtr()->GetLiteralControlBlock() == destblock)
00252     return 1;  // taken block
00253   else
00254     return 0;  // not-taken block
00255 } // end GetNewEdgeMergeValue
00256 
00257 // --------------------------------------------------------------------------
00258 
00259 class pointer_map
00260 {
00261 public:
00262   void *original;  // pointer to original
00263   void *duplicate;  // pointer to duplicate
00264   class pointer_map *next;
00265 
00266   pointer_map() {original = duplicate = NULL; next = NULL;}
00267   ~pointer_map() {delete next;}
00268 
00269   void *lookup_original (void *dup)
00270   {
00271     if (duplicate == dup)
00272       return original;
00273     if (next != NULL)
00274       return next->lookup_original (dup);
00275     else
00276       return NULL;
00277   }
00278 
00279   void *lookup_duplicate (void *orig)
00280   {
00281     if (original == orig)
00282       return duplicate;
00283     if (next != NULL)
00284       return next->lookup_duplicate (orig);
00285     else
00286       return NULL;
00287   }
00288 
00289   class pointer_map *record (void *o, void *d)
00290   {
00291     original = o;
00292     duplicate = d;
00293     next = new pointer_map;
00294     return next;
00295   }
00296 }; // end class pointer_map
00297 
00298 /*
00299  * TailDuplicate
00300  *   sourceregion = region to duplicate
00301  *   dupedge = pointer to edge from last op in head region
00302  *   returns: duplicate of sourceregion
00303  *
00304  * Performs tail duplication of sourceregion.  The duplicate is attached to
00305  * head, while sourceregion remains attached to all other parents in control
00306  * flow.
00307  *
00308  * This is a horrendously long function, so be prepared to tax LEGO knowledge
00309  * to the limit!
00310  */
00311 legoRegion *
00312 TailDuplicate (legoRegion *sourceregion, opEdges *dupedge)
00313 {
00314   regionList *allparents, *allchildren, *lrrscan, *oparents, *ochildren;
00315   int i, j, bingo, regionid, opid, eaid;
00316   double edgeweight, sourceweightratio;
00317   legoRegion *head, *duplicate, *region;
00318   legoProc *parentproc;
00319   legoOp *headop, *origop, *origop2, *dupop, *dupop2;
00320   legoOprd *oprd;
00321   opEdges *edgedictionary, *edgetail, *oescan;
00322   attrs *attrdictionary, *attrtail, *atscan;
00323   opList *oplscan, *oplscanprev;
00324   attrList *atlscan, *atl;
00325   edgeList *edlscan, *edlscanprev, *edlheadtosource;
00326 
00327   pointer_map *map, *tail;
00328 
00329 //  cerr << "TailDuplicate sourceregion id " << sourceregion->GetRegionId() << " with Block Ptr " << sourceregion << "\n";
00330 
00331   headop = dupedge->GetFromOpPtr();
00332   head = (legoRegion *) (headop->GetParentBlockPtr());
00333   // First, some checking.
00334   if (!(IS_BLOCK(sourceregion->GetRegionType())))
00335     {
00336       LegoNonFatal ("TailDuplicate",
00337                     "Region %d not an op-holding block.", regionid);
00338       return NULL;
00339     } // end if
00340 
00341   allparents = sourceregion->GetParents();
00342   for (i = 0, bingo = 0, lrrscan = allparents; lrrscan != NULL;
00343        lrrscan = lrrscan->GetNextListPtr())
00344     {
00345       bingo++;
00346       if (lrrscan->GetRegionPtr() == head)
00347         i = 1;
00348     } // end for
00349   if (i == 0)
00350     {
00351       LegoNonFatal ("TailDuplicate", "Parent given is not actual parent.");
00352       return NULL;
00353     } // end if
00354   if (bingo < 2)
00355     {
00356       // No need to tail duplicate, so return sourceregion.
00357       return sourceregion;
00358     } // end if
00359 
00360   tail = map = new pointer_map;  // initialize pointer mapping table
00361 
00362   // Find parent proc.
00363   parentproc = (legoProc *) FindParentRegionType (RT_PROC, sourceregion);
00364   if (parentproc == NULL)
00365     LegoFatal ("TailDuplicate", "Can't find parent proc of region %d.",
00366                sourceregion->GetRegionId());
00367 
00368   // Get dictionaries.
00369   edgedictionary = parentproc->GetEdgeDictionary();
00370   if (edgedictionary == NULL)
00371     {
00372       LegoNonFatal ("TailDuplicate",
00373                     "Edge dictionary is missing.");
00374       return NULL;
00375     } // end if
00376   attrdictionary = parentproc->GetAttrDictionary();
00377   if (attrdictionary == NULL)
00378     {
00379       LegoNonFatal ("TailDuplicate",
00380                     "Attribute dictionary is missing.");
00381       return NULL;
00382     } // end if
00383 
00384   // Set up tail pointers and max edge/attr id.
00385   for (edgetail = edgedictionary; edgetail->GetNextOpEdgePtr() != NULL;
00386        edgetail = edgetail->GetNextOpEdgePtr()) /* do nothing */;
00387 
00388   for (attrtail = attrdictionary; attrtail->GetNextAttrPtr() != NULL;
00389        attrtail = attrtail->GetNextAttrPtr()) /* do nothing */;
00390 
00391   eaid = FindMaxEdgeAttrId (parentproc);
00392 
00393   // Before we begin, remember the parents and children of sourceregion.
00394   // Form them even if they're not there.
00395   if (sourceregion->GetParents() != NULL)
00396     oparents = new regionList (*(sourceregion->GetParents()));
00397   else
00398     oparents = NULL;
00399   if (sourceregion->GetChildren() != NULL)
00400     ochildren = new regionList (*(sourceregion->GetChildren()));
00401   else
00402     ochildren = NULL;
00403 
00404   // -----------------------------------------------------------------------
00405   // Step 1.  Duplicate the region (including ops).
00406   // -----------------------------------------------------------------------
00407 
00408   // 1a. Copy construct the region.
00409   switch (sourceregion->GetRegionType())
00410     {
00411     case RT_BB:
00412       duplicate = new legoBB (*(legoBB *) sourceregion); break;
00413     case RT_SB:
00414       duplicate = new legoSB (*(legoSB *) sourceregion); break;
00415     case RT_HB:
00416       duplicate = new legoHB (*(legoHB *) sourceregion); break;
00417     default:
00418       LegoFatal ("TailDuplicate", "Refuse to t-d region %d type %d.",
00419                  sourceregion->GetRegionId(),
00420                  (int) sourceregion->GetRegionType());
00421     } // end switch
00422 
00423   region = ((legoRegion *) parentproc->GetParentPtr())->FindMaxRegionId();
00424   regionid = region->GetRegionId();
00425   duplicate->SetRegionId (++regionid);
00426 
00427   // 1b. Duplicate region attributes.
00428   for (atlscan = duplicate->GetRegionAttrListPtr(); atlscan != NULL;
00429        atlscan = atlscan->GetNextListPtr())
00430     {
00431       if (atlscan->GetAttrPtr() == NULL)
00432         continue;
00433       atscan = new attrs (*(atlscan->GetAttrPtr()), NULL, ++eaid);
00434       atlscan->SetAttrPtr (atscan);
00435       atscan->SetAttrId (eaid);
00436       atlscan->SetAttrId (eaid);
00437       attrtail->SetNextAttrPtr (atscan);
00438       attrtail = attrtail->GetNextAttrPtr();
00439     } // end for
00440 
00441   opid = (FindMaxOpId ((legoProc *) parentproc))->GetOpId();
00442 
00443   // 1c. Copy construct each op from sourceregion to duplicate.
00444   for (origop = sourceregion->GetEntryOpsPtr()->GetOpPtr();
00445        origop != NULL;
00446        origop = origop->GetNextLink())
00447     {
00448       // 1c,i. Copy construct the op itself.
00449       dupop = new legoOp (*origop);
00450       tail = tail->record (origop, dupop);
00451       dupop->SetOpId (++opid);  // assign new id
00452       dupop->SetParentBlockPtr (duplicate);
00453 
00454       // Find origop in duplicate (there because of copy constructor).
00455       for (i = 0; i < duplicate->GetCount(); i++)
00456         {
00457           origop2 = (legoOp *) duplicate->GetItem (i);
00458           if (origop2 == origop) break;
00459         } // end for
00460       if (i == duplicate->GetCount())
00461         LegoFatal ("TailDuplicate", "Can't find original "
00462                    "op %d in duplicate.", origop->GetOpId());
00463       duplicate->Detach (i);  // remove original, slide down rest.  Then, ...
00464       duplicate->AddItem (dupop);  // add duplicate to end of region
00465 
00466       // 1c,ii. Duplicate op attributes.
00467       for (atlscan = dupop->GetOpAttrListPtr(); atlscan != NULL;
00468            atlscan = atlscan->GetNextListPtr())
00469         {
00470           if (atlscan->GetAttrPtr() == NULL)
00471             continue;
00472           atscan = new attrs (*(atlscan->GetAttrPtr()), dupop, ++eaid);
00473           atlscan->SetAttrPtr (atscan);
00474           atscan->SetAttrId (eaid);
00475           atlscan->SetAttrId (eaid);
00476           attrtail->SetNextAttrPtr (atscan);
00477           attrtail = attrtail->GetNextAttrPtr();
00478         } // end for
00479 
00480     } // end for
00481 
00482   // 1d. Update duplicate's entry/exit ops.
00483   duplicate->RefreshOps();
00484 
00485   // -----------------------------------------------------------------------
00486   // Step 2.  Update intra-block links, create new intra-block edges.
00487   // -----------------------------------------------------------------------
00488 
00489   // For each duplicated op...
00490   for (i = 0; i < duplicate->GetCount(); i++)
00491     {
00492       dupop = (legoOp *) duplicate->GetItem(i);
00493       // 2a. Update links and edges.
00494       if (i != duplicate->GetCount() - 1)
00495         {
00496           // 2a,i. Set previous and next links.
00497           dupop2 = (legoOp *) duplicate->GetItem(i + 1);
00498           dupop->SetNextLink (dupop2);
00499           dupop2->SetPrevLink (dupop);
00500 
00501           // 2a,ii. Hunt down original edge between them.
00502           // Find original ops by following duplicateOpsPtr list.
00503           for (oplscan = dupop->GetDuplicateOpsPtr(); oplscan != NULL;
00504                oplscan = oplscan->GetNextListPtr())
00505             if ((legoRegion *) oplscan->GetOpPtr()->GetParentBlockPtr()
00506                 == sourceregion) break;
00507           if (oplscan == NULL)
00508             {
00509               LegoNonFatal ("TailDuplicate",
00510                             "Can't find original op for duplicate op %d.",
00511                             dupop->GetOpId());
00512               return NULL;
00513             } // end if
00514           origop = oplscan->GetOpPtr();
00515           for (oplscan = dupop2->GetDuplicateOpsPtr(); oplscan != NULL;
00516                oplscan = oplscan->GetNextListPtr())
00517             if ((legoRegion *) oplscan->GetOpPtr()->GetParentBlockPtr()
00518                 == sourceregion) break;
00519           if (oplscan == NULL)
00520             {
00521               LegoNonFatal ("TailDuplicate",
00522                             "Can't find original op for duplicate op %d.",
00523                             dupop2->GetOpId());
00524               return NULL;
00525             } // end if
00526           origop2 = oplscan->GetOpPtr();
00527 
00528           oescan = FindControlEdge (origop, origop2);
00529           if (oescan == NULL)
00530             {
00531               LegoNonFatal ("TailDuplicate",
00532                             "Can't find edge between original ops %d and %d.",
00533                             origop->GetOpId(), origop2->GetOpId());
00534               return NULL;
00535             } // end if
00536 
00537           // 2a,iii. Copy construct a new edge between dupop and dupop2.
00538           edgetail->SetNextOpEdgePtr
00539             (new opEdges (*oescan, ++eaid, dupop->GetOpId(),
00540                           dupop, dupop2->GetOpId(), dupop2));
00541           edgetail = edgetail->GetNextOpEdgePtr();
00542 
00543           // 2a,iv. Duplicate edge attributes.
00544           for (atlscan = edgetail->GetEdgeAttrListPtr(); atlscan != NULL;
00545                atlscan = atlscan->GetNextListPtr())
00546             {
00547               if (atlscan->GetAttrPtr() == NULL)
00548                 continue;
00549               atscan = new attrs (*(atlscan->GetAttrPtr()), NULL, ++eaid);
00550               atlscan->SetAttrPtr (atscan);
00551               atscan->SetAttrId (eaid);
00552               atlscan->SetAttrId (eaid);
00553               attrtail->SetNextAttrPtr (atscan);
00554               attrtail = attrtail->GetNextAttrPtr();
00555             } // end for
00556 
00557           // 2a,v. If dupop has an outlist, change the entry pointing
00558           //       to origop2 to point to dupop2.
00559           if (dupop->GetOutListPtr() != NULL)
00560             for (oplscan = dupop->GetOutListPtr(); oplscan != NULL;
00561                  oplscan = oplscan->GetNextListPtr())
00562               if (oplscan->GetOpId() == origop2->GetOpId())
00563                 {
00564                   oplscan->SetOpPtr (dupop2);
00565                   oplscan->SetOpId (dupop2->GetOpId());
00566                 } // end if (, for, if)
00567 
00568         } // end if
00569 
00570       // 2b. Update allListPtr as appropriate - ops are enqueued in reverse.
00571       if (i == 0)
00572         dupop->SetListOpPtr (parentproc->GetListOpPtr());
00573       if (i == duplicate->GetCount() - 1)
00574         parentproc->SetListOpPtr (dupop);
00575       else
00576         dupop2->SetListOpPtr (dupop);
00577         
00578     } // end for
00579 
00580   // -----------------------------------------------------------------------
00581   // Step 3.  Connect head and duplicate exclusively (handle jumptables later).
00582   // -----------------------------------------------------------------------
00583   
00584   // 3a. Count how many incoming edges there are to sourceregion (use i to
00585   //     count them).
00586   for (i = 0, edlscan = sourceregion->GetInEdgesPtr();
00587        edlscan != NULL;
00588        i++, edlscan = edlscan->GetNextListPtr()) /* do nothing */;
00589 
00590   // 3b. Redirect the head->sourceregion edge to head->duplicate.
00591   dupop = duplicate->GetEntryOpsPtr()->GetOpPtr();  // should be dup entry op
00592   RedirectEdge (dupedge, EDGE_TO, dupop);
00593 
00594   // 3bb. Fix jump tables if necessary
00595   for (atl = headop->GetOpAttrListPtr(); atl != NULL;
00596        atl = atl->GetNextListPtr())
00597     if (atl->GetAttrType() == ATTR_TBLNAME) break;
00598   if (atl != NULL)
00599     {
00600       jumpTable *jt;
00601       jumpList *jl;
00602 
00603       // For jump tables, there may be more than one edge from headop to 
00604       // sourceregion, we want to redirect all of these edges. 
00605       opEdges *extraedge = FindControlEdge (headop, sourceregion->GetEntryOpsPtr()->GetOpPtr(), 1);
00606       while (extraedge != NULL) {
00607         RedirectEdge (extraedge, EDGE_TO, dupop);
00608         extraedge = FindControlEdge (headop, sourceregion->GetEntryOpsPtr()->GetOpPtr(), 1);
00609       }
00610       
00611       // Now fix the jump table 
00612       for (jt = parentproc->GetJumpDictionary(); jt != NULL;
00613            jt = jt->GetNextTablePtr())
00614         if (strcmp (jt->GetTableName(), atl->GetTableName()) == 0) 
00615           break;
00616       if (jt != NULL) {
00617         for (jl = jt->GetJumpEntryPtr(); jl != NULL;
00618              jl = jl->GetNextListPtr()) {
00619           if (jl->GetOpId() == sourceregion->GetEntryOpsPtr()->GetOpPtr()->GetOpId()) {
00620 //          cerr << "Fixing jump table from opId " << sourceregion->GetEntryOpsPtr()->GetOpPtr()->GetOpId() << " to opId " << duplicate->GetEntryOpsPtr()->GetOpPtr()->GetOpId() << "\n";
00621             jl->SetOpPtr(duplicate->GetEntryOpsPtr()->GetOpPtr());
00622             jl->SetOpId(duplicate->GetEntryOpsPtr()->GetOpPtr()->GetOpId());
00623           }
00624         }
00625       }
00626     } // end if   
00627   
00628   // 3c. If sourceregion had exactly two inedges, then the one remaining edge
00629   //     into sourceregion is no longer a merging edge.
00630   if (i == 2)
00631     {
00632       atlscan = FindFreqAttribute
00633         (sourceregion->GetInEdgesPtr()->GetEdgePtr());
00634       if (atlscan != NULL)
00635         atlscan->GetAttrValPtr()->GetNextIntListPtr()->SetAttrValue
00636           (GetNewEdgeMergeValue (sourceregion->GetInEdgesPtr()->GetEdgePtr(),
00637                                  parentproc));
00638     } // end if
00639 
00640   // 3d. Remove all but head's exit op from duplicate's entry op list.
00641   edgeweight = (double) FindEdgeFrequency (dupedge);
00642   if (edgeweight < 0) edgeweight = 0.0;
00643 
00644   delete dupop->GetInListPtr();
00645   oplscan = new opList;
00646   oplscan->SetOpPtr (headop);
00647   oplscan->SetOpId (headop->GetOpId());
00648   oplscan->SetValid (1);
00649   oplscan->SetWeight (edgeweight);
00650   dupop->SetInListPtr (oplscan);
00651 
00652   // 3e. Almost forgot: find any PBRR in head referring to sourceregion, and
00653   // change it to refer to duplicate.
00654   for (origop = (legoOp *) head->GetItem(0);
00655        origop->GetNextLink() != NULL;
00656        origop = origop->GetNextLink())
00657     {
00658       if (origop->GetOpcode() == PBRR)
00659         {
00660           oprd = origop->GetSrcOprdPtr();  // will be a literal cntl. block id
00661           if (oprd->GetOprdType() == OT_LITERAL_CB &&
00662               oprd->GetLiteralControlBlock() == sourceregion->GetRegionId())
00663             oprd->SetLiteralControlBlock (duplicate->GetRegionId());
00664         } // end if
00665     } // end for
00666 
00667   // 3f. Finally, copy the edge weight to duplicate, and subtract that
00668   // weight from sourceregion. Also, patch it to no longer be a merging edge.
00669   atlscan = FindFreqAttribute (dupedge);
00670   if (atlscan != NULL)
00671     {
00672       edgeweight = (double) (atlscan->GetAttrValPtr()->GetAttrValue());
00673       duplicate->SetWeight (edgeweight);
00674       sourceregion->SetWeight (sourceregion->GetWeight() - edgeweight);
00675 
00676       atlscan->GetAttrValPtr()->GetNextIntListPtr()->SetAttrValue
00677         (GetNewEdgeMergeValue (dupedge, (legoProc *) parentproc));
00678     } // end if
00679 
00680   // -----------------------------------------------------------------------
00681   // Step 4.  Connect duplicate to sourceregion' children.
00682   // -----------------------------------------------------------------------
00683 
00684   allchildren = sourceregion->GetChildren();
00685   sourceweightratio = sourceregion->GetWeight() + duplicate->GetWeight();
00686   if (sourceweightratio != 0.0)
00687     sourceweightratio = sourceregion->GetWeight() / sourceweightratio;
00688   // fraction of weight in original
00689 
00690   // For each child of source region ...
00691   if(allchildren != NULL)
00692   for (lrrscan = allchildren; lrrscan != NULL;
00693        lrrscan = lrrscan->GetNextListPtr())
00694     {
00695       region = lrrscan->GetRegionPtr();
00696       if (region == NULL) continue;
00697 
00698       // 4a. Invalidate child's parents.
00699       region->SetParents (NULL);
00700 
00701       // 4b. Hunt down all edges between sourceregion and child and ...
00702       for (oescan = edgedictionary;
00703            oescan->GetNextOpEdgePtr() != NULL;
00704            oescan = oescan->GetNextOpEdgePtr())
00705         {
00706           origop = oescan->GetFromOpPtr();
00707           origop2 = oescan->GetToOpPtr();
00708           if ( ((legoRegion *)(origop->GetParentBlockPtr()) == sourceregion) &&
00709                ((legoRegion *)(origop2->GetParentBlockPtr()) ==
00710                 region) )  // from sourceregion to child
00711             {
00712               dupop = (legoOp *) map->lookup_duplicate (origop);
00713               if (dupop == NULL)
00714                 LegoFatal ("TailDuplicate", "Mapping error.");
00715 
00716               // 4b,i. Add a new control edge.
00717               edgetail->SetNextOpEdgePtr  // make from duplicate to child
00718                 (new opEdges (*oescan, ++eaid, dupop->GetOpId(),
00719                                   dupop, origop2->GetOpId(), origop2));
00720               edgetail = edgetail->GetNextOpEdgePtr();
00721               //              edgetail = AddEdge (dupop, origop2, ET_CNTL);
00722               //              eaid++;
00723 
00724               // 4b,ii. Duplicate edge attributes.
00725               
00726               //HZ:
00727               //edgetail->SetEdgeAttrListPtr (new attrList
00728               //                            (*(oescan->GetEdgeAttrListPtr())));
00729               if(oescan->GetEdgeAttrListPtr() != NULL)
00730                 edgetail->SetEdgeAttrListPtr (new attrList
00731                                             (*(oescan->GetEdgeAttrListPtr())));
00732               else
00733                 edgetail->SetEdgeAttrListPtr(NULL);  
00734               for (atlscan = edgetail->GetEdgeAttrListPtr(); atlscan != NULL;
00735                    atlscan = atlscan->GetNextListPtr())
00736                 {
00737                   if (atlscan->GetAttrPtr() == NULL)
00738                     continue;
00739                   atscan = new attrs (*(atlscan->GetAttrPtr()), NULL, ++eaid);
00740                   atlscan->SetAttrPtr (atscan);
00741                   atscan->SetAttrId (eaid);
00742                   atlscan->SetAttrId (eaid);
00743                   attrtail->SetNextAttrPtr (atscan);
00744                   attrtail = attrtail->GetNextAttrPtr();
00745                 } // end for
00746 
00747               // 4b,iii. Scale edge weights appropriately as well as the
00748               //         weights of their ops.
00749               // oescan is the original. edgetail is the duplicate.
00750               edgeweight = -1.0;
00751               atlscan = FindFreqAttribute (oescan);
00752               if (atlscan != NULL)
00753                 {
00754                   edgeweight = (double)
00755                     (atlscan->GetAttrValPtr()->GetAttrValue());  // original wt
00756 
00757                   // Scale oescan's weight down to its portion.
00758                   atlscan->GetAttrValPtr()->SetAttrValue
00759                     ((int) (edgeweight * sourceweightratio));
00760                   atlscan->GetAttrValPtr()->GetNextIntListPtr()
00761                     ->SetAttrValue (1);  // it's a merge now!
00762 
00763                   for (oplscan = origop->GetOutListPtr(); oplscan != NULL;
00764                        oplscan = oplscan->GetNextListPtr())
00765                     if (oplscan->GetOpId() == origop2->GetOpId())
00766                       {
00767                         oplscan->SetWeight (edgeweight * sourceweightratio);
00768                         break;
00769                       } // end if
00770 
00771                   // Scale edgetail's weight down to its portion.
00772                   atlscan = FindFreqAttribute (edgetail);
00773                   if (atlscan != NULL)
00774                     {
00775                       atlscan->GetAttrValPtr()->SetAttrValue
00776                         ((int) (edgeweight * (1.0 - sourceweightratio)));
00777                       atlscan->GetAttrValPtr()->GetNextIntListPtr()
00778                         ->SetAttrValue (1);  // it's a merge now!
00779                     } // end if
00780 
00781                   for (oplscan = dupop->GetOutListPtr(); oplscan != NULL;
00782                        oplscan = oplscan->GetNextListPtr())
00783                     if (oplscan->GetOpId() == origop2->GetOpId())
00784                       {
00785                         oplscan->SetWeight
00786                           (edgeweight * (1.0 - sourceweightratio));
00787                         break;
00788                       } // end if
00789                     
00790                 } // end if
00791 
00792               // 4b,iv. While we're here, fix duplicate's out edge.
00793               //              for (edlscan = duplicate->GetOutEdgesPtr();
00794               //                   edlscan != NULL;
00795               //                   edlscan = edlscan->GetNextListPtr())
00796               //                {
00797               //                  if (edlscan->GetEdgePtr() == oescan)
00798               //                    {
00799               //                      edlscan->SetEdgePtr (edgetail);
00800               //                      edlscan->SetEdgeId (edgetail->GetEdgeId());
00801               //                      break;
00802               //                    } // end if
00803               //                } // end for
00804 
00805               // 4b,iv. Oh, and while we're at it, add edge to child.
00806               region->RefreshEdges();
00807               //              for (edlscan = region->GetInEdgesPtr();
00808               //                   edlscan != NULL && edlscan->GetNextListPtr() != NULL;
00809               //                   edlscan = edlscan->GetNextListPtr()) /* nothing */;
00810               //              if (edlscan != NULL)
00811               //                {
00812               //                  edlscan->SetNextListPtr (new edgeList);
00813               //                  edlscan = edlscan->GetNextListPtr();
00814               //                  edlscan->SetEdgePtr (edgetail);
00815               //                  edlscan->SetEdgeId (edgetail->GetEdgeId());
00816               //                  edlscan->SetValid (1);
00817               //                } // end if
00818 
00819               // 4b,v. All right, update the child's entry op too ... geez.
00820               //HZ
00821              if(origop2->GetInListPtr() != NULL)
00822               for (oplscan = origop2->GetInListPtr();
00823                    oplscan != NULL && oplscan->GetNextListPtr() != NULL;
00824                    oplscan = oplscan->GetNextListPtr())  // stop before end
00825                 if (oplscan->GetOpId() == origop->GetOpId())
00826                   oplscan->SetWeight (edgeweight * sourceweightratio);
00827               if (oplscan->GetOpId() == origop->GetOpId())  // for last one
00828                 oplscan->SetWeight (edgeweight * sourceweightratio);
00829               if (oplscan != NULL)
00830                 {
00831                   oplscan->SetNextListPtr (new opList);
00832                   oplscan = oplscan->GetNextListPtr();
00833                   oplscan->SetOpPtr (dupop);
00834                   oplscan->SetOpId (dupop->GetOpId());
00835                   oplscan->SetValid (1);
00836                   oplscan->SetWeight (edgeweight * (1.0 - sourceweightratio));
00837                 } // end if
00838 
00839             } // end if (found an edge to duplicate)
00840 
00841         } // end for (oescan)
00842     } // end for (lrrscan)
00843 
00844   // 4c (kinda). Fix duplicate's out edges.
00845   duplicate->RefreshEdges();
00846 
00847   // Finally finally finally, kill parents and children lists:
00848   // Original (sourceregion's) parents...
00849   for (lrrscan = oparents; lrrscan != NULL;
00850        lrrscan = lrrscan->GetNextListPtr())
00851     {
00852       region = lrrscan->GetRegionPtr();
00853       //      delete region->children;
00854       //      region->children = NULL;
00855       region->SetChildren (NULL);
00856       region->RefreshEdges();
00857     } // end for
00858   // Original (sourceregion's) children...
00859   for (lrrscan = ochildren; lrrscan != NULL;
00860        lrrscan = lrrscan->GetNextListPtr())
00861     {
00862       region = lrrscan->GetRegionPtr();
00863       //      delete region->parents;
00864       //      region->parents = NULL;
00865       region->SetParents (NULL);
00866       region->RefreshEdges();
00867     } // end for
00868   // And sourceregion' parents and children (duplicate's not copy-constr.'d)
00869   delete oparents;
00870   delete ochildren;
00871   sourceregion->SetParents (NULL);//HZ: it is ok, as the function call
00872                                    // GetParents will compute the pointer list
00873                                    // if it is NULL.
00874   sourceregion->SetChildren (NULL);
00875     
00876   return duplicate;
00877 } // end TailDuplicate
00878 
00879 /*
00880  * mdj - Remove Unconditional Branches (DUMMY_BR or BRU).
00881  * Treegion formations results in un-necessary unconditional branches. 
00882  * These braches originally were necessary because of merges, tail 
00883  * duplication eliminates several merges. As a result, unconditional 
00884  * branches can be removed, resulting in larger BBs within a Treegion. 
00885  *
00886  * If it was possible to remove the unconditional branch, 1 is returned,
00887  * otherwise 0 is returned.
00888  *
00889  */
00890 int 
00891 RemoveUncondBranch(legoRegion *sourceblock) {
00892 
00893   regionList *allchildren, *lrrscan;
00894   legoOp *predecessorop, *pbrrop, *predecessorbeforeop, *moveop, *oldbranch;
00895   legoOp  *listop, *verylastop;
00896   legoRegion *predecessor, *dupparent, *region;
00897   regionList *temp;
00898   legoProc *parentproc;
00899   int i; 
00900   
00901 //  cerr << "RemoveUncondBranch sourceblock id " << sourceblock->GetRegionId() << " with Block Ptr " << sourceblock << "\n";
00902 
00903   // sourceblock can not be a merge in order to combine it with its 
00904   // predecessor block (must have only one predecessor block) 
00905   opList *entries = ((legoOp *)sourceblock->GetItem(0))->GetInListPtr();
00906   if (entries != NULL) {
00907     predecessorop = entries->GetOpPtr();
00908     predecessor = (legoRegion *) predecessorop->GetParentBlockPtr();
00909 //    cerr << "RemoveUncondBranch predecessor id " << predecessor->GetRegionId() << " with Block Ptr " << predecessor << "\n";
00910     int entryopid = entries->GetOpPtr()->GetOpId(); 
00911     for (entries = entries->GetNextListPtr();
00912          entries != NULL;
00913          entries = entries->GetNextListPtr()) {
00914       if (entries->GetOpPtr()->GetOpId() != entryopid) {
00915         return 0;
00916       }
00917     }
00918   }
00919   else {
00920     return 0;
00921   }
00922   
00923   // BRUs can branch to more than one location. 
00924   // In order to merge, must be unconditional to only one location. 
00925   
00926   if (predecessorop->GetOpcode() == BRU) {
00927     opList *exits = predecessorop->GetOutListPtr();
00928     if (exits != NULL) {
00929       int exitopid = exits->GetOpPtr()->GetOpId(); 
00930       for (exits = exits->GetNextListPtr();
00931            exits != NULL;
00932            exits = exits->GetNextListPtr()) {
00933         if (exits->GetOpPtr()->GetOpId() != exitopid) {
00934           return 0;
00935         }
00936       }
00937     }
00938     else {
00939       return 0;
00940     }
00941   }
00942   
00943   // Can only be merged with the predecessor block if the branch from 
00944   // predecessor block to source block is unconditional.
00945   if ((predecessorop->GetOpcode() == DUMMY_BR) ||
00946       (predecessorop->GetOpcode() == DUMMY_BRANCH) ||
00947       (predecessorop->GetOpcode() == BRU)) {
00948 //    cerr << "source BB " << sourceblock->GetRegionId() << " will be merged with predecessor BB " << predecessor->GetRegionId() << "\n";    
00949 
00950     allchildren = sourceblock->GetChildren();
00951     for (lrrscan = allchildren; lrrscan != NULL;
00952          lrrscan = lrrscan->GetNextListPtr())
00953       {
00954         region = lrrscan->GetRegionPtr();
00955         if (region == NULL) continue;
00956         
00957         // 4a. Invalidate child's parents.
00958         region->SetParents (NULL);
00959       }
00960     predecessor->SetChildren(NULL);
00961     
00962     // Find parent proc.
00963     parentproc = (legoProc *) FindParentRegionType (RT_PROC, sourceblock);
00964     if (parentproc == NULL)
00965       LegoFatal ("RemoveUncondBranch", "Can't find parent proc of region %d.",
00966                  sourceblock->GetRegionId());
00967     if (predecessorop->GetOpcode() == BRU) {
00968       // predecessor's PBRR will be replaced by sourceblocks PBRR. Get rid of 
00969       // it now. We will deal with the actual branch a little later
00970       for (pbrrop = predecessorop->GetPrevLink(); pbrrop != NULL; 
00971            pbrrop = pbrrop->GetPrevLink())
00972         if (pbrrop->GetOpcode() == PBRR) break;
00973       if (pbrrop != NULL) 
00974         RemoveMidOp(pbrrop, YES); // destroy this one
00975     }
00976     // now move all "internal" ops (other than C_MERGE and BRANCH) 
00977     // from sourceblock to predecessor. 
00978     // I am assuming that the C_MERGE is item = 0 
00979     predecessorbeforeop = predecessorop->GetPrevLink();
00980     int count = sourceblock->GetCount() - 1;
00981     for (i = 1; i < count; i++) {
00982       // move count items, the moved items are always in position following
00983       // the C_MERGE op, as the previously moved item is removed using 
00984       // RemoveMidOp()
00985       moveop = ((legoOp *) sourceblock->GetItem(0))->GetNextLink(); 
00986       // If I'm moving this to a HB, may need to add "orig_wt" attr
00987       if ((predecessor->GetRegionType() == RT_HB) && 
00988           (FindLcAttribute( "use_orig_wt",  predecessor) != NULL )) {
00989         AddWeightAttribute (moveop);
00990         // Copy predecessor op's PredVector
00991         if (predecessorop->GetPredVectorPtr() != NULL) {
00992           moveop->SetPredVectorPtr(new bitvector(*predecessorop->GetPredVectorPtr()));
00993 //        moveop->GetPredVectorPtr()->Show();
00994         }
00995 //      cerr << "OpId = " << moveop->GetOpId() << " (a RemoveUncond op)\n";
00996       }
00997       RemoveMidOp(moveop, NO); // don't destroy this one
00998       AddMidOp(moveop, predecessorbeforeop);
00999       predecessorbeforeop = moveop;
01000 //      cerr << "op " << moveop->GetOpId() << " moved from sourceblock to predecessor block\n";
01001     }
01002     // Now handle the branches (LastOps)
01003     moveop = ((legoOp *) sourceblock->GetItem(0))->GetNextLink(); 
01004     // If I'm moving this to a HB, may need to add "orig_wt" attr
01005     if ((predecessor->GetRegionType() == RT_HB) && 
01006         (FindLcAttribute( "use_orig_wt",  predecessor) != NULL )) {
01007       AddWeightAttribute (moveop);
01008       // Copy predecessor op's PredVector
01009       if (predecessorop->GetPredVectorPtr() != NULL) {
01010         moveop->SetPredVectorPtr(new bitvector(*predecessorop->GetPredVectorPtr()));
01011 //      moveop->GetPredVectorPtr()->Show();
01012       }
01013 //      cerr << "OpId = " << moveop->GetOpId() << " (a RemoveUncond op)\n";
01014     }
01015     // remove the edge from the c_merge to this branch op
01016     RemoveEdge ((legoOp *) sourceblock->GetItem(0), moveop, parentproc, ET_CNTL);
01017     // remove this op from allList
01018     if ((listop = parentproc->GetListOpPtr()) != moveop) {
01019       for (;
01020            listop != NULL && listop->GetListOpPtr() != moveop;
01021            listop = listop->GetListOpPtr())
01022         /* do nothing */;
01023     }
01024     if (listop != NULL)
01025       {
01026         if (parentproc->GetListOpPtr() != moveop)
01027           listop->SetListOpPtr (moveop->GetListOpPtr());
01028         else
01029           parentproc->SetListOpPtr (moveop->GetListOpPtr());
01030       } // end if
01031     moveop->SetListOpPtr (NULL);
01032     
01033     // Detach from region.
01034     sourceblock->Detach(sourceblock->Search(moveop));
01035 //    RemoveLastOp(moveop, NO); // don't destroy this one
01036     AddMidOp(moveop, predecessorbeforeop);
01037     oldbranch = moveop->GetNextLink();
01038     // remove the edge just created by AddMidOp between newbranch and oldbranch
01039     RemoveEdge (moveop, oldbranch, parentproc, ET_CNTL);
01040     // remove the edge from the uncond. branch to the c_merge
01041     RemoveEdge (oldbranch, (legoOp *) sourceblock->GetItem(0), parentproc, ET_CNTL);
01042     // destroy the uncond. branch in predecessor 
01043     // we'll do this one the old fashion way 
01044     // Fix the Links
01045     oldbranch->GetPrevLink()->SetNextLink (NULL);
01046     oldbranch->SetPrevLink (NULL);
01047     oldbranch->SetNextLink (NULL);
01048     // remove from allList 
01049     if ((listop = parentproc->GetListOpPtr()) != oldbranch) {
01050       for (;
01051            listop != NULL && listop->GetListOpPtr() != oldbranch;
01052            listop = listop->GetListOpPtr())
01053         /* do nothing */;
01054     }
01055     if (listop != NULL)
01056       {
01057         if (parentproc->GetListOpPtr() != oldbranch)
01058           listop->SetListOpPtr (oldbranch->GetListOpPtr());
01059         else
01060           parentproc->SetListOpPtr (oldbranch->GetListOpPtr());
01061       } // end if
01062     oldbranch->SetListOpPtr (NULL);
01063     
01064     // Detach from region.
01065     predecessor->Detach(predecessor->Search(oldbranch));
01066 
01067     attrList *atl;
01068     attrs *a;
01069     enum attrTypes atype;
01070     
01071     RemoveLiveAttribute (oldbranch, parentproc);  // kill live attribute right off
01072     
01073     atl = oldbranch->GetOpAttrListPtr();
01074     while (atl != NULL)
01075       {
01076         atype = atl->GetAttrType();
01077         if (atype != ATTR_LC)
01078           {
01079             atl = atl->GetNextListPtr(); continue;  // skip to first lc
01080           } // end if
01081         
01082         // Remove the first attribute here.
01083         a = atl->GetAttrPtr();
01084         RemoveLcAttribute (a->GetAttrString(), oldbranch, parentproc);
01085         
01086         atl = oldbranch->GetOpAttrListPtr();  // reset for next scan
01087       } // end while
01088     delete oldbranch;
01089     
01090 //    RemoveLastOp(oldbranch, YES); // destroy this one
01091 
01092     // destroy C_MERGE in sourceblock (last op remaining)
01093     // we'll do this one the old fashion way 
01094     // remove from allList 
01095     verylastop = (legoOp *) sourceblock->GetItem(0);
01096     if ((listop = parentproc->GetListOpPtr()) != verylastop) {
01097       for (;
01098            listop != NULL && listop->GetListOpPtr() != verylastop;
01099            listop = listop->GetListOpPtr())
01100         /* do nothing */;
01101     }
01102     if (listop != NULL)
01103       {
01104         if (parentproc->GetListOpPtr() != verylastop)
01105           listop->SetListOpPtr (verylastop->GetListOpPtr());
01106         else
01107           parentproc->SetListOpPtr (verylastop->GetListOpPtr());
01108       } // end if
01109     verylastop->SetListOpPtr (NULL);
01110     
01111     // Detach from region.
01112     sourceblock->Detach(0);
01113 
01114     RemoveLiveAttribute (verylastop, parentproc);  // kill live attribute right off
01115     
01116     atl = verylastop->GetOpAttrListPtr();
01117     while (atl != NULL)
01118       {
01119         atype = atl->GetAttrType();
01120         if (atype != ATTR_LC)
01121           {
01122             atl = atl->GetNextListPtr(); continue;  // skip to first lc
01123           } // end if
01124         
01125         // Remove the first attribute here.
01126         a = atl->GetAttrPtr();
01127         RemoveLcAttribute (a->GetAttrString(), verylastop, parentproc);
01128         
01129         atl = verylastop->GetOpAttrListPtr();  // reset for next scan
01130       } // end while
01131     delete verylastop;
01132     
01133     // now destroy sourceblock
01134     dupparent = sourceblock->GetParentPtr();
01135     if (dupparent == NULL)
01136     {
01137       LegoFatal ("TailDuplicate", "Can't find parent of sourceblock to be removed %d.", sourceblock->GetRegionId());
01138     } 
01139     // Get rid of attributes before destroying sourceblock
01140     RemoveLiveAttribute (sourceblock, parentproc); 
01141     atl = sourceblock->GetRegionAttrListPtr();
01142     while (atl != NULL)
01143       {
01144         atype = atl->GetAttrType();
01145         if (atype != ATTR_LC)
01146           {
01147             atl = atl->GetNextListPtr(); continue;  // skip to first lc
01148           } // end if
01149         
01150         // Remove the first attribute here.
01151         a = atl->GetAttrPtr();
01152         RemoveLcAttribute (a->GetAttrString(), sourceblock, parentproc);
01153         
01154         atl = sourceblock->GetRegionAttrListPtr();  // reset for next scan
01155       } // end while
01156     i = dupparent->Search (sourceblock);
01157     if (i == MAX_UNSIGNED)
01158       {
01159         LegoFatal ("TailDuplicate", "Can't find sourceblock block %d in its "
01160                       "parent region %d.", sourceblock->GetRegionId(),
01161                       dupparent->GetRegionId());
01162       } // end if
01163     // Destroying blocks seems to fuck 
01164     // up things such as ParentBlockPtrs of Ops. So I will 
01165     // just leave them as orphaned blocks now and mark them. 
01166     // Will skip them in later in treeform()
01167 //    sourceblock->Mark (RM_GENERAL);
01168     dupparent->DestroyItem (i);
01169 //    cerr << "sourceblock " << sourceblock->GetRegionId() << " removed from parent region " << dupparent->GetRegionId() << " of region type " << dupparent->GetRegionType() << "\n";
01170 //    if (!(dupparent->IsOwner())) 
01171 //      delete sourceblock;
01172 
01173     switch (predecessor->GetRegionType())
01174       {
01175       case RT_BB:
01176         ((legoBB *) predecessor)->RefreshOps(); 
01177         ((legoBB *) predecessor)->RefreshEdges(); 
01178         break;
01179       case RT_SB:
01180         ((legoSB *) predecessor)->RefreshOps(); 
01181         ((legoSB *) predecessor)->RefreshEdges(); 
01182         break;
01183       case RT_HB:
01184         ((legoHB *) predecessor)->RefreshOps(); 
01185         ((legoHB *) predecessor)->RefreshEdges(); 
01186         break;
01187       default:
01188         LegoFatal ("RemoveUncondBranch", "Can not determine RegionType");
01189       } // end switch
01190 
01191 //    predecessor->RefreshOps();
01192 //    predecessor->RefreshEdges();
01193 
01194     region = (legoRegion *) predecessor->GetParentPtr(); 
01195     if (region->GetRegionType() == RT_TREE) {
01196       ((legoTreegion *)region)->RefreshOps();
01197       ((legoTreegion *)region)->RefreshEdges();
01198     }
01199     if (region->GetRegionType() == RT_PROC) 
01200       ((legoProc *)region)->RefreshOps();
01201     
01202     return 1;
01203   }
01204   else {
01205     return 0;
01206   }
01207 }
01208 
01209 /*
01210  *
01211  * This is a recursive function for breaking a superblock region into its 
01212  * component BB regions. If the input region has more than one sub-block, 
01213  * the top sub-block is split off and added to the encompassing proc. A 
01214  * pointer to the remaining sub-block(s) is returned or NULL is returned 
01215  * if the input region has only one sub-block (i.e. only a BB remains).
01216  * NULL is also returned if the region has more than one entry op 
01217  * (i.e. not a superblock/hyperblock or any known region for that matter)
01218  *
01219  */
01220 void
01221 UnBindSB ( legoHB *HB_region ) {
01222   
01223   opList *entry_op_list; 
01224   legoOp *curr_op, *last_op_HB_region, *first_op_new_region, *last_op_new_region;
01225   legoOp *detach_op, *prev_detach_op; 
01226   legoHB *new_region;
01227   legoProc *parentproc;
01228   int max_region_id, eaid;
01229   attrs *attrdictionary, *attrtail, *atscan;
01230   attrList *atlscan;
01231   double BBweight = 0; 
01232   edgeList *entry_edges_list;
01233   opEdges  *entry_edge;
01234   
01235   // Step through the ops in the HB_region to determine if there is more than 
01236   // one real branch in the region. If so, the region must be split.
01237   
01238   entry_op_list = HB_region->GetEntryOpsPtr();
01239   // return if region has more than one entry op (can't think of any 
01240   // region types where this would be the case).
01241   if (entry_op_list->GetNextListPtr() != NULL) {
01242     cerr << "Region " << HB_region->GetRegionId() 
01243       << " has more than one entry op \n";
01244     return;
01245   }
01246   else {
01247     curr_op = entry_op_list->GetOpPtr();
01248   }
01249   
01250   // step through the ops in the region in program order until a branch or 
01251   // DUMMY_BR is found (excluding BRLs)
01252   while ( (IsBranchOpButNotBRL(curr_op) != TRUE) && (curr_op != NULL) ) {
01253     curr_op = curr_op->GetNextLink();
01254   }
01255   if (curr_op == NULL) {
01256     cerr << "Region " << HB_region->GetRegionId() 
01257       << " does not have a branch op \n";
01258     return;
01259   }
01260 
01261   // The top portion of the input HB is split off as a BB
01262   HB_region->SetRegionType(RT_BB);
01263   
01264   // if this is the last op in HB_region, it is already a BB.
01265   if (curr_op->GetNextLink() == NULL) {
01266     return; 
01267   }
01268 
01269   // otherwise, split region at this boundary 
01270 
01271   // 1. copy construct a new region
01272   parentproc = (legoProc *) FindParentRegionType (RT_PROC, HB_region);
01273   max_region_id = parentproc->GetParentPtr()->FindMaxRegionId()->GetRegionId();  
01274   new_region = (legoHB *) new legoHB (*HB_region);
01275   new_region->SetRegionId(max_region_id + 1);
01276   // set region_type to RT_HB for recursive calls 
01277   new_region->SetRegionType(RT_HB);
01278   
01279   // 2. Duplicate region attributes.
01280   eaid = FindMaxEdgeAttrId (parentproc);
01281   attrdictionary = parentproc->GetAttrDictionary();
01282   if (attrdictionary == NULL)
01283     {
01284       LegoNonFatal ("UnBindSB",
01285                     "Attribute dictionary is missing.");
01286       return;
01287     } // end if
01288   for (attrtail = attrdictionary; attrtail->GetNextAttrPtr() != NULL;
01289        attrtail = attrtail->GetNextAttrPtr()) /* do nothing */;
01290   for (atlscan = new_region->GetRegionAttrListPtr(); atlscan != NULL;
01291        atlscan = atlscan->GetNextListPtr())
01292     {
01293       if (atlscan->GetAttrPtr() == NULL)
01294         continue;
01295       atscan = new attrs (*(atlscan->GetAttrPtr()), NULL, ++eaid);
01296       atlscan->SetAttrPtr (atscan);
01297       atscan->SetAttrId (eaid);
01298       atlscan->SetAttrId (eaid);
01299       attrtail->SetNextAttrPtr (atscan);
01300       attrtail = attrtail->GetNextAttrPtr();
01301     } // end for
01302 
01303 
01304   // 3. Split linked list of ops at the curr_op branch/C_MERGE boundary and 
01305   //    update allListPtr
01306 
01307   for (last_op_HB_region = curr_op, last_op_new_region = curr_op; 
01308        last_op_new_region->GetNextLink() != NULL; 
01309        last_op_new_region = last_op_new_region->GetNextLink() ) /* do nothing */ ;
01310 
01311   first_op_new_region = curr_op->GetNextLink();
01312   first_op_new_region->SetPrevLink(NULL);
01313   curr_op->SetNextLink(NULL);
01314 
01315   HB_region->SetListOpPtr(last_op_HB_region);
01316   new_region->SetListOpPtr(last_op_new_region);
01317      
01318   // detach ops that we have already scanned from new_region
01319   detach_op = entry_op_list->GetOpPtr();
01320   while ( detach_op != curr_op ) {
01321     prev_detach_op = detach_op;
01322     detach_op = detach_op->GetNextLink();
01323     new_region->Detach(new_region->Search(prev_detach_op));
01324   }
01325   // include the detach of curr_op, which remains the last op in HB_region
01326   new_region->Detach(new_region->Search(detach_op));
01327 
01328   // detach remaining ops from original HB_region 
01329   // and update their parentBlockPtr to new_region
01330   detach_op = first_op_new_region;
01331   while ( detach_op != NULL ) {
01332     prev_detach_op = detach_op;
01333     detach_op = detach_op->GetNextLink();
01334     prev_detach_op->SetParentBlockPtr(new_region);
01335     HB_region->Detach(HB_region->Search(prev_detach_op));
01336   }
01337 
01338   // 4. pray that RefreshOpsAndEdges will clean up the mess for each block
01339   HB_region->RefreshOps();
01340   HB_region->RefreshEdges();
01341   new_region->RefreshOps();
01342   new_region->RefreshEdges();
01343 
01344   // 5. update region weights for new_region, SB_region should still be ok
01345   entry_edges_list = new_region->GetInEdgesPtr();
01346   if (entry_edges_list != NULL) {
01347     entry_edge = entry_edges_list->GetEdgePtr(); 
01348     while (entry_edge != NULL) {
01349       BBweight += (double) FindEdgeFrequency (entry_edge);
01350       entry_edges_list = entry_edges_list->GetNextListPtr();
01351       if (entry_edges_list == NULL)
01352         entry_edge = NULL;
01353       else 
01354         entry_edge = entry_edges_list->GetEdgePtr();
01355     }
01356   }
01357   new_region->SetWeight(BBweight); 
01358   
01359   // recursively call UnBindSB on remainder of region
01360   UnBindSB(new_region);
01361   
01362   return; 
01363   
01364 }
01365 
01366 /*
01367  *
01368  * calls UnBindSB( legoRegion * ) for each region of the Proc
01369  *
01370  */
01371 void
01372 UnBindSB ( legoProc *proc ) {
01373 
01374   legoRegion *region;
01375   enum regionTypes region_type; 
01376   
01377   for (unsigned i = 0; i < proc->GetCount(); i++) {
01378     region = (legoRegion *) proc->GetItem (i);
01379     region_type = region->GetRegionType();
01380     // Rebel uses RT_HB for superblock regions
01381     // we eventually need to distinquish between real hyperblocks (e.g. due to 
01382     // hammock conversion) and superblock hyperblocks so that UnBindSB does 
01383     // not assign RT_BB to true hyperblocks that should be RT_HB
01384     if ( region_type == RT_HB )
01385       UnBindSB((legoHB *) region); 
01386   }
01387 }
01388 
01389 
01390 // FullyResolvePredicates: Create complementary second predicate destinations 
01391 // for CMPP ops for future use. New second predicate destinations are not 
01392 // used in our source Rebel until transformations such at hammock conversion, 
01393 // if conversion, predication, etc. Opcodes will be changed from _UN_UN to 
01394 // _UN_UC couterparts. 
01395 void FullyResolvePredicates( legoRegion *Region, legoOp *PredecessorCMPP )
01396 {
01397   regionList *Descendant;
01398   legoRegion *ParentRegion, *CurrentRegion; 
01399   legoOp *CurrentOp, *BranchOp, *PBROp, *ThisPredecessorCMPP;
01400   int OpCount, i, MaxRegNum;
01401   legoOprd *p1, *p2, *new_predicate; 
01402   
01403   MaxRegNum = FindMaxRegNum ((legoProc *) FindParentRegionType (RT_PROC, Region));
01404 
01405   ParentRegion = Region->GetParentPtr();
01406   
01407   ThisPredecessorCMPP = PredecessorCMPP;
01408   PredecessorCMPP = NULL; 
01409   
01410   OpCount = Region->GetCount();
01411   for (i = 0; i < OpCount; i++) {
01412     
01413     CurrentOp = (legoOp *) Region->GetItem(i); 
01414     
01415     // 
01416     if (CurrentOp->GetOpcode() >= CMPP_W_FALSE_UN_UN &&
01417         CurrentOp->GetOpcode() <= FCMPP_D_TRUE_AC_AC) {
01418       derr( "CMPP op found (OpId = " << CurrentOp->GetOpId() << ")\n" ); 
01419       
01420       // make sure that the second D-action is a complement (odd-number opcode)
01421       div_t remainder = div(CurrentOp->GetOpcode(), 2);
01422       if (remainder.rem == 0) {
01423         CurrentOp->SetOpcode((CurrentOp->GetOpcode() + 1));
01424       }
01425       else {
01426         // Assume Already Fully Resolved
01427         cerr << "\nAssuming already Fully Resolved\n";
01428         return; 
01429      }
01430       
01431       p1 = CurrentOp->GetDestOprdPtr();  // first destination!
01432       if (p1 == NULL || p1->GetNextOprdPtr() == NULL)
01433         {
01434           LegoFatal ("FullyResolvePredicates", "CMPP %d has bad destinations.", CurrentOp->GetOpId());
01435         } // end if
01436       p2 = p1->GetNextOprdPtr();  // p2 is there always!
01437       if (p1->GetNextOprdPtr()->GetOprdType() != OT_UNDEFINED) {
01438         ; // Good. We already have a second predicate
01439       }
01440       else {   // Make a second destination. 
01441         // Make the new operand and plop it into the CMPP.
01442         p2->SetOprdType (p1->GetOprdType());
01443         p2->SetOprdRegNum (++MaxRegNum);
01444         p2->SetOprdRegType (p1->GetOprdRegType());
01445         p2->SetOprdDataType (p1->GetOprdDataType());
01446         p2->SetOprdFileType (p1->GetOprdFileType());
01447         p2->SetOprdOmega (p1->GetOprdOmega());
01448         p2->SetOprdRegStyle (p1->GetOprdRegStyle());
01449         p2->SetIntValue (p1->GetOprdIntValue());
01450       } // end else
01451 
01452       // Tail Duplication results in duplicate predicate register numbers. 
01453       // Safer is each CMPP dest has a unique number 
01454       p1->SetOprdRegNum (++MaxRegNum);
01455       // Also update the branch this CMPP reaches
01456       for (BranchOp = CurrentOp->GetNextLink(); 
01457            ((BranchOp->GetOpcode() != BRCT) && 
01458             (BranchOp->GetOpcode() != BRCF));
01459            BranchOp = BranchOp->GetNextLink()) 
01460         ;// Do nothing
01461       BranchOp->GetSrcOprdPtr()->GetNextOprdPtr()->SetOprdRegNum(MaxRegNum);
01462       
01463       if (ThisPredecessorCMPP != NULL) {
01464         
01465         // Find the BRCT or BRCF for this CMPP
01466         for (BranchOp = ThisPredecessorCMPP->GetNextLink(); 
01467              ((BranchOp->GetOpcode() != BRCT) && 
01468               (BranchOp->GetOpcode() != BRCT));
01469              BranchOp = BranchOp->GetNextLink()) 
01470           ;// Do nothing
01471 
01472         // Find the PBR for this conditional branch
01473         for (PBROp = BranchOp->GetPrevLink(); 
01474              ((PBROp->GetOpcode() != PBRR) && 
01475               (PBROp->GetOpcode() != PBRA));
01476              PBROp = PBROp->GetPrevLink()) 
01477           ;// Do nothing
01478 
01479         // Predicate this CMPP op on the appropriate predecessor CMPP dest
01480         if (BranchOp->GetOpcode() == BRCT) {
01481           if (PBROp->GetSrcOprdPtr()->GetLiteralControlBlock() == 
01482               ((legoRegion *) CurrentOp->GetParentBlockPtr())->GetRegionId()) {
01483             new_predicate = new legoOprd(*ThisPredecessorCMPP->GetDestOprdPtr());
01484           }
01485           else {
01486             new_predicate = new legoOprd(*ThisPredecessorCMPP->GetDestOprdPtr()
01487                                          ->GetNextOprdPtr());
01488           }
01489         }
01490         else {
01491           if (PBROp->GetSrcOprdPtr()->GetLiteralControlBlock() == 
01492               ((legoRegion *) CurrentOp->GetParentBlockPtr())->GetRegionId()) {
01493             new_predicate = new legoOprd(*ThisPredecessorCMPP->GetDestOprdPtr()
01494                                          ->GetNextOprdPtr());
01495           }
01496           else {
01497             new_predicate = new legoOprd(*ThisPredecessorCMPP->GetDestOprdPtr());
01498           }
01499         }
01500         new_predicate->SetNextOprdPtr(NULL);
01501         new_predicate->SetParentOpPtr(CurrentOp);
01502         CurrentOp->SetPredOprdPtr(new_predicate);
01503       }
01504       PredecessorCMPP = CurrentOp; 
01505       break; 
01506     }
01507   }
01508 
01509   // Mark this block
01510   Region->Mark( RM_GENERAL );
01511   
01512   derr( "   Examining children of region " << Region->GetRegionId()
01513        << "\n" );
01514   // Cycle through all of the children for the current node being processed
01515   for (Descendant = Region->GetChildren(); 
01516        Descendant != NULL;
01517        Descendant = Descendant->GetNextListPtr() ) {
01518     
01519     derr( "   Child of region " << Region->GetRegionId()
01520          << " is region " << Descendant->GetRegionPtr()->GetRegionId()
01521          << "\n" );
01522     // Check if the current descendant is in the same tree.
01523     if ( ParentRegion != Descendant->GetRegionPtr()->GetParentPtr()
01524         || Region == Descendant->GetRegionPtr()
01525         || Descendant->GetRegionPtr()->IsMarked( RM_GENERAL ) == 1 )
01526       continue;
01527     
01528     CurrentRegion = Descendant->GetRegionPtr();
01529     derr( " FullyResolvePredicates for region " << CurrentRegion->GetRegionId()
01530          << "\n" );
01531     FullyResolvePredicates( CurrentRegion, PredecessorCMPP );
01532   }
01533   
01534   derr( "<< FullyResolvePredicates: block " << Region->GetRegionId()
01535        << " -- DONE\n" );
01536 }
01537 
01538 //HZ: code transformation for multiple (two actually) copies of code
01539 //
01540 //Function name: MulCpBB(legoBB *BB_orig) 
01541 //
01542 //step 1. create a new BB named BB_header. Copy the inedgesPtr and parents
01543 // information of BB_orig to BB_header. Fill in the BB with the ops of CMERGE,
01544 // HW probing instruction e.g., LDPRED, CMP instruction setting the branch
01545 // condition, and the branch instruction. Set the entryops and exitops Ptr, copy
01546 // the inListPtr of the CMERGE of BB_orig to the CMERGE of BB_header. 
01547 //
01548 //step 2. duplicate BB_orig (the duplicate name BB_dup). 
01549 //
01550 //step 3. Create edges between
01551 // BB_header and BB_orig, between BB_header and BB_dup. Set parent chidlren
01552 // relationship among them.
01553 //
01554 void MulCpBB(legoBB *BB_orig)
01555 {
01556     legoProc * parentproc = (legoProc *) FindParentRegionType (RT_PROC, BB_orig);
01557     int max_op_id = FindMaxOpId(parentproc)->GetOpId();
01558             
01559     //step 0. Make up a new op (brct br)
01560 
01561     legoOp * cond_br;
01562     cond_br = new legoOp (++max_op_id);
01563     cond_br->SetOpcode (BRCT);
01564     
01565     int max_reg_num = FindMaxRegNum(parentproc);
01566 
01567     legoOprd *oprd;
01568     oprd = new legoOprd;
01569     oprd->SetOprdType (OT_REG);
01570     oprd->SetOprdFileType(FT_BTR);
01571     oprd->SetOprdRegType (RT_R);
01572     oprd->SetOprdDataType (DT_B);
01573     int btr_num = ++max_reg_num;
01574     oprd->SetOprdRegNum(btr_num);
01575     oprd->SetParentOpPtr (cond_br);
01576     cond_br->SetSrcOprdPtr (oprd);
01577     
01578     legoOprd *oprd2;
01579     oprd2 = new legoOprd;
01580     oprd2->SetOprdType (OT_REG);
01581     oprd2->SetOprdFileType(FT_PR);
01582     oprd2->SetOprdRegType (RT_R);
01583     oprd2->SetOprdDataType (DT_P);
01584     int pr_num = ++max_reg_num;
01585     oprd2->SetOprdRegNum(pr_num);
01586     oprd2->SetParentOpPtr (cond_br);
01587     oprd->SetNextOprdPtr (oprd2);    
01588         
01589     oprd = new legoOprd;
01590     oprd->SetOprdType (OT_LITERAL_P);
01591     oprd->SetParentOpPtr (cond_br);
01592     oprd->SetLiteralPredicate(1);
01593     cond_br->SetPredOprdPtr (oprd);    
01594     
01595     AddMidOp(cond_br, (legoOp *)BB_orig->GetItem(0));
01596     
01597     //add LDPRED op in the header_bb
01598     legoOp * new_ld;
01599     new_ld = new legoOp (++max_op_id);
01600     new_ld->SetOpcode (LDPRED);
01601     
01602     oprd = new legoOprd;
01603     oprd->SetOprdType (OT_REG);
01604     oprd->SetOprdFileType(FT_GPR);
01605     oprd->SetOprdRegType (RT_R);
01606     oprd->SetOprdDataType (DT_I);
01607     int ld_gpr_num = ++max_reg_num;
01608     oprd->SetOprdRegNum(ld_gpr_num);
01609     oprd->SetParentOpPtr (new_ld);
01610     new_ld->SetDestOprdPtr (oprd);
01611     
01612     oprd = new legoOprd;
01613     oprd->SetOprdType (OT_LITERAL_I);
01614     oprd->SetParentOpPtr (new_ld);
01615     oprd->SetLiteralInteger(0);
01616     new_ld->SetSrcOprdPtr (oprd);
01617     
01618     oprd = new legoOprd;
01619     oprd->SetOprdType (OT_LITERAL_P);
01620     oprd->SetParentOpPtr (new_ld);
01621     oprd->SetLiteralPredicate(1);
01622     new_ld->SetPredOprdPtr (oprd);    
01623     
01624     AddMidOp(new_ld, (legoOp *)BB_orig->GetItem(0));
01625     
01626     //add PBRR op in the header_bb
01627     legoOp * pbrr_op;
01628     pbrr_op = new legoOp (++max_op_id);
01629     pbrr_op->SetOpcode (PBRR);
01630     
01631     oprd = new legoOprd;
01632     
01633     oprd->SetOprdType (OT_REG);
01634     oprd->SetOprdFileType(FT_BTR);
01635     oprd->SetOprdRegType (RT_R);
01636     oprd->SetOprdDataType (DT_B);
01637     oprd->SetOprdRegNum(btr_num);
01638     oprd->SetParentOpPtr (pbrr_op);
01639     pbrr_op->SetDestOprdPtr (oprd);
01640     
01641     legoOprd * pbrrsrc_oprd = new legoOprd;
01642     pbrrsrc_oprd->SetOprdType (OT_LITERAL_CB);
01643     pbrrsrc_oprd->SetParentOpPtr (pbrr_op);
01644     pbrr_op->SetSrcOprdPtr(pbrrsrc_oprd);
01645     
01646     oprd = new legoOprd;
01647     oprd->SetOprdType (OT_LITERAL_I);
01648     oprd->SetParentOpPtr (pbrr_op);
01649     oprd->SetLiteralInteger(0);
01650     pbrrsrc_oprd->SetNextOprdPtr (oprd);
01651     
01652     oprd = new legoOprd;
01653     oprd->SetOprdType (OT_LITERAL_P);
01654     oprd->SetParentOpPtr (pbrr_op);
01655     oprd->SetLiteralPredicate(1);
01656     pbrr_op->SetPredOprdPtr (oprd);    
01657     
01658     AddMidOp(pbrr_op, new_ld);
01659     
01660     //add CMPP op in the header_bb
01661     legoOp * cmpp_op;
01662     cmpp_op = new legoOp (++max_op_id);
01663     cmpp_op->SetOpcode (CMPP_W_EQ_UN_UN);
01664     
01665     oprd = new legoOprd;
01666     oprd->SetOprdType (OT_REG);
01667     oprd->SetOprdFileType(FT_PR);
01668     oprd->SetOprdRegType (RT_R);
01669     oprd->SetOprdDataType (DT_P);
01670     oprd->SetOprdRegNum(pr_num);
01671     oprd->SetParentOpPtr (cmpp_op);
01672     cmpp_op->SetDestOprdPtr(oprd);
01673     
01674     oprd2 = new legoOprd;
01675     oprd2->SetOprdType (OT_UNDEFINED);
01676     oprd2->SetParentOpPtr (cmpp_op);
01677             
01678     oprd->SetNextOprdPtr (oprd2);    
01679 
01680     oprd = new legoOprd;
01681     oprd->SetOprdType (OT_REG);
01682     oprd->SetOprdFileType(FT_GPR);
01683     oprd->SetOprdRegType (RT_R);
01684     oprd->SetOprdDataType (DT_I);
01685     oprd->SetOprdRegNum(ld_gpr_num);
01686     oprd->SetParentOpPtr (cmpp_op);
01687     cmpp_op->SetSrcOprdPtr (oprd);
01688     
01689     oprd2 = new legoOprd;
01690     oprd2->SetOprdType (OT_LITERAL_I);
01691     oprd2->SetParentOpPtr (cmpp_op);
01692     oprd2->SetLiteralInteger(0);
01693     oprd->SetNextOprdPtr(oprd2);
01694     
01695     oprd = new legoOprd;
01696     oprd->SetOprdType (OT_LITERAL_P);
01697     oprd->SetParentOpPtr (cmpp_op);
01698     oprd->SetLiteralPredicate(1);
01699     cmpp_op->SetPredOprdPtr (oprd);    
01700     
01701     AddMidOp(cmpp_op, pbrr_op);
01702         
01703     //step 1, fortunately, there is a legoUtil function that we can use
01704     // to save the trouble here.    
01705 //    legoBB * new_orig_bb = (legoBB *) SplitParentBlockBeforeOp(
01706 //          BB_orig->GetEntryOpsPtr()->GetOpPtr()->GetNextLink());
01707     legoBB * new_orig_bb = (legoBB *) SplitParentBlockBeforeOp(
01708             cond_br->GetNextLink());
01709     legoBB * header_bb = BB_orig;
01710     
01711     
01712 //    BB_orig->RefreshEdges();
01713     //step 2. BB duplicate, as it is not tail duplication, the entry edges are
01714     // not set as well as the inoplist of its CMERGE
01715     legoBB * dup_bb = BBDuplicate(new_orig_bb);
01716     
01717     //step 3. Fix the control edges among BB header, BB_dup, and BB_orig
01718     legoOp *from_op, *to_op;
01719     from_op = header_bb->GetExitOpsPtr()->GetOpPtr();
01720     to_op = dup_bb->GetEntryOpsPtr()->GetOpPtr();
01721     opEdges * edge1;
01722     edge1 = AddEdge(from_op, to_op, ET_CNTL);
01723     if(edge1 == NULL)
01724         LegoFatal ("MulCpBB", "Adding edge failed");
01725     header_bb->RefreshAll(); 
01726     //AddToList(header_bb->GetOutEdgesPtr(), edge1);
01727     //AddToList(dup_bb->GetInEdgesPtr(), edge1);
01728     dup_bb->RefreshAll();
01729     AddToList(from_op->GetOutListPtr(), to_op, 1, 0);
01730     AddToList(to_op->GetInListPtr(), from_op, 1, 0);
01731     
01732     pbrrsrc_oprd->SetLiteralControlBlock(dup_bb->GetRegionId());
01733 
01734 }
01735 
01736 //Duplicate a BB (BB_orig). Returns a pointer to the duplicated BB
01737 legoBB * BBDuplicate(legoBB * BB_orig)
01738 {
01739   regionList *allparents, *allchildren, *lrrscan, *oparents, *ochildren;
01740   int i, j, bingo, regionid, opid, eaid;
01741   double edgeweight, sourceweightratio;
01742   legoRegion *head, *duplicate, *region;
01743   legoProc *parentproc;
01744   legoOp *headop, *origop, *origop2, *dupop, *dupop2;
01745   legoOprd *oprd;
01746   opEdges *edgedictionary, *edgetail, *oescan;
01747   attrs *attrdictionary, *attrtail, *atscan;
01748   opList *oplscan, *oplscanprev;
01749   attrList *atlscan, *atl;
01750   edgeList *edlscan, *edlscanprev, *edlheadtosource;
01751 
01752   pointer_map *map, *tail;
01753 
01754   // First, some checking.
01755   if (BB_orig->GetRegionType() != RT_BB)
01756     {
01757       LegoNonFatal ("BBDuplicate",
01758                     "Region %d not a basic block.", BB_orig->GetRegionId());
01759       return NULL;
01760     } // end if
01761 
01762   allparents = BB_orig->GetParents();
01763 
01764   tail = map = new pointer_map;  // initialize pointer mapping table
01765 
01766   // Find parent proc.
01767   parentproc = (legoProc *) FindParentRegionType (RT_PROC, BB_orig);
01768   if (parentproc == NULL)
01769     LegoFatal ("BBDuplicate", "Can't find parent proc of region %d.",
01770                BB_orig->GetRegionId());
01771 
01772   // Get dictionaries.
01773   edgedictionary = parentproc->GetEdgeDictionary();
01774   if (edgedictionary == NULL)
01775     {
01776       LegoNonFatal ("BBDuplicate",
01777                     "Proc Edge dictionary is missing.");
01778       return NULL;
01779     } // end if
01780   attrdictionary = parentproc->GetAttrDictionary();
01781   if (attrdictionary == NULL)
01782     {
01783       LegoNonFatal ("BBDuplicate",
01784                     "Attribute dictionary is missing.");
01785       return NULL;
01786     } // end if
01787 
01788   // Set up tail pointers and max edge/attr id.
01789   for (edgetail = edgedictionary; edgetail->GetNextOpEdgePtr() != NULL;
01790        edgetail = edgetail->GetNextOpEdgePtr()) /* do nothing */;
01791 
01792   for (attrtail = attrdictionary; attrtail->GetNextAttrPtr() != NULL;
01793        attrtail = attrtail->GetNextAttrPtr()) /* do nothing */;
01794 
01795   eaid = FindMaxEdgeAttrId (parentproc);
01796 
01797   // Before we begin, remember the parents and children of sourceregion.
01798   // Form them even if they're not there.
01799   if (BB_orig->GetParents() != NULL)
01800     oparents = new regionList (*(BB_orig->GetParents())); 
01801     //HZ: should be the BB_header
01802   else
01803     oparents = NULL;
01804   if (BB_orig->GetChildren() != NULL)
01805     ochildren = new regionList (*(BB_orig->GetChildren()));
01806   else
01807     ochildren = NULL;
01808 
01809   // -----------------------------------------------------------------------
01810   // Step 1.  Duplicate the region (including ops).
01811   // -----------------------------------------------------------------------
01812 
01813   // 1a. Copy construct the region.
01814   
01815   duplicate = new legoBB (*(legoBB *) BB_orig);
01816 
01817   region = ((legoRegion *) parentproc->GetParentPtr())->FindMaxRegionId();
01818   regionid = region->GetRegionId();
01819   duplicate->SetRegionId (++regionid);
01820 
01821   // 1b. Duplicate region attributes.
01822   for (atlscan = duplicate->GetRegionAttrListPtr(); atlscan != NULL;
01823        atlscan = atlscan->GetNextListPtr())
01824     {
01825       if (atlscan->GetAttrPtr() == NULL)
01826         continue;
01827       atscan = new attrs (*(atlscan->GetAttrPtr()), NULL, ++eaid);
01828       atlscan->SetAttrPtr (atscan);
01829       atscan->SetAttrId (eaid);
01830       atlscan->SetAttrId (eaid);
01831       attrtail->SetNextAttrPtr (atscan);
01832       attrtail = attrtail->GetNextAttrPtr();
01833     } // end for
01834 
01835   opid = (FindMaxOpId ((legoProc *) parentproc))->GetOpId();
01836 
01837   // 1c. Copy construct each op from sourceregion to duplicate.
01838   for (origop = BB_orig->GetEntryOpsPtr()->GetOpPtr();
01839        origop != NULL;
01840        origop = origop->GetNextLink())
01841     {
01842       // 1c,i. Copy construct the op itself.
01843       dupop = new legoOp (*origop);
01844       tail = tail->record (origop, dupop);
01845       dupop->SetOpId (++opid);  // assign new id
01846       dupop->SetParentBlockPtr (duplicate);
01847 
01848       // Find origop in duplicate (there because of copy constructor).
01849       for (i = 0; i < duplicate->GetCount(); i++)
01850         {
01851           origop2 = (legoOp *) duplicate->GetItem (i);
01852           if (origop2 == origop) break;
01853         } // end for
01854       if (i == duplicate->GetCount())
01855         LegoFatal ("TailDuplicate", "Can't find original "
01856                    "op %d in duplicate.", origop->GetOpId());
01857       duplicate->Detach (i);  // remove original, slide down rest.  Then, ...
01858       duplicate->AddItem (dupop);  // add duplicate to end of region
01859 
01860       // 1c,ii. Duplicate op attributes.
01861       for (atlscan = dupop->GetOpAttrListPtr(); atlscan != NULL;
01862            atlscan = atlscan->GetNextListPtr())
01863         {
01864           if (atlscan->GetAttrPtr() == NULL)
01865             continue;
01866           atscan = new attrs (*(atlscan->GetAttrPtr()), dupop, ++eaid);
01867           atlscan->SetAttrPtr (atscan);
01868           atscan->SetAttrId (eaid);
01869           atlscan->SetAttrId (eaid);
01870           attrtail->SetNextAttrPtr (atscan);
01871           attrtail = attrtail->GetNextAttrPtr();
01872         } // end for
01873 
01874     } // end for
01875 
01876   // 1d. Update duplicate's entry/exit ops.
01877   //duplicate->RefreshOps();
01878 
01879   // -----------------------------------------------------------------------
01880   // Step 2.  Update intra-block links, create new intra-block edges.
01881   // -----------------------------------------------------------------------
01882 
01883   // For each duplicated op...
01884   for (i = 0; i < duplicate->GetCount(); i++)
01885     {
01886       dupop = (legoOp *) duplicate->GetItem(i);
01887       // 2a. Update links and edges.
01888       if (i != duplicate->GetCount() - 1)
01889         {
01890           // 2a,i. Set previous and next links.
01891           dupop2 = (legoOp *) duplicate->GetItem(i + 1);
01892           dupop->SetNextLink (dupop2);
01893           dupop2->SetPrevLink (dupop);
01894 
01895           // 2a,ii. Hunt down original edge between them.
01896           // Find original ops by following duplicateOpsPtr list.
01897           for (oplscan = dupop->GetDuplicateOpsPtr(); oplscan != NULL;
01898                oplscan = oplscan->GetNextListPtr())
01899             if ((legoRegion *) oplscan->GetOpPtr()->GetParentBlockPtr()
01900                 == BB_orig) break;
01901           if (oplscan == NULL)
01902             {
01903               LegoNonFatal ("BBDuplicate",
01904                             "Can't find original op for duplicate op %d.",
01905                             dupop->GetOpId());
01906               return NULL;
01907             } // end if
01908           origop = oplscan->GetOpPtr();
01909           for (oplscan = dupop2->GetDuplicateOpsPtr(); oplscan != NULL;
01910                oplscan = oplscan->GetNextListPtr())
01911             if ((legoRegion *) oplscan->GetOpPtr()->GetParentBlockPtr()
01912                 == BB_orig) break;
01913           if (oplscan == NULL)
01914             {
01915               LegoNonFatal ("BBDuplicate",
01916                             "Can't find original op for duplicate op %d.",
01917                             dupop2->GetOpId());
01918               return NULL;
01919             } // end if
01920           origop2 = oplscan->GetOpPtr();
01921 
01922           oescan = FindControlEdge (origop, origop2);
01923           if (oescan == NULL)
01924             {
01925               LegoNonFatal ("BBDuplicate",
01926                             "Can't find edge between original ops %d and %d.",
01927                             origop->GetOpId(), origop2->GetOpId());
01928               return NULL;
01929             } // end if
01930 
01931           // 2a,iii. Copy construct a new edge between dupop and dupop2.
01932           edgetail->SetNextOpEdgePtr
01933             (new opEdges (*oescan, ++eaid, dupop->GetOpId(),
01934                           dupop, dupop2->GetOpId(), dupop2));
01935           edgetail = edgetail->GetNextOpEdgePtr();
01936 
01937           // 2a,iv. Duplicate edge attributes.
01938           for (atlscan = edgetail->GetEdgeAttrListPtr(); atlscan != NULL;
01939                atlscan = atlscan->GetNextListPtr())
01940             {
01941               if (atlscan->GetAttrPtr() == NULL)
01942                 continue;
01943               atscan = new attrs (*(atlscan->GetAttrPtr()), NULL, ++eaid);
01944               atlscan->SetAttrPtr (atscan);
01945               atscan->SetAttrId (eaid);
01946               atlscan->SetAttrId (eaid);
01947               attrtail->SetNextAttrPtr (atscan);
01948               attrtail = attrtail->GetNextAttrPtr();
01949             } // end for
01950 
01951           // 2a,v. If dupop has an outlist, change the entry pointing
01952           //       to origop2 to point to dupop2.
01953           if (dupop->GetOutListPtr() != NULL)
01954             for (oplscan = dupop->GetOutListPtr(); oplscan != NULL;
01955                  oplscan = oplscan->GetNextListPtr())
01956               if (oplscan->GetOpId() == origop2->GetOpId())
01957                 {
01958                   oplscan->SetOpPtr (dupop2);
01959                   oplscan->SetOpId (dupop2->GetOpId());
01960                 } // end if (, for, if)
01961 
01962         } // end if
01963 
01964       // 2b. Update allListPtr as appropriate - ops are enqueued in reverse.
01965       if (i == 0)
01966         dupop->SetListOpPtr (parentproc->GetListOpPtr());
01967       if (i == duplicate->GetCount() - 1)
01968         parentproc->SetListOpPtr (dupop);
01969       else
01970         dupop2->SetListOpPtr (dupop);
01971         
01972     } // end for
01973     
01974     duplicate->RefreshOps();
01975     duplicate->RefreshEdges();
01976   // -----------------------------------------------------------------------
01977   // Step 3.  Connect head and duplicate exclusively (handle jumptables later).
01978   // -----------------------------------------------------------------------
01979   
01980 
01981   // -----------------------------------------------------------------------
01982   // Step 4.  Connect duplicate to sourceregion' children.
01983   // -----------------------------------------------------------------------
01984 
01985   allchildren = BB_orig->GetChildren();
01986   sourceweightratio = BB_orig->GetWeight() + duplicate->GetWeight();
01987   if (sourceweightratio != 0.0)
01988     sourceweightratio = BB_orig->GetWeight() / sourceweightratio;
01989   // fraction of weight in original
01990 
01991   // For each child of source region ...
01992   if(allchildren != NULL)
01993   for (lrrscan = allchildren; lrrscan != NULL;
01994        lrrscan = lrrscan->GetNextListPtr())
01995     {
01996       region = lrrscan->GetRegionPtr();
01997       if (region == NULL) continue;
01998 
01999       // 4a. Invalidate child's parents.
02000       region->SetParents (NULL);
02001 
02002       // 4b. Hunt down all edges between sourceregion and child and ...
02003       for (oescan = edgedictionary;
02004            oescan->GetNextOpEdgePtr() != NULL;
02005            oescan = oescan->GetNextOpEdgePtr())
02006         {
02007           origop = oescan->GetFromOpPtr();
02008           origop2 = oescan->GetToOpPtr();
02009           if ( ((legoRegion *)(origop->GetParentBlockPtr()) == BB_orig) &&
02010                ((legoRegion *)(origop2->GetParentBlockPtr()) ==
02011                 region) )  // from sourceregion to child
02012             {
02013               dupop = (legoOp *) map->lookup_duplicate (origop);
02014               if (dupop == NULL)
02015                 LegoFatal ("BBDuplicate", "Mapping error.");
02016 
02017               // 4b,i. Add a new control edge.
02018               edgetail->SetNextOpEdgePtr  // make from duplicate to child
02019                 (new opEdges (*oescan, ++eaid, dupop->GetOpId(),
02020                                   dupop, origop2->GetOpId(), origop2));
02021               edgetail = edgetail->GetNextOpEdgePtr();
02022               //              edgetail = AddEdge (dupop, origop2, ET_CNTL);
02023               //              eaid++;
02024 
02025               // 4b,ii. Duplicate edge attributes.
02026               
02027               //HZ:
02028               //edgetail->SetEdgeAttrListPtr (new attrList
02029               //                            (*(oescan->GetEdgeAttrListPtr())));
02030               if(oescan->GetEdgeAttrListPtr() != NULL)
02031                 edgetail->SetEdgeAttrListPtr (new attrList
02032                                             (*(oescan->GetEdgeAttrListPtr())));
02033               else
02034                 edgetail->SetEdgeAttrListPtr(NULL);  
02035               for (atlscan = edgetail->GetEdgeAttrListPtr(); atlscan != NULL;
02036                    atlscan = atlscan->GetNextListPtr())
02037                 {
02038                   if (atlscan->GetAttrPtr() == NULL)
02039                     continue;
02040                   atscan = new attrs (*(atlscan->GetAttrPtr()), NULL, ++eaid);
02041                   atlscan->SetAttrPtr (atscan);
02042                   atscan->SetAttrId (eaid);
02043                   atlscan->SetAttrId (eaid);
02044                   attrtail->SetNextAttrPtr (atscan);
02045                   attrtail = attrtail->GetNextAttrPtr();
02046                 } // end for
02047 
02048               // 4b,iii. Scale edge weights appropriately as well as the
02049               //         weights of their ops.
02050               // oescan is the original. edgetail is the duplicate.
02051               edgeweight = -1.0;
02052               atlscan = FindFreqAttribute (oescan);
02053               if (atlscan != NULL)
02054                 {
02055                   edgeweight = (double)
02056                     (atlscan->GetAttrValPtr()->GetAttrValue());  // original wt
02057 
02058                   // Scale oescan's weight down to its portion.
02059                   atlscan->GetAttrValPtr()->SetAttrValue
02060                     ((int) (edgeweight * sourceweightratio));
02061                   atlscan->GetAttrValPtr()->GetNextIntListPtr()
02062                     ->SetAttrValue (1);  // it's a merge now!
02063 
02064                   for (oplscan = origop->GetOutListPtr(); oplscan != NULL;
02065                        oplscan = oplscan->GetNextListPtr())
02066                     if (oplscan->GetOpId() == origop2->GetOpId())
02067                       {
02068                         oplscan->SetWeight (edgeweight * sourceweightratio);
02069                         break;
02070                       } // end if
02071 
02072                   // Scale edgetail's weight down to its portion.
02073                   atlscan = FindFreqAttribute (edgetail);
02074                   if (atlscan != NULL)
02075                     {
02076                       atlscan->GetAttrValPtr()->SetAttrValue
02077                         ((int) (edgeweight * (1.0 - sourceweightratio)));
02078                       atlscan->GetAttrValPtr()->GetNextIntListPtr()
02079                         ->SetAttrValue (1);  // it's a merge now!
02080                     } // end if
02081 
02082                   for (oplscan = dupop->GetOutListPtr(); oplscan != NULL;
02083                        oplscan = oplscan->GetNextListPtr())
02084                     if (oplscan->GetOpId() == origop2->GetOpId())
02085                       {
02086                         oplscan->SetWeight
02087                           (edgeweight * (1.0 - sourceweightratio));
02088                         break;
02089                       } // end if
02090                     
02091                 } // end if
02092 
02093               // 4b,iv. While we're here, fix duplicate's out edge.
02094               //              for (edlscan = duplicate->GetOutEdgesPtr();
02095               //                   edlscan != NULL;
02096               //                   edlscan = edlscan->GetNextListPtr())
02097               //                {
02098               //                  if (edlscan->GetEdgePtr() == oescan)
02099               //                    {
02100               //                      edlscan->SetEdgePtr (edgetail);
02101               //                      edlscan->SetEdgeId (edgetail->GetEdgeId());
02102               //                      break;
02103               //                    } // end if
02104               //                } // end for
02105 
02106               // 4b,iv. Oh, and while we're at it, add edge to child.
02107               region->RefreshEdges();
02108               //              for (edlscan = region->GetInEdgesPtr();
02109               //                   edlscan != NULL && edlscan->GetNextListPtr() != NULL;
02110               //                   edlscan = edlscan->GetNextListPtr()) /* nothing */;
02111               //              if (edlscan != NULL)
02112               //                {
02113               //                  edlscan->SetNextListPtr (new edgeList);
02114               //                  edlscan = edlscan->GetNextListPtr();
02115               //                  edlscan->SetEdgePtr (edgetail);
02116               //                  edlscan->SetEdgeId (edgetail->GetEdgeId());
02117               //                  edlscan->SetValid (1);
02118               //                } // end if
02119 
02120               // 4b,v. All right, update the child's entry op too ... geez.
02121               //HZ
02122              if(origop2->GetInListPtr() != NULL)
02123               for (oplscan = origop2->GetInListPtr();
02124                    oplscan != NULL && oplscan->GetNextListPtr() != NULL;
02125                    oplscan = oplscan->GetNextListPtr())  // stop before end
02126                 if (oplscan->GetOpId() == origop->GetOpId())
02127                   oplscan->SetWeight (edgeweight * sourceweightratio);
02128               if (oplscan->GetOpId() == origop->GetOpId())  // for last one
02129                 oplscan->SetWeight (edgeweight * sourceweightratio);
02130               if (oplscan != NULL)
02131                 {
02132                   oplscan->SetNextListPtr (new opList);
02133                   oplscan = oplscan->GetNextListPtr();
02134                   oplscan->SetOpPtr (dupop);
02135                   oplscan->SetOpId (dupop->GetOpId());
02136                   oplscan->SetValid (1);
02137                   oplscan->SetWeight (edgeweight * (1.0 - sourceweightratio));
02138                 } // end if
02139 
02140             } // end if (found an edge to duplicate)
02141 
02142         } // end for (oescan)
02143     } // end for (lrrscan)
02144 
02145   // 4c (kinda). Fix duplicate's out edges.
02146   duplicate->RefreshEdges();
02147 
02148   // Finally finally finally, kill parents and children lists:
02149   // Original (sourceregion's) parents...
02150   for (lrrscan = oparents; lrrscan != NULL;
02151        lrrscan = lrrscan->GetNextListPtr())
02152     {
02153       region = lrrscan->GetRegionPtr();
02154       //      delete region->children;
02155       //      region->children = NULL;
02156       region->SetChildren (NULL);
02157       region->RefreshEdges();
02158     } // end for
02159   // Original (sourceregion's) children...
02160   for (lrrscan = ochildren; lrrscan != NULL;
02161        lrrscan = lrrscan->GetNextListPtr())
02162     {
02163       region = lrrscan->GetRegionPtr();
02164       //      delete region->parents;
02165       //      region->parents = NULL;
02166       region->SetParents (NULL);
02167       region->RefreshEdges();
02168     } // end for
02169   // And sourceregion' parents and children (duplicate's not copy-constr.'d)
02170   delete oparents;
02171   delete ochildren;
02172   BB_orig->SetParents (NULL); //HZ: it is ok, as the function call
02173                                    // GetParents will compute the pointer list
02174                                    // if it is NULL.
02175   BB_orig->SetChildren (NULL); 
02176     
02177   return (legoBB *) duplicate;    
02178 }
02179 

Generated on Mon Jul 21 20:28:05 2003 for TINKER LEGO DOC by doxygen 1.3.2