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

list_scheduler.H

Go to the documentation of this file.
00001 #ifndef _LIST_SCHEDULER_H_
00002 #define _LIST_SCHEDULER_H_
00003 
00004 #include <stl.h>
00005 #include "TinkerKnobs.H"
00006 #include "dag.H"
00007 #include "machine.h"
00008 #include "chains.H"
00009 #include "opList.H"
00010 #include "rdef.H"
00011 
00012 #define UNSCHEDULED           -1   // Marks an Op as unscheduled
00013 #define RENAMING_CONFLICT      1   // Marks ops that can't be renamed 
00014 #define NO_RENAMING_CONFLICT   0   // Marks ops that can be renamed 
00015 
00016 extern clock_t start_live, finish_live, start_rdef, finish_rdef;
00017 extern double clocks_per_sec;
00018 extern double total_live; 
00019 
00020 class list_scheduler {
00021 
00022 protected:
00023 
00024    typedef vector < BigListElement >::iterator ListIterator;
00025 
00026    vector < BigListElement >* List;
00027    ListIterator ListHead, ListTail, ListPtr;
00028 
00029    int    ListCount,
00030           ScheduleCluster,
00031           NumClusters;
00032 
00033    int PlayDoh;
00034    char aggr_list_sched;
00035 
00036    dag *DPG;
00037    legoRegion *Region;
00038 
00039    machine *Machine;
00040    int BypassLatency;           // The latency of result forwarding,
00041                                 //    this indicates if results are
00042                                 //    forwarded using the result
00043                                 //    bus OR are written to registers
00044                                 //    before they can be used
00045    legoOp *TailOp;
00046 
00047    int DominatorParallelism,
00048        CodeGen,
00049        CreateSchedVizFiles,
00050        TreeTraversalSched,
00051        NoSpeculation,
00052        AllowPBRSpeculation,
00053        AllowLoadSpeculation,
00054        AllowOnlySafeSpeculation,
00055        AllowDownwardCodeMotion,
00056        AllowMultiWayBR;
00057 
00058    FILE *SchedFile, *ListFile; 
00059 
00060    int bus_needed;
00061 
00062    int current_block_int;
00063    legoOp *current_before_op;
00064    ListIterator Op;
00065    
00066    //HZ: Note:
00067    // Matt used the word 'attribute' to describe the private/public variables of
00068    // the class. Also the word is used in the description of the Rebel code.
00069    // The meaning of the word in the comments should be clear from the context.
00070 
00071    // DescendantofBlock: Returns YES if this operation 
00072    // belongs to a block which is a descendant of the 
00073    // block identified by a pointer of value input_block_int.      
00074    int          DescendantofBlock( int input_block_int, legoOp *op );
00075 
00076    // DescendantofCurBlockPtr: Returns YES if this operation 
00077    // belongs to a block which is a descendant of the 
00078    // block identified by the current_block_int attribute. 
00079    // It can be seen as a special case of the previous function with
00080    // the input_block_int is current_block_int and op as Node->GetOp().
00081    int          DescendantofCurBlockPtr( ListIterator Node);
00082    
00083    // TruePredecessorsScheduled: Returns YES if all predecessors of an 
00084    // operation have been scheduled, returns NO otherwise
00085    // Same as PredecessorsScheduled except that it 
00086    // ignores anti/output-deps   
00087    // HZ: If the current Node is a ld op (but not ld verify), the memory
00088    // deps is not enforced. (enables moving ld above store -- data speculation)
00089    //    Otherwise, (i.e., if the Node is a st or ld verify instr), the memory  
00090    //    deps is enforced.
00091    //   Control deps are enforced between the br op and the br op in its parent
00092    //   basic block. So the control speculation is also enabled.
00093    int          TruePredecessorsScheduled( ListIterator Node);
00094    
00095    // PredecessorsScheduled: Returns YES if all predecessors of an 
00096    // operation have been scheduled, returns NO otherwise   
00097    // HZ: enforce all the data deps including MEM deps among mem ops & control  
00098    //deps between br ops.
00099    int          PredecessorsScheduled( ListIterator Node);
00100    
00101    //BuildReadyTimes: Finds the ReadyTimes for each operand of an unscheduled
00102    // operation that will now be a Candidate for scheduling
00103    // HZ: The operands' ready times of the op are computed using its
00104    // predecessor's schedule time & latency.
00105    // Different set of ready times are computed with respect to different
00106    // dependency types:
00107    //   operand_ready_times: ready time considering all types of deps (reg, mem,
00108    //                            and cntl)
00109    //   true_operand_ready_times: ready time considering all types of deps
00110    //                           except reg_out and reg_anti deps.
00111    //   dsld_operand_ready_times: (ds stands for data speculative) ready time
00112    //                           considering all types of deps except mem dep if
00113    //                           the Node is a ld but not ld verify instr.
00114    //   true_dsld_operand_ready_times: ready time considering all deps except
00115    //                           reg_out , reg_anti and mem dep if Node is a ld
00116    //                           but not ld verify instr.
00117    void         BuildReadyTimes( ListIterator Node, int IssueCycle);
00118    
00119    // GetCandidateNodeTree: Tree-Traversal version of this function. scans 
00120    // the list of Ops to try and find one which is unscheduled, has all TRUE 
00121    // predecessors scheduled (excluding anti/output-deps) and meets requirements 
00122    // of tree-traversal scheduling (is dominated by cur_block_ptr)  Creates 
00123    // "int *operand_ready_times" for the op to be used during scheduling
00124    // HZ: Currently, if fully_if_convert and final_pass are both set,
00125    //     it scans through the unscheduled instructions (all instructions are
00126    //     maintained in attribute List), check whether the predecessors have
00127    //     been scheduled (i.e., enforce all the deps). If one is found, build
00128    //     its readytimes.
00129    //     If fully_if_convert is not set, check only the true predecessors of the
00130    //     unscheduled instruction to see whether they are scheduled. If the true
00131    //     predecessors of an unscheduled instruction are scheduled, then build  
00132    //     its ready times. Also check the oppurtunitis of renaming to get better
00133    //     readytimes (when ture_dsld_ready_time < dsld_ready_time). Then build
00134    //     readytimes one more time.
00135    //     Note that: the instructions in List are ordered by the Tree Traveral
00136    //     method and the dominence by cur_block_ptr is enforced.
00137    //      
00138    vector < BigListElement >::iterator
00139                 GetCandidateNodeTree(int, knobs *Knobs,
00140                                      legoRegion *proc_ptr, int Final_Pass);
00141                                      
00142    // GetCandidateNode: scans the list of Ops to try and find one which 
00143    // is unscheduled and has all predecessors scheduled.  Creates 
00144    // "int *operand_ready_times" for the op to be used during scheduling
00145    // HZ: checks whether the predecessors have been scheduled (i.e., enforce all
00146    //  deps).
00147    vector < BigListElement >::iterator
00148                 GetCandidateNode( int );
00149    
00150    // ResetListPtr: sets the attribute ListPtr to the first unscheduled Op in List
00151    void         ResetListPtr();
00152 
00153    // HZ: Simple rename of the dsts of the op
00154    // If IncMaxRegNum == 1, rename the dsts of the op starting from reg no (++MaxRegNum)
00155    // If IncMaxRegNum == 0, rename the dsts of the op starting from RegNum.
00156    // Simple rename works by setting just the reg no of the dsts of the op and
00157    // update the DAG by remove the Output and Anti(def) dep.
00158    void SimpleRename (legoOp *op, int RegNum, int IncMaxRegNum);
00159    
00160    //HZ: Rename the uses of the def.
00161    // For each use of the def (obtained by GetDUChain), set the oprdRegNum to
00162    // RegNum , also call the function ReverseGlobalRename(use, RegNum, orig_def)
00163    // to rename the defs of the use.
00164    void ForwardGlobalRename (legoOprd *def, int RegNum, legoOprd *orig_def);
00165    
00166    //HZ: Rename the defs of the use
00167    // For each def of the use (obtained by GetUDChain), set the oprdRegNum to
00168    // RegNum, also call the function ForwardGlobalRename(def, RegNum, orig_def)
00169    // to rename the uses of the def.
00170    //
00171    // Doubtful point: the setting of the ReDoLiveVarsAfterGlobal
00172    void ReverseGlobalRename (legoOprd *use, int RegNum, legoOprd *orig_def);   
00173       
00174    //HZ: Rename the dsts of the op.
00175    // If IncMaxRegNum == 1, rename the dsts of the op starting from reg no (++MaxRegNum)
00176    // If IncMaxRegNum == 0, rename the dsts of the op starting from RegNum.
00177    // For each dst of the op, after change the reg no, call
00178    // ForwardGlobalRename(def, localRegNum, def) to rename the reg no globally
00179    // Then remove the output deps on its predecessors and the antidep based on
00180    // the renamed def.
00181    void GlobalRename (legoOp *op, int RegNum, int IncMaxRegNum);
00182 
00183    //HZ: AddCopyOps: add the copy (move) ops of the op.
00184    //There are two scenarios considered in this function:
00185    // (1) If the op is scheduled, we are dealing with the dominate parallelism
00186    //   (Doubtful point for me at this time)
00187    // (2) If the op is unscheduled, we are doing the first step of
00188    //    renamewithcopy.
00189    // For each dst reg of the op, a copy (move) inst is created with the
00190    //  consideration of the predicate register.(e.g., mov r1,
00191    //  r1 (p1) ). Then the related DU, UD chains, and the copy ops are appended
00192    //  at the end of the List. Also the predecessor & successor
00193    //  dependency relationships in DAG are updated. 
00194    int AddCopyOps (legoOp *op);
00195 
00196    //HZ: Return true if orig_def is descendant of the BB that the def resides in.
00197    // This happens when a use has two reaching defs. In the renaming process,
00198    // just rename one of them is not enough. Matt called this 'Merge Problem' as
00199    // two defs merge at the same use.
00200    // Because of the nature of treegion, this mergeing use should not be in the
00201    // same treegion as the two defs.
00202    int IsRemoteMergeProblem (legoOprd *def, legoOprd *orig_def);
00203    
00204    //HZ: Check whether a merge problem exist for the orig_def.
00205    // For each use of the orig_def (obtained by GetDUChain()), if the use is
00206    // preceeds the def (due to the loop back), or the use is not descendant of
00207    // the def, or the use is in different treegions, check the defs of this use
00208    // to see whether there is a merge problem between the orig_def and any of the
00209    // defs. Also checks whether the dst of the orig_def are among the live-ins
00210    // of the treegion. If so, return YES to show that there is merge problem.
00211    int IsMergeProblem (legoOprd *orig_def);
00212 
00213    //HZ: Rename the dst reg of the op.
00214    // Based on the following conditions to decide which renaming scheme will be
00215    // used: 
00216    //      whether there are any uses of the dsts of the op that are outside
00217    //      of treegion, or there are any uses that are not descedant of the
00218    //      BB where the op resides in. => variable UseOutsideTreeOrNotDom
00219    // If UseOutsideTreeOrNotDom is false, the SimpleRename is used.
00220    // If UseOutsideTreeOrNotDom is true, more conditions need to be checked to
00221    // determine either SimpleRenameWithCopy or GlobalRename to be used:
00222    //     -Check whether Merge problem exists. If not, the global rename is
00223    //      used. 
00224    //     -If there is Merge Problem, add a copy op if the op
00225    //      has at least one use that it dominates and there is no use preceeds
00226    //      the op.
00227    //     -Otherwise, return RENAMING_CONFLICT.
00228    // For the input Hazardous, if set, the Merge problem is assumed to exist. So
00229    // the SimpleRenameWithCopy is favored. 
00230    //
00231    // Doubtful point: (future work on DDG & scheduler) DDG analysis of FICT
00232    int Rename (legoOp *op, int RegNum, knobs *Knobs, 
00233                legoRegion *proc_ptr, int Final_Pass, 
00234                int IncMaxRegNum, int Hazardous);
00235 
00236    //HZ: Check whether there are any dsts of the op that are live along the edge.
00237    int anyliveout (legoOp *op, opEdges *edge);
00238 
00239    //HZ: The define (renamed_def) has been renamed. So we need to remove the output
00240    //dep caused by this define. The function does so by checking both its
00241    //successors and predecessors. Then remove the corresponding dependence edge
00242    //in the DAG.
00243    void RemoveOutputDepsAfterRename (legoOprd *renamed_def);
00244    
00245    //HZ: Same as the one above except that it just checks predecessors.
00246    void RemoveOutputDepsAfterRenameUp (legoOprd *renamed_def);
00247    
00248    //HZ: Anti Dep removal after renaming the use.
00249    //   In the following scenario:
00250    //   Inst. a     <- r1, r2 ( use of r1 has been renamed)
00251    //               ... (other instructions)
00252    //   Inst. b  r1 <- (define of r1)
00253    //   Looking through the successors of instruction a, remove the anti
00254    //   dep if the reg no, reg type, Oprd File Type, etc. match. Remove the
00255    //   dep edge by removing the successor from instr a and removing predecessor
00256    //   from instr. b. Also it is noted that for brl op, when reg no is INTP1 ~
00257    //   DBL_P2. This dep edge is not removed.
00258    void RemoveAntiDepsAfterUseRename (legoOprd *renamed_use);
00259    
00260    //HZ: Anti Dep removal after renaming the def.
00261    //   In the following scenario:
00262    //   Inst. a     <- r1, r2 ( use of r1)
00263    //               ... (other instructions)
00264    //   Inst. b  r1 <- (define of r1 has been renamed)
00265    //   Looking through the predecessors of instruction b, remove the anti
00266    //   dep if the reg no, reg type, Oprd File Type, etc. match. Remove the
00267    //   dep edge by removing the successor from instr a and removing predecessor
00268    //   from instr. b. Also it is noted that for brl op, when reg no is INTP1 ~
00269    //   DBL_P2. This dep edge is not removed.
00270    void RemoveAntiDepsAfterDefRename (legoOprd *renamed_def);
00271 
00272    
00273    /*
00274    * copy_operand 
00275    *   Src = source operand
00276    *   Target = target operand
00277    *
00278    * Copies fields from Src to Target, assuming a register-type operand.
00279    * Does NOT copy next and prev pointers.
00280    */  
00281    void         copy_operand(legoOprd *Src, legoOprd *Target);
00282    
00283    /*
00284    * add_to_existing_attr
00285    *   Attr = existing live attribute
00286    *   NewOprd = new operand to add to attribute
00287    *
00288    * Adds a copy of the operand NewOprd to attribute Attr. If a copy
00289    * already resides in Attr, no action is taken.
00290    */   
00291    void         add_to_existing_attr(attrs *Attr, legoOprd *NewOprd);
00292    
00293    /*
00294    * create_new_attr
00295    *   Edge = edge on which to add live attribute
00296    *   Oprd = operand to add to attribute
00297    *   Proc = proc to whose dictionary to add edge
00298    *
00299    * Creates a new live attribute for Edge containing a copy of Oprd.
00300    */   
00301    void         create_new_attr(opEdges *Edge, legoOprd *Oprd, 
00302                                 legoProc *Proc);
00303                                 
00304    //HZ: Fix the liveness after we move the op sepculatively up to a different
00305    // block from its orginal block (where before_op resides in).
00306    // Add the dsts of the op to live attr of the edges along the path from its  
00307    // original block to its current block. 
00308    int          FixLiveVarsUp (legoOp *op, legoOp *before_op, 
00309                                legoProc *proc_ptr);
00310    
00311    //HZ: Fix the liveness after we move the op sepculatively down to a different
00312    // block from its orginal block.
00313    // Add the srcs of the op to live attr of the edge.
00314    // Note: if op is a brl instr, the src oprds are MACRO REGS (from INT_P1 to
00315    // DBL_P2)
00316    int          FixLiveVarsDown (legoOp *op, opEdges *edge, 
00317                                legoProc *proc_ptr);
00318    //HZ: Add use to the live attr of the edges along the path from the BB where
00319    // before_op resides in to the BB where the use is.
00320    int          FixLiveVarsFromUses(legoOprd *use, legoOp *before_op, 
00321                                     legoProc *proc_ptr);
00322    
00323    //HZ: Determine whether there is any instruction in the path from op to
00324    // before op that uses the same dst reg as compare_dest.
00325    // (the path is obtained using GetPrevLink or GetInList()->GetOp)
00326    int          AnyOutputDepsBetween(legoOp *op, legoOp *op_in_multiop, 
00327                                      legoOprd *compare_dest);
00328    
00329    // DoTheMessyStuff: This code allows branches to be scheduled above other 
00330    // operations (or allows ops to move below branches) during scheduling.
00331    // This usually results in copy of ops (depending on liveness out of the 
00332    // branches. Priority lists, liveness, and reaching definitions are updated 
00333    // incrementally.    
00334    //HZ: As it is said by Matt, this function moves the br op upwards. So the input
00335    // op is a br instr. The other input proc_ptr is used for updating the       
00336    // liveness attr.
00337    // This is how it is done:
00338    //   1. Process the case that the op is the exit op of the treegion or the op
00339    //   is either BRU or DUMMY BR. (return RENAMING CONFLICT)
00340    //   2. If the op is either BRCT or BRCF, then there are two exit edges,
00341    //      called first edge and second edge of
00342    //      the op (not the treegion). Processing each instruction that
00343    //      is above the op but not scheduled yet (variable above_op):
00344    //      a. If above_op is brl or store, set the attribute
00345    //         "no_longer_speculative".
00346    //      b. Check the control dep between above_op and op using
00347    //         DPG->AreOpsDependent(above_op, op) (Doubtful point for me,
00348    //        ambiguous in what the function does exactly)
00349    //      c. If above_op has control dep on op, then if the above_op is live on
00350    //         second edge or the above_op is either store/brl, a duplicate of
00351    //         the above op will be created (duplicate the predicate needs more
00352    //         work). Then the duplicate will be placed after the C_MERGE op
00353    //         along the second edge. Also the related DU, UD chain and DDG will 
00354    //         be updated to reflect the correct dep info and the liveness on the
00355    //         second edge need to be fixed by calling FixLiveVarsDown.
00356    //      d. If above_op has control dep on op, then if the above_op is live on
00357    //         first edge or the above_op is either store/brl, the above op      
00358    //         will be moved after the C_MERGE op along the first edge (there is
00359    //         no needs to duplicate the above op as it is processed along the
00360    //         second edge already). Also the related DU, UD chain and DDG will 
00361    //         be updated to reflect the correct dep info and the liveness on the
00362    //         first edge need to be fixed by calling FixLiveVarsDown.
00363    //      e. Processing the dead ops by adding the DPRemoveAttribute and remove
00364    //         the dep with its successors and predecessors.
00365    int          DoTheMessyStuff( legoOp * op, legoRegion * proc_ptr);
00366 
00367    // This routine returns the second, complementary destination for a CMPP op.
00368    // If the second predicate dest is OT_UNDEFINED, one will be created. 
00369    // if the CMPP opcode does not produce a complementary second dest, the 
00370    // opcode will be updated. The second destination oprd is returned.
00371    legoOprd*    GetComplementaryDestOprd( legoOp * cmppop);
00372    
00373    // This routine cleans up ops and adds a dp_remove attr so that they 
00374    // can be remove after procedure is scheduled. Removing them earlier fucks 
00375    // up priority lists and RDefs() 
00376    //HZ: This is the way how to do it:
00377    //    1. RemoveOp and AddOp such that the infor in priority list & RDefs are
00378    //       not disturbed.
00379    //    2. Set the schedule time as zero for the op and add DPRemoveAttribute
00380    //    3. Remove the dep between the op and its successors & predecessors.
00381    void         PrepareToDie( legoOp * op);
00382    
00383    // As a result of control flow changes during the forming of Multi-Way 
00384    // branches, some ops get re-targeted. Need to update the dag to reflect 
00385    // new predecessor ops for control deps in these cases. 
00386    //HZ: This is the way it works: (the op is branch op ??)
00387    //    1.  Find the C_MERGE op preceeding the op and set the inlist of the
00388    //        C_MERGE op to include the new_predecessor_op.
00389    //    2.  Remove old predecessor/successor pair (CONT Dep) between the op and
00390    //        the old_predecessor_op.
00391    //    3.  Add control dep between op & new_predecessor_op.
00392    //    4.  Repeat step 2,3 for the C_MERGE op.        
00393    void         UpdatePredecessorBranch( legoOp * op, legoOp *
00394                              old_predecessor_op, legoOp * new_predecessor_op);
00395 
00396    // Allowing Multi-Way branches to be formed during list scheduling requires
00397    // even MoreMessyStuff. 
00398    // Here I DoMoreMessyStuff.    
00399    //HZ: DoMoreMessy stuff happens when we are trying to schedule the branch op
00400    // (op) speculatively  (i.e., the current_before_op is in a different BB from
00401    //  the BB where the op resides in.) After calling the function
00402    //  DoTheMessyStuff to move its above ops into its descendant BBs, the op and
00403    //  the CMERGE_op are the instructions left in the BB. The function
00404    //  DoMoreMessyStuff moves such a br upwards to its parentBB to form a
00405    //  multiway br. (the resulted empty BB is removed ??)
00406    //  This is the way how to do it:
00407    //    If Final_Pass is not set, return RENAMING_CONFLICT.
00408    //    1.  Find the related pointers, including predecessor_branch_op,
00409    //        original_block, c_merge_op
00410    //    2.  Find the last op in the predecessor_branc_op's multiop, since we
00411    //        will move the op just before this last op.
00412    //    3.  Since we currently can not handle the jump table, check the
00413    //        attributes of the op and predecessor_branch_op. If ATTR_TBLNAME is
00414    //        found, return RENAMING_CONFLICT. (Jump table is a doubtful point
00415    //        for me)
00416    //    4.  If the op is either an DUMMY_BR or an BRU instr:
00417    //         a. Update the inlist of the C_MERGE op following the op so that
00418    //            the predecessor_branch_op is in the inlist. Also adjust the
00419    //            edge from op to its following C_MERGE so that the edge starts  
00420    //            from predecessor_branch_op to the C_MERGE. Delete the edge from
00421    //            the predecessor to the C_MERGE which is just before the op.
00422    //            Update the outlist of the predecessor_branch_op.
00423    //         b. Retarget PBR of predecessor_branch_op to the target of the op
00424    //            if the predecessor is a BRU instr or the op is in the taken
00425    //            path of the predecssor_branch_op. (Doubtful point: what if the
00426    //            op is on the fall-through path of the predecessor_branch_op?)
00427    //         c. PrepareToDie the op and its pbrrop (probably already scheduled)
00428    //    5.  If the op is a RTS instr:
00429    //         a. If the predecessor_branch_op is either an BRU or an DUMMY_BR,
00430    //            replace the predecessor_branch_op with this RTS by:
00431    //            Move the RTS to the last op found in step 2; Remove the control
00432    //            dep of the predecessor and its following C_MERGE and set the
00433    //            predicate of the predecessor_branch_op as the predicate of the
00434    //            RTS; PrepareToDie the predecessor_branch_op & its pbrr and free
00435    //            the resources that scheduled to the predecessor_branch_op (PBRR
00436    //            op takes no resources ?).
00437    //         b. If the predecessor_branch_op is cond br, change the
00438    //            predecessor_branch_op to an BRU instr and move the RTS up.
00439    //            Implementing this involves the following steps:
00440    //              b1. check whether the op is in the taken path of the
00441    //                  predecessor_branch_op
00442    //              b2. create a predicate for the RTS op that will be moved up.
00443    //                  Based on the CMPP op / orig_fall_through attribute of the
00444    //                  predecessor_branch_op, a predicate orpd is constructed.
00445    //              b3. Adjust the UD, DU chains to include the new predicate
00446    //                  oprd.
00447    //              b4. If the op is in the taken path of the
00448    //                  predecessor_branch_op and the predecessor_branch_op is
00449    //                  BRCF, set the predicate value of the RTS as the
00450    //                  complementary of what cmpp set. Also set the predicate
00451    //                  value of the predecessor_branch_op as what cmpp set.
00452    //              b5. If the op is in the taken path of the
00453    //                  predecessor_branch_op and the predecessor_branch_op is
00454    //                  BRCT, set the predicate value of the RTS as what cmpp set
00455    //                  and set the predicate value of the predecessor_branch_op
00456    //                  as the complementary of what cmpp set.
00457    //              b6. Process the other two cases of the RTS is in the fall
00458    //                  through path of the predecessor_branch_op which is either
00459    //                  BRCT or BRCF.
00460    //              b7. move up the RTS op, change the predecessor_branch_op 
00461    //                  (BRCT/BRCF) to BRU and update the the target of the
00462    //                  pbrr to point to the right CB.
00463    //    6.  If the op is a BRCT or BRCF instr:
00464    //         a. If the predecessor_branch_op is a BRU instr, we will retarget
00465    //            this predecessor_branch_op to the op's fall through block and
00466    //            change the the op to a BRU instr. Then mode the op upwards,
00467    //            update the control edges, UD DU chain for the predicates,
00468    //            update the predecessor/successor relationship, etc.
00469    //         b. If the predecessor_branch_op is a BRCT/BRCF instr, we will
00470    //            combine the op and predecessor_branch_op into a BRU and a BRC.
00471    //              b1. If the op is in the taken path of the
00472    //                  predecessor_branch_op, make the op a predicated BRU and
00473    //                  retarget the predecessor_branch_op to the fall-through
00474    //                  path of the op. Also do the related book-keeping
00475    //                  including: creating the new predicate, update the in/out
00476    //                  edges, in/out lists, DU/UD chain, predecessor/successor
00477    //                  dep relationship, change the op to BRU, etc.
00478    //              b2. If the op is in the fall-through path of the
00479    //                  predecessor_branch_op, change the predecessor_branch_op
00480    //                  to a BRU targeting at its orginal taken path. Change the
00481    //                  position of the op and predecessor_branch_op such that
00482    //                  the brc* happens at the end of the multiway branch. (o.w.,
00483    //                  yula may take the fall-thru path of the brc*
00484    //                  incorrectly.)
00485    //    7.  If the original block only has c_merge op left, destroy the
00486    //        cmerge_op and the BB. (actually, it is not deleted here, but the
00487    //        edge info. is updated. The actual removal happened after the
00488    //        procedure is scheduled (in Function ScheduleProc in schedule.C)).
00489    // 
00490    int          DoMoreMessyStuff( legoOp * op, int Final_Pass );
00491 
00492    //HZ: Scan the current region under scheduling. For each br instr, if it is
00493    //    not DUMMY_BR or dp_removed, find the the corresponding PBR and move the
00494    //    PBR just before the br inst. If the need_duplicate attribute is set for
00495    //    the PBR, duplicate the PBR and move the duplicated pbrr just before the
00496    //    br.
00497    void         PlacePBRsJustBeforeBranches(); 
00498    
00499    //HZ: Scan through the current region. Put the br to the end of the BB that
00500    //    it resides in.
00501    void         PlaceBranchesLast();
00502    
00503    //ScheduleOp: indicate that op is scheduled in Cycle
00504    //HZ: Try to schedule the op at Cycle.
00505    //  1. If the current region is BB (i.e., not formed as a treegion), move the op
00506    //     and set the schedule time of the op as Cycle.
00507    //  2. If the current region is a treegion, then deicde whether scheduling the
00508    //     op is speculative or not. Currently, if the code has predicated instr
00509    //     (due to the if-conversion), the speculative scheduling is not
00510    //     supported (i.e., the predicated instr is scheduled using
00511    //     non-speculative way). The speculativeness is determined from the fact
00512    //     whether the op is in the same BB as where current_before_op resides.
00513    //  3. If the scheduling of the op is speculative:
00514    //        a. If the op is st or brl, such a speculative code motion is not
00515    //           allowed. Return RENAMING_CONFLICT.
00516    //        b. check whether a liveness violation may be resulted from the code
00517    //           motion. (doubltful point in prothe last multi_op in the code ?)
00518    //        c. If there is possible liveness violation, renaming of the op is
00519    //           required.
00520    //        d. Set the speculative attr of the op.
00521    //        e. Perform the actual schedule of the op. If the op is a br instr
00522    //           (but not brl), call the function DoTheMessyStuff and
00523    //           DoMoreMessyStuff in sequence. (here the code needs to be
00524    //           updated!!!)
00525    //        f. Set the schedule time of the op. Also if the liveness needs to
00526    //           be re-analyzed, recall the LiveVariables function.
00527    //  4. If the scheduling is non-speculative:
00528    //        if the op is br, call DoTheMessyStuff, move the op and set the
00529    //        schedule time.
00530    
00531    // Input argument update_at_cycle_end is related with the last multiop
00532    // processing in step 3b.
00533    int          ScheduleOp(legoOp * op, int Cycle, knobs * Knobs, legoRegion *
00534                            proc_ptr, int Final_Pass, int Predicated, 
00535                            int update_at_cycle_end);
00536                            
00537    //HZ: This function seems not useful anymore and is replaced with the
00538    // function IsDominatorParallelwithRenameGeneral
00539    int          IsDominatorParallelwithRename(legoOp *op, int readytime, 
00540                                               legoTreegion* treegion,
00541                                               knobs *Knobs, 
00542                                               legoRegion *proc_ptr, 
00543                                               int Final_Pass);
00544    
00545    //HZ: Check whether there exists dominiate parallelism for the op. If so,
00546    // try to remove the op and update the UD/DU chain and deps relationship with
00547    // its duplicated op (i.e., combining the op with its duplicate). 
00548    //  The following steps are involved:
00549    //  1. For br ops (i.e., the op is a br), do not apply dominame parallelism
00550    //  2. Do not allow speculative stores and brls as a result of combining.
00551    //  3. do not apply dominate parallelism to C_MERGE ops.
00552    //  4. Scan through the instrs from current_before_op to its previous op
00553    //     with the same schedule time. For each one of them (op_in_multiop):
00554    //       a. Check if op_in_multiop BB dominates the BB where the op resides.
00555    //       b. Check whether the op is the same as the op_in_multiop by:
00556    //            b1. check the opcode;
00557    //            b2. check src oprds;
00558    //            b3: check pred src oprds;
00559    //            b4. if the op is a brl instr, it needs to make sure that there
00560    //                is no st/macro def bwteen the op and the op_in_multiop.
00561    //       c. If the src checking in step b succeeds, the op_in_multiop's
00562    //          BB dominates the op's BB, and the readytime is before the
00563    //          schedule time of the op_in_multiop, try to merge the op and the
00564    //          op_in_multiop.
00565    //            c1. If their dst reg nums are different:, try to use rename to
00566    //                get the same reg num. The merge involves the update of the
00567    //                UD/DU chain, fix of the liveness. (Predecessor/successor
00568    //                relationship has been processed in renaming process)
00569    //            c2. If they have the same dst reg num, merge the two ops.
00570    //       d. if speculative combining, add 'speculative' attr to op_in_multiop
00571    //          and add 'dp_remove' attr to the op.
00572    //       e. move the op_in_multiop if there is anti dep in the multiop. Also
00573    //          move the op to the op_in_multiop.
00574    //       f. Set the predicate of the op_in_multiop using the non-speculative
00575    //          predicate promotion. (doubtful point for me at this time)
00576    int          IsDominatorParallelwithRenameGeneral(legoOp *op, int readytime, 
00577                                               legoTreegion* treegion,
00578                                               knobs *Knobs, 
00579                                               legoRegion *proc_ptr, 
00580                                               int Final_Pass);
00581                            
00582    //HZ: Doubt ful point: could not find the definition of this function and seems
00583    //not used in the list_scheduler.
00584    int          checkIssue( int );
00585 
00586 
00587 public:
00588 
00589    list_scheduler()     {}
00590    list_scheduler( legoRegion *region, machine *MDES, knobs *Knobs );
00591    ~list_scheduler()    {
00592      if ( CreateSchedVizFiles ) {
00593        fclose (SchedFile); 
00594        fclose (ListFile); 
00595      }
00596    }
00597 
00598    // Set the parameters for the scheduler from the knobs ptr
00599    virtual void SetKnobs( knobs * );
00600 
00601    // ShowParameters - show the values of knobs used in scheduling in
00602    //    formatted output. This can be called from a program to show
00603    //    knobs settings in 'nice' output.
00604    virtual void ShowParameters( knobs * );
00605 
00606    // Returns 1 if dominator parallelism is being used, 0 otherwise
00607    int DominatorParallel()      { return DominatorParallelism; }
00608 
00609    // Schedule: schedule the 'current' region, return a pointer to the first
00610    // Op in the region
00611    //HZ: The following steps are involved:
00612    //  1. Compute the liveness of the region, if necessary
00613    //     (if ReDoLiveVarsNextTreegion is set, doubtfult point: Is there any
00614    //      chance that this variable is set?)
00615    //  2. Process the DEFINE instrs for BB scheduling, treegion scheduling.
00616    //  3. Scheduling the region -scheduling outer loop
00617    //       a. Get the candidate inst using GetCandidateNodeTree for treegion
00618    //          scheduling and GetCandidateNode for BB scheduling.
00619    //       b. Scheduling the instrs at the current_cycle (try to schedule the
00620    //          candidate instr)
00621    //            b1. If DominatorParallelism is allowed, determine if the srcs
00622    //                and dsts are ready, they try function
00623    //                IsDominatorParallelWithRanmeGeneral.
00624    //            b2. If DPScheduleTime == 0 (i.e., no dominator parallelism is
00625    //                found or allowed, check the resource by RU_can_schedule_op
00626    //                If DPScheduleTime != 0, set the mdes_slot = 0 to indicate
00627    //                the op is a pseudo op as a result of the Dominator
00628    //                parallelism scheduling.
00629    //            b3. If there is no problem with the resources, then call the
00630    //                function ScheduleOp to perform the code motion.
00631    //            b4. If there is no conflict (RENAMING CONFLICT) from the
00632    //                function ScheduleOp, do RU_Schedule_Op_at and also do
00633    //                machine->adjustIssueStatus &
00634    //                machine->adjustWriteBackStatus to make the execution       
00635    //                estimation more accurate.
00636    //            b5. Find another Candidate Node and repeat until there is no
00637    //                more available candidates.
00638    //  4. If the aggressive_list_scheduling is set, scan one more time (i.e.,
00639    //     go back to step 3b one more time) without increase current_cycle.
00640    //     Increase the current_cycle and go back to step 3.
00641    virtual legoOp *Schedule( int *UsefulInstrsScheduled, int *scheduleLength,
00642                              knobs *Knobs, int Final_Pass, int Predicated );
00643 };
00644 
00645 #endif

Generated on Mon Jul 21 20:27:49 2003 for TINKER LEGO DOC by doxygen 1.3.2