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

Side by Side Diff: src/IceCfg.cpp

Issue 620373004: Subzero: Add a few performance measurement tools. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Improve the use of containers Created 6 years, 2 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
« no previous file with comments | « src/IceCfg.h ('k') | src/IceCfgNode.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "IceClFlags.h" 17 #include "IceClFlags.h"
18 #include "IceDefs.h" 18 #include "IceDefs.h"
19 #include "IceInst.h" 19 #include "IceInst.h"
20 #include "IceLiveness.h" 20 #include "IceLiveness.h"
21 #include "IceOperand.h" 21 #include "IceOperand.h"
22 #include "IceTargetLowering.h" 22 #include "IceTargetLowering.h"
23 23
24 namespace Ice { 24 namespace Ice {
25 25
26 Cfg::Cfg(GlobalContext *Ctx) 26 Cfg::Cfg(GlobalContext *Ctx)
27 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void), 27 : Ctx(Ctx), FunctionName(""), ReturnType(IceType_void),
28 IsInternalLinkage(false), HasError(false), ErrorMessage(""), Entry(NULL), 28 IsInternalLinkage(false), HasError(false), FocusedTiming(false),
29 NextInstNumber(1), Live(nullptr), 29 ErrorMessage(""), Entry(NULL), NextInstNumber(1), Live(nullptr),
30 Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)), 30 Target(TargetLowering::createLowering(Ctx->getTargetArch(), this)),
31 VMetadata(new VariablesMetadata(this)), 31 VMetadata(new VariablesMetadata(this)),
32 TargetAssembler( 32 TargetAssembler(
33 TargetLowering::createAssembler(Ctx->getTargetArch(), this)), 33 TargetLowering::createAssembler(Ctx->getTargetArch(), this)),
34 CurrentNode(NULL) {} 34 CurrentNode(NULL) {}
35 35
36 Cfg::~Cfg() {} 36 Cfg::~Cfg() {}
37 37
38 void Cfg::setError(const IceString &Message) { 38 void Cfg::setError(const IceString &Message) {
39 HasError = true; 39 HasError = true;
(...skipping 22 matching lines...) Expand all
62 ImplicitArgs.push_back(Arg); 62 ImplicitArgs.push_back(Arg);
63 } 63 }
64 64
65 // Returns whether the stack frame layout has been computed yet. This 65 // Returns whether the stack frame layout has been computed yet. This
66 // is used for dumping the stack frame location of Variables. 66 // is used for dumping the stack frame location of Variables.
67 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); } 67 bool Cfg::hasComputedFrame() const { return getTarget()->hasComputedFrame(); }
68 68
69 void Cfg::translate() { 69 void Cfg::translate() {
70 if (hasError()) 70 if (hasError())
71 return; 71 return;
72 static TimerIdT IDtranslate = GlobalContext::getTimerID("translate"); 72 VerboseMask OldVerboseMask = getContext()->getVerbose();
73 TimerMarker T(IDtranslate, getContext()); 73 const IceString &TimingFocusOn = getContext()->getFlags().TimingFocusOn;
74 if (TimingFocusOn == "*" || TimingFocusOn == getFunctionName())
75 setFocusedTiming();
76 bool VerboseFocus =
77 (getContext()->getFlags().VerboseFocusOn == getFunctionName());
78 if (VerboseFocus)
79 getContext()->setVerbose(IceV_All);
80 TimerMarker T(TimerStack::TT_translate, this);
74 81
75 dump("Initial CFG"); 82 dump("Initial CFG");
76 83
77 // The set of translation passes and their order are determined by 84 // The set of translation passes and their order are determined by
78 // the target. 85 // the target.
79 getTarget()->translate(); 86 getTarget()->translate();
80 87
81 dump("Final output"); 88 dump("Final output");
89 if (getFocusedTiming())
90 getContext()->dumpTimers();
91 if (VerboseFocus)
92 getContext()->setVerbose(OldVerboseMask);
82 } 93 }
83 94
84 void Cfg::computePredecessors() { 95 void Cfg::computePredecessors() {
85 for (CfgNode *Node : Nodes) 96 for (CfgNode *Node : Nodes)
86 Node->computePredecessors(); 97 Node->computePredecessors();
87 } 98 }
88 99
89 void Cfg::renumberInstructions() { 100 void Cfg::renumberInstructions() {
90 static TimerIdT IDrenumberInstructions = 101 TimerMarker T(TimerStack::TT_renumberInstructions, this);
91 GlobalContext::getTimerID("renumberInstructions");
92 TimerMarker T(IDrenumberInstructions, getContext());
93 NextInstNumber = 1; 102 NextInstNumber = 1;
94 for (CfgNode *Node : Nodes) 103 for (CfgNode *Node : Nodes)
95 Node->renumberInstructions(); 104 Node->renumberInstructions();
96 } 105 }
97 106
98 // placePhiLoads() must be called before placePhiStores(). 107 // placePhiLoads() must be called before placePhiStores().
99 void Cfg::placePhiLoads() { 108 void Cfg::placePhiLoads() {
100 static TimerIdT IDplacePhiLoads = GlobalContext::getTimerID("placePhiLoads"); 109 TimerMarker T(TimerStack::TT_placePhiLoads, this);
101 TimerMarker T(IDplacePhiLoads, getContext());
102 for (CfgNode *Node : Nodes) 110 for (CfgNode *Node : Nodes)
103 Node->placePhiLoads(); 111 Node->placePhiLoads();
104 } 112 }
105 113
106 // placePhiStores() must be called after placePhiLoads(). 114 // placePhiStores() must be called after placePhiLoads().
107 void Cfg::placePhiStores() { 115 void Cfg::placePhiStores() {
108 static TimerIdT IDplacePhiStores = 116 TimerMarker T(TimerStack::TT_placePhiStores, this);
109 GlobalContext::getTimerID("placePhiStores");
110 TimerMarker T(IDplacePhiStores, getContext());
111 for (CfgNode *Node : Nodes) 117 for (CfgNode *Node : Nodes)
112 Node->placePhiStores(); 118 Node->placePhiStores();
113 } 119 }
114 120
115 void Cfg::deletePhis() { 121 void Cfg::deletePhis() {
116 static TimerIdT IDdeletePhis = GlobalContext::getTimerID("deletePhis"); 122 TimerMarker T(TimerStack::TT_deletePhis, this);
117 TimerMarker T(IDdeletePhis, getContext());
118 for (CfgNode *Node : Nodes) 123 for (CfgNode *Node : Nodes)
119 Node->deletePhis(); 124 Node->deletePhis();
120 } 125 }
121 126
122 void Cfg::doArgLowering() { 127 void Cfg::doArgLowering() {
123 static TimerIdT IDdoArgLowering = GlobalContext::getTimerID("doArgLowering"); 128 TimerMarker T(TimerStack::TT_doArgLowering, this);
124 TimerMarker T(IDdoArgLowering, getContext());
125 getTarget()->lowerArguments(); 129 getTarget()->lowerArguments();
126 } 130 }
127 131
128 void Cfg::doAddressOpt() { 132 void Cfg::doAddressOpt() {
129 static TimerIdT IDdoAddressOpt = GlobalContext::getTimerID("doAddressOpt"); 133 TimerMarker T(TimerStack::TT_doAddressOpt, this);
130 TimerMarker T(IDdoAddressOpt, getContext());
131 for (CfgNode *Node : Nodes) 134 for (CfgNode *Node : Nodes)
132 Node->doAddressOpt(); 135 Node->doAddressOpt();
133 } 136 }
134 137
135 void Cfg::doNopInsertion() { 138 void Cfg::doNopInsertion() {
136 static TimerIdT IDdoNopInsertion = 139 TimerMarker T(TimerStack::TT_doNopInsertion, this);
137 GlobalContext::getTimerID("doNopInsertion");
138 TimerMarker T(IDdoNopInsertion, getContext());
139 for (CfgNode *Node : Nodes) 140 for (CfgNode *Node : Nodes)
140 Node->doNopInsertion(); 141 Node->doNopInsertion();
141 } 142 }
142 143
143 void Cfg::genCode() { 144 void Cfg::genCode() {
144 static TimerIdT IDgenCode = GlobalContext::getTimerID("genCode"); 145 TimerMarker T(TimerStack::TT_genCode, this);
145 TimerMarker T(IDgenCode, getContext());
146 for (CfgNode *Node : Nodes) 146 for (CfgNode *Node : Nodes)
147 Node->genCode(); 147 Node->genCode();
148 } 148 }
149 149
150 // Compute the stack frame layout. 150 // Compute the stack frame layout.
151 void Cfg::genFrame() { 151 void Cfg::genFrame() {
152 static TimerIdT IDgenFrame = GlobalContext::getTimerID("genFrame"); 152 TimerMarker T(TimerStack::TT_genFrame, this);
153 TimerMarker T(IDgenFrame, getContext());
154 getTarget()->addProlog(Entry); 153 getTarget()->addProlog(Entry);
155 // TODO: Consider folding epilog generation into the final 154 // TODO: Consider folding epilog generation into the final
156 // emission/assembly pass to avoid an extra iteration over the node 155 // emission/assembly pass to avoid an extra iteration over the node
157 // list. Or keep a separate list of exit nodes. 156 // list. Or keep a separate list of exit nodes.
158 for (CfgNode *Node : Nodes) 157 for (CfgNode *Node : Nodes)
159 if (Node->getHasReturn()) 158 if (Node->getHasReturn())
160 getTarget()->addEpilog(Node); 159 getTarget()->addEpilog(Node);
161 } 160 }
162 161
163 // This is a lightweight version of live-range-end calculation. Marks 162 // This is a lightweight version of live-range-end calculation. Marks
164 // the last use of only those variables whose definition and uses are 163 // the last use of only those variables whose definition and uses are
165 // completely with a single block. It is a quick single pass and 164 // completely with a single block. It is a quick single pass and
166 // doesn't need to iterate until convergence. 165 // doesn't need to iterate until convergence.
167 void Cfg::livenessLightweight() { 166 void Cfg::livenessLightweight() {
168 static TimerIdT IDlivenessLightweight = 167 TimerMarker T(TimerStack::TT_livenessLightweight, this);
169 GlobalContext::getTimerID("livenessLightweight");
170 TimerMarker T(IDlivenessLightweight, getContext());
171 getVMetadata()->init(); 168 getVMetadata()->init();
172 for (CfgNode *Node : Nodes) 169 for (CfgNode *Node : Nodes)
173 Node->livenessLightweight(); 170 Node->livenessLightweight();
174 } 171 }
175 172
176 void Cfg::liveness(LivenessMode Mode) { 173 void Cfg::liveness(LivenessMode Mode) {
177 static TimerIdT IDliveness = GlobalContext::getTimerID("liveness"); 174 TimerMarker T(TimerStack::TT_liveness, this);
178 TimerMarker T(IDliveness, getContext());
179 Live.reset(new Liveness(this, Mode)); 175 Live.reset(new Liveness(this, Mode));
180 getVMetadata()->init(); 176 getVMetadata()->init();
181 Live->init(); 177 Live->init();
182 // Initialize with all nodes needing to be processed. 178 // Initialize with all nodes needing to be processed.
183 llvm::BitVector NeedToProcess(Nodes.size(), true); 179 llvm::BitVector NeedToProcess(Nodes.size(), true);
184 while (NeedToProcess.any()) { 180 while (NeedToProcess.any()) {
185 // Iterate in reverse topological order to speed up convergence. 181 // Iterate in reverse topological order to speed up convergence.
186 // TODO(stichnot): Use llvm::make_range with LLVM 3.5. 182 // TODO(stichnot): Use llvm::make_range with LLVM 3.5.
187 for (auto I = Nodes.rbegin(), E = Nodes.rend(); I != E; ++I) { 183 for (auto I = Nodes.rbegin(), E = Nodes.rend(); I != E; ++I) {
188 CfgNode *Node = *I; 184 CfgNode *Node = *I;
(...skipping 12 matching lines...) Expand all
201 if (Mode == Liveness_Intervals) { 197 if (Mode == Liveness_Intervals) {
202 // Reset each variable's live range. 198 // Reset each variable's live range.
203 for (Variable *Var : Variables) 199 for (Variable *Var : Variables)
204 Var->resetLiveRange(); 200 Var->resetLiveRange();
205 } 201 }
206 // Collect timing for just the portion that constructs the live 202 // Collect timing for just the portion that constructs the live
207 // range intervals based on the end-of-live-range computation, for a 203 // range intervals based on the end-of-live-range computation, for a
208 // finer breakdown of the cost. 204 // finer breakdown of the cost.
209 // Make a final pass over instructions to delete dead instructions 205 // Make a final pass over instructions to delete dead instructions
210 // and build each Variable's live range. 206 // and build each Variable's live range.
211 static TimerIdT IDliveRange = GlobalContext::getTimerID("liveRange"); 207 TimerMarker T1(TimerStack::TT_liveRange, this);
212 TimerMarker T1(IDliveRange, getContext());
213 for (CfgNode *Node : Nodes) 208 for (CfgNode *Node : Nodes)
214 Node->livenessPostprocess(Mode, getLiveness()); 209 Node->livenessPostprocess(Mode, getLiveness());
215 if (Mode == Liveness_Intervals) { 210 if (Mode == Liveness_Intervals) {
216 // Special treatment for live in-args. Their liveness needs to 211 // Special treatment for live in-args. Their liveness needs to
217 // extend beyond the beginning of the function, otherwise an arg 212 // extend beyond the beginning of the function, otherwise an arg
218 // whose only use is in the first instruction will end up having 213 // whose only use is in the first instruction will end up having
219 // the trivial live range [1,1) and will *not* interfere with 214 // the trivial live range [1,1) and will *not* interfere with
220 // other arguments. So if the first instruction of the method is 215 // other arguments. So if the first instruction of the method is
221 // "r=arg1+arg2", both args may be assigned the same register. 216 // "r=arg1+arg2", both args may be assigned the same register.
222 for (SizeT I = 0; I < Args.size(); ++I) { 217 for (SizeT I = 0; I < Args.size(); ++I) {
(...skipping 25 matching lines...) Expand all
248 if (Var->getWeight().isInf()) 243 if (Var->getWeight().isInf())
249 Var->setLiveRangeInfiniteWeight(); 244 Var->setLiveRangeInfiniteWeight();
250 } 245 }
251 dump(); 246 dump();
252 } 247 }
253 } 248 }
254 249
255 // Traverse every Variable of every Inst and verify that it 250 // Traverse every Variable of every Inst and verify that it
256 // appears within the Variable's computed live range. 251 // appears within the Variable's computed live range.
257 bool Cfg::validateLiveness() const { 252 bool Cfg::validateLiveness() const {
258 static TimerIdT IDvalidateLiveness = 253 TimerMarker T(TimerStack::TT_validateLiveness, this);
259 GlobalContext::getTimerID("validateLiveness");
260 TimerMarker T(IDvalidateLiveness, getContext());
261 bool Valid = true; 254 bool Valid = true;
262 Ostream &Str = Ctx->getStrDump(); 255 Ostream &Str = Ctx->getStrDump();
263 for (CfgNode *Node : Nodes) { 256 for (CfgNode *Node : Nodes) {
264 for (Inst *Inst : Node->getInsts()) { 257 for (Inst *Inst : Node->getInsts()) {
265 if (Inst->isDeleted()) 258 if (Inst->isDeleted())
266 continue; 259 continue;
267 if (llvm::isa<InstFakeKill>(Inst)) 260 if (llvm::isa<InstFakeKill>(Inst))
268 continue; 261 continue;
269 InstNumberT InstNumber = Inst->getNumber(); 262 InstNumberT InstNumber = Inst->getNumber();
270 Variable *Dest = Inst->getDest(); 263 Variable *Dest = Inst->getDest();
(...skipping 22 matching lines...) Expand all
293 Str << " live range " << Var->getLiveRange() << "\n"; 286 Str << " live range " << Var->getLiveRange() << "\n";
294 } 287 }
295 } 288 }
296 } 289 }
297 } 290 }
298 } 291 }
299 return Valid; 292 return Valid;
300 } 293 }
301 294
302 void Cfg::doBranchOpt() { 295 void Cfg::doBranchOpt() {
303 static TimerIdT IDdoBranchOpt = GlobalContext::getTimerID("doBranchOpt"); 296 TimerMarker T(TimerStack::TT_doBranchOpt, this);
304 TimerMarker T(IDdoBranchOpt, getContext());
305 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 297 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
306 auto NextNode = I; 298 auto NextNode = I;
307 ++NextNode; 299 ++NextNode;
308 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode); 300 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode);
309 } 301 }
310 } 302 }
311 303
312 // ======================== Dump routines ======================== // 304 // ======================== Dump routines ======================== //
313 305
314 void Cfg::emit() { 306 void Cfg::emit() {
315 static TimerIdT IDemit = GlobalContext::getTimerID("emit"); 307 TimerMarker T(TimerStack::TT_emit, this);
316 TimerMarker T(IDemit, getContext());
317 Ostream &Str = Ctx->getStrEmit(); 308 Ostream &Str = Ctx->getStrEmit();
318 if (!Ctx->testAndSetHasEmittedFirstMethod()) { 309 if (!Ctx->testAndSetHasEmittedFirstMethod()) {
319 // Print a helpful command for assembling the output. 310 // Print a helpful command for assembling the output.
320 // TODO: have the Target emit the header 311 // TODO: have the Target emit the header
321 // TODO: need a per-file emit in addition to per-CFG 312 // TODO: need a per-file emit in addition to per-CFG
322 Str << "# $LLVM_BIN_PATH/llvm-mc" 313 Str << "# $LLVM_BIN_PATH/llvm-mc"
323 << " -arch=x86" 314 << " -arch=x86"
324 << " -x86-asm-syntax=intel" 315 << " -x86-asm-syntax=intel"
325 << " -filetype=obj" 316 << " -filetype=obj"
326 << " -o=MyObj.o" 317 << " -o=MyObj.o"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 } 371 }
381 } 372 }
382 // Print each basic block 373 // Print each basic block
383 for (CfgNode *Node : Nodes) 374 for (CfgNode *Node : Nodes)
384 Node->dump(this); 375 Node->dump(this);
385 if (getContext()->isVerbose(IceV_Instructions)) 376 if (getContext()->isVerbose(IceV_Instructions))
386 Str << "}\n"; 377 Str << "}\n";
387 } 378 }
388 379
389 } // end of namespace Ice 380 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceCfg.h ('k') | src/IceCfgNode.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698