blob: efc203bcc6355fc460e710eaa9367e9d34ca91c8 [file] [log] [blame]
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001//===-- ModuloScheduling.cpp - ModuloScheduling ----------------*- C++ -*-===//
2//
John Criswell482202a2003-10-20 19:43:21 +00003// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00007//
John Criswell482202a2003-10-20 19:43:21 +00008//===----------------------------------------------------------------------===//
Misha Brukmanb4402432005-04-21 23:30:14 +00009//
10// This ModuloScheduling pass is based on the Swing Modulo Scheduling
11// algorithm.
12//
Guochun Shi45d8f322003-03-27 17:57:44 +000013//===----------------------------------------------------------------------===//
14
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +000015#define DEBUG_TYPE "ModuloSched"
16
17#include "ModuloScheduling.h"
Tanya Lattner13417b52005-03-23 01:47:20 +000018#include "llvm/Constants.h"
Tanya Lattner081fbd12004-07-30 23:36:10 +000019#include "llvm/Instructions.h"
20#include "llvm/Function.h"
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +000021#include "llvm/CodeGen/MachineFunction.h"
22#include "llvm/CodeGen/Passes.h"
23#include "llvm/Support/CFG.h"
24#include "llvm/Target/TargetSchedInfo.h"
Reid Spencer7c16caa2004-09-01 22:55:40 +000025#include "llvm/Support/Debug.h"
26#include "llvm/Support/GraphWriter.h"
Tanya Lattner56807c62005-02-10 17:02:58 +000027#include "llvm/ADT/SCCIterator.h"
Reid Spencer7c16caa2004-09-01 22:55:40 +000028#include "llvm/ADT/StringExtras.h"
Tanya Lattnerab9cf272004-11-22 20:41:24 +000029#include "llvm/ADT/Statistic.h"
Tanya Lattner56807c62005-02-10 17:02:58 +000030#include "llvm/Support/Timer.h"
Misha Brukman84817852004-08-02 13:59:10 +000031#include <cmath>
Alkis Evlogimenos20f1b0b2004-09-28 14:42:44 +000032#include <algorithm>
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +000033#include <fstream>
34#include <sstream>
Misha Brukman84817852004-08-02 13:59:10 +000035#include <utility>
36#include <vector>
Misha Brukman9da1134b2004-10-10 23:34:50 +000037#include "../MachineCodeForInstruction.h"
38#include "../SparcV9TmpInstr.h"
39#include "../SparcV9Internals.h"
40#include "../SparcV9RegisterInfo.h"
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +000041using namespace llvm;
42
43/// Create ModuloSchedulingPass
44///
45FunctionPass *llvm::createModuloSchedulingPass(TargetMachine & targ) {
46 DEBUG(std::cerr << "Created ModuloSchedulingPass\n");
Misha Brukmanb4402432005-04-21 23:30:14 +000047 return new ModuloSchedulingPass(targ);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +000048}
49
Tanya Lattner081fbd12004-07-30 23:36:10 +000050
51//Graph Traits for printing out the dependence graph
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +000052template<typename GraphType>
53static void WriteGraphToFile(std::ostream &O, const std::string &GraphName,
54 const GraphType &GT) {
55 std::string Filename = GraphName + ".dot";
56 O << "Writing '" << Filename << "'...";
57 std::ofstream F(Filename.c_str());
Misha Brukmanb4402432005-04-21 23:30:14 +000058
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +000059 if (F.good())
60 WriteGraph(F, GT);
61 else
62 O << " error opening file for writing!";
63 O << "\n";
64};
Guochun Shi45d8f322003-03-27 17:57:44 +000065
Tanya Lattner56807c62005-02-10 17:02:58 +000066
67#if 1
68#define TIME_REGION(VARNAME, DESC) \
69 NamedRegionTimer VARNAME(DESC)
70#else
71#define TIME_REGION(VARNAME, DESC)
72#endif
73
74
Tanya Lattner081fbd12004-07-30 23:36:10 +000075//Graph Traits for printing out the dependence graph
Brian Gaeke960707c2003-11-11 22:41:34 +000076namespace llvm {
Tanya Lattner42ed1482005-04-22 06:32:48 +000077
78 //Loop statistics
Tanya Lattnerab9cf272004-11-22 20:41:24 +000079 Statistic<> ValidLoops("modulosched-validLoops", "Number of candidate loops modulo-scheduled");
Tanya Lattner42ed1482005-04-22 06:32:48 +000080 Statistic<> JumboBB("modulosched-jumboBB", "Basic Blocks with more then 100 instructions");
81 Statistic<> LoopsWithCalls("modulosched-loopCalls", "Loops with calls");
82 Statistic<> LoopsWithCondMov("modulosched-loopCondMov", "Loops with conditional moves");
83 Statistic<> InvalidLoops("modulosched-invalidLoops", "Loops with unknown trip counts or loop invariant trip counts");
Tanya Lattner56807c62005-02-10 17:02:58 +000084 Statistic<> SingleBBLoops("modulosched-singeBBLoops", "Number of single basic block loops");
Tanya Lattner42ed1482005-04-22 06:32:48 +000085
86 //Scheduling Statistics
87 Statistic<> MSLoops("modulosched-schedLoops", "Number of loops successfully modulo-scheduled");
Tanya Lattnerc28fd0d2005-02-16 04:00:59 +000088 Statistic<> NoSched("modulosched-noSched", "No schedule");
89 Statistic<> SameStage("modulosched-sameStage", "Max stage is 0");
Tanya Lattner42ed1482005-04-22 06:32:48 +000090 Statistic<> ResourceConstraint("modulosched-resourceConstraint", "Loops constrained by resources");
91 Statistic<> RecurrenceConstraint("modulosched-recurrenceConstraint", "Loops constrained by recurrences");
92 Statistic<> FinalIISum("modulosched-finalIISum", "Sum of all final II");
93 Statistic<> IISum("modulosched-IISum", "Sum of all theoretical II");
Brian Gaeke960707c2003-11-11 22:41:34 +000094
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +000095 template<>
96 struct DOTGraphTraits<MSchedGraph*> : public DefaultDOTGraphTraits {
97 static std::string getGraphName(MSchedGraph *F) {
98 return "Dependence Graph";
99 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000100
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000101 static std::string getNodeLabel(MSchedGraphNode *Node, MSchedGraph *Graph) {
102 if (Node->getInst()) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000103 std::stringstream ss;
104 ss << *(Node->getInst());
105 return ss.str(); //((MachineInstr*)Node->getInst());
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000106 }
107 else
Jeff Cohen33a030e2005-07-27 05:53:44 +0000108 return "No Inst";
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000109 }
110 static std::string getEdgeSourceLabel(MSchedGraphNode *Node,
Jeff Cohen33a030e2005-07-27 05:53:44 +0000111 MSchedGraphNode::succ_iterator I) {
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000112 //Label each edge with the type of dependence
113 std::string edgelabel = "";
114 switch (I.getEdge().getDepOrderType()) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000115
Misha Brukmanb4402432005-04-21 23:30:14 +0000116 case MSchedGraphEdge::TrueDep:
Jeff Cohen33a030e2005-07-27 05:53:44 +0000117 edgelabel = "True";
118 break;
Misha Brukmanb4402432005-04-21 23:30:14 +0000119
120 case MSchedGraphEdge::AntiDep:
Jeff Cohen33a030e2005-07-27 05:53:44 +0000121 edgelabel = "Anti";
122 break;
123
Misha Brukmanb4402432005-04-21 23:30:14 +0000124 case MSchedGraphEdge::OutputDep:
Jeff Cohen33a030e2005-07-27 05:53:44 +0000125 edgelabel = "Output";
126 break;
127
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000128 default:
Jeff Cohen33a030e2005-07-27 05:53:44 +0000129 edgelabel = "Unknown";
130 break;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000131 }
Tanya Lattnera6820d62004-05-08 16:12:10 +0000132
133 //FIXME
134 int iteDiff = I.getEdge().getIteDiff();
135 std::string intStr = "(IteDiff: ";
136 intStr += itostr(iteDiff);
137
138 intStr += ")";
139 edgelabel += intStr;
140
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000141 return edgelabel;
Tanya Lattnera6820d62004-05-08 16:12:10 +0000142 }
Guochun Shi45d8f322003-03-27 17:57:44 +0000143 };
Guochun Shi45d8f322003-03-27 17:57:44 +0000144}
Tanya Lattner7efb18f2003-08-28 17:12:14 +0000145
Tanya Lattner13417b52005-03-23 01:47:20 +0000146
147#include <unistd.h>
148
Misha Brukman80f283b2003-10-10 17:41:32 +0000149/// ModuloScheduling::runOnFunction - main transformation entry point
Tanya Lattner081fbd12004-07-30 23:36:10 +0000150/// The Swing Modulo Schedule algorithm has three basic steps:
151/// 1) Computation and Analysis of the dependence graph
152/// 2) Ordering of the nodes
153/// 3) Scheduling
Misha Brukmanb4402432005-04-21 23:30:14 +0000154///
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000155bool ModuloSchedulingPass::runOnFunction(Function &F) {
Tanya Lattner42ed1482005-04-22 06:32:48 +0000156 alarm(100);
Tanya Lattner13417b52005-03-23 01:47:20 +0000157
Tanya Lattner7efb18f2003-08-28 17:12:14 +0000158 bool Changed = false;
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000159 int numMS = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +0000160
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +0000161 DEBUG(std::cerr << "Creating ModuloSchedGraph for each valid BasicBlock in " + F.getName() + "\n");
Misha Brukmanb4402432005-04-21 23:30:14 +0000162
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000163 //Get MachineFunction
164 MachineFunction &MF = MachineFunction::get(&F);
Misha Brukmanb4402432005-04-21 23:30:14 +0000165
Tanya Lattner91964492005-03-29 20:35:10 +0000166 DependenceAnalyzer &DA = getAnalysis<DependenceAnalyzer>();
Misha Brukmanb4402432005-04-21 23:30:14 +0000167
Tanya Lattner13417b52005-03-23 01:47:20 +0000168
Tanya Lattner081fbd12004-07-30 23:36:10 +0000169 //Worklist
170 std::vector<MachineBasicBlock*> Worklist;
Misha Brukmanb4402432005-04-21 23:30:14 +0000171
Tanya Lattner081fbd12004-07-30 23:36:10 +0000172 //Iterate over BasicBlocks and put them into our worklist if they are valid
173 for (MachineFunction::iterator BI = MF.begin(); BI != MF.end(); ++BI)
Tanya Lattner42ed1482005-04-22 06:32:48 +0000174 if(MachineBBisValid(BI)) {
175 if(BI->size() < 100) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000176 Worklist.push_back(&*BI);
177 ++ValidLoops;
Tanya Lattner42ed1482005-04-22 06:32:48 +0000178 }
179 else
Jeff Cohen33a030e2005-07-27 05:53:44 +0000180 ++JumboBB;
Tanya Lattner8bf63742005-06-17 04:00:57 +0000181
Tanya Lattnerab9cf272004-11-22 20:41:24 +0000182 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000183
Tanya Lattner444be612004-11-02 21:04:56 +0000184 defaultInst = 0;
185
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +0000186 DEBUG(if(Worklist.size() == 0) std::cerr << "No single basic block loops in function to ModuloSchedule\n");
Tanya Lattnera6820d62004-05-08 16:12:10 +0000187
Tanya Lattner081fbd12004-07-30 23:36:10 +0000188 //Iterate over the worklist and perform scheduling
Misha Brukmanb4402432005-04-21 23:30:14 +0000189 for(std::vector<MachineBasicBlock*>::iterator BI = Worklist.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +0000190 BE = Worklist.end(); BI != BE; ++BI) {
Tanya Lattner56807c62005-02-10 17:02:58 +0000191
192 //Print out BB for debugging
Tanya Lattner42ed1482005-04-22 06:32:48 +0000193 DEBUG(std::cerr << "BB Size: " << (*BI)->size() << "\n");
Tanya Lattner56807c62005-02-10 17:02:58 +0000194 DEBUG(std::cerr << "ModuloScheduling BB: \n"; (*BI)->print(std::cerr));
195
Tanya Lattner13417b52005-03-23 01:47:20 +0000196 //Print out LLVM BB
197 DEBUG(std::cerr << "ModuloScheduling LLVMBB: \n"; (*BI)->getBasicBlock()->print(std::cerr));
198
Tanya Lattner56807c62005-02-10 17:02:58 +0000199 //Catch the odd case where we only have TmpInstructions and no real Value*s
200 if(!CreateDefMap(*BI)) {
201 //Clear out our maps for the next basic block that is processed
202 nodeToAttributesMap.clear();
203 partialOrder.clear();
204 recurrenceList.clear();
205 FinalNodeOrder.clear();
206 schedule.clear();
207 defMap.clear();
208 continue;
209 }
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000210
Tanya Lattner8d64e9a2005-04-05 16:36:44 +0000211 MSchedGraph *MSG = new MSchedGraph(*BI, target, indVarInstrs[*BI], DA, machineTollvm[*BI]);
Misha Brukmanb4402432005-04-21 23:30:14 +0000212
Tanya Lattner081fbd12004-07-30 23:36:10 +0000213 //Write Graph out to file
214 DEBUG(WriteGraphToFile(std::cerr, F.getName(), MSG));
Tanya Lattner42ed1482005-04-22 06:32:48 +0000215 DEBUG(MSG->print(std::cerr));
Misha Brukmanb4402432005-04-21 23:30:14 +0000216
Tanya Lattner081fbd12004-07-30 23:36:10 +0000217 //Calculate Resource II
218 int ResMII = calculateResMII(*BI);
Misha Brukmanb4402432005-04-21 23:30:14 +0000219
Tanya Lattner081fbd12004-07-30 23:36:10 +0000220 //Calculate Recurrence II
221 int RecMII = calculateRecMII(MSG, ResMII);
Tanya Lattner56807c62005-02-10 17:02:58 +0000222
223 DEBUG(std::cerr << "Number of reccurrences found: " << recurrenceList.size() << "\n");
Misha Brukmanb4402432005-04-21 23:30:14 +0000224
Tanya Lattner081fbd12004-07-30 23:36:10 +0000225 //Our starting initiation interval is the maximum of RecMII and ResMII
Tanya Lattner42ed1482005-04-22 06:32:48 +0000226 if(RecMII < ResMII)
227 ++RecurrenceConstraint;
228 else
229 ++ResourceConstraint;
230
Tanya Lattner56807c62005-02-10 17:02:58 +0000231 II = std::max(RecMII, ResMII);
Tanya Lattner42ed1482005-04-22 06:32:48 +0000232 int mII = II;
Misha Brukmanb4402432005-04-21 23:30:14 +0000233
Tanya Lattner081fbd12004-07-30 23:36:10 +0000234 //Print out II, RecMII, and ResMII
Tanya Lattnerddebd1e2004-10-30 00:39:07 +0000235 DEBUG(std::cerr << "II starts out as " << II << " ( RecMII=" << RecMII << " and ResMII=" << ResMII << ")\n");
Misha Brukmanb4402432005-04-21 23:30:14 +0000236
Tanya Lattnerddebd1e2004-10-30 00:39:07 +0000237 //Dump node properties if in debug mode
Misha Brukmanb4402432005-04-21 23:30:14 +0000238 DEBUG(for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +0000239 E = nodeToAttributesMap.end(); I !=E; ++I) {
240 std::cerr << "Node: " << *(I->first) << " ASAP: " << I->second.ASAP << " ALAP: "
241 << I->second.ALAP << " MOB: " << I->second.MOB << " Depth: " << I->second.depth
242 << " Height: " << I->second.height << "\n";
243 });
Tanya Lattnerddebd1e2004-10-30 00:39:07 +0000244
Tanya Lattner081fbd12004-07-30 23:36:10 +0000245 //Calculate Node Properties
246 calculateNodeAttributes(MSG, ResMII);
Misha Brukmanb4402432005-04-21 23:30:14 +0000247
Tanya Lattner081fbd12004-07-30 23:36:10 +0000248 //Dump node properties if in debug mode
Misha Brukmanb4402432005-04-21 23:30:14 +0000249 DEBUG(for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +0000250 E = nodeToAttributesMap.end(); I !=E; ++I) {
251 std::cerr << "Node: " << *(I->first) << " ASAP: " << I->second.ASAP << " ALAP: "
252 << I->second.ALAP << " MOB: " << I->second.MOB << " Depth: " << I->second.depth
253 << " Height: " << I->second.height << "\n";
254 });
Misha Brukmanb4402432005-04-21 23:30:14 +0000255
Tanya Lattner081fbd12004-07-30 23:36:10 +0000256 //Put nodes in order to schedule them
257 computePartialOrder();
Misha Brukmanb4402432005-04-21 23:30:14 +0000258
Tanya Lattner081fbd12004-07-30 23:36:10 +0000259 //Dump out partial order
Misha Brukmanb4402432005-04-21 23:30:14 +0000260 DEBUG(for(std::vector<std::set<MSchedGraphNode*> >::iterator I = partialOrder.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +0000261 E = partialOrder.end(); I !=E; ++I) {
262 std::cerr << "Start set in PO\n";
263 for(std::set<MSchedGraphNode*>::iterator J = I->begin(), JE = I->end(); J != JE; ++J)
264 std::cerr << "PO:" << **J << "\n";
265 });
Misha Brukmanb4402432005-04-21 23:30:14 +0000266
Tanya Lattner081fbd12004-07-30 23:36:10 +0000267 //Place nodes in final order
268 orderNodes();
Misha Brukmanb4402432005-04-21 23:30:14 +0000269
Tanya Lattner081fbd12004-07-30 23:36:10 +0000270 //Dump out order of nodes
271 DEBUG(for(std::vector<MSchedGraphNode*>::iterator I = FinalNodeOrder.begin(), E = FinalNodeOrder.end(); I != E; ++I) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000272 std::cerr << "FO:" << **I << "\n";
273 });
Misha Brukmanb4402432005-04-21 23:30:14 +0000274
Tanya Lattner081fbd12004-07-30 23:36:10 +0000275 //Finally schedule nodes
Tanya Lattner42ed1482005-04-22 06:32:48 +0000276 bool haveSched = computeSchedule(*BI, MSG);
Misha Brukmanb4402432005-04-21 23:30:14 +0000277
Tanya Lattner081fbd12004-07-30 23:36:10 +0000278 //Print out final schedule
279 DEBUG(schedule.print(std::cerr));
Misha Brukmanb4402432005-04-21 23:30:14 +0000280
Tanya Lattnerddebd1e2004-10-30 00:39:07 +0000281 //Final scheduling step is to reconstruct the loop only if we actual have
282 //stage > 0
Tanya Lattner8d64e9a2005-04-05 16:36:44 +0000283 if(haveSched) {
Tanya Lattnerddebd1e2004-10-30 00:39:07 +0000284 reconstructLoop(*BI);
Tanya Lattnerab9cf272004-11-22 20:41:24 +0000285 ++MSLoops;
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000286 Changed = true;
Tanya Lattner8bf63742005-06-17 04:00:57 +0000287 FinalIISum += II;
288 IISum += mII;
Tanya Lattner8d64e9a2005-04-05 16:36:44 +0000289
290 if(schedule.getMaxStage() == 0)
Jeff Cohen33a030e2005-07-27 05:53:44 +0000291 ++SameStage;
Tanya Lattnerc28fd0d2005-02-16 04:00:59 +0000292 }
Tanya Lattner8bf63742005-06-17 04:00:57 +0000293 else {
Tanya Lattner8d64e9a2005-04-05 16:36:44 +0000294 ++NoSched;
Tanya Lattner8bf63742005-06-17 04:00:57 +0000295 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000296
Tanya Lattner081fbd12004-07-30 23:36:10 +0000297 //Clear out our maps for the next basic block that is processed
298 nodeToAttributesMap.clear();
299 partialOrder.clear();
300 recurrenceList.clear();
301 FinalNodeOrder.clear();
302 schedule.clear();
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000303 defMap.clear();
Tanya Lattner081fbd12004-07-30 23:36:10 +0000304 //Clean up. Nuke old MachineBB and llvmBB
305 //BasicBlock *llvmBB = (BasicBlock*) (*BI)->getBasicBlock();
306 //Function *parent = (Function*) llvmBB->getParent();
307 //Should't std::find work??
308 //parent->getBasicBlockList().erase(std::find(parent->getBasicBlockList().begin(), parent->getBasicBlockList().end(), *llvmBB));
309 //parent->getBasicBlockList().erase(llvmBB);
Misha Brukmanb4402432005-04-21 23:30:14 +0000310
Tanya Lattner081fbd12004-07-30 23:36:10 +0000311 //delete(llvmBB);
312 //delete(*BI);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000313 }
Tanya Lattner13417b52005-03-23 01:47:20 +0000314
Misha Brukmanb4402432005-04-21 23:30:14 +0000315 alarm(0);
Tanya Lattner7efb18f2003-08-28 17:12:14 +0000316 return Changed;
317}
Brian Gaeke960707c2003-11-11 22:41:34 +0000318
Tanya Lattner56807c62005-02-10 17:02:58 +0000319bool ModuloSchedulingPass::CreateDefMap(MachineBasicBlock *BI) {
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000320 defaultInst = 0;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000321
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000322 for(MachineBasicBlock::iterator I = BI->begin(), E = BI->end(); I != E; ++I) {
323 for(unsigned opNum = 0; opNum < I->getNumOperands(); ++opNum) {
324 const MachineOperand &mOp = I->getOperand(opNum);
325 if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000326 //assert if this is the second def we have seen
327 //DEBUG(std::cerr << "Putting " << *(mOp.getVRegValue()) << " into map\n");
328 //assert(!defMap.count(mOp.getVRegValue()) && "Def already in the map");
329 if(defMap.count(mOp.getVRegValue()))
330 return false;
Tanya Lattnerab9cf272004-11-22 20:41:24 +0000331
Jeff Cohen33a030e2005-07-27 05:53:44 +0000332 defMap[mOp.getVRegValue()] = &*I;
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000333 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000334
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000335 //See if we can use this Value* as our defaultInst
336 if(!defaultInst && mOp.getType() == MachineOperand::MO_VirtualRegister) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000337 Value *V = mOp.getVRegValue();
338 if(!isa<TmpInstruction>(V) && !isa<Argument>(V) && !isa<Constant>(V) && !isa<PHINode>(V))
339 defaultInst = (Instruction*) V;
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000340 }
341 }
342 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000343
Tanya Lattner56807c62005-02-10 17:02:58 +0000344 if(!defaultInst)
345 return false;
Misha Brukmanb4402432005-04-21 23:30:14 +0000346
Tanya Lattner56807c62005-02-10 17:02:58 +0000347 return true;
Misha Brukmanb4402432005-04-21 23:30:14 +0000348
Tanya Lattner7beb51c2004-11-16 21:31:37 +0000349}
Tanya Lattner081fbd12004-07-30 23:36:10 +0000350/// This function checks if a Machine Basic Block is valid for modulo
351/// scheduling. This means that it has no control flow (if/else or
352/// calls) in the block. Currently ModuloScheduling only works on
353/// single basic block loops.
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000354bool ModuloSchedulingPass::MachineBBisValid(const MachineBasicBlock *BI) {
355
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000356 bool isLoop = false;
Misha Brukmanb4402432005-04-21 23:30:14 +0000357
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000358 //Check first if its a valid loop
Misha Brukmanb4402432005-04-21 23:30:14 +0000359 for(succ_const_iterator I = succ_begin(BI->getBasicBlock()),
Jeff Cohen33a030e2005-07-27 05:53:44 +0000360 E = succ_end(BI->getBasicBlock()); I != E; ++I) {
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000361 if (*I == BI->getBasicBlock()) // has single block loop
362 isLoop = true;
363 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000364
Tanya Lattner081fbd12004-07-30 23:36:10 +0000365 if(!isLoop)
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000366 return false;
Tanya Lattner201e9722004-12-02 07:22:15 +0000367
368 //Check that we have a conditional branch (avoiding MS infinite loops)
369 if(BranchInst *b = dyn_cast<BranchInst>(((BasicBlock*) BI->getBasicBlock())->getTerminator()))
370 if(b->isUnconditional())
371 return false;
372
Tanya Lattnerab9cf272004-11-22 20:41:24 +0000373 //Check size of our basic block.. make sure we have more then just the terminator in it
374 if(BI->getBasicBlock()->size() == 1)
375 return false;
376
Tanya Lattner56807c62005-02-10 17:02:58 +0000377 //Increase number of single basic block loops for stats
378 ++SingleBBLoops;
379
Tanya Lattner081fbd12004-07-30 23:36:10 +0000380 //Get Target machine instruction info
381 const TargetInstrInfo *TMI = target.getInstrInfo();
Misha Brukmanb4402432005-04-21 23:30:14 +0000382
Tanya Lattner13417b52005-03-23 01:47:20 +0000383 //Check each instruction and look for calls, keep map to get index later
384 std::map<const MachineInstr*, unsigned> indexMap;
385
386 unsigned count = 0;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000387 for(MachineBasicBlock::const_iterator I = BI->begin(), E = BI->end(); I != E; ++I) {
Tanya Lattner081fbd12004-07-30 23:36:10 +0000388 //Get opcode to check instruction type
389 MachineOpCode OC = I->getOpcode();
Misha Brukmanb4402432005-04-21 23:30:14 +0000390
Tanya Lattner91964492005-03-29 20:35:10 +0000391 //Look for calls
Tanya Lattner42ed1482005-04-22 06:32:48 +0000392 if(TMI->isCall(OC)) {
393 ++LoopsWithCalls;
Tanya Lattner081fbd12004-07-30 23:36:10 +0000394 return false;
Tanya Lattner42ed1482005-04-22 06:32:48 +0000395 }
396
Tanya Lattner56807c62005-02-10 17:02:58 +0000397 //Look for conditional move
Misha Brukmanb4402432005-04-21 23:30:14 +0000398 if(OC == V9::MOVRZr || OC == V9::MOVRZi || OC == V9::MOVRLEZr || OC == V9::MOVRLEZi
Tanya Lattner56807c62005-02-10 17:02:58 +0000399 || OC == V9::MOVRLZr || OC == V9::MOVRLZi || OC == V9::MOVRNZr || OC == V9::MOVRNZi
Misha Brukmanb4402432005-04-21 23:30:14 +0000400 || OC == V9::MOVRGZr || OC == V9::MOVRGZi || OC == V9::MOVRGEZr
Tanya Lattner56807c62005-02-10 17:02:58 +0000401 || OC == V9::MOVRGEZi || OC == V9::MOVLEr || OC == V9::MOVLEi || OC == V9::MOVLEUr
402 || OC == V9::MOVLEUi || OC == V9::MOVFLEr || OC == V9::MOVFLEi
403 || OC == V9::MOVNEr || OC == V9::MOVNEi || OC == V9::MOVNEGr || OC == V9::MOVNEGi
Tanya Lattner8bf63742005-06-17 04:00:57 +0000404 || OC == V9::MOVFNEr || OC == V9::MOVFNEi || OC == V9::MOVGr || OC == V9::MOVGi) {
Tanya Lattner42ed1482005-04-22 06:32:48 +0000405 ++LoopsWithCondMov;
Tanya Lattner56807c62005-02-10 17:02:58 +0000406 return false;
Tanya Lattner42ed1482005-04-22 06:32:48 +0000407 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000408
Tanya Lattner13417b52005-03-23 01:47:20 +0000409 indexMap[I] = count;
410
411 if(TMI->isNop(OC))
412 continue;
413
414 ++count;
Tanya Lattner081fbd12004-07-30 23:36:10 +0000415 }
Tanya Lattner13417b52005-03-23 01:47:20 +0000416
417 //Apply a simple pattern match to make sure this loop can be modulo scheduled
418 //This means only loops with a branch associated to the iteration count
419
420 //Get the branch
421 BranchInst *b = dyn_cast<BranchInst>(((BasicBlock*) BI->getBasicBlock())->getTerminator());
422
423 //Get the condition for the branch (we already checked if it was conditional)
424 Value *cond = b->getCondition();
425
426 DEBUG(std::cerr << "Condition: " << *cond << "\n");
427
428 //List of instructions associated with induction variable
429 std::set<Instruction*> indVar;
430 std::vector<Instruction*> stack;
431
432 BasicBlock *BB = (BasicBlock*) BI->getBasicBlock();
433
434 //Add branch
435 indVar.insert(b);
436
437 if(Instruction *I = dyn_cast<Instruction>(cond))
438 if(I->getParent() == BB) {
Tanya Lattner42ed1482005-04-22 06:32:48 +0000439 if (!assocIndVar(I, indVar, stack, BB)) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000440 ++InvalidLoops;
441 return false;
Tanya Lattner42ed1482005-04-22 06:32:48 +0000442 }
Tanya Lattner13417b52005-03-23 01:47:20 +0000443 }
Tanya Lattner42ed1482005-04-22 06:32:48 +0000444 else {
445 ++InvalidLoops;
Tanya Lattner13417b52005-03-23 01:47:20 +0000446 return false;
Tanya Lattner42ed1482005-04-22 06:32:48 +0000447 }
448 else {
449 ++InvalidLoops;
Tanya Lattner13417b52005-03-23 01:47:20 +0000450 return false;
Tanya Lattner42ed1482005-04-22 06:32:48 +0000451 }
Tanya Lattner13417b52005-03-23 01:47:20 +0000452 //The indVar set must be >= 3 instructions for this loop to match (FIX ME!)
453 if(indVar.size() < 3 )
454 return false;
455
456 //Dump out instructions associate with indvar for debug reasons
457 DEBUG(for(std::set<Instruction*>::iterator N = indVar.begin(), NE = indVar.end(); N != NE; ++N) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000458 std::cerr << **N << "\n";
459 });
Tanya Lattner13417b52005-03-23 01:47:20 +0000460
Tanya Lattner91964492005-03-29 20:35:10 +0000461 //Create map of machine instr to llvm instr
462 std::map<MachineInstr*, Instruction*> mllvm;
463 for(BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
464 MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(I);
465 for (unsigned j = 0; j < tempMvec.size(); j++) {
466 mllvm[tempMvec[j]] = I;
467 }
468 }
469
Tanya Lattner13417b52005-03-23 01:47:20 +0000470 //Convert list of LLVM Instructions to list of Machine instructions
471 std::map<const MachineInstr*, unsigned> mIndVar;
472 for(std::set<Instruction*>::iterator N = indVar.begin(), NE = indVar.end(); N != NE; ++N) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000473
Tanya Lattner8d64e9a2005-04-05 16:36:44 +0000474 //If we have a load, we can't handle this loop because there is no way to preserve dependences
475 //between loads and stores
476 if(isa<LoadInst>(*N))
477 return false;
478
Tanya Lattner13417b52005-03-23 01:47:20 +0000479 MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(*N);
480 for (unsigned j = 0; j < tempMvec.size(); j++) {
481 MachineOpCode OC = (tempMvec[j])->getOpcode();
482 if(TMI->isNop(OC))
Jeff Cohen33a030e2005-07-27 05:53:44 +0000483 continue;
Tanya Lattner13417b52005-03-23 01:47:20 +0000484 if(!indexMap.count(tempMvec[j]))
Jeff Cohen33a030e2005-07-27 05:53:44 +0000485 continue;
Tanya Lattner13417b52005-03-23 01:47:20 +0000486 mIndVar[(MachineInstr*) tempMvec[j]] = indexMap[(MachineInstr*) tempMvec[j]];
487 DEBUG(std::cerr << *(tempMvec[j]) << " at index " << indexMap[(MachineInstr*) tempMvec[j]] << "\n");
488 }
489 }
490
Tanya Lattner8d64e9a2005-04-05 16:36:44 +0000491 //Must have some guts to the loop body (more then 1 instr, dont count nops in size)
492 if(mIndVar.size() >= (BI->size()-3))
Tanya Lattner13417b52005-03-23 01:47:20 +0000493 return false;
494
495 //Put into a map for future access
496 indVarInstrs[BI] = mIndVar;
Tanya Lattner91964492005-03-29 20:35:10 +0000497 machineTollvm[BI] = mllvm;
Tanya Lattner13417b52005-03-23 01:47:20 +0000498 return true;
499}
500
Misha Brukmanb4402432005-04-21 23:30:14 +0000501bool ModuloSchedulingPass::assocIndVar(Instruction *I, std::set<Instruction*> &indVar,
Jeff Cohen33a030e2005-07-27 05:53:44 +0000502 std::vector<Instruction*> &stack, BasicBlock *BB) {
Tanya Lattner13417b52005-03-23 01:47:20 +0000503
504 stack.push_back(I);
505
506 //If this is a phi node, check if its the canonical indvar
507 if(PHINode *PN = dyn_cast<PHINode>(I)) {
508 if (Instruction *Inc =
509 dyn_cast<Instruction>(PN->getIncomingValueForBlock(BB)))
510 if (Inc->getOpcode() == Instruction::Add && Inc->getOperand(0) == PN)
511 if (ConstantInt *CI = dyn_cast<ConstantInt>(Inc->getOperand(1)))
512 if (CI->equalsInt(1)) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000513 //We have found the indvar, so add the stack, and inc instruction to the set
514 indVar.insert(stack.begin(), stack.end());
515 indVar.insert(Inc);
516 stack.pop_back();
517 return true;
518 }
Tanya Lattner13417b52005-03-23 01:47:20 +0000519 return false;
520 }
521 else {
522 //Loop over each of the instructions operands, check if they are an instruction and in this BB
523 for(unsigned i = 0; i < I->getNumOperands(); ++i) {
524 if(Instruction *N = dyn_cast<Instruction>(I->getOperand(i))) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000525 if(N->getParent() == BB)
526 if(!assocIndVar(N, indVar, stack, BB))
527 return false;
Tanya Lattner13417b52005-03-23 01:47:20 +0000528 }
529 }
530 }
531
532 stack.pop_back();
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000533 return true;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000534}
535
536//ResMII is calculated by determining the usage count for each resource
537//and using the maximum.
538//FIXME: In future there should be a way to get alternative resources
539//for each instruction
540int ModuloSchedulingPass::calculateResMII(const MachineBasicBlock *BI) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000541
Tanya Lattner56807c62005-02-10 17:02:58 +0000542 TIME_REGION(X, "calculateResMII");
543
Tanya Lattner081fbd12004-07-30 23:36:10 +0000544 const TargetInstrInfo *mii = target.getInstrInfo();
545 const TargetSchedInfo *msi = target.getSchedInfo();
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000546
547 int ResMII = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +0000548
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000549 //Map to keep track of usage count of each resource
550 std::map<unsigned, unsigned> resourceUsageCount;
551
552 for(MachineBasicBlock::const_iterator I = BI->begin(), E = BI->end(); I != E; ++I) {
553
554 //Get resource usage for this instruction
Tanya Lattner081fbd12004-07-30 23:36:10 +0000555 InstrRUsage rUsage = msi->getInstrRUsage(I->getOpcode());
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000556 std::vector<std::vector<resourceId_t> > resources = rUsage.resourcesByCycle;
557
558 //Loop over resources in each cycle and increments their usage count
559 for(unsigned i=0; i < resources.size(); ++i)
560 for(unsigned j=0; j < resources[i].size(); ++j) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000561 if(!resourceUsageCount.count(resources[i][j])) {
562 resourceUsageCount[resources[i][j]] = 1;
563 }
564 else {
565 resourceUsageCount[resources[i][j]] = resourceUsageCount[resources[i][j]] + 1;
566 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000567 }
568 }
569
570 //Find maximum usage count
Misha Brukmanb4402432005-04-21 23:30:14 +0000571
Tanya Lattnera6820d62004-05-08 16:12:10 +0000572 //Get max number of instructions that can be issued at once. (FIXME)
Tanya Lattner081fbd12004-07-30 23:36:10 +0000573 int issueSlots = msi->maxNumIssueTotal;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000574
575 for(std::map<unsigned,unsigned>::iterator RB = resourceUsageCount.begin(), RE = resourceUsageCount.end(); RB != RE; ++RB) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000576
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000577 //Get the total number of the resources in our cpu
Tanya Lattnera066df62004-05-26 06:27:18 +0000578 int resourceNum = CPUResource::getCPUResource(RB->first)->maxNumUsers;
Misha Brukmanb4402432005-04-21 23:30:14 +0000579
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000580 //Get total usage count for this resources
581 unsigned usageCount = RB->second;
Misha Brukmanb4402432005-04-21 23:30:14 +0000582
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000583 //Divide the usage count by either the max number we can issue or the number of
584 //resources (whichever is its upper bound)
585 double finalUsageCount;
Tanya Lattner8bf63742005-06-17 04:00:57 +0000586 DEBUG(std::cerr << "Resource Num: " << RB->first << " Usage: " << usageCount << " TotalNum: " << resourceNum << "\n");
587
Tanya Lattnera066df62004-05-26 06:27:18 +0000588 if( resourceNum <= issueSlots)
589 finalUsageCount = ceil(1.0 * usageCount / resourceNum);
590 else
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000591 finalUsageCount = ceil(1.0 * usageCount / issueSlots);
Misha Brukmanb4402432005-04-21 23:30:14 +0000592
593
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000594 //Only keep track of the max
595 ResMII = std::max( (int) finalUsageCount, ResMII);
596
597 }
598
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000599 return ResMII;
600
601}
602
Tanya Lattner081fbd12004-07-30 23:36:10 +0000603/// calculateRecMII - Calculates the value of the highest recurrence
604/// By value we mean the total latency
Tanya Lattnera6820d62004-05-08 16:12:10 +0000605int ModuloSchedulingPass::calculateRecMII(MSchedGraph *graph, int MII) {
Tanya Lattner56807c62005-02-10 17:02:58 +0000606 /*std::vector<MSchedGraphNode*> vNodes;
Tanya Lattnera6820d62004-05-08 16:12:10 +0000607 //Loop over all nodes in the graph
608 for(MSchedGraph::iterator I = graph->begin(), E = graph->end(); I != E; ++I) {
609 findAllReccurrences(I->second, vNodes, MII);
610 vNodes.clear();
Tanya Lattner56807c62005-02-10 17:02:58 +0000611 }*/
Misha Brukmanb4402432005-04-21 23:30:14 +0000612
Tanya Lattner56807c62005-02-10 17:02:58 +0000613 TIME_REGION(X, "calculateRecMII");
Tanya Lattnera6820d62004-05-08 16:12:10 +0000614
Tanya Lattner56807c62005-02-10 17:02:58 +0000615 findAllCircuits(graph, MII);
Tanya Lattnera6820d62004-05-08 16:12:10 +0000616 int RecMII = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +0000617
Tanya Lattner13417b52005-03-23 01:47:20 +0000618 for(std::set<std::pair<int, std::vector<MSchedGraphNode*> > >::iterator I = recurrenceList.begin(), E=recurrenceList.end(); I !=E; ++I) {
Tanya Lattnera6820d62004-05-08 16:12:10 +0000619 RecMII = std::max(RecMII, I->first);
Tanya Lattner081fbd12004-07-30 23:36:10 +0000620 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000621
Tanya Lattnera6820d62004-05-08 16:12:10 +0000622 return MII;
623}
624
Tanya Lattner081fbd12004-07-30 23:36:10 +0000625/// calculateNodeAttributes - The following properties are calculated for
626/// each node in the dependence graph: ASAP, ALAP, Depth, Height, and
627/// MOB.
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000628void ModuloSchedulingPass::calculateNodeAttributes(MSchedGraph *graph, int MII) {
629
Tanya Lattner56807c62005-02-10 17:02:58 +0000630 TIME_REGION(X, "calculateNodeAttributes");
631
Tanya Lattnerddebd1e2004-10-30 00:39:07 +0000632 assert(nodeToAttributesMap.empty() && "Node attribute map was not cleared");
633
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000634 //Loop over the nodes and add them to the map
635 for(MSchedGraph::iterator I = graph->begin(), E = graph->end(); I != E; ++I) {
Tanya Lattnerddebd1e2004-10-30 00:39:07 +0000636
637 DEBUG(std::cerr << "Inserting node into attribute map: " << *I->second << "\n");
638
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000639 //Assert if its already in the map
Tanya Lattnerddebd1e2004-10-30 00:39:07 +0000640 assert(nodeToAttributesMap.count(I->second) == 0 &&
Jeff Cohen33a030e2005-07-27 05:53:44 +0000641 "Node attributes are already in the map");
Misha Brukmanb4402432005-04-21 23:30:14 +0000642
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000643 //Put into the map with default attribute values
644 nodeToAttributesMap[I->second] = MSNodeAttributes();
645 }
646
647 //Create set to deal with reccurrences
648 std::set<MSchedGraphNode*> visitedNodes;
Misha Brukmanb4402432005-04-21 23:30:14 +0000649
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000650 //Now Loop over map and calculate the node attributes
651 for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(), E = nodeToAttributesMap.end(); I != E; ++I) {
Tanya Lattnera6820d62004-05-08 16:12:10 +0000652 calculateASAP(I->first, MII, (MSchedGraphNode*) 0);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000653 visitedNodes.clear();
654 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000655
Tanya Lattnera6820d62004-05-08 16:12:10 +0000656 int maxASAP = findMaxASAP();
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000657 //Calculate ALAP which depends on ASAP being totally calculated
Tanya Lattnera6820d62004-05-08 16:12:10 +0000658 for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(), E = nodeToAttributesMap.end(); I != E; ++I) {
659 calculateALAP(I->first, MII, maxASAP, (MSchedGraphNode*) 0);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000660 visitedNodes.clear();
Tanya Lattnera6820d62004-05-08 16:12:10 +0000661 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000662
663 //Calculate MOB which depends on ASAP being totally calculated, also do depth and height
Tanya Lattnera6820d62004-05-08 16:12:10 +0000664 for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(), E = nodeToAttributesMap.end(); I != E; ++I) {
665 (I->second).MOB = std::max(0,(I->second).ALAP - (I->second).ASAP);
Misha Brukmanb4402432005-04-21 23:30:14 +0000666
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000667 DEBUG(std::cerr << "MOB: " << (I->second).MOB << " (" << *(I->first) << ")\n");
Tanya Lattnera6820d62004-05-08 16:12:10 +0000668 calculateDepth(I->first, (MSchedGraphNode*) 0);
669 calculateHeight(I->first, (MSchedGraphNode*) 0);
670 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000671
672
673}
674
Tanya Lattner081fbd12004-07-30 23:36:10 +0000675/// ignoreEdge - Checks to see if this edge of a recurrence should be ignored or not
Tanya Lattnera6820d62004-05-08 16:12:10 +0000676bool ModuloSchedulingPass::ignoreEdge(MSchedGraphNode *srcNode, MSchedGraphNode *destNode) {
677 if(destNode == 0 || srcNode ==0)
678 return false;
Misha Brukmanb4402432005-04-21 23:30:14 +0000679
Tanya Lattnera6820d62004-05-08 16:12:10 +0000680 bool findEdge = edgesToIgnore.count(std::make_pair(srcNode, destNode->getInEdgeNum(srcNode)));
Misha Brukmanb4402432005-04-21 23:30:14 +0000681
Tanya Lattner13417b52005-03-23 01:47:20 +0000682 DEBUG(std::cerr << "Ignoring edge? from: " << *srcNode << " to " << *destNode << "\n");
683
Tanya Lattnera6820d62004-05-08 16:12:10 +0000684 return findEdge;
685}
686
Tanya Lattner081fbd12004-07-30 23:36:10 +0000687
Misha Brukmanb4402432005-04-21 23:30:14 +0000688/// calculateASAP - Calculates the
Tanya Lattnera6820d62004-05-08 16:12:10 +0000689int ModuloSchedulingPass::calculateASAP(MSchedGraphNode *node, int MII, MSchedGraphNode *destNode) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000690
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000691 DEBUG(std::cerr << "Calculating ASAP for " << *node << "\n");
692
Tanya Lattnera6820d62004-05-08 16:12:10 +0000693 //Get current node attributes
694 MSNodeAttributes &attributes = nodeToAttributesMap.find(node)->second;
695
696 if(attributes.ASAP != -1)
697 return attributes.ASAP;
Misha Brukmanb4402432005-04-21 23:30:14 +0000698
Tanya Lattnera6820d62004-05-08 16:12:10 +0000699 int maxPredValue = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +0000700
Tanya Lattnera6820d62004-05-08 16:12:10 +0000701 //Iterate over all of the predecessors and find max
702 for(MSchedGraphNode::pred_iterator P = node->pred_begin(), E = node->pred_end(); P != E; ++P) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000703
Tanya Lattnera6820d62004-05-08 16:12:10 +0000704 //Only process if we are not ignoring the edge
705 if(!ignoreEdge(*P, node)) {
706 int predASAP = -1;
707 predASAP = calculateASAP(*P, MII, node);
Misha Brukmanb4402432005-04-21 23:30:14 +0000708
Tanya Lattnera6820d62004-05-08 16:12:10 +0000709 assert(predASAP != -1 && "ASAP has not been calculated");
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000710 int iteDiff = node->getInEdge(*P).getIteDiff();
Misha Brukmanb4402432005-04-21 23:30:14 +0000711
Tanya Lattnera6820d62004-05-08 16:12:10 +0000712 int currentPredValue = predASAP + (*P)->getLatency() - (iteDiff * MII);
713 DEBUG(std::cerr << "pred ASAP: " << predASAP << ", iteDiff: " << iteDiff << ", PredLatency: " << (*P)->getLatency() << ", Current ASAP pred: " << currentPredValue << "\n");
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000714 maxPredValue = std::max(maxPredValue, currentPredValue);
715 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000716 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000717
Tanya Lattnera6820d62004-05-08 16:12:10 +0000718 attributes.ASAP = maxPredValue;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000719
720 DEBUG(std::cerr << "ASAP: " << attributes.ASAP << " (" << *node << ")\n");
Misha Brukmanb4402432005-04-21 23:30:14 +0000721
Tanya Lattnera6820d62004-05-08 16:12:10 +0000722 return maxPredValue;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000723}
724
725
Misha Brukmanb4402432005-04-21 23:30:14 +0000726int ModuloSchedulingPass::calculateALAP(MSchedGraphNode *node, int MII,
Jeff Cohen33a030e2005-07-27 05:53:44 +0000727 int maxASAP, MSchedGraphNode *srcNode) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000728
Tanya Lattnera6820d62004-05-08 16:12:10 +0000729 DEBUG(std::cerr << "Calculating ALAP for " << *node << "\n");
Misha Brukmanb4402432005-04-21 23:30:14 +0000730
Tanya Lattnera6820d62004-05-08 16:12:10 +0000731 MSNodeAttributes &attributes = nodeToAttributesMap.find(node)->second;
Misha Brukmanb4402432005-04-21 23:30:14 +0000732
Tanya Lattnera6820d62004-05-08 16:12:10 +0000733 if(attributes.ALAP != -1)
734 return attributes.ALAP;
Misha Brukmanb4402432005-04-21 23:30:14 +0000735
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000736 if(node->hasSuccessors()) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000737
Tanya Lattnera6820d62004-05-08 16:12:10 +0000738 //Trying to deal with the issue where the node has successors, but
739 //we are ignoring all of the edges to them. So this is my hack for
740 //now.. there is probably a more elegant way of doing this (FIXME)
741 bool processedOneEdge = false;
742
743 //FIXME, set to something high to start
744 int minSuccValue = 9999999;
Misha Brukmanb4402432005-04-21 23:30:14 +0000745
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000746 //Iterate over all of the predecessors and fine max
Misha Brukmanb4402432005-04-21 23:30:14 +0000747 for(MSchedGraphNode::succ_iterator P = node->succ_begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +0000748 E = node->succ_end(); P != E; ++P) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000749
Tanya Lattnera6820d62004-05-08 16:12:10 +0000750 //Only process if we are not ignoring the edge
751 if(!ignoreEdge(node, *P)) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000752 processedOneEdge = true;
753 int succALAP = -1;
754 succALAP = calculateALAP(*P, MII, maxASAP, node);
755
756 assert(succALAP != -1 && "Successors ALAP should have been caclulated");
757
758 int iteDiff = P.getEdge().getIteDiff();
759
760 int currentSuccValue = succALAP - node->getLatency() + iteDiff * MII;
761
762 DEBUG(std::cerr << "succ ALAP: " << succALAP << ", iteDiff: " << iteDiff << ", SuccLatency: " << (*P)->getLatency() << ", Current ALAP succ: " << currentSuccValue << "\n");
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000763
Jeff Cohen33a030e2005-07-27 05:53:44 +0000764 minSuccValue = std::min(minSuccValue, currentSuccValue);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000765 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000766 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000767
Tanya Lattnera6820d62004-05-08 16:12:10 +0000768 if(processedOneEdge)
Jeff Cohen33a030e2005-07-27 05:53:44 +0000769 attributes.ALAP = minSuccValue;
Misha Brukmanb4402432005-04-21 23:30:14 +0000770
Tanya Lattnera6820d62004-05-08 16:12:10 +0000771 else
772 attributes.ALAP = maxASAP;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000773 }
Tanya Lattnera6820d62004-05-08 16:12:10 +0000774 else
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000775 attributes.ALAP = maxASAP;
Tanya Lattnera6820d62004-05-08 16:12:10 +0000776
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000777 DEBUG(std::cerr << "ALAP: " << attributes.ALAP << " (" << *node << ")\n");
Tanya Lattnera6820d62004-05-08 16:12:10 +0000778
779 if(attributes.ALAP < 0)
780 attributes.ALAP = 0;
781
782 return attributes.ALAP;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000783}
784
785int ModuloSchedulingPass::findMaxASAP() {
786 int maxASAP = 0;
787
788 for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +0000789 E = nodeToAttributesMap.end(); I != E; ++I)
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000790 maxASAP = std::max(maxASAP, I->second.ASAP);
791 return maxASAP;
792}
793
794
Tanya Lattnera6820d62004-05-08 16:12:10 +0000795int ModuloSchedulingPass::calculateHeight(MSchedGraphNode *node,MSchedGraphNode *srcNode) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000796
Tanya Lattnera6820d62004-05-08 16:12:10 +0000797 MSNodeAttributes &attributes = nodeToAttributesMap.find(node)->second;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000798
Tanya Lattnera6820d62004-05-08 16:12:10 +0000799 if(attributes.height != -1)
800 return attributes.height;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000801
Tanya Lattnera6820d62004-05-08 16:12:10 +0000802 int maxHeight = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +0000803
Tanya Lattnera6820d62004-05-08 16:12:10 +0000804 //Iterate over all of the predecessors and find max
Misha Brukmanb4402432005-04-21 23:30:14 +0000805 for(MSchedGraphNode::succ_iterator P = node->succ_begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +0000806 E = node->succ_end(); P != E; ++P) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000807
808
Tanya Lattnera6820d62004-05-08 16:12:10 +0000809 if(!ignoreEdge(node, *P)) {
810 int succHeight = calculateHeight(*P, node);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000811
Tanya Lattnera6820d62004-05-08 16:12:10 +0000812 assert(succHeight != -1 && "Successors Height should have been caclulated");
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000813
Tanya Lattnera6820d62004-05-08 16:12:10 +0000814 int currentHeight = succHeight + node->getLatency();
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000815 maxHeight = std::max(maxHeight, currentHeight);
816 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000817 }
Tanya Lattnera6820d62004-05-08 16:12:10 +0000818 attributes.height = maxHeight;
819 DEBUG(std::cerr << "Height: " << attributes.height << " (" << *node << ")\n");
820 return maxHeight;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000821}
822
823
Misha Brukmanb4402432005-04-21 23:30:14 +0000824int ModuloSchedulingPass::calculateDepth(MSchedGraphNode *node,
Jeff Cohen33a030e2005-07-27 05:53:44 +0000825 MSchedGraphNode *destNode) {
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000826
Tanya Lattnera6820d62004-05-08 16:12:10 +0000827 MSNodeAttributes &attributes = nodeToAttributesMap.find(node)->second;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000828
Tanya Lattnera6820d62004-05-08 16:12:10 +0000829 if(attributes.depth != -1)
830 return attributes.depth;
831
832 int maxDepth = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +0000833
Tanya Lattnera6820d62004-05-08 16:12:10 +0000834 //Iterate over all of the predecessors and fine max
835 for(MSchedGraphNode::pred_iterator P = node->pred_begin(), E = node->pred_end(); P != E; ++P) {
836
837 if(!ignoreEdge(*P, node)) {
838 int predDepth = -1;
839 predDepth = calculateDepth(*P, node);
Misha Brukmanb4402432005-04-21 23:30:14 +0000840
Tanya Lattnera6820d62004-05-08 16:12:10 +0000841 assert(predDepth != -1 && "Predecessors ASAP should have been caclulated");
842
843 int currentDepth = predDepth + (*P)->getLatency();
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000844 maxDepth = std::max(maxDepth, currentDepth);
845 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000846 }
Tanya Lattnera6820d62004-05-08 16:12:10 +0000847 attributes.depth = maxDepth;
Misha Brukmanb4402432005-04-21 23:30:14 +0000848
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000849 DEBUG(std::cerr << "Depth: " << attributes.depth << " (" << *node << "*)\n");
Tanya Lattnera6820d62004-05-08 16:12:10 +0000850 return maxDepth;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +0000851}
852
853
Tanya Lattnera6820d62004-05-08 16:12:10 +0000854
855void ModuloSchedulingPass::addReccurrence(std::vector<MSchedGraphNode*> &recurrence, int II, MSchedGraphNode *srcBENode, MSchedGraphNode *destBENode) {
856 //Check to make sure that this recurrence is unique
857 bool same = false;
858
859
860 //Loop over all recurrences already in our list
861 for(std::set<std::pair<int, std::vector<MSchedGraphNode*> > >::iterator R = recurrenceList.begin(), RE = recurrenceList.end(); R != RE; ++R) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000862
Tanya Lattnera6820d62004-05-08 16:12:10 +0000863 bool all_same = true;
864 //First compare size
865 if(R->second.size() == recurrence.size()) {
Misha Brukmanb4402432005-04-21 23:30:14 +0000866
Tanya Lattnera6820d62004-05-08 16:12:10 +0000867 for(std::vector<MSchedGraphNode*>::const_iterator node = R->second.begin(), end = R->second.end(); node != end; ++node) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000868 if(std::find(recurrence.begin(), recurrence.end(), *node) == recurrence.end()) {
869 all_same = all_same && false;
870 break;
871 }
872 else
873 all_same = all_same && true;
Tanya Lattnera6820d62004-05-08 16:12:10 +0000874 }
875 if(all_same) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000876 same = true;
877 break;
Tanya Lattnera6820d62004-05-08 16:12:10 +0000878 }
879 }
880 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000881
Tanya Lattnera6820d62004-05-08 16:12:10 +0000882 if(!same) {
Tanya Lattnera066df62004-05-26 06:27:18 +0000883 srcBENode = recurrence.back();
884 destBENode = recurrence.front();
Misha Brukmanb4402432005-04-21 23:30:14 +0000885
Tanya Lattnera066df62004-05-26 06:27:18 +0000886 //FIXME
887 if(destBENode->getInEdge(srcBENode).getIteDiff() == 0) {
888 //DEBUG(std::cerr << "NOT A BACKEDGE\n");
Misha Brukmanb4402432005-04-21 23:30:14 +0000889 //find actual backedge HACK HACK
Tanya Lattnera066df62004-05-26 06:27:18 +0000890 for(unsigned i=0; i< recurrence.size()-1; ++i) {
Jeff Cohen33a030e2005-07-27 05:53:44 +0000891 if(recurrence[i+1]->getInEdge(recurrence[i]).getIteDiff() == 1) {
892 srcBENode = recurrence[i];
893 destBENode = recurrence[i+1];
894 break;
895 }
896
Tanya Lattnera066df62004-05-26 06:27:18 +0000897 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000898
Tanya Lattnera066df62004-05-26 06:27:18 +0000899 }
Tanya Lattnera6820d62004-05-08 16:12:10 +0000900 DEBUG(std::cerr << "Back Edge to Remove: " << *srcBENode << " to " << *destBENode << "\n");
901 edgesToIgnore.insert(std::make_pair(srcBENode, destBENode->getInEdgeNum(srcBENode)));
902 recurrenceList.insert(std::make_pair(II, recurrence));
903 }
Misha Brukmanb4402432005-04-21 23:30:14 +0000904
Tanya Lattnera6820d62004-05-08 16:12:10 +0000905}
906
Tanya Lattner56807c62005-02-10 17:02:58 +0000907int CircCount;
908
909void ModuloSchedulingPass::unblock(MSchedGraphNode *u, std::set<MSchedGraphNode*> &blocked,
Jeff Cohen33a030e2005-07-27 05:53:44 +0000910 std::map<MSchedGraphNode*, std::set<MSchedGraphNode*> > &B) {
Tanya Lattner56807c62005-02-10 17:02:58 +0000911
912 //Unblock u
913 DEBUG(std::cerr << "Unblocking: " << *u << "\n");
914 blocked.erase(u);
915
916 //std::set<MSchedGraphNode*> toErase;
917 while (!B[u].empty()) {
918 MSchedGraphNode *W = *B[u].begin();
919 B[u].erase(W);
920 //toErase.insert(*W);
921 DEBUG(std::cerr << "Removed: " << *W << "from B-List\n");
922 if(blocked.count(W))
923 unblock(W, blocked, B);
924 }
925
926}
927
Misha Brukmanb4402432005-04-21 23:30:14 +0000928bool ModuloSchedulingPass::circuit(MSchedGraphNode *v, std::vector<MSchedGraphNode*> &stack,
Jeff Cohen33a030e2005-07-27 05:53:44 +0000929 std::set<MSchedGraphNode*> &blocked, std::vector<MSchedGraphNode*> &SCC,
930 MSchedGraphNode *s, std::map<MSchedGraphNode*, std::set<MSchedGraphNode*> > &B,
931 int II, std::map<MSchedGraphNode*, MSchedGraphNode*> &newNodes) {
Tanya Lattner56807c62005-02-10 17:02:58 +0000932 bool f = false;
Misha Brukmanb4402432005-04-21 23:30:14 +0000933
Tanya Lattner56807c62005-02-10 17:02:58 +0000934 DEBUG(std::cerr << "Finding Circuits Starting with: ( " << v << ")"<< *v << "\n");
935
936 //Push node onto the stack
937 stack.push_back(v);
938
939 //block this node
940 blocked.insert(v);
941
942 //Loop over all successors of node v that are in the scc, create Adjaceny list
943 std::set<MSchedGraphNode*> AkV;
944 for(MSchedGraphNode::succ_iterator I = v->succ_begin(), E = v->succ_end(); I != E; ++I) {
945 if((std::find(SCC.begin(), SCC.end(), *I) != SCC.end())) {
946 AkV.insert(*I);
947 }
948 }
949
950 for(std::set<MSchedGraphNode*>::iterator I = AkV.begin(), E = AkV.end(); I != E; ++I) {
951 if(*I == s) {
952 //We have a circuit, so add it to our list
Tanya Lattner42ed1482005-04-22 06:32:48 +0000953 addRecc(stack, newNodes);
Tanya Lattner56807c62005-02-10 17:02:58 +0000954 f = true;
Tanya Lattner56807c62005-02-10 17:02:58 +0000955 }
956 else if(!blocked.count(*I)) {
957 if(circuit(*I, stack, blocked, SCC, s, B, II, newNodes))
Jeff Cohen33a030e2005-07-27 05:53:44 +0000958 f = true;
Tanya Lattner56807c62005-02-10 17:02:58 +0000959 }
960 else
961 DEBUG(std::cerr << "Blocked: " << **I << "\n");
962 }
963
964
965 if(f) {
966 unblock(v, blocked, B);
967 }
968 else {
Misha Brukmanb4402432005-04-21 23:30:14 +0000969 for(std::set<MSchedGraphNode*>::iterator I = AkV.begin(), E = AkV.end(); I != E; ++I)
Tanya Lattner56807c62005-02-10 17:02:58 +0000970 B[*I].insert(v);
971
972 }
973
974 //Pop v
975 stack.pop_back();
976
977 return f;
978
979}
980
Tanya Lattner42ed1482005-04-22 06:32:48 +0000981void ModuloSchedulingPass::addRecc(std::vector<MSchedGraphNode*> &stack, std::map<MSchedGraphNode*, MSchedGraphNode*> &newNodes) {
982 std::vector<MSchedGraphNode*> recc;
983 //Dump recurrence for now
984 DEBUG(std::cerr << "Starting Recc\n");
Jeff Cohen33a030e2005-07-27 05:53:44 +0000985
Tanya Lattner42ed1482005-04-22 06:32:48 +0000986 int totalDelay = 0;
987 int totalDistance = 0;
988 MSchedGraphNode *lastN = 0;
989 MSchedGraphNode *start = 0;
990 MSchedGraphNode *end = 0;
991
992 //Loop over recurrence, get delay and distance
993 for(std::vector<MSchedGraphNode*>::iterator N = stack.begin(), NE = stack.end(); N != NE; ++N) {
994 DEBUG(std::cerr << **N << "\n");
995 totalDelay += (*N)->getLatency();
996 if(lastN) {
997 int iteDiff = (*N)->getInEdge(lastN).getIteDiff();
998 totalDistance += iteDiff;
999
1000 if(iteDiff > 0) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001001 start = lastN;
1002 end = *N;
Tanya Lattner42ed1482005-04-22 06:32:48 +00001003 }
1004 }
1005 //Get the original node
1006 lastN = *N;
1007 recc.push_back(newNodes[*N]);
1008
1009
1010 }
1011
1012 //Get the loop edge
1013 totalDistance += lastN->getIteDiff(*stack.begin());
1014
1015 DEBUG(std::cerr << "End Recc\n");
1016 CircCount++;
1017
Jeff Cohen33a030e2005-07-27 05:53:44 +00001018 if(start && end) {
Tanya Lattner42ed1482005-04-22 06:32:48 +00001019 //Insert reccurrence into the list
1020 DEBUG(std::cerr << "Ignore Edge from!!: " << *start << " to " << *end << "\n");
1021 edgesToIgnore.insert(std::make_pair(newNodes[start], (newNodes[end])->getInEdgeNum(newNodes[start])));
1022 }
1023 else {
1024 //Insert reccurrence into the list
1025 DEBUG(std::cerr << "Ignore Edge from: " << *lastN << " to " << **stack.begin() << "\n");
1026 edgesToIgnore.insert(std::make_pair(newNodes[lastN], newNodes[(*stack.begin())]->getInEdgeNum(newNodes[lastN])));
1027
1028 }
1029 //Adjust II until we get close to the inequality delay - II*distance <= 0
1030 int RecMII = II; //Starting value
1031 int value = totalDelay-(RecMII * totalDistance);
1032 int lastII = II;
1033 while(value < 0) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001034
Tanya Lattner42ed1482005-04-22 06:32:48 +00001035 lastII = RecMII;
1036 RecMII--;
1037 value = totalDelay-(RecMII * totalDistance);
1038 }
1039
1040 recurrenceList.insert(std::make_pair(lastII, recc));
1041
1042}
1043
Tanya Lattner8bf63742005-06-17 04:00:57 +00001044void ModuloSchedulingPass::addSCC(std::vector<MSchedGraphNode*> &SCC, std::map<MSchedGraphNode*, MSchedGraphNode*> &newNodes) {
1045
1046 int totalDelay = 0;
1047 int totalDistance = 0;
1048 std::vector<MSchedGraphNode*> recc;
1049 MSchedGraphNode *start = 0;
1050 MSchedGraphNode *end = 0;
1051
1052 //Loop over recurrence, get delay and distance
1053 for(std::vector<MSchedGraphNode*>::iterator N = SCC.begin(), NE = SCC.end(); N != NE; ++N) {
1054 DEBUG(std::cerr << **N << "\n");
1055 totalDelay += (*N)->getLatency();
1056
1057 for(unsigned i = 0; i < (*N)->succ_size(); ++i) {
1058 MSchedGraphEdge *edge = (*N)->getSuccessor(i);
1059 if(find(SCC.begin(), SCC.end(), edge->getDest()) != SCC.end()) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001060 totalDistance += edge->getIteDiff();
1061 if(edge->getIteDiff() > 0)
1062 if(!start && !end) {
1063 start = *N;
1064 end = edge->getDest();
1065 }
1066
Tanya Lattner8bf63742005-06-17 04:00:57 +00001067 }
1068 }
1069
1070
1071 //Get the original node
1072 recc.push_back(newNodes[*N]);
1073
1074
1075 }
1076
1077 DEBUG(std::cerr << "End Recc\n");
1078 CircCount++;
1079
1080 assert( (start && end) && "Must have start and end node to ignore edge for SCC");
1081
Jeff Cohen33a030e2005-07-27 05:53:44 +00001082 if(start && end) {
Tanya Lattner8bf63742005-06-17 04:00:57 +00001083 //Insert reccurrence into the list
1084 DEBUG(std::cerr << "Ignore Edge from!!: " << *start << " to " << *end << "\n");
1085 edgesToIgnore.insert(std::make_pair(newNodes[start], (newNodes[end])->getInEdgeNum(newNodes[start])));
1086 }
1087
1088 int lastII = totalDelay / totalDistance;
1089
1090
1091 recurrenceList.insert(std::make_pair(lastII, recc));
1092
1093}
Tanya Lattner42ed1482005-04-22 06:32:48 +00001094
Tanya Lattner56807c62005-02-10 17:02:58 +00001095void ModuloSchedulingPass::findAllCircuits(MSchedGraph *g, int II) {
1096
1097 CircCount = 0;
1098
Misha Brukmanb4402432005-04-21 23:30:14 +00001099 //Keep old to new node mapping information
Tanya Lattner56807c62005-02-10 17:02:58 +00001100 std::map<MSchedGraphNode*, MSchedGraphNode*> newNodes;
1101
1102 //copy the graph
1103 MSchedGraph *MSG = new MSchedGraph(*g, newNodes);
1104
1105 DEBUG(std::cerr << "Finding All Circuits\n");
1106
1107 //Set of blocked nodes
1108 std::set<MSchedGraphNode*> blocked;
1109
1110 //Stack holding current circuit
1111 std::vector<MSchedGraphNode*> stack;
1112
1113 //Map for B Lists
1114 std::map<MSchedGraphNode*, std::set<MSchedGraphNode*> > B;
1115
1116 //current node
1117 MSchedGraphNode *s;
1118
1119
1120 //Iterate over the graph until its down to one node or empty
1121 while(MSG->size() > 1) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001122
Tanya Lattner56807c62005-02-10 17:02:58 +00001123 //Write Graph out to file
1124 //WriteGraphToFile(std::cerr, "Graph" + utostr(MSG->size()), MSG);
1125
1126 DEBUG(std::cerr << "Graph Size: " << MSG->size() << "\n");
1127 DEBUG(std::cerr << "Finding strong component Vk with least vertex\n");
1128
1129 //Iterate over all the SCCs in the graph
1130 std::set<MSchedGraphNode*> Visited;
1131 std::vector<MSchedGraphNode*> Vk;
1132 MSchedGraphNode* s = 0;
Tanya Lattner8bf63742005-06-17 04:00:57 +00001133 int numEdges = 0;
Tanya Lattner56807c62005-02-10 17:02:58 +00001134
1135 //Find scc with the least vertex
1136 for (MSchedGraph::iterator GI = MSG->begin(), E = MSG->end(); GI != E; ++GI)
1137 if (Visited.insert(GI->second).second) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001138 for (scc_iterator<MSchedGraphNode*> SCCI = scc_begin(GI->second),
1139 E = scc_end(GI->second); SCCI != E; ++SCCI) {
1140 std::vector<MSchedGraphNode*> &nextSCC = *SCCI;
Tanya Lattner56807c62005-02-10 17:02:58 +00001141
Jeff Cohen33a030e2005-07-27 05:53:44 +00001142 if (Visited.insert(nextSCC[0]).second) {
1143 Visited.insert(nextSCC.begin()+1, nextSCC.end());
Tanya Lattner56807c62005-02-10 17:02:58 +00001144
Jeff Cohen33a030e2005-07-27 05:53:44 +00001145 if(nextSCC.size() > 1) {
1146 std::cerr << "SCC size: " << nextSCC.size() << "\n";
1147
1148 for(unsigned i = 0; i < nextSCC.size(); ++i) {
1149 //Loop over successor and see if in scc, then count edge
1150 MSchedGraphNode *node = nextSCC[i];
1151 for(MSchedGraphNode::succ_iterator S = node->succ_begin(), SE = node->succ_end(); S != SE; ++S) {
1152 if(find(nextSCC.begin(), nextSCC.end(), *S) != nextSCC.end())
1153 numEdges++;
1154 }
1155 }
1156 std::cerr << "Num Edges: " << numEdges << "\n";
1157 }
Tanya Lattner56807c62005-02-10 17:02:58 +00001158
Jeff Cohen33a030e2005-07-27 05:53:44 +00001159 //Ignore self loops
1160 if(nextSCC.size() > 1) {
Tanya Lattner13417b52005-03-23 01:47:20 +00001161
Jeff Cohen33a030e2005-07-27 05:53:44 +00001162 //Get least vertex in Vk
1163 if(!s) {
1164 s = nextSCC[0];
1165 Vk = nextSCC;
1166 }
Tanya Lattner56807c62005-02-10 17:02:58 +00001167
Jeff Cohen33a030e2005-07-27 05:53:44 +00001168 for(unsigned i = 0; i < nextSCC.size(); ++i) {
1169 if(nextSCC[i] < s) {
1170 s = nextSCC[i];
1171 Vk = nextSCC;
1172 }
1173 }
1174 }
1175 }
1176 }
Tanya Lattner56807c62005-02-10 17:02:58 +00001177 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001178
1179
Tanya Lattner56807c62005-02-10 17:02:58 +00001180
1181 //Process SCC
1182 DEBUG(for(std::vector<MSchedGraphNode*>::iterator N = Vk.begin(), NE = Vk.end();
Jeff Cohen33a030e2005-07-27 05:53:44 +00001183 N != NE; ++N) { std::cerr << *((*N)->getInst()); });
Misha Brukmanb4402432005-04-21 23:30:14 +00001184
Tanya Lattner56807c62005-02-10 17:02:58 +00001185 //Iterate over all nodes in this scc
1186 for(std::vector<MSchedGraphNode*>::iterator N = Vk.begin(), NE = Vk.end();
Jeff Cohen33a030e2005-07-27 05:53:44 +00001187 N != NE; ++N) {
Tanya Lattner56807c62005-02-10 17:02:58 +00001188 blocked.erase(*N);
1189 B[*N].clear();
1190 }
1191 if(Vk.size() > 1) {
Tanya Lattner8bf63742005-06-17 04:00:57 +00001192 if(numEdges < 98)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001193 circuit(s, stack, blocked, Vk, s, B, II, newNodes);
Tanya Lattner8bf63742005-06-17 04:00:57 +00001194 else
Jeff Cohen33a030e2005-07-27 05:53:44 +00001195 addSCC(Vk, newNodes);
Misha Brukmanb4402432005-04-21 23:30:14 +00001196
Tanya Lattner42ed1482005-04-22 06:32:48 +00001197 //Delete nodes from the graph
Tanya Lattner56807c62005-02-10 17:02:58 +00001198 //Find all nodes up to s and delete them
1199 std::vector<MSchedGraphNode*> nodesToRemove;
1200 nodesToRemove.push_back(s);
1201 for(MSchedGraph::iterator N = MSG->begin(), NE = MSG->end(); N != NE; ++N) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001202 if(N->second < s )
1203 nodesToRemove.push_back(N->second);
Tanya Lattner56807c62005-02-10 17:02:58 +00001204 }
1205 for(std::vector<MSchedGraphNode*>::iterator N = nodesToRemove.begin(), NE = nodesToRemove.end(); N != NE; ++N) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001206 DEBUG(std::cerr << "Deleting Node: " << **N << "\n");
1207 MSG->deleteNode(*N);
Tanya Lattner56807c62005-02-10 17:02:58 +00001208 }
1209 }
1210 else
1211 break;
Tanya Lattner42ed1482005-04-22 06:32:48 +00001212 }
Tanya Lattner56807c62005-02-10 17:02:58 +00001213 DEBUG(std::cerr << "Num Circuits found: " << CircCount << "\n");
1214}
1215
1216
Misha Brukmanb4402432005-04-21 23:30:14 +00001217void ModuloSchedulingPass::findAllReccurrences(MSchedGraphNode *node,
Jeff Cohen33a030e2005-07-27 05:53:44 +00001218 std::vector<MSchedGraphNode*> &visitedNodes,
1219 int II) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001220
Tanya Lattnera6820d62004-05-08 16:12:10 +00001221
Alkis Evlogimenos20f1b0b2004-09-28 14:42:44 +00001222 if(std::find(visitedNodes.begin(), visitedNodes.end(), node) != visitedNodes.end()) {
Tanya Lattnera6820d62004-05-08 16:12:10 +00001223 std::vector<MSchedGraphNode*> recurrence;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001224 bool first = true;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001225 int delay = 0;
1226 int distance = 0;
1227 int RecMII = II; //Starting value
1228 MSchedGraphNode *last = node;
Chris Lattner3e689f82004-08-04 03:51:55 +00001229 MSchedGraphNode *srcBackEdge = 0;
1230 MSchedGraphNode *destBackEdge = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +00001231
Tanya Lattnera6820d62004-05-08 16:12:10 +00001232
1233
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001234 for(std::vector<MSchedGraphNode*>::iterator I = visitedNodes.begin(), E = visitedNodes.end();
Jeff Cohen33a030e2005-07-27 05:53:44 +00001235 I !=E; ++I) {
Tanya Lattnera6820d62004-05-08 16:12:10 +00001236
Misha Brukmanb4402432005-04-21 23:30:14 +00001237 if(*I == node)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001238 first = false;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001239 if(first)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001240 continue;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001241
1242 delay = delay + (*I)->getLatency();
1243
1244 if(*I != node) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001245 int diff = (*I)->getInEdge(last).getIteDiff();
1246 distance += diff;
1247 if(diff > 0) {
1248 srcBackEdge = last;
1249 destBackEdge = *I;
1250 }
Tanya Lattnera6820d62004-05-08 16:12:10 +00001251 }
1252
1253 recurrence.push_back(*I);
1254 last = *I;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001255 }
Tanya Lattnera6820d62004-05-08 16:12:10 +00001256
1257
Misha Brukmanb4402432005-04-21 23:30:14 +00001258
Tanya Lattnera6820d62004-05-08 16:12:10 +00001259 //Get final distance calc
1260 distance += node->getInEdge(last).getIteDiff();
Tanya Lattnerab9cf272004-11-22 20:41:24 +00001261 DEBUG(std::cerr << "Reccurrence Distance: " << distance << "\n");
Tanya Lattnera6820d62004-05-08 16:12:10 +00001262
1263 //Adjust II until we get close to the inequality delay - II*distance <= 0
Misha Brukmanb4402432005-04-21 23:30:14 +00001264
Tanya Lattnera6820d62004-05-08 16:12:10 +00001265 int value = delay-(RecMII * distance);
1266 int lastII = II;
1267 while(value <= 0) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001268
Tanya Lattnera6820d62004-05-08 16:12:10 +00001269 lastII = RecMII;
1270 RecMII--;
1271 value = delay-(RecMII * distance);
1272 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001273
1274
Tanya Lattnera6820d62004-05-08 16:12:10 +00001275 DEBUG(std::cerr << "Final II for this recurrence: " << lastII << "\n");
1276 addReccurrence(recurrence, lastII, srcBackEdge, destBackEdge);
1277 assert(distance != 0 && "Recurrence distance should not be zero");
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001278 return;
1279 }
1280
Tanya Lattnerc227ad22005-01-18 04:15:41 +00001281 unsigned count = 0;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001282 for(MSchedGraphNode::succ_iterator I = node->succ_begin(), E = node->succ_end(); I != E; ++I) {
1283 visitedNodes.push_back(node);
Tanya Lattnerc227ad22005-01-18 04:15:41 +00001284 //if(!edgesToIgnore.count(std::make_pair(node, count)))
Tanya Lattnera6820d62004-05-08 16:12:10 +00001285 findAllReccurrences(*I, visitedNodes, II);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001286 visitedNodes.pop_back();
Tanya Lattnerc227ad22005-01-18 04:15:41 +00001287 count++;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001288 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001289}
1290
Misha Brukmanb4402432005-04-21 23:30:14 +00001291void ModuloSchedulingPass::searchPath(MSchedGraphNode *node,
Jeff Cohen33a030e2005-07-27 05:53:44 +00001292 std::vector<MSchedGraphNode*> &path,
1293 std::set<MSchedGraphNode*> &nodesToAdd,
1294 std::set<MSchedGraphNode*> &new_reccurrence) {
Tanya Lattnera31ad512005-02-23 02:01:42 +00001295 //Push node onto the path
1296 path.push_back(node);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001297
Misha Brukmanb4402432005-04-21 23:30:14 +00001298 //Loop over all successors and see if there is a path from this node to
Tanya Lattnera31ad512005-02-23 02:01:42 +00001299 //a recurrence in the partial order, if so.. add all nodes to be added to recc
Misha Brukmanb4402432005-04-21 23:30:14 +00001300 for(MSchedGraphNode::succ_iterator S = node->succ_begin(), SE = node->succ_end(); S != SE;
Tanya Lattnera31ad512005-02-23 02:01:42 +00001301 ++S) {
1302
Tanya Lattner4d0ee752005-04-30 23:07:59 +00001303 //Check if we should ignore this edge first
1304 if(ignoreEdge(node,*S))
1305 continue;
1306
1307 //check if successor is in this recurrence, we will get to it eventually
1308 if(new_reccurrence.count(*S))
1309 continue;
1310
1311 //If this node exists in a recurrence already in the partial
1312 //order, then add all nodes in the path to the set of nodes to add
1313 //Check if its already in our partial order, if not add it to the
1314 //final vector
1315 bool found = false;
Misha Brukmanb4402432005-04-21 23:30:14 +00001316 for(std::vector<std::set<MSchedGraphNode*> >::iterator PO = partialOrder.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001317 PE = partialOrder.end(); PO != PE; ++PO) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001318
Tanya Lattnera31ad512005-02-23 02:01:42 +00001319 if(PO->count(*S)) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001320 found = true;
1321 break;
Tanya Lattnera31ad512005-02-23 02:01:42 +00001322 }
Tanya Lattner4d0ee752005-04-30 23:07:59 +00001323 }
1324
1325 if(!found) {
1326 nodesToAdd.insert(*S);
1327 searchPath(*S, path, nodesToAdd, new_reccurrence);
1328 }
Tanya Lattnera31ad512005-02-23 02:01:42 +00001329 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001330
Tanya Lattnera31ad512005-02-23 02:01:42 +00001331 //Pop Node off the path
1332 path.pop_back();
1333}
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001334
Misha Brukmanb4402432005-04-21 23:30:14 +00001335void ModuloSchedulingPass::pathToRecc(MSchedGraphNode *node,
Jeff Cohen33a030e2005-07-27 05:53:44 +00001336 std::vector<MSchedGraphNode*> &path,
1337 std::set<MSchedGraphNode*> &poSet,
1338 std::set<MSchedGraphNode*> &lastNodes) {
Tanya Lattner13417b52005-03-23 01:47:20 +00001339 //Push node onto the path
1340 path.push_back(node);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001341
Tanya Lattner13417b52005-03-23 01:47:20 +00001342 DEBUG(std::cerr << "Current node: " << *node << "\n");
1343
Misha Brukmanb4402432005-04-21 23:30:14 +00001344 //Loop over all successors and see if there is a path from this node to
Tanya Lattner13417b52005-03-23 01:47:20 +00001345 //a recurrence in the partial order, if so.. add all nodes to be added to recc
Misha Brukmanb4402432005-04-21 23:30:14 +00001346 for(MSchedGraphNode::succ_iterator S = node->succ_begin(), SE = node->succ_end(); S != SE;
Tanya Lattner13417b52005-03-23 01:47:20 +00001347 ++S) {
1348 DEBUG(std::cerr << "Succ:" << **S << "\n");
1349 //Check if we should ignore this edge first
1350 if(ignoreEdge(node,*S))
1351 continue;
Misha Brukmanb4402432005-04-21 23:30:14 +00001352
Tanya Lattner13417b52005-03-23 01:47:20 +00001353 if(poSet.count(*S)) {
1354 DEBUG(std::cerr << "Found path to recc from no pred\n");
1355 //Loop over path, if it exists in lastNodes, then add to poset, and remove from lastNodes
1356 for(std::vector<MSchedGraphNode*>::iterator I = path.begin(), IE = path.end(); I != IE; ++I) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001357 if(lastNodes.count(*I)) {
1358 DEBUG(std::cerr << "Inserting node into recc: " << **I << "\n");
1359 poSet.insert(*I);
1360 lastNodes.erase(*I);
1361 }
Tanya Lattner13417b52005-03-23 01:47:20 +00001362 }
1363 }
1364 else
1365 pathToRecc(*S, path, poSet, lastNodes);
1366 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001367
Tanya Lattner13417b52005-03-23 01:47:20 +00001368 //Pop Node off the path
1369 path.pop_back();
1370}
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001371
Tanya Lattnera6820d62004-05-08 16:12:10 +00001372void ModuloSchedulingPass::computePartialOrder() {
Tanya Lattner13c71ca2004-11-24 01:49:10 +00001373
Tanya Lattner56807c62005-02-10 17:02:58 +00001374 TIME_REGION(X, "calculatePartialOrder");
Tanya Lattner42ed1482005-04-22 06:32:48 +00001375
1376 DEBUG(std::cerr << "Computing Partial Order\n");
Misha Brukmanb4402432005-04-21 23:30:14 +00001377
Tanya Lattner42ed1482005-04-22 06:32:48 +00001378 //Only push BA branches onto the final node order, we put other
1379 //branches after it FIXME: Should we really be pushing branches on
1380 //it a specific order instead of relying on BA being there?
1381
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00001382 std::vector<MSchedGraphNode*> branches;
Tanya Lattner42ed1482005-04-22 06:32:48 +00001383
1384 //Steps to add a recurrence to the partial order 1) Find reccurrence
1385 //with the highest RecMII. Add it to the partial order. 2) For each
1386 //recurrence with decreasing RecMII, add it to the partial order
1387 //along with any nodes that connect this recurrence to recurrences
1388 //already in the partial order
1389 for(std::set<std::pair<int, std::vector<MSchedGraphNode*> > >::reverse_iterator
Jeff Cohen33a030e2005-07-27 05:53:44 +00001390 I = recurrenceList.rbegin(), E=recurrenceList.rend(); I !=E; ++I) {
Tanya Lattnera6820d62004-05-08 16:12:10 +00001391
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001392 std::set<MSchedGraphNode*> new_recurrence;
Tanya Lattnera31ad512005-02-23 02:01:42 +00001393
Tanya Lattnera6820d62004-05-08 16:12:10 +00001394 //Loop through recurrence and remove any nodes already in the partial order
Misha Brukmanb4402432005-04-21 23:30:14 +00001395 for(std::vector<MSchedGraphNode*>::const_iterator N = I->second.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001396 NE = I->second.end(); N != NE; ++N) {
Tanya Lattnera31ad512005-02-23 02:01:42 +00001397
Tanya Lattnera6820d62004-05-08 16:12:10 +00001398 bool found = false;
Misha Brukmanb4402432005-04-21 23:30:14 +00001399 for(std::vector<std::set<MSchedGraphNode*> >::iterator PO = partialOrder.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001400 PE = partialOrder.end(); PO != PE; ++PO) {
1401 if(PO->count(*N))
1402 found = true;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001403 }
Tanya Lattnera31ad512005-02-23 02:01:42 +00001404
1405 //Check if its a branch, and remove to handle special
Tanya Lattnera6820d62004-05-08 16:12:10 +00001406 if(!found) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001407 if((*N)->isBranch() && !(*N)->hasPredecessors()) {
1408 branches.push_back(*N);
1409 }
1410 else
1411 new_recurrence.insert(*N);
Tanya Lattnera31ad512005-02-23 02:01:42 +00001412 }
1413
Tanya Lattnera6820d62004-05-08 16:12:10 +00001414 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001415
Tanya Lattnera31ad512005-02-23 02:01:42 +00001416
1417 if(new_recurrence.size() > 0) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001418
Tanya Lattnera31ad512005-02-23 02:01:42 +00001419 std::vector<MSchedGraphNode*> path;
1420 std::set<MSchedGraphNode*> nodesToAdd;
1421
Tanya Lattner42ed1482005-04-22 06:32:48 +00001422 //Dump recc we are dealing with (minus nodes already in PO)
1423 DEBUG(std::cerr << "Recc: ");
1424 DEBUG(for(std::set<MSchedGraphNode*>::iterator R = new_recurrence.begin(), RE = new_recurrence.end(); R != RE; ++R) { std::cerr << **R ; });
1425
Tanya Lattnera31ad512005-02-23 02:01:42 +00001426 //Add nodes that connect this recurrence to recurrences in the partial path
1427 for(std::set<MSchedGraphNode*>::iterator N = new_recurrence.begin(),
Tanya Lattner13417b52005-03-23 01:47:20 +00001428 NE = new_recurrence.end(); N != NE; ++N)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001429 searchPath(*N, path, nodesToAdd, new_recurrence);
Misha Brukmanb4402432005-04-21 23:30:14 +00001430
Tanya Lattnera31ad512005-02-23 02:01:42 +00001431 //Add nodes to this recurrence if they are not already in the partial order
1432 for(std::set<MSchedGraphNode*>::iterator N = nodesToAdd.begin(), NE = nodesToAdd.end();
Jeff Cohen33a030e2005-07-27 05:53:44 +00001433 N != NE; ++N) {
1434 bool found = false;
1435 for(std::vector<std::set<MSchedGraphNode*> >::iterator PO = partialOrder.begin(),
1436 PE = partialOrder.end(); PO != PE; ++PO) {
1437 if(PO->count(*N))
1438 found = true;
1439 }
1440 if(!found) {
1441 assert("FOUND CONNECTOR");
1442 new_recurrence.insert(*N);
1443 }
Tanya Lattnera31ad512005-02-23 02:01:42 +00001444 }
1445
Tanya Lattnera6820d62004-05-08 16:12:10 +00001446 partialOrder.push_back(new_recurrence);
Tanya Lattnera31ad512005-02-23 02:01:42 +00001447
Tanya Lattner42ed1482005-04-22 06:32:48 +00001448
1449 //Dump out partial order
1450 DEBUG(for(std::vector<std::set<MSchedGraphNode*> >::iterator I = partialOrder.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001451 E = partialOrder.end(); I !=E; ++I) {
1452 std::cerr << "Start set in PO\n";
1453 for(std::set<MSchedGraphNode*>::iterator J = I->begin(), JE = I->end(); J != JE; ++J)
1454 std::cerr << "PO:" << **J << "\n";
1455 });
Tanya Lattner42ed1482005-04-22 06:32:48 +00001456
Tanya Lattnera31ad512005-02-23 02:01:42 +00001457 }
Tanya Lattnera6820d62004-05-08 16:12:10 +00001458 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001459
Tanya Lattnera6820d62004-05-08 16:12:10 +00001460 //Add any nodes that are not already in the partial order
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001461 //Add them in a set, one set per connected component
1462 std::set<MSchedGraphNode*> lastNodes;
Tanya Lattner13417b52005-03-23 01:47:20 +00001463 std::set<MSchedGraphNode*> noPredNodes;
Misha Brukmanb4402432005-04-21 23:30:14 +00001464 for(std::map<MSchedGraphNode*, MSNodeAttributes>::iterator I = nodeToAttributesMap.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001465 E = nodeToAttributesMap.end(); I != E; ++I) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001466
Tanya Lattnera6820d62004-05-08 16:12:10 +00001467 bool found = false;
Misha Brukmanb4402432005-04-21 23:30:14 +00001468
Tanya Lattnera6820d62004-05-08 16:12:10 +00001469 //Check if its already in our partial order, if not add it to the final vector
Misha Brukmanb4402432005-04-21 23:30:14 +00001470 for(std::vector<std::set<MSchedGraphNode*> >::iterator PO = partialOrder.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001471 PE = partialOrder.end(); PO != PE; ++PO) {
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001472 if(PO->count(I->first))
Jeff Cohen33a030e2005-07-27 05:53:44 +00001473 found = true;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001474 }
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00001475 if(!found)
1476 lastNodes.insert(I->first);
Tanya Lattnera6820d62004-05-08 16:12:10 +00001477 }
1478
Tanya Lattner13417b52005-03-23 01:47:20 +00001479 //For each node w/out preds, see if there is a path to one of the
1480 //recurrences, and if so add them to that current recc
1481 /*for(std::set<MSchedGraphNode*>::iterator N = noPredNodes.begin(), NE = noPredNodes.end();
1482 N != NE; ++N) {
1483 DEBUG(std::cerr << "No Pred Path from: " << **N << "\n");
Misha Brukmanb4402432005-04-21 23:30:14 +00001484 for(std::vector<std::set<MSchedGraphNode*> >::iterator PO = partialOrder.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001485 PE = partialOrder.end(); PO != PE; ++PO) {
Tanya Lattner13417b52005-03-23 01:47:20 +00001486 std::vector<MSchedGraphNode*> path;
1487 pathToRecc(*N, path, *PO, lastNodes);
1488 }
1489 }*/
Misha Brukmanb4402432005-04-21 23:30:14 +00001490
Tanya Lattner13417b52005-03-23 01:47:20 +00001491
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001492 //Break up remaining nodes that are not in the partial order
Tanya Lattner13417b52005-03-23 01:47:20 +00001493 ///into their connected compoenents
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00001494 while(lastNodes.size() > 0) {
Tanya Lattner13417b52005-03-23 01:47:20 +00001495 std::set<MSchedGraphNode*> ccSet;
1496 connectedComponentSet(*(lastNodes.begin()),ccSet, lastNodes);
1497 if(ccSet.size() > 0)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001498 partialOrder.push_back(ccSet);
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00001499 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001500
1501
Tanya Lattner13c71ca2004-11-24 01:49:10 +00001502 //Clean up branches by putting them in final order
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00001503 assert(branches.size() == 0 && "We should not have any branches in our graph");
Tanya Lattnera6820d62004-05-08 16:12:10 +00001504}
1505
1506
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001507void ModuloSchedulingPass::connectedComponentSet(MSchedGraphNode *node, std::set<MSchedGraphNode*> &ccSet, std::set<MSchedGraphNode*> &lastNodes) {
1508
Tanya Lattner13c71ca2004-11-24 01:49:10 +00001509//Add to final set
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00001510 if( !ccSet.count(node) && lastNodes.count(node)) {
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001511 lastNodes.erase(node);
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00001512 ccSet.insert(node);
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001513 }
1514 else
1515 return;
Misha Brukmanb4402432005-04-21 23:30:14 +00001516
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001517 //Loop over successors and recurse if we have not seen this node before
1518 for(MSchedGraphNode::succ_iterator node_succ = node->succ_begin(), end=node->succ_end(); node_succ != end; ++node_succ) {
1519 connectedComponentSet(*node_succ, ccSet, lastNodes);
1520 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001521
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001522}
1523
1524void ModuloSchedulingPass::predIntersect(std::set<MSchedGraphNode*> &CurrentSet, std::set<MSchedGraphNode*> &IntersectResult) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001525
Tanya Lattnera6820d62004-05-08 16:12:10 +00001526 for(unsigned j=0; j < FinalNodeOrder.size(); ++j) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001527 for(MSchedGraphNode::pred_iterator P = FinalNodeOrder[j]->pred_begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001528 E = FinalNodeOrder[j]->pred_end(); P != E; ++P) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001529
Tanya Lattnera6820d62004-05-08 16:12:10 +00001530 //Check if we are supposed to ignore this edge or not
1531 if(ignoreEdge(*P,FinalNodeOrder[j]))
Jeff Cohen33a030e2005-07-27 05:53:44 +00001532 continue;
1533
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001534 if(CurrentSet.count(*P))
Jeff Cohen33a030e2005-07-27 05:53:44 +00001535 if(std::find(FinalNodeOrder.begin(), FinalNodeOrder.end(), *P) == FinalNodeOrder.end())
1536 IntersectResult.insert(*P);
Tanya Lattnera6820d62004-05-08 16:12:10 +00001537 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001538 }
Tanya Lattnera6820d62004-05-08 16:12:10 +00001539}
1540
Tanya Lattnera6820d62004-05-08 16:12:10 +00001541
Misha Brukmanb4402432005-04-21 23:30:14 +00001542
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001543
1544
1545void ModuloSchedulingPass::succIntersect(std::set<MSchedGraphNode*> &CurrentSet, std::set<MSchedGraphNode*> &IntersectResult) {
1546
Tanya Lattnera6820d62004-05-08 16:12:10 +00001547 for(unsigned j=0; j < FinalNodeOrder.size(); ++j) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001548 for(MSchedGraphNode::succ_iterator P = FinalNodeOrder[j]->succ_begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001549 E = FinalNodeOrder[j]->succ_end(); P != E; ++P) {
Tanya Lattnera6820d62004-05-08 16:12:10 +00001550
1551 //Check if we are supposed to ignore this edge or not
1552 if(ignoreEdge(FinalNodeOrder[j],*P))
Jeff Cohen33a030e2005-07-27 05:53:44 +00001553 continue;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001554
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001555 if(CurrentSet.count(*P))
Jeff Cohen33a030e2005-07-27 05:53:44 +00001556 if(std::find(FinalNodeOrder.begin(), FinalNodeOrder.end(), *P) == FinalNodeOrder.end())
1557 IntersectResult.insert(*P);
Tanya Lattnera6820d62004-05-08 16:12:10 +00001558 }
1559 }
1560}
1561
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001562void dumpIntersection(std::set<MSchedGraphNode*> &IntersectCurrent) {
Tanya Lattnera6820d62004-05-08 16:12:10 +00001563 std::cerr << "Intersection (";
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001564 for(std::set<MSchedGraphNode*>::iterator I = IntersectCurrent.begin(), E = IntersectCurrent.end(); I != E; ++I)
Tanya Lattnera6820d62004-05-08 16:12:10 +00001565 std::cerr << **I << ", ";
1566 std::cerr << ")\n";
1567}
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001568
1569
1570
1571void ModuloSchedulingPass::orderNodes() {
Misha Brukmanb4402432005-04-21 23:30:14 +00001572
Tanya Lattner56807c62005-02-10 17:02:58 +00001573 TIME_REGION(X, "orderNodes");
1574
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001575 int BOTTOM_UP = 0;
1576 int TOP_DOWN = 1;
1577
Tanya Lattnera6820d62004-05-08 16:12:10 +00001578 //Set default order
1579 int order = BOTTOM_UP;
1580
Misha Brukmanb4402432005-04-21 23:30:14 +00001581
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001582 //Loop over all the sets and place them in the final node order
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001583 for(std::vector<std::set<MSchedGraphNode*> >::iterator CurrentSet = partialOrder.begin(), E= partialOrder.end(); CurrentSet != E; ++CurrentSet) {
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001584
Tanya Lattnera6820d62004-05-08 16:12:10 +00001585 DEBUG(std::cerr << "Processing set in S\n");
Tanya Lattner081fbd12004-07-30 23:36:10 +00001586 DEBUG(dumpIntersection(*CurrentSet));
1587
Tanya Lattnera6820d62004-05-08 16:12:10 +00001588 //Result of intersection
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001589 std::set<MSchedGraphNode*> IntersectCurrent;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001590
Tanya Lattnera6820d62004-05-08 16:12:10 +00001591 predIntersect(*CurrentSet, IntersectCurrent);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001592
1593 //If the intersection of predecessor and current set is not empty
1594 //sort nodes bottom up
Tanya Lattnera6820d62004-05-08 16:12:10 +00001595 if(IntersectCurrent.size() != 0) {
1596 DEBUG(std::cerr << "Final Node Order Predecessors and Current Set interesection is NOT empty\n");
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001597 order = BOTTOM_UP;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001598 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001599 //If empty, use successors
1600 else {
Tanya Lattnera6820d62004-05-08 16:12:10 +00001601 DEBUG(std::cerr << "Final Node Order Predecessors and Current Set interesection is empty\n");
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001602
Tanya Lattnera6820d62004-05-08 16:12:10 +00001603 succIntersect(*CurrentSet, IntersectCurrent);
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001604
1605 //sort top-down
Tanya Lattnera6820d62004-05-08 16:12:10 +00001606 if(IntersectCurrent.size() != 0) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001607 DEBUG(std::cerr << "Final Node Order Successors and Current Set interesection is NOT empty\n");
1608 order = TOP_DOWN;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001609 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001610 else {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001611 DEBUG(std::cerr << "Final Node Order Successors and Current Set interesection is empty\n");
1612 //Find node with max ASAP in current Set
1613 MSchedGraphNode *node;
1614 int maxASAP = 0;
1615 DEBUG(std::cerr << "Using current set of size " << CurrentSet->size() << "to find max ASAP\n");
1616 for(std::set<MSchedGraphNode*>::iterator J = CurrentSet->begin(), JE = CurrentSet->end(); J != JE; ++J) {
1617 //Get node attributes
1618 MSNodeAttributes nodeAttr= nodeToAttributesMap.find(*J)->second;
1619 //assert(nodeAttr != nodeToAttributesMap.end() && "Node not in attributes map!");
1620
1621 if(maxASAP <= nodeAttr.ASAP) {
1622 maxASAP = nodeAttr.ASAP;
1623 node = *J;
1624 }
1625 }
1626 assert(node != 0 && "In node ordering node should not be null");
1627 IntersectCurrent.insert(node);
1628 order = BOTTOM_UP;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001629 }
1630 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001631
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001632 //Repeat until all nodes are put into the final order from current set
Tanya Lattnera6820d62004-05-08 16:12:10 +00001633 while(IntersectCurrent.size() > 0) {
1634
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001635 if(order == TOP_DOWN) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001636 DEBUG(std::cerr << "Order is TOP DOWN\n");
Tanya Lattnera6820d62004-05-08 16:12:10 +00001637
Jeff Cohen33a030e2005-07-27 05:53:44 +00001638 while(IntersectCurrent.size() > 0) {
1639 DEBUG(std::cerr << "Intersection is not empty, so find heighest height\n");
1640
1641 int MOB = 0;
1642 int height = 0;
1643 MSchedGraphNode *highestHeightNode = *(IntersectCurrent.begin());
1644
1645 //Find node in intersection with highest heigh and lowest MOB
1646 for(std::set<MSchedGraphNode*>::iterator I = IntersectCurrent.begin(),
1647 E = IntersectCurrent.end(); I != E; ++I) {
1648
1649 //Get current nodes properties
1650 MSNodeAttributes nodeAttr= nodeToAttributesMap.find(*I)->second;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001651
Jeff Cohen33a030e2005-07-27 05:53:44 +00001652 if(height < nodeAttr.height) {
1653 highestHeightNode = *I;
1654 height = nodeAttr.height;
1655 MOB = nodeAttr.MOB;
1656 }
1657 else if(height == nodeAttr.height) {
1658 if(MOB > nodeAttr.height) {
1659 highestHeightNode = *I;
1660 height = nodeAttr.height;
1661 MOB = nodeAttr.MOB;
1662 }
1663 }
1664 }
1665
1666 //Append our node with greatest height to the NodeOrder
1667 if(std::find(FinalNodeOrder.begin(), FinalNodeOrder.end(), highestHeightNode) == FinalNodeOrder.end()) {
1668 DEBUG(std::cerr << "Adding node to Final Order: " << *highestHeightNode << "\n");
1669 FinalNodeOrder.push_back(highestHeightNode);
1670 }
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001671
Jeff Cohen33a030e2005-07-27 05:53:44 +00001672 //Remove V from IntersectOrder
1673 IntersectCurrent.erase(std::find(IntersectCurrent.begin(),
1674 IntersectCurrent.end(), highestHeightNode));
Tanya Lattnera6820d62004-05-08 16:12:10 +00001675
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001676
Jeff Cohen33a030e2005-07-27 05:53:44 +00001677 //Intersect V's successors with CurrentSet
1678 for(MSchedGraphNode::succ_iterator P = highestHeightNode->succ_begin(),
1679 E = highestHeightNode->succ_end(); P != E; ++P) {
1680 //if(lower_bound(CurrentSet->begin(),
1681 // CurrentSet->end(), *P) != CurrentSet->end()) {
1682 if(std::find(CurrentSet->begin(), CurrentSet->end(), *P) != CurrentSet->end()) {
1683 if(ignoreEdge(highestHeightNode, *P))
1684 continue;
1685 //If not already in Intersect, add
1686 if(!IntersectCurrent.count(*P))
1687 IntersectCurrent.insert(*P);
1688 }
1689 }
1690 } //End while loop over Intersect Size
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001691
Jeff Cohen33a030e2005-07-27 05:53:44 +00001692 //Change direction
1693 order = BOTTOM_UP;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001694
Jeff Cohen33a030e2005-07-27 05:53:44 +00001695 //Reset Intersect to reflect changes in OrderNodes
1696 IntersectCurrent.clear();
1697 predIntersect(*CurrentSet, IntersectCurrent);
1698
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001699 } //End If TOP_DOWN
Jeff Cohen33a030e2005-07-27 05:53:44 +00001700
1701 //Begin if BOTTOM_UP
Tanya Lattnera6820d62004-05-08 16:12:10 +00001702 else {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001703 DEBUG(std::cerr << "Order is BOTTOM UP\n");
1704 while(IntersectCurrent.size() > 0) {
1705 DEBUG(std::cerr << "Intersection of size " << IntersectCurrent.size() << ", finding highest depth\n");
Tanya Lattnera6820d62004-05-08 16:12:10 +00001706
Jeff Cohen33a030e2005-07-27 05:53:44 +00001707 //dump intersection
1708 DEBUG(dumpIntersection(IntersectCurrent));
1709 //Get node with highest depth, if a tie, use one with lowest
1710 //MOB
1711 int MOB = 0;
1712 int depth = 0;
1713 MSchedGraphNode *highestDepthNode = *(IntersectCurrent.begin());
1714
1715 for(std::set<MSchedGraphNode*>::iterator I = IntersectCurrent.begin(),
1716 E = IntersectCurrent.end(); I != E; ++I) {
1717 //Find node attribute in graph
1718 MSNodeAttributes nodeAttr= nodeToAttributesMap.find(*I)->second;
1719
1720 if(depth < nodeAttr.depth) {
1721 highestDepthNode = *I;
1722 depth = nodeAttr.depth;
1723 MOB = nodeAttr.MOB;
1724 }
1725 else if(depth == nodeAttr.depth) {
1726 if(MOB > nodeAttr.MOB) {
1727 highestDepthNode = *I;
1728 depth = nodeAttr.depth;
1729 MOB = nodeAttr.MOB;
1730 }
1731 }
1732 }
1733
1734
Tanya Lattnera6820d62004-05-08 16:12:10 +00001735
Jeff Cohen33a030e2005-07-27 05:53:44 +00001736 //Append highest depth node to the NodeOrder
1737 if(std::find(FinalNodeOrder.begin(), FinalNodeOrder.end(), highestDepthNode) == FinalNodeOrder.end()) {
1738 DEBUG(std::cerr << "Adding node to Final Order: " << *highestDepthNode << "\n");
1739 FinalNodeOrder.push_back(highestDepthNode);
1740 }
1741 //Remove heightestDepthNode from IntersectOrder
1742 IntersectCurrent.erase(highestDepthNode);
1743
Tanya Lattnera6820d62004-05-08 16:12:10 +00001744
Jeff Cohen33a030e2005-07-27 05:53:44 +00001745 //Intersect heightDepthNode's pred with CurrentSet
1746 for(MSchedGraphNode::pred_iterator P = highestDepthNode->pred_begin(),
1747 E = highestDepthNode->pred_end(); P != E; ++P) {
1748 if(CurrentSet->count(*P)) {
1749 if(ignoreEdge(*P, highestDepthNode))
1750 continue;
1751
1752 //If not already in Intersect, add
1753 if(!IntersectCurrent.count(*P))
1754 IntersectCurrent.insert(*P);
1755 }
1756 }
1757
1758 } //End while loop over Intersect Size
1759
1760 //Change order
1761 order = TOP_DOWN;
1762
1763 //Reset IntersectCurrent to reflect changes in OrderNodes
1764 IntersectCurrent.clear();
1765 succIntersect(*CurrentSet, IntersectCurrent);
1766 } //End if BOTTOM_DOWN
1767
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00001768 DEBUG(std::cerr << "Current Intersection Size: " << IntersectCurrent.size() << "\n");
Tanya Lattnera6820d62004-05-08 16:12:10 +00001769 }
1770 //End Wrapping while loop
Misha Brukmanb4402432005-04-21 23:30:14 +00001771 DEBUG(std::cerr << "Ending Size of Current Set: " << CurrentSet->size() << "\n");
Tanya Lattnera6820d62004-05-08 16:12:10 +00001772 }//End for over all sets of nodes
Misha Brukmanb4402432005-04-21 23:30:14 +00001773
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00001774 //FIXME: As the algorithm stands it will NEVER add an instruction such as ba (with no
1775 //data dependencies) to the final order. We add this manually. It will always be
1776 //in the last set of S since its not part of a recurrence
1777 //Loop over all the sets and place them in the final node order
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001778 std::vector<std::set<MSchedGraphNode*> > ::reverse_iterator LastSet = partialOrder.rbegin();
1779 for(std::set<MSchedGraphNode*>::iterator CurrentNode = LastSet->begin(), LastNode = LastSet->end();
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00001780 CurrentNode != LastNode; ++CurrentNode) {
1781 if((*CurrentNode)->getInst()->getOpcode() == V9::BA)
1782 FinalNodeOrder.push_back(*CurrentNode);
1783 }
Tanya Lattnera6820d62004-05-08 16:12:10 +00001784 //Return final Order
1785 //return FinalNodeOrder;
1786}
1787
Tanya Lattner42ed1482005-04-22 06:32:48 +00001788bool ModuloSchedulingPass::computeSchedule(const MachineBasicBlock *BB, MSchedGraph *MSG) {
Tanya Lattnera6820d62004-05-08 16:12:10 +00001789
Tanya Lattner56807c62005-02-10 17:02:58 +00001790 TIME_REGION(X, "computeSchedule");
1791
Tanya Lattnera6820d62004-05-08 16:12:10 +00001792 bool success = false;
Misha Brukmanb4402432005-04-21 23:30:14 +00001793
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001794 //FIXME: Should be set to max II of the original loop
1795 //Cap II in order to prevent infinite loop
Tanya Lattner42ed1482005-04-22 06:32:48 +00001796 int capII = MSG->totalDelay();
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001797
Tanya Lattnera6820d62004-05-08 16:12:10 +00001798 while(!success) {
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00001799
Tanya Lattnera31ad512005-02-23 02:01:42 +00001800 //Keep track of branches, but do not insert into the schedule
1801 std::vector<MSchedGraphNode*> branches;
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00001802
Tanya Lattnera6820d62004-05-08 16:12:10 +00001803 //Loop over the final node order and process each node
Misha Brukmanb4402432005-04-21 23:30:14 +00001804 for(std::vector<MSchedGraphNode*>::iterator I = FinalNodeOrder.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00001805 E = FinalNodeOrder.end(); I != E; ++I) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001806
Tanya Lattnera6820d62004-05-08 16:12:10 +00001807 //CalculateEarly and Late start
Tanya Lattner4d0ee752005-04-30 23:07:59 +00001808 bool initialLSVal = false;
1809 bool initialESVal = false;
1810 int EarlyStart = 0;
1811 int LateStart = 0;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001812 bool hasSucc = false;
1813 bool hasPred = false;
Tanya Lattner13417b52005-03-23 01:47:20 +00001814 bool sched;
1815
1816 if((*I)->isBranch())
Jeff Cohen33a030e2005-07-27 05:53:44 +00001817 if((*I)->hasPredecessors())
1818 sched = true;
1819 else
1820 sched = false;
Tanya Lattner13417b52005-03-23 01:47:20 +00001821 else
Jeff Cohen33a030e2005-07-27 05:53:44 +00001822 sched = true;
Tanya Lattner13417b52005-03-23 01:47:20 +00001823
1824 if(sched) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001825 //Loop over nodes in the schedule and determine if they are predecessors
1826 //or successors of the node we are trying to schedule
1827 for(MSSchedule::schedule_iterator nodesByCycle = schedule.begin(), nodesByCycleEnd = schedule.end();
1828 nodesByCycle != nodesByCycleEnd; ++nodesByCycle) {
1829
1830 //For this cycle, get the vector of nodes schedule and loop over it
1831 for(std::vector<MSchedGraphNode*>::iterator schedNode = nodesByCycle->second.begin(), SNE = nodesByCycle->second.end(); schedNode != SNE; ++schedNode) {
1832
1833 if((*I)->isPredecessor(*schedNode)) {
1834 int diff = (*I)->getInEdge(*schedNode).getIteDiff();
1835 int ES_Temp = nodesByCycle->first + (*schedNode)->getLatency() - diff * II;
1836 DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << nodesByCycle->first << "\n");
1837 DEBUG(std::cerr << "Temp EarlyStart: " << ES_Temp << " Prev EarlyStart: " << EarlyStart << "\n");
1838 if(initialESVal)
1839 EarlyStart = std::max(EarlyStart, ES_Temp);
1840 else {
1841 EarlyStart = ES_Temp;
1842 initialESVal = true;
1843 }
1844 hasPred = true;
1845 }
1846 if((*I)->isSuccessor(*schedNode)) {
1847 int diff = (*schedNode)->getInEdge(*I).getIteDiff();
1848 int LS_Temp = nodesByCycle->first - (*I)->getLatency() + diff * II;
1849 DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << nodesByCycle->first << "\n");
1850 DEBUG(std::cerr << "Temp LateStart: " << LS_Temp << " Prev LateStart: " << LateStart << "\n");
1851 if(initialLSVal)
1852 LateStart = std::min(LateStart, LS_Temp);
1853 else {
1854 LateStart = LS_Temp;
1855 initialLSVal = true;
1856 }
1857 hasSucc = true;
1858 }
1859 }
1860 }
Tanya Lattnera6820d62004-05-08 16:12:10 +00001861 }
Tanya Lattnera066df62004-05-26 06:27:18 +00001862 else {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001863 branches.push_back(*I);
1864 continue;
Tanya Lattnera31ad512005-02-23 02:01:42 +00001865 }
1866
1867 //Check if this node is a pred or succ to a branch, and restrict its placement
1868 //even though the branch is not in the schedule
Tanya Lattner4d0ee752005-04-30 23:07:59 +00001869 /*int count = branches.size();
Tanya Lattnera31ad512005-02-23 02:01:42 +00001870 for(std::vector<MSchedGraphNode*>::iterator B = branches.begin(), BE = branches.end();
Jeff Cohen33a030e2005-07-27 05:53:44 +00001871 B != BE; ++B) {
1872 if((*I)->isPredecessor(*B)) {
1873 int diff = (*I)->getInEdge(*B).getIteDiff();
1874 int ES_Temp = (II+count-1) + (*B)->getLatency() - diff * II;
1875 DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << (II+count)-1 << "\n");
1876 DEBUG(std::cerr << "Temp EarlyStart: " << ES_Temp << " Prev EarlyStart: " << EarlyStart << "\n");
1877 EarlyStart = std::max(EarlyStart, ES_Temp);
1878 hasPred = true;
1879 }
1880
1881 if((*I)->isSuccessor(*B)) {
1882 int diff = (*B)->getInEdge(*I).getIteDiff();
1883 int LS_Temp = (II+count-1) - (*I)->getLatency() + diff * II;
1884 DEBUG(std::cerr << "Diff: " << diff << " Cycle: " << (II+count-1) << "\n");
1885 DEBUG(std::cerr << "Temp LateStart: " << LS_Temp << " Prev LateStart: " << LateStart << "\n");
1886 LateStart = std::min(LateStart, LS_Temp);
1887 hasSucc = true;
1888 }
1889
1890 count--;
Tanya Lattner4d0ee752005-04-30 23:07:59 +00001891 }*/
Misha Brukmanb4402432005-04-21 23:30:14 +00001892
Tanya Lattnera6820d62004-05-08 16:12:10 +00001893 //Check if the node has no pred or successors and set Early Start to its ASAP
1894 if(!hasSucc && !hasPred)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001895 EarlyStart = nodeToAttributesMap.find(*I)->second.ASAP;
Misha Brukmanb4402432005-04-21 23:30:14 +00001896
Tanya Lattnera31ad512005-02-23 02:01:42 +00001897 DEBUG(std::cerr << "Has Successors: " << hasSucc << ", Has Pred: " << hasPred << "\n");
1898 DEBUG(std::cerr << "EarlyStart: " << EarlyStart << ", LateStart: " << LateStart << "\n");
1899
Tanya Lattnera6820d62004-05-08 16:12:10 +00001900 //Now, try to schedule this node depending upon its pred and successor in the schedule
1901 //already
1902 if(!hasSucc && hasPred)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001903 success = scheduleNode(*I, EarlyStart, (EarlyStart + II -1));
Tanya Lattnera6820d62004-05-08 16:12:10 +00001904 else if(!hasPred && hasSucc)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001905 success = scheduleNode(*I, LateStart, (LateStart - II +1));
Tanya Lattnerc227ad22005-01-18 04:15:41 +00001906 else if(hasPred && hasSucc) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001907 if(EarlyStart > LateStart) {
1908 success = false;
1909 //LateStart = EarlyStart;
1910 DEBUG(std::cerr << "Early Start can not be later then the late start cycle, schedule fails\n");
1911 }
1912 else
1913 success = scheduleNode(*I, EarlyStart, std::min(LateStart, (EarlyStart + II -1)));
Tanya Lattnerc227ad22005-01-18 04:15:41 +00001914 }
Tanya Lattnera6820d62004-05-08 16:12:10 +00001915 else
Jeff Cohen33a030e2005-07-27 05:53:44 +00001916 success = scheduleNode(*I, EarlyStart, EarlyStart + II - 1);
Misha Brukmanb4402432005-04-21 23:30:14 +00001917
Tanya Lattnera6820d62004-05-08 16:12:10 +00001918 if(!success) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001919 ++II;
1920 schedule.clear();
1921 break;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001922 }
Misha Brukmanb4402432005-04-21 23:30:14 +00001923
Tanya Lattnera6820d62004-05-08 16:12:10 +00001924 }
Tanya Lattnera066df62004-05-26 06:27:18 +00001925
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001926 if(success) {
1927 DEBUG(std::cerr << "Constructing Schedule Kernel\n");
Tanya Lattner13417b52005-03-23 01:47:20 +00001928 success = schedule.constructKernel(II, branches, indVarInstrs[BB]);
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001929 DEBUG(std::cerr << "Done Constructing Schedule Kernel\n");
1930 if(!success) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00001931 ++II;
1932 schedule.clear();
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001933 }
Tanya Lattner13417b52005-03-23 01:47:20 +00001934 DEBUG(std::cerr << "Final II: " << II << "\n");
Tanya Lattnera066df62004-05-26 06:27:18 +00001935 }
Tanya Lattner8bf63742005-06-17 04:00:57 +00001936
Misha Brukmanb4402432005-04-21 23:30:14 +00001937
Tanya Lattnera31ad512005-02-23 02:01:42 +00001938 if(II >= capII) {
1939 DEBUG(std::cerr << "Maximum II reached, giving up\n");
Tanya Lattner201e9722004-12-02 07:22:15 +00001940 return false;
Tanya Lattnera31ad512005-02-23 02:01:42 +00001941 }
Tanya Lattner201e9722004-12-02 07:22:15 +00001942
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00001943 assert(II < capII && "The II should not exceed the original loop number of cycles");
Misha Brukmanb4402432005-04-21 23:30:14 +00001944 }
Tanya Lattner201e9722004-12-02 07:22:15 +00001945 return true;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001946}
1947
1948
Misha Brukmanb4402432005-04-21 23:30:14 +00001949bool ModuloSchedulingPass::scheduleNode(MSchedGraphNode *node,
Jeff Cohen33a030e2005-07-27 05:53:44 +00001950 int start, int end) {
Tanya Lattnera6820d62004-05-08 16:12:10 +00001951 bool success = false;
1952
1953 DEBUG(std::cerr << *node << " (Start Cycle: " << start << ", End Cycle: " << end << ")\n");
1954
Tanya Lattnera6820d62004-05-08 16:12:10 +00001955 //Make sure start and end are not negative
Tanya Lattner13417b52005-03-23 01:47:20 +00001956 //if(start < 0) {
1957 //start = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +00001958
Tanya Lattner13417b52005-03-23 01:47:20 +00001959 //}
1960 //if(end < 0)
1961 //end = 0;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001962
1963 bool forward = true;
1964 if(start > end)
1965 forward = false;
1966
Tanya Lattnera6820d62004-05-08 16:12:10 +00001967 bool increaseSC = true;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001968 int cycle = start ;
1969
1970
1971 while(increaseSC) {
Misha Brukmanb4402432005-04-21 23:30:14 +00001972
Tanya Lattnera6820d62004-05-08 16:12:10 +00001973 increaseSC = false;
1974
Tanya Lattner8bf63742005-06-17 04:00:57 +00001975 increaseSC = schedule.insert(node, cycle, II);
Misha Brukmanb4402432005-04-21 23:30:14 +00001976
1977 if(!increaseSC)
Tanya Lattnera6820d62004-05-08 16:12:10 +00001978 return true;
1979
1980 //Increment cycle to try again
1981 if(forward) {
1982 ++cycle;
1983 DEBUG(std::cerr << "Increase cycle: " << cycle << "\n");
1984 if(cycle > end)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001985 return false;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001986 }
1987 else {
1988 --cycle;
1989 DEBUG(std::cerr << "Decrease cycle: " << cycle << "\n");
1990 if(cycle < end)
Jeff Cohen33a030e2005-07-27 05:53:44 +00001991 return false;
Tanya Lattnera6820d62004-05-08 16:12:10 +00001992 }
1993 }
Tanya Lattnera066df62004-05-26 06:27:18 +00001994
Tanya Lattnera6820d62004-05-08 16:12:10 +00001995 return success;
Tanya Lattnerdd10fbe2004-03-01 02:50:01 +00001996}
Tanya Lattnera066df62004-05-26 06:27:18 +00001997
Tanya Lattner13417b52005-03-23 01:47:20 +00001998void ModuloSchedulingPass::writePrologues(std::vector<MachineBasicBlock *> &prologues, MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_prologues, std::map<const Value*, std::pair<const MachineInstr*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation) {
Tanya Lattnera066df62004-05-26 06:27:18 +00001999
Tanya Lattner081fbd12004-07-30 23:36:10 +00002000 //Keep a map to easily know whats in the kernel
Tanya Lattnera066df62004-05-26 06:27:18 +00002001 std::map<int, std::set<const MachineInstr*> > inKernel;
2002 int maxStageCount = 0;
2003
Tanya Lattner201e9722004-12-02 07:22:15 +00002004 //Keep a map of new values we consumed in case they need to be added back
2005 std::map<Value*, std::map<int, Value*> > consumedValues;
2006
Tanya Lattner081fbd12004-07-30 23:36:10 +00002007 MSchedGraphNode *branch = 0;
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00002008 MSchedGraphNode *BAbranch = 0;
Tanya Lattner081fbd12004-07-30 23:36:10 +00002009
Tanya Lattner91964492005-03-29 20:35:10 +00002010 DEBUG(schedule.print(std::cerr));
Tanya Lattnerab9cf272004-11-22 20:41:24 +00002011
Tanya Lattner201e9722004-12-02 07:22:15 +00002012 std::vector<MSchedGraphNode*> branches;
2013
Tanya Lattnera066df62004-05-26 06:27:18 +00002014 for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
2015 maxStageCount = std::max(maxStageCount, I->second);
Misha Brukmanb4402432005-04-21 23:30:14 +00002016
Tanya Lattnera066df62004-05-26 06:27:18 +00002017 //Put int the map so we know what instructions in each stage are in the kernel
Tanya Lattner13417b52005-03-23 01:47:20 +00002018 DEBUG(std::cerr << "Inserting instruction " << *(I->first) << " into map at stage " << I->second << "\n");
2019 inKernel[I->second].insert(I->first);
Tanya Lattnera066df62004-05-26 06:27:18 +00002020 }
2021
Tanya Lattner081fbd12004-07-30 23:36:10 +00002022 //Get target information to look at machine operands
2023 const TargetInstrInfo *mii = target.getInstrInfo();
2024
2025 //Now write the prologues
2026 for(int i = 0; i < maxStageCount; ++i) {
2027 BasicBlock *llvmBB = new BasicBlock("PROLOGUE", (Function*) (origBB->getBasicBlock()->getParent()));
Tanya Lattnera066df62004-05-26 06:27:18 +00002028 MachineBasicBlock *machineBB = new MachineBasicBlock(llvmBB);
Misha Brukmanb4402432005-04-21 23:30:14 +00002029
Tanya Lattner081fbd12004-07-30 23:36:10 +00002030 DEBUG(std::cerr << "i=" << i << "\n");
Tanya Lattner13417b52005-03-23 01:47:20 +00002031 for(int j = i; j >= 0; --j) {
Tanya Lattner081fbd12004-07-30 23:36:10 +00002032 for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002033 if(inKernel[j].count(&*MI)) {
2034 MachineInstr *instClone = MI->clone();
2035 machineBB->push_back(instClone);
2036
2037 //If its a branch, insert a nop
2038 if(mii->isBranch(instClone->getOpcode()))
2039 BuildMI(machineBB, V9::NOP, 0);
2040
Misha Brukmanb4402432005-04-21 23:30:14 +00002041
Jeff Cohen33a030e2005-07-27 05:53:44 +00002042 DEBUG(std::cerr << "Cloning: " << *MI << "\n");
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002043
Jeff Cohen33a030e2005-07-27 05:53:44 +00002044 //After cloning, we may need to save the value that this instruction defines
2045 for(unsigned opNum=0; opNum < MI->getNumOperands(); ++opNum) {
2046 Instruction *tmp;
2047
2048 //get machine operand
2049 MachineOperand &mOp = instClone->getOperand(opNum);
2050 if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
Tanya Lattner081fbd12004-07-30 23:36:10 +00002051
Jeff Cohen33a030e2005-07-27 05:53:44 +00002052 //Check if this is a value we should save
2053 if(valuesToSave.count(mOp.getVRegValue())) {
2054 //Save copy in tmpInstruction
2055 tmp = new TmpInstruction(mOp.getVRegValue());
2056
2057 //Add TmpInstruction to safe LLVM Instruction MCFI
2058 MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(defaultInst);
2059 tempMvec.addTemp((Value*) tmp);
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002060
Jeff Cohen33a030e2005-07-27 05:53:44 +00002061 DEBUG(std::cerr << "Value: " << *(mOp.getVRegValue()) << " New Value: " << *tmp << " Stage: " << i << "\n");
2062
2063 newValues[mOp.getVRegValue()][i]= tmp;
2064 newValLocation[tmp] = machineBB;
Tanya Lattner081fbd12004-07-30 23:36:10 +00002065
Jeff Cohen33a030e2005-07-27 05:53:44 +00002066 DEBUG(std::cerr << "Machine Instr Operands: " << *(mOp.getVRegValue()) << ", 0, " << *tmp << "\n");
2067
2068 //Create machine instruction and put int machineBB
2069 MachineInstr *saveValue;
2070 if(mOp.getVRegValue()->getType() == Type::FloatTy)
2071 saveValue = BuildMI(machineBB, V9::FMOVS, 3).addReg(mOp.getVRegValue()).addRegDef(tmp);
2072 else if(mOp.getVRegValue()->getType() == Type::DoubleTy)
2073 saveValue = BuildMI(machineBB, V9::FMOVD, 3).addReg(mOp.getVRegValue()).addRegDef(tmp);
2074 else
2075 saveValue = BuildMI(machineBB, V9::ORr, 3).addReg(mOp.getVRegValue()).addImm(0).addRegDef(tmp);
2076
Tanya Lattner13417b52005-03-23 01:47:20 +00002077
Jeff Cohen33a030e2005-07-27 05:53:44 +00002078 DEBUG(std::cerr << "Created new machine instr: " << *saveValue << "\n");
2079 }
2080 }
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002081
Jeff Cohen33a030e2005-07-27 05:53:44 +00002082 //We may also need to update the value that we use if its from an earlier prologue
2083 if(j != 0) {
2084 if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
2085 if(newValues.count(mOp.getVRegValue())) {
2086 if(newValues[mOp.getVRegValue()].count(i-1)) {
2087 Value *oldV = mOp.getVRegValue();
2088 DEBUG(std::cerr << "Replaced this value: " << mOp.getVRegValue() << " With:" << (newValues[mOp.getVRegValue()][i-1]) << "\n");
2089 //Update the operand with the right value
2090 mOp.setValueReg(newValues[mOp.getVRegValue()][i-1]);
Tanya Lattner201e9722004-12-02 07:22:15 +00002091
Jeff Cohen33a030e2005-07-27 05:53:44 +00002092 //Remove this value since we have consumed it
2093 //NOTE: Should this only be done if j != maxStage?
2094 consumedValues[oldV][i-1] = (newValues[oldV][i-1]);
2095 DEBUG(std::cerr << "Deleted value: " << consumedValues[oldV][i-1] << "\n");
2096 newValues[oldV].erase(i-1);
2097 }
2098 }
2099 else
2100 if(consumedValues.count(mOp.getVRegValue()))
2101 assert(!consumedValues[mOp.getVRegValue()].count(i-1) && "Found a case where we need the value");
2102 }
2103 }
2104 }
2105 }
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002106 }
Tanya Lattnera066df62004-05-26 06:27:18 +00002107 }
2108
Tanya Lattner8bf63742005-06-17 04:00:57 +00002109 MachineFunction *F = (((MachineBasicBlock*)origBB)->getParent());
2110 MachineFunction::BasicBlockListType &BL = F->getBasicBlockList();
2111 MachineFunction::BasicBlockListType::iterator BLI = origBB;
2112 assert(BLI != BL.end() && "Must find original BB in machine function\n");
2113 BL.insert(BLI,machineBB);
Tanya Lattnera066df62004-05-26 06:27:18 +00002114 prologues.push_back(machineBB);
2115 llvm_prologues.push_back(llvmBB);
2116 }
2117}
2118
Tanya Lattner13417b52005-03-23 01:47:20 +00002119void ModuloSchedulingPass::writeEpilogues(std::vector<MachineBasicBlock *> &epilogues, const MachineBasicBlock *origBB, std::vector<BasicBlock*> &llvm_epilogues, std::map<const Value*, std::pair<const MachineInstr*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues,std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs ) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002120
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002121 std::map<int, std::set<const MachineInstr*> > inKernel;
Misha Brukmanb4402432005-04-21 23:30:14 +00002122
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002123 for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002124
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002125 //Ignore the branch, we will handle this separately
Tanya Lattner13417b52005-03-23 01:47:20 +00002126 //if(I->first->isBranch())
2127 //continue;
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002128
2129 //Put int the map so we know what instructions in each stage are in the kernel
Tanya Lattner13417b52005-03-23 01:47:20 +00002130 inKernel[I->second].insert(I->first);
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002131 }
2132
Tanya Lattner081fbd12004-07-30 23:36:10 +00002133 std::map<Value*, Value*> valPHIs;
2134
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002135 //some debug stuff, will remove later
2136 DEBUG(for(std::map<Value*, std::map<int, Value*> >::iterator V = newValues.begin(), E = newValues.end(); V !=E; ++V) {
2137 std::cerr << "Old Value: " << *(V->first) << "\n";
2138 for(std::map<int, Value*>::iterator I = V->second.begin(), IE = V->second.end(); I != IE; ++I)
2139 std::cerr << "Stage: " << I->first << " Value: " << *(I->second) << "\n";
2140 });
2141
2142 //some debug stuff, will remove later
2143 DEBUG(for(std::map<Value*, std::map<int, Value*> >::iterator V = kernelPHIs.begin(), E = kernelPHIs.end(); V !=E; ++V) {
2144 std::cerr << "Old Value: " << *(V->first) << "\n";
2145 for(std::map<int, Value*>::iterator I = V->second.begin(), IE = V->second.end(); I != IE; ++I)
2146 std::cerr << "Stage: " << I->first << " Value: " << *(I->second) << "\n";
2147 });
2148
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002149 //Now write the epilogues
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002150 for(int i = schedule.getMaxStage()-1; i >= 0; --i) {
Tanya Lattner081fbd12004-07-30 23:36:10 +00002151 BasicBlock *llvmBB = new BasicBlock("EPILOGUE", (Function*) (origBB->getBasicBlock()->getParent()));
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002152 MachineBasicBlock *machineBB = new MachineBasicBlock(llvmBB);
Misha Brukmanb4402432005-04-21 23:30:14 +00002153
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002154 DEBUG(std::cerr << " Epilogue #: " << i << "\n");
Tanya Lattner081fbd12004-07-30 23:36:10 +00002155
Tanya Lattner081fbd12004-07-30 23:36:10 +00002156
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002157 std::map<Value*, int> inEpilogue;
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002158
2159 for(MachineBasicBlock::const_iterator MI = origBB->begin(), ME = origBB->end(); ME != MI; ++MI) {
2160 for(int j=schedule.getMaxStage(); j > i; --j) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002161 if(inKernel[j].count(&*MI)) {
2162 DEBUG(std::cerr << "Cloning instruction " << *MI << "\n");
2163 MachineInstr *clone = MI->clone();
2164
2165 //Update operands that need to use the result from the phi
2166 for(unsigned opNum=0; opNum < clone->getNumOperands(); ++opNum) {
2167 //get machine operand
2168 const MachineOperand &mOp = clone->getOperand(opNum);
2169
2170 if((mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse())) {
2171
2172 DEBUG(std::cerr << "Writing PHI for " << (mOp.getVRegValue()) << "\n");
2173
2174 //If this is the last instructions for the max iterations ago, don't update operands
2175 if(inEpilogue.count(mOp.getVRegValue()))
2176 if(inEpilogue[mOp.getVRegValue()] == i)
2177 continue;
2178
2179 //Quickly write appropriate phis for this operand
2180 if(newValues.count(mOp.getVRegValue())) {
2181 if(newValues[mOp.getVRegValue()].count(i)) {
2182 Instruction *tmp = new TmpInstruction(newValues[mOp.getVRegValue()][i]);
2183
2184 //Get machine code for this instruction
2185 MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(defaultInst);
2186 tempMvec.addTemp((Value*) tmp);
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002187
Jeff Cohen33a030e2005-07-27 05:53:44 +00002188 //assert of no kernelPHI for this value
2189 assert(kernelPHIs[mOp.getVRegValue()][i] !=0 && "Must have final kernel phi to construct epilogue phi");
Tanya Lattner13417b52005-03-23 01:47:20 +00002190
Jeff Cohen33a030e2005-07-27 05:53:44 +00002191 MachineInstr *saveValue = BuildMI(machineBB, V9::PHI, 3).addReg(newValues[mOp.getVRegValue()][i]).addReg(kernelPHIs[mOp.getVRegValue()][i]).addRegDef(tmp);
2192 DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
2193 valPHIs[mOp.getVRegValue()] = tmp;
2194 }
2195 }
2196
2197 if(valPHIs.count(mOp.getVRegValue())) {
2198 //Update the operand in the cloned instruction
2199 clone->getOperand(opNum).setValueReg(valPHIs[mOp.getVRegValue()]);
2200 }
2201 }
2202 else if((mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef())) {
2203 inEpilogue[mOp.getVRegValue()] = i;
2204 }
2205 }
2206 machineBB->push_back(clone);
2207 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002208 }
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002209 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002210
Tanya Lattner8bf63742005-06-17 04:00:57 +00002211 MachineFunction *F = (((MachineBasicBlock*)origBB)->getParent());
2212 MachineFunction::BasicBlockListType &BL = F->getBasicBlockList();
2213 MachineFunction::BasicBlockListType::iterator BLI = (MachineBasicBlock*) origBB;
2214 assert(BLI != BL.end() && "Must find original BB in machine function\n");
2215 BL.insert(BLI,machineBB);
2216 epilogues.push_back(machineBB);
2217 llvm_epilogues.push_back(llvmBB);
2218
2219 DEBUG(std::cerr << "EPILOGUE #" << i << "\n");
2220 DEBUG(machineBB->print(std::cerr));
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002221 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002222}
2223
Tanya Lattner13417b52005-03-23 01:47:20 +00002224void ModuloSchedulingPass::writeKernel(BasicBlock *llvmBB, MachineBasicBlock *machineBB, std::map<const Value*, std::pair<const MachineInstr*, int> > &valuesToSave, std::map<Value*, std::map<int, Value*> > &newValues, std::map<Value*, MachineBasicBlock*> &newValLocation, std::map<Value*, std::map<int, Value*> > &kernelPHIs) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002225
Tanya Lattner081fbd12004-07-30 23:36:10 +00002226 //Keep track of operands that are read and saved from a previous iteration. The new clone
2227 //instruction will use the result of the phi instead.
2228 std::map<Value*, Value*> finalPHIValue;
2229 std::map<Value*, Value*> kernelValue;
2230
Tanya Lattnerc0d9dcd2004-12-03 05:25:22 +00002231 //Branches are a special case
2232 std::vector<MachineInstr*> branches;
2233
Tanya Lattner13417b52005-03-23 01:47:20 +00002234 //Get target information to look at machine operands
2235 const TargetInstrInfo *mii = target.getInstrInfo();
Misha Brukmanb4402432005-04-21 23:30:14 +00002236
Tanya Lattner13417b52005-03-23 01:47:20 +00002237 //Create TmpInstructions for the final phis
2238 for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
Tanya Lattner081fbd12004-07-30 23:36:10 +00002239
Tanya Lattner13417b52005-03-23 01:47:20 +00002240 DEBUG(std::cerr << "Stage: " << I->second << " Inst: " << *(I->first) << "\n";);
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002241
Tanya Lattner081fbd12004-07-30 23:36:10 +00002242 //Clone instruction
Tanya Lattner13417b52005-03-23 01:47:20 +00002243 const MachineInstr *inst = I->first;
Tanya Lattner081fbd12004-07-30 23:36:10 +00002244 MachineInstr *instClone = inst->clone();
Tanya Lattner081fbd12004-07-30 23:36:10 +00002245
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002246 //Insert into machine basic block
2247 machineBB->push_back(instClone);
2248
Tanya Lattner13417b52005-03-23 01:47:20 +00002249 if(mii->isBranch(instClone->getOpcode()))
2250 BuildMI(machineBB, V9::NOP, 0);
2251
Tanya Lattner7beb51c2004-11-16 21:31:37 +00002252 DEBUG(std::cerr << "Cloned Inst: " << *instClone << "\n");
2253
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002254 //Loop over Machine Operands
2255 for(unsigned i=0; i < inst->getNumOperands(); ++i) {
2256 //get machine operand
2257 const MachineOperand &mOp = inst->getOperand(i);
Misha Brukmanb4402432005-04-21 23:30:14 +00002258
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002259 if(I->second != 0) {
Tanya Lattner081fbd12004-07-30 23:36:10 +00002260 if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002261
Jeff Cohen33a030e2005-07-27 05:53:44 +00002262 //Check to see where this operand is defined if this instruction is from max stage
2263 if(I->second == schedule.getMaxStage()) {
2264 DEBUG(std::cerr << "VREG: " << *(mOp.getVRegValue()) << "\n");
2265 }
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002266
Jeff Cohen33a030e2005-07-27 05:53:44 +00002267 //If its in the value saved, we need to create a temp instruction and use that instead
2268 if(valuesToSave.count(mOp.getVRegValue())) {
Tanya Lattner7beb51c2004-11-16 21:31:37 +00002269
Jeff Cohen33a030e2005-07-27 05:53:44 +00002270 //Check if we already have a final PHI value for this
2271 if(!finalPHIValue.count(mOp.getVRegValue())) {
2272 //Only create phi if the operand def is from a stage before this one
2273 if(schedule.defPreviousStage(mOp.getVRegValue(), I->second)) {
2274 TmpInstruction *tmp = new TmpInstruction(mOp.getVRegValue());
2275
2276 //Get machine code for this instruction
2277 MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(defaultInst);
2278 tempMvec.addTemp((Value*) tmp);
2279
2280 //Update the operand in the cloned instruction
2281 instClone->getOperand(i).setValueReg(tmp);
2282
2283 //save this as our final phi
2284 finalPHIValue[mOp.getVRegValue()] = tmp;
2285 newValLocation[tmp] = machineBB;
2286 }
2287 }
2288 else {
2289 //Use the previous final phi value
2290 instClone->getOperand(i).setValueReg(finalPHIValue[mOp.getVRegValue()]);
2291 }
2292 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002293 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002294 }
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002295 if(I->second != schedule.getMaxStage()) {
Tanya Lattner081fbd12004-07-30 23:36:10 +00002296 if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002297 if(valuesToSave.count(mOp.getVRegValue())) {
2298
2299 TmpInstruction *tmp = new TmpInstruction(mOp.getVRegValue());
2300
2301 //Get machine code for this instruction
2302 MachineCodeForInstruction & tempVec = MachineCodeForInstruction::get(defaultInst);
2303 tempVec.addTemp((Value*) tmp);
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002304
Jeff Cohen33a030e2005-07-27 05:53:44 +00002305 //Create new machine instr and put in MBB
2306 MachineInstr *saveValue;
2307 if(mOp.getVRegValue()->getType() == Type::FloatTy)
2308 saveValue = BuildMI(machineBB, V9::FMOVS, 3).addReg(mOp.getVRegValue()).addRegDef(tmp);
2309 else if(mOp.getVRegValue()->getType() == Type::DoubleTy)
2310 saveValue = BuildMI(machineBB, V9::FMOVD, 3).addReg(mOp.getVRegValue()).addRegDef(tmp);
2311 else
2312 saveValue = BuildMI(machineBB, V9::ORr, 3).addReg(mOp.getVRegValue()).addImm(0).addRegDef(tmp);
2313
2314
2315 //Save for future cleanup
2316 kernelValue[mOp.getVRegValue()] = tmp;
2317 newValLocation[tmp] = machineBB;
2318 kernelPHIs[mOp.getVRegValue()][schedule.getMaxStage()-1] = tmp;
2319 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002320 }
2321 }
2322 }
Misha Brukmanb4402432005-04-21 23:30:14 +00002323
Tanya Lattner081fbd12004-07-30 23:36:10 +00002324 }
2325
Tanya Lattnerc0d9dcd2004-12-03 05:25:22 +00002326 //Add branches
2327 for(std::vector<MachineInstr*>::iterator I = branches.begin(), E = branches.end(); I != E; ++I) {
2328 machineBB->push_back(*I);
2329 BuildMI(machineBB, V9::NOP, 0);
2330 }
2331
2332
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002333 DEBUG(std::cerr << "KERNEL before PHIs\n");
2334 DEBUG(machineBB->print(std::cerr));
2335
2336
2337 //Loop over each value we need to generate phis for
Misha Brukmanb4402432005-04-21 23:30:14 +00002338 for(std::map<Value*, std::map<int, Value*> >::iterator V = newValues.begin(),
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002339 E = newValues.end(); V != E; ++V) {
2340
Tanya Lattner081fbd12004-07-30 23:36:10 +00002341
2342 DEBUG(std::cerr << "Writing phi for" << *(V->first));
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002343 DEBUG(std::cerr << "\nMap of Value* for this phi\n");
Misha Brukmanb4402432005-04-21 23:30:14 +00002344 DEBUG(for(std::map<int, Value*>::iterator I = V->second.begin(),
Jeff Cohen33a030e2005-07-27 05:53:44 +00002345 IE = V->second.end(); I != IE; ++I) {
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002346 std::cerr << "Stage: " << I->first;
2347 std::cerr << " Value: " << *(I->second) << "\n";
2348 });
Tanya Lattner081fbd12004-07-30 23:36:10 +00002349
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002350 //If we only have one current iteration live, its safe to set lastPhi = to kernel value
2351 if(V->second.size() == 1) {
2352 assert(kernelValue[V->first] != 0 && "Kernel value* must exist to create phi");
Misha Brukmanb4402432005-04-21 23:30:14 +00002353 MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(),V9::PHI, 3).addReg(V->second.begin()->second).addReg(kernelValue[V->first]).addRegDef(finalPHIValue[V->first]);
Tanya Lattner13417b52005-03-23 01:47:20 +00002354 DEBUG(std::cerr << "Resulting PHI (one live): " << *saveValue << "\n");
2355 kernelPHIs[V->first][V->second.begin()->first] = kernelValue[V->first];
2356 DEBUG(std::cerr << "Put kernel phi in at stage: " << schedule.getMaxStage()-1 << " (map stage = " << V->second.begin()->first << ")\n");
2357 }
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002358 else {
2359
2360 //Keep track of last phi created.
2361 Instruction *lastPhi = 0;
Misha Brukmanb4402432005-04-21 23:30:14 +00002362
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002363 unsigned count = 1;
2364 //Loop over the the map backwards to generate phis
Misha Brukmanb4402432005-04-21 23:30:14 +00002365 for(std::map<int, Value*>::reverse_iterator I = V->second.rbegin(), IE = V->second.rend();
Jeff Cohen33a030e2005-07-27 05:53:44 +00002366 I != IE; ++I) {
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002367
2368 if(count < (V->second).size()) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002369 if(lastPhi == 0) {
2370 lastPhi = new TmpInstruction(I->second);
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002371
Jeff Cohen33a030e2005-07-27 05:53:44 +00002372 //Get machine code for this instruction
2373 MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(defaultInst);
2374 tempMvec.addTemp((Value*) lastPhi);
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002375
Jeff Cohen33a030e2005-07-27 05:53:44 +00002376 MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(kernelValue[V->first]).addReg(I->second).addRegDef(lastPhi);
2377 DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
2378 newValLocation[lastPhi] = machineBB;
2379 }
2380 else {
2381 Instruction *tmp = new TmpInstruction(I->second);
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002382
Jeff Cohen33a030e2005-07-27 05:53:44 +00002383 //Get machine code for this instruction
2384 MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(defaultInst);
2385 tempMvec.addTemp((Value*) tmp);
2386
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002387
Jeff Cohen33a030e2005-07-27 05:53:44 +00002388 MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPhi).addReg(I->second).addRegDef(tmp);
2389 DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
2390 lastPhi = tmp;
2391 kernelPHIs[V->first][I->first] = lastPhi;
2392 newValLocation[lastPhi] = machineBB;
2393 }
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002394 }
2395 //Final phi value
2396 else {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002397 //The resulting value must be the Value* we created earlier
2398 assert(lastPhi != 0 && "Last phi is NULL!\n");
2399 MachineInstr *saveValue = BuildMI(*machineBB, machineBB->begin(), V9::PHI, 3).addReg(lastPhi).addReg(I->second).addRegDef(finalPHIValue[V->first]);
2400 DEBUG(std::cerr << "Resulting PHI: " << *saveValue << "\n");
2401 kernelPHIs[V->first][I->first] = finalPHIValue[V->first];
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002402 }
2403
2404 ++count;
2405 }
2406
2407 }
Misha Brukmanb4402432005-04-21 23:30:14 +00002408 }
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002409
2410 DEBUG(std::cerr << "KERNEL after PHIs\n");
2411 DEBUG(machineBB->print(std::cerr));
Tanya Lattner081fbd12004-07-30 23:36:10 +00002412}
2413
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002414
Tanya Lattner081fbd12004-07-30 23:36:10 +00002415void ModuloSchedulingPass::removePHIs(const MachineBasicBlock *origBB, std::vector<MachineBasicBlock *> &prologues, std::vector<MachineBasicBlock *> &epilogues, MachineBasicBlock *kernelBB, std::map<Value*, MachineBasicBlock*> &newValLocation) {
2416
2417 //Worklist to delete things
2418 std::vector<std::pair<MachineBasicBlock*, MachineBasicBlock::iterator> > worklist;
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002419
2420 //Worklist of TmpInstructions that need to be added to a MCFI
2421 std::vector<Instruction*> addToMCFI;
Misha Brukmanb4402432005-04-21 23:30:14 +00002422
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002423 //Worklist to add OR instructions to end of kernel so not to invalidate the iterator
2424 //std::vector<std::pair<Instruction*, Value*> > newORs;
2425
Tanya Lattner081fbd12004-07-30 23:36:10 +00002426 const TargetInstrInfo *TMI = target.getInstrInfo();
2427
2428 //Start with the kernel and for each phi insert a copy for the phi def and for each arg
2429 for(MachineBasicBlock::iterator I = kernelBB->begin(), E = kernelBB->end(); I != E; ++I) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002430
Tanya Lattner444be612004-11-02 21:04:56 +00002431 DEBUG(std::cerr << "Looking at Instr: " << *I << "\n");
Tanya Lattner081fbd12004-07-30 23:36:10 +00002432 //Get op code and check if its a phi
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002433 if(I->getOpcode() == V9::PHI) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002434
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002435 DEBUG(std::cerr << "Replacing PHI: " << *I << "\n");
2436 Instruction *tmp = 0;
Tanya Lattner081fbd12004-07-30 23:36:10 +00002437
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002438 for(unsigned i = 0; i < I->getNumOperands(); ++i) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002439 //Get Operand
2440 const MachineOperand &mOp = I->getOperand(i);
2441 assert(mOp.getType() == MachineOperand::MO_VirtualRegister && "Should be a Value*\n");
2442
2443 if(!tmp) {
2444 tmp = new TmpInstruction(mOp.getVRegValue());
2445 addToMCFI.push_back(tmp);
2446 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002447
Jeff Cohen33a030e2005-07-27 05:53:44 +00002448 //Now for all our arguments we read, OR to the new TmpInstruction that we created
2449 if(mOp.isUse()) {
2450 DEBUG(std::cerr << "Use: " << mOp << "\n");
2451 //Place a copy at the end of its BB but before the branches
2452 assert(newValLocation.count(mOp.getVRegValue()) && "We must know where this value is located\n");
2453 //Reverse iterate to find the branches, we can safely assume no instructions have been
2454 //put in the nop positions
2455 for(MachineBasicBlock::iterator inst = --(newValLocation[mOp.getVRegValue()])->end(), endBB = (newValLocation[mOp.getVRegValue()])->begin(); inst != endBB; --inst) {
2456 MachineOpCode opc = inst->getOpcode();
2457 if(TMI->isBranch(opc) || TMI->isNop(opc))
2458 continue;
2459 else {
2460 if(mOp.getVRegValue()->getType() == Type::FloatTy)
2461 BuildMI(*(newValLocation[mOp.getVRegValue()]), ++inst, V9::FMOVS, 3).addReg(mOp.getVRegValue()).addRegDef(tmp);
2462 else if(mOp.getVRegValue()->getType() == Type::DoubleTy)
2463 BuildMI(*(newValLocation[mOp.getVRegValue()]), ++inst, V9::FMOVD, 3).addReg(mOp.getVRegValue()).addRegDef(tmp);
2464 else
2465 BuildMI(*(newValLocation[mOp.getVRegValue()]), ++inst, V9::ORr, 3).addReg(mOp.getVRegValue()).addImm(0).addRegDef(tmp);
2466
2467 break;
2468 }
2469
2470 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002471
Jeff Cohen33a030e2005-07-27 05:53:44 +00002472 }
2473 else {
2474 //Remove the phi and replace it with an OR
2475 DEBUG(std::cerr << "Def: " << mOp << "\n");
2476 //newORs.push_back(std::make_pair(tmp, mOp.getVRegValue()));
2477 if(tmp->getType() == Type::FloatTy)
2478 BuildMI(*kernelBB, I, V9::FMOVS, 3).addReg(tmp).addRegDef(mOp.getVRegValue());
2479 else if(tmp->getType() == Type::DoubleTy)
2480 BuildMI(*kernelBB, I, V9::FMOVD, 3).addReg(tmp).addRegDef(mOp.getVRegValue());
2481 else
2482 BuildMI(*kernelBB, I, V9::ORr, 3).addReg(tmp).addImm(0).addRegDef(mOp.getVRegValue());
2483
2484
2485 worklist.push_back(std::make_pair(kernelBB, I));
2486 }
2487
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002488 }
Misha Brukmanb4402432005-04-21 23:30:14 +00002489
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002490 }
2491
Misha Brukmanb4402432005-04-21 23:30:14 +00002492
Tanya Lattner081fbd12004-07-30 23:36:10 +00002493 }
2494
Tanya Lattner444be612004-11-02 21:04:56 +00002495 //Add TmpInstructions to some MCFI
2496 if(addToMCFI.size() > 0) {
2497 MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(defaultInst);
2498 for(unsigned x = 0; x < addToMCFI.size(); ++x) {
2499 tempMvec.addTemp(addToMCFI[x]);
2500 }
2501 addToMCFI.clear();
2502 }
2503
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002504
Tanya Lattner081fbd12004-07-30 23:36:10 +00002505 //Remove phis from epilogue
2506 for(std::vector<MachineBasicBlock*>::iterator MB = epilogues.begin(), ME = epilogues.end(); MB != ME; ++MB) {
2507 for(MachineBasicBlock::iterator I = (*MB)->begin(), E = (*MB)->end(); I != E; ++I) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002508
Tanya Lattner444be612004-11-02 21:04:56 +00002509 DEBUG(std::cerr << "Looking at Instr: " << *I << "\n");
Tanya Lattner081fbd12004-07-30 23:36:10 +00002510 //Get op code and check if its a phi
Brian Gaeke75935252004-08-18 20:04:24 +00002511 if(I->getOpcode() == V9::PHI) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002512 Instruction *tmp = 0;
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002513
Jeff Cohen33a030e2005-07-27 05:53:44 +00002514 for(unsigned i = 0; i < I->getNumOperands(); ++i) {
2515 //Get Operand
2516 const MachineOperand &mOp = I->getOperand(i);
2517 assert(mOp.getType() == MachineOperand::MO_VirtualRegister && "Should be a Value*\n");
2518
2519 if(!tmp) {
2520 tmp = new TmpInstruction(mOp.getVRegValue());
2521 addToMCFI.push_back(tmp);
2522 }
2523
2524 //Now for all our arguments we read, OR to the new TmpInstruction that we created
2525 if(mOp.isUse()) {
2526 DEBUG(std::cerr << "Use: " << mOp << "\n");
2527 //Place a copy at the end of its BB but before the branches
2528 assert(newValLocation.count(mOp.getVRegValue()) && "We must know where this value is located\n");
2529 //Reverse iterate to find the branches, we can safely assume no instructions have been
2530 //put in the nop positions
2531 for(MachineBasicBlock::iterator inst = --(newValLocation[mOp.getVRegValue()])->end(), endBB = (newValLocation[mOp.getVRegValue()])->begin(); inst != endBB; --inst) {
2532 MachineOpCode opc = inst->getOpcode();
2533 if(TMI->isBranch(opc) || TMI->isNop(opc))
2534 continue;
2535 else {
2536 if(mOp.getVRegValue()->getType() == Type::FloatTy)
2537 BuildMI(*(newValLocation[mOp.getVRegValue()]), ++inst, V9::FMOVS, 3).addReg(mOp.getVRegValue()).addRegDef(tmp);
2538 else if(mOp.getVRegValue()->getType() == Type::DoubleTy)
2539 BuildMI(*(newValLocation[mOp.getVRegValue()]), ++inst, V9::FMOVD, 3).addReg(mOp.getVRegValue()).addRegDef(tmp);
2540 else
2541 BuildMI(*(newValLocation[mOp.getVRegValue()]), ++inst, V9::ORr, 3).addReg(mOp.getVRegValue()).addImm(0).addRegDef(tmp);
2542
Tanya Lattner13417b52005-03-23 01:47:20 +00002543
Jeff Cohen33a030e2005-07-27 05:53:44 +00002544 break;
2545 }
2546
2547 }
2548
2549 }
2550 else {
2551 //Remove the phi and replace it with an OR
2552 DEBUG(std::cerr << "Def: " << mOp << "\n");
2553 if(tmp->getType() == Type::FloatTy)
2554 BuildMI(**MB, I, V9::FMOVS, 3).addReg(tmp).addRegDef(mOp.getVRegValue());
2555 else if(tmp->getType() == Type::DoubleTy)
2556 BuildMI(**MB, I, V9::FMOVD, 3).addReg(tmp).addRegDef(mOp.getVRegValue());
2557 else
2558 BuildMI(**MB, I, V9::ORr, 3).addReg(tmp).addImm(0).addRegDef(mOp.getVRegValue());
Tanya Lattner13417b52005-03-23 01:47:20 +00002559
Jeff Cohen33a030e2005-07-27 05:53:44 +00002560 worklist.push_back(std::make_pair(*MB,I));
2561 }
2562
2563 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002564 }
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002565
Misha Brukmanb4402432005-04-21 23:30:14 +00002566
Tanya Lattner081fbd12004-07-30 23:36:10 +00002567 }
2568 }
2569
Tanya Lattner444be612004-11-02 21:04:56 +00002570
2571 if(addToMCFI.size() > 0) {
2572 MachineCodeForInstruction & tempMvec = MachineCodeForInstruction::get(defaultInst);
2573 for(unsigned x = 0; x < addToMCFI.size(); ++x) {
2574 tempMvec.addTemp(addToMCFI[x]);
2575 }
2576 addToMCFI.clear();
2577 }
2578
Tanya Lattner081fbd12004-07-30 23:36:10 +00002579 //Delete the phis
2580 for(std::vector<std::pair<MachineBasicBlock*, MachineBasicBlock::iterator> >::iterator I = worklist.begin(), E = worklist.end(); I != E; ++I) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002581
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002582 DEBUG(std::cerr << "Deleting PHI " << *I->second << "\n");
Tanya Lattner081fbd12004-07-30 23:36:10 +00002583 I->first->erase(I->second);
Jeff Cohen33a030e2005-07-27 05:53:44 +00002584
Tanya Lattner081fbd12004-07-30 23:36:10 +00002585 }
2586
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002587
2588 assert((addToMCFI.size() == 0) && "We should have added all TmpInstructions to some MachineCodeForInstruction");
Tanya Lattner50cbb9a2004-05-28 20:14:12 +00002589}
2590
2591
Tanya Lattner081fbd12004-07-30 23:36:10 +00002592void ModuloSchedulingPass::reconstructLoop(MachineBasicBlock *BB) {
Tanya Lattnera066df62004-05-26 06:27:18 +00002593
Tanya Lattner56807c62005-02-10 17:02:58 +00002594 TIME_REGION(X, "reconstructLoop");
2595
2596
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002597 DEBUG(std::cerr << "Reconstructing Loop\n");
2598
Tanya Lattner081fbd12004-07-30 23:36:10 +00002599 //First find the value *'s that we need to "save"
Tanya Lattner13417b52005-03-23 01:47:20 +00002600 std::map<const Value*, std::pair<const MachineInstr*, int> > valuesToSave;
Tanya Lattnera066df62004-05-26 06:27:18 +00002601
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002602 //Keep track of instructions we have already seen and their stage because
2603 //we don't want to "save" values if they are used in the kernel immediately
2604 std::map<const MachineInstr*, int> lastInstrs;
Tanya Lattner8bf63742005-06-17 04:00:57 +00002605 std::map<const Value*, int> phiUses;
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002606
Tanya Lattner081fbd12004-07-30 23:36:10 +00002607 //Loop over kernel and only look at instructions from a stage > 0
2608 //Look at its operands and save values *'s that are read
Tanya Lattnera066df62004-05-26 06:27:18 +00002609 for(MSSchedule::kernel_iterator I = schedule.kernel_begin(), E = schedule.kernel_end(); I != E; ++I) {
Tanya Lattnera066df62004-05-26 06:27:18 +00002610
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002611 if(I->second !=0) {
Tanya Lattnera066df62004-05-26 06:27:18 +00002612 //For this instruction, get the Value*'s that it reads and put them into the set.
2613 //Assert if there is an operand of another type that we need to save
Tanya Lattner13417b52005-03-23 01:47:20 +00002614 const MachineInstr *inst = I->first;
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002615 lastInstrs[inst] = I->second;
2616
Tanya Lattnera066df62004-05-26 06:27:18 +00002617 for(unsigned i=0; i < inst->getNumOperands(); ++i) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002618 //get machine operand
2619 const MachineOperand &mOp = inst->getOperand(i);
2620
2621 if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isUse()) {
2622 //find the value in the map
2623 if (const Value* srcI = mOp.getVRegValue()) {
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002624
Jeff Cohen33a030e2005-07-27 05:53:44 +00002625 if(isa<Constant>(srcI) || isa<Argument>(srcI))
2626 continue;
Tanya Lattner444be612004-11-02 21:04:56 +00002627
Jeff Cohen33a030e2005-07-27 05:53:44 +00002628 //Before we declare this Value* one that we should save
2629 //make sure its def is not of the same stage as this instruction
2630 //because it will be consumed before its used
2631 Instruction *defInst = (Instruction*) srcI;
2632
2633 //Should we save this value?
2634 bool save = true;
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002635
Jeff Cohen33a030e2005-07-27 05:53:44 +00002636 //Continue if not in the def map, loop invariant code does not need to be saved
2637 if(!defMap.count(srcI))
2638 continue;
Tanya Lattner7beb51c2004-11-16 21:31:37 +00002639
Jeff Cohen33a030e2005-07-27 05:53:44 +00002640 MachineInstr *defInstr = defMap[srcI];
2641
Tanya Lattner7beb51c2004-11-16 21:31:37 +00002642
Jeff Cohen33a030e2005-07-27 05:53:44 +00002643 if(lastInstrs.count(defInstr)) {
2644 if(lastInstrs[defInstr] == I->second) {
2645 save = false;
2646
2647 }
2648 }
2649
2650 if(save) {
2651 assert(!phiUses.count(srcI) && "Did not expect to see phi use twice");
2652 if(isa<PHINode>(srcI))
2653 phiUses[srcI] = I->second;
2654
2655 valuesToSave[srcI] = std::make_pair(I->first, i);
Tanya Lattner8bf63742005-06-17 04:00:57 +00002656
Jeff Cohen33a030e2005-07-27 05:53:44 +00002657 }
2658 }
2659 }
2660 else if(mOp.getType() == MachineOperand::MO_VirtualRegister && mOp.isDef()) {
2661 if (const Value* destI = mOp.getVRegValue()) {
2662 if(!isa<PHINode>(destI))
2663 continue;
2664 if(phiUses.count(destI)) {
2665 if(phiUses[destI] == I->second) {
2666 //remove from save list
2667 valuesToSave.erase(destI);
2668 }
2669 }
2670 }
2671 }
2672
2673 if(mOp.getType() != MachineOperand::MO_VirtualRegister && mOp.isUse()) {
2674 assert("Our assumption is wrong. We have another type of register that needs to be saved\n");
2675 }
Tanya Lattnera066df62004-05-26 06:27:18 +00002676 }
Tanya Lattnera066df62004-05-26 06:27:18 +00002677 }
2678 }
2679
Tanya Lattner081fbd12004-07-30 23:36:10 +00002680 //The new loop will consist of one or more prologues, the kernel, and one or more epilogues.
2681
2682 //Map to keep track of old to new values
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002683 std::map<Value*, std::map<int, Value*> > newValues;
Misha Brukmanb4402432005-04-21 23:30:14 +00002684
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002685 //Map to keep track of old to new values in kernel
2686 std::map<Value*, std::map<int, Value*> > kernelPHIs;
2687
Tanya Lattner081fbd12004-07-30 23:36:10 +00002688 //Another map to keep track of what machine basic blocks these new value*s are in since
2689 //they have no llvm instruction equivalent
2690 std::map<Value*, MachineBasicBlock*> newValLocation;
2691
2692 std::vector<MachineBasicBlock*> prologues;
2693 std::vector<BasicBlock*> llvm_prologues;
2694
2695
2696 //Write prologue
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002697 if(schedule.getMaxStage() != 0)
2698 writePrologues(prologues, BB, llvm_prologues, valuesToSave, newValues, newValLocation);
Misha Brukmanb4402432005-04-21 23:30:14 +00002699
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002700 //Print out epilogues and prologue
Misha Brukmanb4402432005-04-21 23:30:14 +00002701 DEBUG(for(std::vector<MachineBasicBlock*>::iterator I = prologues.begin(), E = prologues.end();
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002702 I != E; ++I) {
2703 std::cerr << "PROLOGUE\n";
2704 (*I)->print(std::cerr);
2705 });
Tanya Lattner081fbd12004-07-30 23:36:10 +00002706
2707 BasicBlock *llvmKernelBB = new BasicBlock("Kernel", (Function*) (BB->getBasicBlock()->getParent()));
2708 MachineBasicBlock *machineKernelBB = new MachineBasicBlock(llvmKernelBB);
Tanya Lattner8bf63742005-06-17 04:00:57 +00002709
2710 MachineFunction *F = (((MachineBasicBlock*)BB)->getParent());
2711 MachineFunction::BasicBlockListType &BL = F->getBasicBlockList();
2712 MachineFunction::BasicBlockListType::iterator BLI = BB;
2713 assert(BLI != BL.end() && "Must find original BB in machine function\n");
2714 BL.insert(BLI,machineKernelBB);
2715
2716 //(((MachineBasicBlock*)BB)->getParent())->getBasicBlockList().push_back(machineKernelBB);
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002717 writeKernel(llvmKernelBB, machineKernelBB, valuesToSave, newValues, newValLocation, kernelPHIs);
Misha Brukmanb4402432005-04-21 23:30:14 +00002718
2719
Tanya Lattner081fbd12004-07-30 23:36:10 +00002720 std::vector<MachineBasicBlock*> epilogues;
2721 std::vector<BasicBlock*> llvm_epilogues;
2722
2723 //Write epilogues
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002724 if(schedule.getMaxStage() != 0)
2725 writeEpilogues(epilogues, BB, llvm_epilogues, valuesToSave, newValues, newValLocation, kernelPHIs);
Tanya Lattner081fbd12004-07-30 23:36:10 +00002726
2727
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00002728 //Fix our branches
2729 fixBranches(prologues, llvm_prologues, machineKernelBB, llvmKernelBB, epilogues, llvm_epilogues, BB);
2730
2731 //Remove phis
2732 removePHIs(BB, prologues, epilogues, machineKernelBB, newValLocation);
Misha Brukmanb4402432005-04-21 23:30:14 +00002733
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00002734 //Print out epilogues and prologue
Misha Brukmanb4402432005-04-21 23:30:14 +00002735 DEBUG(for(std::vector<MachineBasicBlock*>::iterator I = prologues.begin(), E = prologues.end();
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00002736 I != E; ++I) {
2737 std::cerr << "PROLOGUE\n";
2738 (*I)->print(std::cerr);
2739 });
Misha Brukmanb4402432005-04-21 23:30:14 +00002740
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00002741 DEBUG(std::cerr << "KERNEL\n");
2742 DEBUG(machineKernelBB->print(std::cerr));
2743
Misha Brukmanb4402432005-04-21 23:30:14 +00002744 DEBUG(for(std::vector<MachineBasicBlock*>::iterator I = epilogues.begin(), E = epilogues.end();
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00002745 I != E; ++I) {
2746 std::cerr << "EPILOGUE\n";
2747 (*I)->print(std::cerr);
2748 });
2749
2750
2751 DEBUG(std::cerr << "New Machine Function" << "\n");
2752 DEBUG(std::cerr << BB->getParent() << "\n");
2753
2754
2755}
2756
2757void ModuloSchedulingPass::fixBranches(std::vector<MachineBasicBlock *> &prologues, std::vector<BasicBlock*> &llvm_prologues, MachineBasicBlock *machineKernelBB, BasicBlock *llvmKernelBB, std::vector<MachineBasicBlock *> &epilogues, std::vector<BasicBlock*> &llvm_epilogues, MachineBasicBlock *BB) {
2758
Tanya Lattner081fbd12004-07-30 23:36:10 +00002759 const TargetInstrInfo *TMI = target.getInstrInfo();
2760
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002761 if(schedule.getMaxStage() != 0) {
2762 //Fix prologue branches
2763 for(unsigned I = 0; I < prologues.size(); ++I) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002764
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002765 //Find terminator since getFirstTerminator does not work!
2766 for(MachineBasicBlock::reverse_iterator mInst = prologues[I]->rbegin(), mInstEnd = prologues[I]->rend(); mInst != mInstEnd; ++mInst) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002767 MachineOpCode OC = mInst->getOpcode();
2768 //If its a branch update its branchto
2769 if(TMI->isBranch(OC)) {
2770 for(unsigned opNum = 0; opNum < mInst->getNumOperands(); ++opNum) {
2771 MachineOperand &mOp = mInst->getOperand(opNum);
2772 if (mOp.getType() == MachineOperand::MO_PCRelativeDisp) {
2773 //Check if we are branching to the kernel, if not branch to epilogue
2774 if(mOp.getVRegValue() == BB->getBasicBlock()) {
2775 if(I == prologues.size()-1)
2776 mOp.setValueReg(llvmKernelBB);
2777 else
2778 mOp.setValueReg(llvm_prologues[I+1]);
2779 }
2780 else {
2781 mOp.setValueReg(llvm_epilogues[(llvm_epilogues.size()-1-I)]);
2782 }
2783 }
2784 }
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002785
Jeff Cohen33a030e2005-07-27 05:53:44 +00002786 DEBUG(std::cerr << "New Prologue Branch: " << *mInst << "\n");
2787 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002788 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002789
Tanya Lattner081fbd12004-07-30 23:36:10 +00002790
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002791 //Update llvm basic block with our new branch instr
2792 DEBUG(std::cerr << BB->getBasicBlock()->getTerminator() << "\n");
2793 const BranchInst *branchVal = dyn_cast<BranchInst>(BB->getBasicBlock()->getTerminator());
Misha Brukmanb4402432005-04-21 23:30:14 +00002794
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002795 if(I == prologues.size()-1) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002796 TerminatorInst *newBranch = new BranchInst(llvmKernelBB,
2797 llvm_epilogues[(llvm_epilogues.size()-1-I)],
2798 branchVal->getCondition(),
2799 llvm_prologues[I]);
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002800 }
2801 else
Jeff Cohen33a030e2005-07-27 05:53:44 +00002802 TerminatorInst *newBranch = new BranchInst(llvm_prologues[I+1],
2803 llvm_epilogues[(llvm_epilogues.size()-1-I)],
2804 branchVal->getCondition(),
2805 llvm_prologues[I]);
Tanya Lattner081fbd12004-07-30 23:36:10 +00002806
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002807 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002808 }
2809
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00002810 Value *origBranchExit = 0;
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002811
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00002812 //Fix up kernel machine branches
Tanya Lattner081fbd12004-07-30 23:36:10 +00002813 for(MachineBasicBlock::reverse_iterator mInst = machineKernelBB->rbegin(), mInstEnd = machineKernelBB->rend(); mInst != mInstEnd; ++mInst) {
2814 MachineOpCode OC = mInst->getOpcode();
2815 if(TMI->isBranch(OC)) {
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00002816 for(unsigned opNum = 0; opNum < mInst->getNumOperands(); ++opNum) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002817 MachineOperand &mOp = mInst->getOperand(opNum);
2818
2819 if(mOp.getType() == MachineOperand::MO_PCRelativeDisp) {
2820 if(mOp.getVRegValue() == BB->getBasicBlock())
2821 mOp.setValueReg(llvmKernelBB);
2822 else
2823 if(llvm_epilogues.size() > 0) {
2824 assert(origBranchExit == 0 && "There should only be one branch out of the loop");
2825
2826 origBranchExit = mOp.getVRegValue();
2827 mOp.setValueReg(llvm_epilogues[0]);
2828 }
2829 else
2830 origBranchExit = mOp.getVRegValue();
2831 }
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002832 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002833 }
2834 }
Misha Brukmanb4402432005-04-21 23:30:14 +00002835
Tanya Lattner081fbd12004-07-30 23:36:10 +00002836 //Update kernelLLVM branches
2837 const BranchInst *branchVal = dyn_cast<BranchInst>(BB->getBasicBlock()->getTerminator());
Misha Brukmanb4402432005-04-21 23:30:14 +00002838
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002839 assert(origBranchExit != 0 && "We must have the original bb the kernel exits to!");
Misha Brukmanb4402432005-04-21 23:30:14 +00002840
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002841 if(epilogues.size() > 0) {
2842 TerminatorInst *newBranch = new BranchInst(llvmKernelBB,
Jeff Cohen33a030e2005-07-27 05:53:44 +00002843 llvm_epilogues[0],
2844 branchVal->getCondition(),
2845 llvmKernelBB);
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002846 }
2847 else {
2848 BasicBlock *origBBExit = dyn_cast<BasicBlock>(origBranchExit);
2849 assert(origBBExit !=0 && "Original exit basic block must be set");
2850 TerminatorInst *newBranch = new BranchInst(llvmKernelBB,
Jeff Cohen33a030e2005-07-27 05:53:44 +00002851 origBBExit,
2852 branchVal->getCondition(),
2853 llvmKernelBB);
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002854 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002855
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002856 if(schedule.getMaxStage() != 0) {
Tanya Lattner081fbd12004-07-30 23:36:10 +00002857 //Lastly add unconditional branches for the epilogues
2858 for(unsigned I = 0; I < epilogues.size(); ++I) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002859
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002860 //Now since we don't have fall throughs, add a unconditional branch to the next prologue
Tanya Lattner081fbd12004-07-30 23:36:10 +00002861 if(I != epilogues.size()-1) {
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002862 BuildMI(epilogues[I], V9::BA, 1).addPCDisp(llvm_epilogues[I+1]);
Tanya Lattner081fbd12004-07-30 23:36:10 +00002863 //Add unconditional branch to end of epilogue
Misha Brukmanb4402432005-04-21 23:30:14 +00002864 TerminatorInst *newBranch = new BranchInst(llvm_epilogues[I+1],
Jeff Cohen33a030e2005-07-27 05:53:44 +00002865 llvm_epilogues[I]);
Tanya Lattner081fbd12004-07-30 23:36:10 +00002866
Tanya Lattnera066df62004-05-26 06:27:18 +00002867 }
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002868 else {
Tanya Lattnerd8cc4fa2004-11-29 04:39:47 +00002869 BuildMI(epilogues[I], V9::BA, 1).addPCDisp(origBranchExit);
Misha Brukmanb4402432005-04-21 23:30:14 +00002870
2871
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002872 //Update last epilogue exit branch
2873 BranchInst *branchVal = (BranchInst*) dyn_cast<BranchInst>(BB->getBasicBlock()->getTerminator());
2874 //Find where we are supposed to branch to
2875 BasicBlock *nextBlock = 0;
2876 for(unsigned j=0; j <branchVal->getNumSuccessors(); ++j) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002877 if(branchVal->getSuccessor(j) != BB->getBasicBlock())
2878 nextBlock = branchVal->getSuccessor(j);
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002879 }
Misha Brukmanb4402432005-04-21 23:30:14 +00002880
Tanya Lattnerd38a7602004-10-14 06:04:28 +00002881 assert((nextBlock != 0) && "Next block should not be null!");
2882 TerminatorInst *newBranch = new BranchInst(nextBlock, llvm_epilogues[I]);
2883 }
2884 //Add one more nop!
2885 BuildMI(epilogues[I], V9::NOP, 0);
Misha Brukmanb4402432005-04-21 23:30:14 +00002886
Tanya Lattner081fbd12004-07-30 23:36:10 +00002887 }
Tanya Lattner8d64e9a2005-04-05 16:36:44 +00002888 }
Tanya Lattnera066df62004-05-26 06:27:18 +00002889
Tanya Lattner081fbd12004-07-30 23:36:10 +00002890 //FIX UP Machine BB entry!!
2891 //We are looking at the predecesor of our loop basic block and we want to change its ba instruction
Misha Brukmanb4402432005-04-21 23:30:14 +00002892
Tanya Lattnera066df62004-05-26 06:27:18 +00002893
Tanya Lattner081fbd12004-07-30 23:36:10 +00002894 //Find all llvm basic blocks that branch to the loop entry and change to our first prologue.
2895 const BasicBlock *llvmBB = BB->getBasicBlock();
2896
Tanya Lattnerddebd1e2004-10-30 00:39:07 +00002897 std::vector<const BasicBlock*>Preds (pred_begin(llvmBB), pred_end(llvmBB));
2898
2899 //for(pred_const_iterator P = pred_begin(llvmBB), PE = pred_end(llvmBB); P != PE; ++PE) {
Misha Brukmanb4402432005-04-21 23:30:14 +00002900 for(std::vector<const BasicBlock*>::iterator P = Preds.begin(), PE = Preds.end(); P != PE; ++P) {
Tanya Lattner081fbd12004-07-30 23:36:10 +00002901 if(*P == llvmBB)
2902 continue;
2903 else {
2904 DEBUG(std::cerr << "Found our entry BB\n");
2905 //Get the Terminator instruction for this basic block and print it out
2906 DEBUG(std::cerr << *((*P)->getTerminator()) << "\n");
2907 //Update the terminator
2908 TerminatorInst *term = ((BasicBlock*)*P)->getTerminator();
2909 for(unsigned i=0; i < term->getNumSuccessors(); ++i) {
Jeff Cohen33a030e2005-07-27 05:53:44 +00002910 if(term->getSuccessor(i) == llvmBB) {
2911 DEBUG(std::cerr << "Replacing successor bb\n");
2912 if(llvm_prologues.size() > 0) {
2913 term->setSuccessor(i, llvm_prologues[0]);
2914 //Also update its corresponding machine instruction
2915 MachineCodeForInstruction & tempMvec =
2916 MachineCodeForInstruction::get(term);
2917 for (unsigned j = 0; j < tempMvec.size(); j++) {
2918 MachineInstr *temp = tempMvec[j];
2919 MachineOpCode opc = temp->getOpcode();
2920 if(TMI->isBranch(opc)) {
2921 DEBUG(std::cerr << *temp << "\n");
2922 //Update branch
2923 for(unsigned opNum = 0; opNum < temp->getNumOperands(); ++opNum) {
2924 MachineOperand &mOp = temp->getOperand(opNum);
2925 if (mOp.getType() == MachineOperand::MO_PCRelativeDisp) {
2926 if(mOp.getVRegValue() == llvmBB)
2927 mOp.setValueReg(llvm_prologues[0]);
2928 }
2929 }
2930 }
2931 }
2932 }
2933 else {
2934 term->setSuccessor(i, llvmKernelBB);
2935 //Also update its corresponding machine instruction
2936 MachineCodeForInstruction & tempMvec =
2937 MachineCodeForInstruction::get(term);
2938 for (unsigned j = 0; j < tempMvec.size(); j++) {
2939 MachineInstr *temp = tempMvec[j];
2940 MachineOpCode opc = temp->getOpcode();
2941 if(TMI->isBranch(opc)) {
2942 DEBUG(std::cerr << *temp << "\n");
2943 //Update branch
2944 for(unsigned opNum = 0; opNum < temp->getNumOperands(); ++opNum) {
2945 MachineOperand &mOp = temp->getOperand(opNum);
2946 if (mOp.getType() == MachineOperand::MO_PCRelativeDisp) {
2947 if(mOp.getVRegValue() == llvmBB)
2948 mOp.setValueReg(llvmKernelBB);
2949 }
2950 }
2951 }
2952 }
2953 }
2954 }
Tanya Lattner081fbd12004-07-30 23:36:10 +00002955 }
2956 break;
2957 }
2958 }
Misha Brukmanb4402432005-04-21 23:30:14 +00002959
Tanya Lattner081fbd12004-07-30 23:36:10 +00002960
Tanya Lattnerdbac0cb2004-10-10 22:44:35 +00002961 //BB->getParent()->getBasicBlockList().erase(BB);
Tanya Lattnera066df62004-05-26 06:27:18 +00002962
2963}
2964