1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
|
//===-- ModuloSchedulingSuperBlock.cpp - ModuloScheduling--------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This ModuloScheduling pass is based on the Swing Modulo Scheduling
// algorithm, but has been extended to support SuperBlocks (multiple
// basic block, single entry, multipl exit loops).
//
//===----------------------------------------------------------------------===//
#define DEBUG_TYPE "ModuloSchedSB"
#include "DependenceAnalyzer.h"
#include "ModuloSchedulingSuperBlock.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Instructions.h"
#include "../MachineCodeForInstruction.h"
#include "../SparcV9RegisterInfo.h"
#include "../SparcV9Internals.h"
#include "../SparcV9TmpInstr.h"
#include <fstream>
#include <sstream>
using namespace llvm;
/// Create ModuloSchedulingSBPass
///
FunctionPass *llvm::createModuloSchedulingSBPass(TargetMachine & targ) {
DEBUG(std::cerr << "Created ModuloSchedulingSBPass\n");
return new ModuloSchedulingSBPass(targ);
}
//Graph Traits for printing out the dependence graph
template<typename GraphType>
static void WriteGraphToFile(std::ostream &O, const std::string &GraphName,
const GraphType >) {
std::string Filename = GraphName + ".dot";
O << "Writing '" << Filename << "'...";
std::ofstream F(Filename.c_str());
if (F.good())
WriteGraph(F, GT);
else
O << " error opening file for writing!";
O << "\n";
};
namespace llvm {
Statistic<> NumLoops("moduloschedSB-numLoops", "Total Number of Loops");
Statistic<> NumSB("moduloschedSB-numSuperBlocks", "Total Number of SuperBlocks");
Statistic<> BBWithCalls("modulosched-BBCalls", "Basic Blocks rejected due to calls");
Statistic<> BBWithCondMov("modulosched-loopCondMov", "Basic Blocks rejected due to conditional moves");
bool ModuloSchedulingSBPass::runOnFunction(Function &F) {
bool Changed = false;
//Get MachineFunction
MachineFunction &MF = MachineFunction::get(&F);
//Get Loop Info & Dependence Anaysis info
LoopInfo &LI = getAnalysis<LoopInfo>();
DependenceAnalyzer &DA = getAnalysis<DependenceAnalyzer>();
//Worklist of superblocks
std::vector<std::vector<const MachineBasicBlock*> > Worklist;
FindSuperBlocks(F, LI, Worklist);
DEBUG(if(Worklist.size() == 0) std::cerr << "No superblocks in function to ModuloSchedule\n");
//Loop over worklist and ModuloSchedule each SuperBlock
for(std::vector<std::vector<const MachineBasicBlock*> >::iterator SB = Worklist.begin(),
SBE = Worklist.end(); SB != SBE; ++SB) {
//Print out Superblock
DEBUG(std::cerr << "ModuloScheduling SB: \n";
for(std::vector<const MachineBasicBlock*>::const_iterator BI = SB->begin(),
BE = SB->end(); BI != BE; ++BI) {
(*BI)->print(std::cerr);});
if(!CreateDefMap(*SB)) {
defaultInst = 0;
defMap.clear();
continue;
}
MSchedGraph *MSG = new MSchedGraph(*SB, target, indVarInstrs[*SB], DA,
machineTollvm[*SB]);
//Write Graph out to file
DEBUG(WriteGraphToFile(std::cerr, F.getName(), MSG));
DEBUG(MSG->print(std::cerr));
}
return Changed;
}
void ModuloSchedulingSBPass::FindSuperBlocks(Function &F, LoopInfo &LI,
std::vector<std::vector<const MachineBasicBlock*> > &Worklist) {
//Get MachineFunction
MachineFunction &MF = MachineFunction::get(&F);
//Map of LLVM BB to machine BB
std::map<BasicBlock*, MachineBasicBlock*> bbMap;
for (MachineFunction::iterator BI = MF.begin(); BI != MF.end(); ++BI) {
BasicBlock *llvmBB = (BasicBlock*) BI->getBasicBlock();
assert(!bbMap.count(llvmBB) && "LLVM BB already in map!");
bbMap[llvmBB] = &*BI;
}
//Iterate over the loops, and find super blocks
for(LoopInfo::iterator LB = LI.begin(), LE = LI.end(); LB != LE; ++LB) {
Loop *L = *LB;
++NumLoops;
//If loop is not single entry, try the next one
if(!L->getLoopPreheader())
continue;
//Check size of this loop, we don't want SBB loops
if(L->getBlocks().size() == 1)
continue;
//Check if this loop contains no sub loops
if(L->getSubLoops().size() == 0) {
std::vector<const MachineBasicBlock*> superBlock;
//Get Loop Headers
BasicBlock *header = L->getHeader();
//Follow the header and make sure each BB only has one entry and is valid
BasicBlock *current = header;
assert(bbMap.count(current) && "LLVM BB must have corresponding Machine BB\n");
MachineBasicBlock *currentMBB = bbMap[header];
bool done = false;
bool success = true;
while(!done) {
if(MachineBBisValid(currentMBB)) {
//Loop over successors of this BB, they should be in the loop block
//and be valid
BasicBlock *next = 0;
for(succ_iterator I = succ_begin(current), E = succ_end(current);
I != E; ++I) {
if(L->contains(*I)) {
if(!next)
next = *I;
else {
done = true;
success = false;
break;
}
}
}
if(success) {
superBlock.push_back(currentMBB);
if(next == header)
done = true;
else if(!next->getSinglePredecessor()) {
done = true;
success = false;
}
else {
//Check that the next BB only has one entry
current = next;
assert(bbMap.count(current) && "LLVM BB must have corresponding Machine BB");
currentMBB = bbMap[current];
}
}
}
else {
done = true;
success = false;
}
}
if(success) {
++NumSB;
Worklist.push_back(superBlock);
}
}
}
}
/// This function checks if a Machine Basic Block is valid for modulo
/// scheduling. This means that it has no control flow (if/else or
/// calls) in the block. Currently ModuloScheduling only works on
/// single basic block loops.
bool ModuloSchedulingSBPass::MachineBBisValid(const MachineBasicBlock *BI) {
//Check size of our basic block.. make sure we have more then just the terminator in it
if(BI->getBasicBlock()->size() == 1)
return false;
//Get Target machine instruction info
const TargetInstrInfo *TMI = target.getInstrInfo();
//Check each instruction and look for calls, keep map to get index later
std::map<const MachineInstr*, unsigned> indexMap;
unsigned count = 0;
for(MachineBasicBlock::const_iterator I = BI->begin(), E = BI->end(); I != E; ++I) {
//Get opcode to check instruction type
MachineOpCode OC = I->getOpcode();
//Look for calls
if(TMI->isCall(OC)) {
++BBWithCalls;
return false;
}
//Look for conditional move
if(OC == V9::MOVRZr || OC == V9::MOVRZi || OC == V9::MOVRLEZr || OC == V9::MOVRLEZi
|| OC == V9::MOVRLZr || OC == V9::MOVRLZi || OC == V9::MOVRNZr || OC == V9::MOVRNZi
|| OC == V9::MOVRGZr || OC == V9::MOVRGZi || OC == V9::MOVRGEZr
|| OC == V9::MOVRGEZi || OC == V9::MOVLEr || OC == V9::MOVLEi || OC == V9::MOVLEUr
|| OC == V9::MOVLEUi || OC == V9::MOVFLEr || OC == V9::MOVFLEi
|| OC == V9::MOVNEr || OC == V9::MOVNEi || OC == V9::MOVNEGr || OC == V9::MOVNEGi
|| OC ==
|