Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: src/IceCfg.cpp

Issue 300563003: Subzero: Initial O2 lowering (Closed) Base URL: https://gerrit.chromium.org/gerrit/p/native_client/pnacl-subzero.git@master
Patch Set: Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===// 1 //===- subzero/src/IceCfg.cpp - Control flow graph implementation ---------===//
2 // 2 //
3 // The Subzero Code Generator 3 // The Subzero Code Generator
4 // 4 //
5 // This file is distributed under the University of Illinois Open Source 5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details. 6 // License. See LICENSE.TXT for details.
7 // 7 //
8 //===----------------------------------------------------------------------===// 8 //===----------------------------------------------------------------------===//
9 // 9 //
10 // This file implements the Cfg class, including constant pool 10 // This file implements the Cfg class, including constant pool
11 // management. 11 // management.
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #include "IceCfg.h" 15 #include "IceCfg.h"
16 #include "IceCfgNode.h" 16 #include "IceCfgNode.h"
17 #include "IceDefs.h" 17 #include "IceDefs.h"
18 #include "IceInst.h" 18 #include "IceInst.h"
19 #include "IceLiveness.h"
19 #include "IceOperand.h" 20 #include "IceOperand.h"
20 #include "IceTargetLowering.h" 21 #include "IceTargetLowering.h"
21 22
22 namespace Ice { 23 namespace Ice {
23 24
24 Cfg::Cfg(GlobalContext *Ctx) 25 Cfg::Cfg(GlobalContext *Ctx)
25 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void), 26 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void),
26 IsInternalLinkage(false), HasError(false), ErrorMessage(""), Entry(NULL), 27 IsInternalLinkage(false), HasError(false), ErrorMessage(""), Entry(NULL),
27 NextInstNumber(1), 28 NextInstNumber(1), Live(NULL),
28 Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)), 29 Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)),
29 CurrentNode(NULL) {} 30 CurrentNode(NULL) {}
30 31
31 Cfg::~Cfg() {} 32 Cfg::~Cfg() {}
32 33
33 void Cfg::setError(const IceString &Message) { 34 void Cfg::setError(const IceString &Message) {
34 HasError = true; 35 HasError = true;
35 ErrorMessage = Message; 36 ErrorMessage = Message;
36 Ctx->getStrDump() << "ICE translation error: " << ErrorMessage << "\n"; 37 Ctx->getStrDump() << "ICE translation error: " << ErrorMessage << "\n";
37 } 38 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 dump(); 83 dump();
83 } 84 }
84 } 85 }
85 86
86 void Cfg::computePredecessors() { 87 void Cfg::computePredecessors() {
87 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 88 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
88 (*I)->computePredecessors(); 89 (*I)->computePredecessors();
89 } 90 }
90 } 91 }
91 92
93 void Cfg::renumberInstructions() {
94 NextInstNumber = 1;
95 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
96 (*I)->renumberInstructions();
97 }
98 }
99
92 // placePhiLoads() must be called before placePhiStores(). 100 // placePhiLoads() must be called before placePhiStores().
93 void Cfg::placePhiLoads() { 101 void Cfg::placePhiLoads() {
94 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 102 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
95 (*I)->placePhiLoads(); 103 (*I)->placePhiLoads();
96 } 104 }
97 } 105 }
98 106
99 // placePhiStores() must be called after placePhiLoads(). 107 // placePhiStores() must be called after placePhiLoads().
100 void Cfg::placePhiStores() { 108 void Cfg::placePhiStores() {
101 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 109 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
102 (*I)->placePhiStores(); 110 (*I)->placePhiStores();
103 } 111 }
104 } 112 }
105 113
106 void Cfg::deletePhis() { 114 void Cfg::deletePhis() {
107 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 115 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
108 (*I)->deletePhis(); 116 (*I)->deletePhis();
109 } 117 }
110 } 118 }
111 119
120 void Cfg::doAddressOpt() {
121 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
122 (*I)->doAddressOpt();
123 }
124 }
125
112 void Cfg::genCode() { 126 void Cfg::genCode() {
113 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 127 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
114 (*I)->genCode(); 128 (*I)->genCode();
115 } 129 }
116 } 130 }
117 131
118 // Compute the stack frame layout. 132 // Compute the stack frame layout.
119 void Cfg::genFrame() { 133 void Cfg::genFrame() {
120 getTarget()->addProlog(Entry); 134 getTarget()->addProlog(Entry);
121 // TODO: Consider folding epilog generation into the final 135 // TODO: Consider folding epilog generation into the final
122 // emission/assembly pass to avoid an extra iteration over the node 136 // emission/assembly pass to avoid an extra iteration over the node
123 // list. Or keep a separate list of exit nodes. 137 // list. Or keep a separate list of exit nodes.
124 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 138 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
125 CfgNode *Node = *I; 139 CfgNode *Node = *I;
126 if (Node->getHasReturn()) 140 if (Node->getHasReturn())
127 getTarget()->addEpilog(Node); 141 getTarget()->addEpilog(Node);
128 } 142 }
129 } 143 }
130 144
145 void Cfg::liveness(LivenessMode Mode) {
146 if (Mode == Liveness_LREndLightweight) {
147 // Lightweight liveness is a quick single pass and doesn't need to
148 // iterate until convergence.
149 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
150 (*I)->liveness(Mode, getLiveness());
JF 2014/05/25 22:50:50 Can't getLiveness() return a nullptr here?
Jim Stichnoth 2014/05/29 01:39:46 Yes, but as it turns out, the "lightweight" mode d
151 }
152 return;
153 }
154
155 Live.reset(new Liveness(this, Mode));
156 Live->init();
157 llvm::BitVector NeedToProcess(Nodes.size());
158 // Mark all nodes as needing to be processed.
159 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
160 NeedToProcess[(*I)->getIndex()] = true;
161 }
JF 2014/05/25 22:50:50 Can you set the entire bit vector to true? If all
Jim Stichnoth 2014/05/29 01:39:46 Done (via the constructor). That loop-based initi
162 while (NeedToProcess.any()) {
163 // Iterate in reverse topological order to speed up convergence.
164 for (NodeList::reverse_iterator I = Nodes.rbegin(), E = Nodes.rend();
165 I != E; ++I) {
166 CfgNode *Node = *I;
167 if (NeedToProcess[Node->getIndex()]) {
168 NeedToProcess[Node->getIndex()] = false;
169 bool Changed = Node->liveness(Mode, getLiveness());
170 if (Changed) {
171 // If the beginning-of-block liveness changed since the last
172 // iteration, mark all in-edges as needing to be processed.
173 const NodeList &InEdges = Node->getInEdges();
174 for (NodeList::const_iterator I1 = InEdges.begin(),
175 E1 = InEdges.end();
176 I1 != E1; ++I1) {
177 CfgNode *Pred = *I1;
178 NeedToProcess[Pred->getIndex()] = true;
179 }
180 }
181 }
182 }
183 }
184 if (Mode == Liveness_RangesFull) {
185 // Reset each variable's live range.
186 for (VarList::const_iterator I = Variables.begin(), E = Variables.end();
187 I != E; ++I) {
188 if (Variable *Var = *I)
189 Var->resetLiveRange();
190 }
191 }
192 Timer T_liveRange;
JF 2014/05/25 22:50:50 Why just time this part?
Jim Stichnoth 2014/05/29 01:39:46 Added a comment to explain. Basically, I want a b
193 // Make a final pass over instructions to delete dead instructions
194 // and build each Variable's live range.
195 for (NodeList::iterator I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
196 (*I)->livenessPostprocess(Mode, getLiveness());
197 }
198 if (Mode == Liveness_RangesFull) {
199 // Special treatment for live in-args. Their liveness needs to
200 // extend beyond the beginning of the function, otherwise an arg
201 // whose only use is in the first instruction will end up having
202 // the trivial live range [1,1) and will *not* interfere with
203 // other arguments. So if the first instruction of the method is
204 // "r=arg1+arg2", both args may be assigned the same register.
205 for (SizeT I = 0; I < Args.size(); ++I) {
206 Variable *Arg = Args[I];
207 if (!Live->getLiveRange(Arg).isEmpty()) {
208 // Add live range [-1,0) with weight 0.
209 Live->addLiveRange(Arg, -1, 0, 0);
210 }
211 Variable *Lo = Arg->getLo();
212 if (Lo && !Live->getLiveRange(Lo).isEmpty())
213 Live->addLiveRange(Lo, -1, 0, 0);
214 Variable *Hi = Arg->getHi();
215 if (Hi && !Live->getLiveRange(Hi).isEmpty())
216 Live->addLiveRange(Hi, -1, 0, 0);
JF 2014/05/25 22:50:50 What's this lo/hi thing?
Jim Stichnoth 2014/05/29 01:39:46 Added a comment explaining. BTW, there's a TODO i
217 }
218 // Copy Liveness::LiveRanges into individual variables. TODO:
219 // Remove Variable::LiveRange and redirect to
220 // Liveness::LiveRanges. TODO: make sure Variable weights
221 // are applied properly.
222 SizeT NumVars = Variables.size();
223 for (SizeT i = 0; i < NumVars; ++i) {
224 Variable *Var = Variables[i];
225 Var->setLiveRange(Live->getLiveRange(Var));
226 if (Var->getWeight().isInf())
227 Var->setLiveRangeInfiniteWeight();
228 setCurrentNode(NULL);
229 }
230 T_liveRange.printElapsedUs(getContext(), "live range construction");
231 dump();
jvoung (off chromium) 2014/05/28 17:48:15 If ctx->isVerbose, then dump() to avoid iterating
Jim Stichnoth 2014/05/29 01:39:46 Good idea. dump() now takes an optional intro mes
232 // TODO: validateLiveness() is a heavyweight operation inside an
233 // assert(). In a Release build with asserts enabled, we may want
234 // to disable this call.
235 assert(validateLiveness());
JF 2014/05/25 22:50:50 Could you validate passes after the pass instead?
Jim Stichnoth 2014/05/29 01:39:46 Removed the liveness validation from liveness(), a
236 }
237 }
238
239 // Traverse every Variable of every Inst and verify that it
240 // appears within the Variable's computed live range.
241 bool Cfg::validateLiveness() const {
242 bool Valid = true;
243 for (NodeList::const_iterator I1 = Nodes.begin(), E1 = Nodes.end(); I1 != E1;
244 ++I1) {
245 CfgNode *Node = *I1;
246 InstList &Insts = Node->getInsts();
247 for (InstList::const_iterator I2 = Insts.begin(), E2 = Insts.end();
248 I2 != E2; ++I2) {
249 Inst *Inst = *I2;
250 if (Inst->isDeleted())
251 continue;
252 if (llvm::isa<InstFakeKill>(Inst))
253 continue;
254 int32_t InstNumber = Inst->getNumber();
255 Variable *Dest = Inst->getDest();
256 if (Dest) {
257 // TODO: This instruction should actually begin Dest's live
258 // range, so we could probably test that this instruction is
259 // the beginning of some segment of Dest's live range. But
260 // this wouldn't work with non-SSA temporaries during
261 // lowering.
262 if (!Dest->getLiveRange().containsValue(InstNumber)) {
263 Valid = false;
264 assert(Valid);
JF 2014/05/25 22:50:50 i'm confused by this. Do you want to print the inv
Jim Stichnoth 2014/05/29 01:39:46 Done.
265 }
266 }
267 SizeT VarIndex = 0;
jvoung (off chromium) 2014/05/28 17:48:15 VarIndex unused (just incremented)?
Jim Stichnoth 2014/05/29 01:39:46 This iterator pattern is copied in several places.
268 for (SizeT I = 0; I < Inst->getSrcSize(); ++I) {
269 Operand *Src = Inst->getSrc(I);
270 SizeT NumVars = Src->getNumVars();
271 for (SizeT J = 0; J < NumVars; ++J, ++VarIndex) {
272 const Variable *Var = Src->getVar(J);
273 if (!Var->getLiveRange().containsValue(InstNumber)) {
274 Valid = false;
275 assert(Valid);
JF 2014/05/25 22:50:50 Ditto.
Jim Stichnoth 2014/05/29 01:39:46 Done.
276 }
277 }
278 }
279 }
280 }
281 return Valid;
282 }
283
131 // ======================== Dump routines ======================== // 284 // ======================== Dump routines ======================== //
132 285
133 void Cfg::emit() { 286 void Cfg::emit() {
134 Ostream &Str = Ctx->getStrEmit(); 287 Ostream &Str = Ctx->getStrEmit();
135 Timer T_emit; 288 Timer T_emit;
136 if (!Ctx->testAndSetHasEmittedFirstMethod()) { 289 if (!Ctx->testAndSetHasEmittedFirstMethod()) {
137 // Print a helpful command for assembling the output. 290 // Print a helpful command for assembling the output.
138 // TODO: have the Target emit the header 291 // TODO: have the Target emit the header
139 // TODO: need a per-file emit in addition to per-CFG 292 // TODO: need a per-file emit in addition to per-CFG
140 Str << "# $LLVM_BIN_PATH/llvm-mc" 293 Str << "# $LLVM_BIN_PATH/llvm-mc"
(...skipping 28 matching lines...) Expand all
169 Str << ReturnType << " @" << getFunctionName() << "("; 322 Str << ReturnType << " @" << getFunctionName() << "(";
170 for (SizeT i = 0; i < Args.size(); ++i) { 323 for (SizeT i = 0; i < Args.size(); ++i) {
171 if (i > 0) 324 if (i > 0)
172 Str << ", "; 325 Str << ", ";
173 Str << Args[i]->getType() << " "; 326 Str << Args[i]->getType() << " ";
174 Args[i]->dump(this); 327 Args[i]->dump(this);
175 } 328 }
176 Str << ") {\n"; 329 Str << ") {\n";
177 } 330 }
178 setCurrentNode(NULL); 331 setCurrentNode(NULL);
332 if (getContext()->isVerbose(IceV_Liveness)) {
333 // Print summary info about variables
334 for (VarList::const_iterator I = Variables.begin(), E = Variables.end();
335 I != E; ++I) {
336 Variable *Var = *I;
337 Str << "//"
338 << " multiblock=" << Var->isMultiblockLife() << " "
339 << " weight=" << Var->getWeight() << " ";
340 Var->dump(this);
341 Str << " LIVE=" << Var->getLiveRange() << "\n";
342 }
343 }
179 // Print each basic block 344 // Print each basic block
180 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E; 345 for (NodeList::const_iterator I = Nodes.begin(), E = Nodes.end(); I != E;
181 ++I) { 346 ++I) {
182 (*I)->dump(this); 347 (*I)->dump(this);
183 } 348 }
184 if (getContext()->isVerbose(IceV_Instructions)) { 349 if (getContext()->isVerbose(IceV_Instructions)) {
185 Str << "}\n"; 350 Str << "}\n";
186 } 351 }
187 } 352 }
188 353
189 } // end of namespace Ice 354 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceCfg.h ('k') | src/IceCfgNode.h » ('j') | src/IceCfgNode.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698