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
1.3.2