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

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: Minor fixes 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
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 VerboseMask OldVerboseMask = getContext()->getVerbose();
73 const IceString &TimingFocusOn = getContext()->getFlags().TimingFocusOn;
74 if (TimingFocusOn == "*" || TimingFocusOn == getFunctionName())
75 setFocusedTiming();
76 bool VerboseFocus = (getContext()->getFlags().VerboseFocusOn == getFunctionNam e());
jvoung (off chromium) 2014/10/06 16:30:56 80 col ?
Jim Stichnoth 2014/10/06 21:29:57 Done.
77 if (VerboseFocus)
78 getContext()->setVerbose(IceV_All);
72 static TimerIdT IDtranslate = GlobalContext::getTimerID("translate"); 79 static TimerIdT IDtranslate = GlobalContext::getTimerID("translate");
73 TimerMarker T(IDtranslate, getContext()); 80 TimerMarker T(IDtranslate, 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 static TimerIdT IDrenumberInstructions =
91 GlobalContext::getTimerID("renumberInstructions"); 102 GlobalContext::getTimerID("renumberInstructions");
92 TimerMarker T(IDrenumberInstructions, getContext()); 103 TimerMarker T(IDrenumberInstructions, this);
93 NextInstNumber = 1; 104 NextInstNumber = 1;
94 for (CfgNode *Node : Nodes) 105 for (CfgNode *Node : Nodes)
95 Node->renumberInstructions(); 106 Node->renumberInstructions();
96 } 107 }
97 108
98 // placePhiLoads() must be called before placePhiStores(). 109 // placePhiLoads() must be called before placePhiStores().
99 void Cfg::placePhiLoads() { 110 void Cfg::placePhiLoads() {
100 static TimerIdT IDplacePhiLoads = GlobalContext::getTimerID("placePhiLoads"); 111 static TimerIdT IDplacePhiLoads = GlobalContext::getTimerID("placePhiLoads");
101 TimerMarker T(IDplacePhiLoads, getContext()); 112 TimerMarker T(IDplacePhiLoads, this);
102 for (CfgNode *Node : Nodes) 113 for (CfgNode *Node : Nodes)
103 Node->placePhiLoads(); 114 Node->placePhiLoads();
104 } 115 }
105 116
106 // placePhiStores() must be called after placePhiLoads(). 117 // placePhiStores() must be called after placePhiLoads().
107 void Cfg::placePhiStores() { 118 void Cfg::placePhiStores() {
108 static TimerIdT IDplacePhiStores = 119 static TimerIdT IDplacePhiStores =
109 GlobalContext::getTimerID("placePhiStores"); 120 GlobalContext::getTimerID("placePhiStores");
110 TimerMarker T(IDplacePhiStores, getContext()); 121 TimerMarker T(IDplacePhiStores, this);
111 for (CfgNode *Node : Nodes) 122 for (CfgNode *Node : Nodes)
112 Node->placePhiStores(); 123 Node->placePhiStores();
113 } 124 }
114 125
115 void Cfg::deletePhis() { 126 void Cfg::deletePhis() {
116 static TimerIdT IDdeletePhis = GlobalContext::getTimerID("deletePhis"); 127 static TimerIdT IDdeletePhis = GlobalContext::getTimerID("deletePhis");
117 TimerMarker T(IDdeletePhis, getContext()); 128 TimerMarker T(IDdeletePhis, this);
118 for (CfgNode *Node : Nodes) 129 for (CfgNode *Node : Nodes)
119 Node->deletePhis(); 130 Node->deletePhis();
120 } 131 }
121 132
122 void Cfg::doArgLowering() { 133 void Cfg::doArgLowering() {
123 static TimerIdT IDdoArgLowering = GlobalContext::getTimerID("doArgLowering"); 134 static TimerIdT IDdoArgLowering = GlobalContext::getTimerID("doArgLowering");
124 TimerMarker T(IDdoArgLowering, getContext()); 135 TimerMarker T(IDdoArgLowering, this);
125 getTarget()->lowerArguments(); 136 getTarget()->lowerArguments();
126 } 137 }
127 138
128 void Cfg::doAddressOpt() { 139 void Cfg::doAddressOpt() {
129 static TimerIdT IDdoAddressOpt = GlobalContext::getTimerID("doAddressOpt"); 140 static TimerIdT IDdoAddressOpt = GlobalContext::getTimerID("doAddressOpt");
130 TimerMarker T(IDdoAddressOpt, getContext()); 141 TimerMarker T(IDdoAddressOpt, this);
131 for (CfgNode *Node : Nodes) 142 for (CfgNode *Node : Nodes)
132 Node->doAddressOpt(); 143 Node->doAddressOpt();
133 } 144 }
134 145
135 void Cfg::doNopInsertion() { 146 void Cfg::doNopInsertion() {
136 static TimerIdT IDdoNopInsertion = 147 static TimerIdT IDdoNopInsertion =
137 GlobalContext::getTimerID("doNopInsertion"); 148 GlobalContext::getTimerID("doNopInsertion");
138 TimerMarker T(IDdoNopInsertion, getContext()); 149 TimerMarker T(IDdoNopInsertion, this);
139 for (CfgNode *Node : Nodes) 150 for (CfgNode *Node : Nodes)
140 Node->doNopInsertion(); 151 Node->doNopInsertion();
141 } 152 }
142 153
143 void Cfg::genCode() { 154 void Cfg::genCode() {
144 static TimerIdT IDgenCode = GlobalContext::getTimerID("genCode"); 155 static TimerIdT IDgenCode = GlobalContext::getTimerID("genCode");
145 TimerMarker T(IDgenCode, getContext()); 156 TimerMarker T(IDgenCode, this);
146 for (CfgNode *Node : Nodes) 157 for (CfgNode *Node : Nodes)
147 Node->genCode(); 158 Node->genCode();
148 } 159 }
149 160
150 // Compute the stack frame layout. 161 // Compute the stack frame layout.
151 void Cfg::genFrame() { 162 void Cfg::genFrame() {
152 static TimerIdT IDgenFrame = GlobalContext::getTimerID("genFrame"); 163 static TimerIdT IDgenFrame = GlobalContext::getTimerID("genFrame");
153 TimerMarker T(IDgenFrame, getContext()); 164 TimerMarker T(IDgenFrame, this);
154 getTarget()->addProlog(Entry); 165 getTarget()->addProlog(Entry);
155 // TODO: Consider folding epilog generation into the final 166 // TODO: Consider folding epilog generation into the final
156 // emission/assembly pass to avoid an extra iteration over the node 167 // emission/assembly pass to avoid an extra iteration over the node
157 // list. Or keep a separate list of exit nodes. 168 // list. Or keep a separate list of exit nodes.
158 for (CfgNode *Node : Nodes) 169 for (CfgNode *Node : Nodes)
159 if (Node->getHasReturn()) 170 if (Node->getHasReturn())
160 getTarget()->addEpilog(Node); 171 getTarget()->addEpilog(Node);
161 } 172 }
162 173
163 // This is a lightweight version of live-range-end calculation. Marks 174 // This is a lightweight version of live-range-end calculation. Marks
164 // the last use of only those variables whose definition and uses are 175 // 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 176 // completely with a single block. It is a quick single pass and
166 // doesn't need to iterate until convergence. 177 // doesn't need to iterate until convergence.
167 void Cfg::livenessLightweight() { 178 void Cfg::livenessLightweight() {
168 static TimerIdT IDlivenessLightweight = 179 static TimerIdT IDlivenessLightweight =
169 GlobalContext::getTimerID("livenessLightweight"); 180 GlobalContext::getTimerID("livenessLightweight");
170 TimerMarker T(IDlivenessLightweight, getContext()); 181 TimerMarker T(IDlivenessLightweight, this);
171 getVMetadata()->init(); 182 getVMetadata()->init();
172 for (CfgNode *Node : Nodes) 183 for (CfgNode *Node : Nodes)
173 Node->livenessLightweight(); 184 Node->livenessLightweight();
174 } 185 }
175 186
176 void Cfg::liveness(LivenessMode Mode) { 187 void Cfg::liveness(LivenessMode Mode) {
177 static TimerIdT IDliveness = GlobalContext::getTimerID("liveness"); 188 static TimerIdT IDliveness = GlobalContext::getTimerID("liveness");
178 TimerMarker T(IDliveness, getContext()); 189 TimerMarker T(IDliveness, this);
179 Live.reset(new Liveness(this, Mode)); 190 Live.reset(new Liveness(this, Mode));
180 getVMetadata()->init(); 191 getVMetadata()->init();
181 Live->init(); 192 Live->init();
182 // Initialize with all nodes needing to be processed. 193 // Initialize with all nodes needing to be processed.
183 llvm::BitVector NeedToProcess(Nodes.size(), true); 194 llvm::BitVector NeedToProcess(Nodes.size(), true);
184 while (NeedToProcess.any()) { 195 while (NeedToProcess.any()) {
185 // Iterate in reverse topological order to speed up convergence. 196 // Iterate in reverse topological order to speed up convergence.
186 // TODO(stichnot): Use llvm::make_range with LLVM 3.5. 197 // TODO(stichnot): Use llvm::make_range with LLVM 3.5.
187 for (auto I = Nodes.rbegin(), E = Nodes.rend(); I != E; ++I) { 198 for (auto I = Nodes.rbegin(), E = Nodes.rend(); I != E; ++I) {
188 CfgNode *Node = *I; 199 CfgNode *Node = *I;
(...skipping 13 matching lines...) Expand all
202 // Reset each variable's live range. 213 // Reset each variable's live range.
203 for (Variable *Var : Variables) 214 for (Variable *Var : Variables)
204 Var->resetLiveRange(); 215 Var->resetLiveRange();
205 } 216 }
206 // Collect timing for just the portion that constructs the live 217 // Collect timing for just the portion that constructs the live
207 // range intervals based on the end-of-live-range computation, for a 218 // range intervals based on the end-of-live-range computation, for a
208 // finer breakdown of the cost. 219 // finer breakdown of the cost.
209 // Make a final pass over instructions to delete dead instructions 220 // Make a final pass over instructions to delete dead instructions
210 // and build each Variable's live range. 221 // and build each Variable's live range.
211 static TimerIdT IDliveRange = GlobalContext::getTimerID("liveRange"); 222 static TimerIdT IDliveRange = GlobalContext::getTimerID("liveRange");
212 TimerMarker T1(IDliveRange, getContext()); 223 TimerMarker T1(IDliveRange, this);
213 for (CfgNode *Node : Nodes) 224 for (CfgNode *Node : Nodes)
214 Node->livenessPostprocess(Mode, getLiveness()); 225 Node->livenessPostprocess(Mode, getLiveness());
215 if (Mode == Liveness_Intervals) { 226 if (Mode == Liveness_Intervals) {
216 // Special treatment for live in-args. Their liveness needs to 227 // Special treatment for live in-args. Their liveness needs to
217 // extend beyond the beginning of the function, otherwise an arg 228 // extend beyond the beginning of the function, otherwise an arg
218 // whose only use is in the first instruction will end up having 229 // whose only use is in the first instruction will end up having
219 // the trivial live range [1,1) and will *not* interfere with 230 // the trivial live range [1,1) and will *not* interfere with
220 // other arguments. So if the first instruction of the method is 231 // other arguments. So if the first instruction of the method is
221 // "r=arg1+arg2", both args may be assigned the same register. 232 // "r=arg1+arg2", both args may be assigned the same register.
222 for (SizeT I = 0; I < Args.size(); ++I) { 233 for (SizeT I = 0; I < Args.size(); ++I) {
(...skipping 27 matching lines...) Expand all
250 } 261 }
251 dump(); 262 dump();
252 } 263 }
253 } 264 }
254 265
255 // Traverse every Variable of every Inst and verify that it 266 // Traverse every Variable of every Inst and verify that it
256 // appears within the Variable's computed live range. 267 // appears within the Variable's computed live range.
257 bool Cfg::validateLiveness() const { 268 bool Cfg::validateLiveness() const {
258 static TimerIdT IDvalidateLiveness = 269 static TimerIdT IDvalidateLiveness =
259 GlobalContext::getTimerID("validateLiveness"); 270 GlobalContext::getTimerID("validateLiveness");
260 TimerMarker T(IDvalidateLiveness, getContext()); 271 TimerMarker T(IDvalidateLiveness, this);
261 bool Valid = true; 272 bool Valid = true;
262 Ostream &Str = Ctx->getStrDump(); 273 Ostream &Str = Ctx->getStrDump();
263 for (CfgNode *Node : Nodes) { 274 for (CfgNode *Node : Nodes) {
264 for (Inst *Inst : Node->getInsts()) { 275 for (Inst *Inst : Node->getInsts()) {
265 if (Inst->isDeleted()) 276 if (Inst->isDeleted())
266 continue; 277 continue;
267 if (llvm::isa<InstFakeKill>(Inst)) 278 if (llvm::isa<InstFakeKill>(Inst))
268 continue; 279 continue;
269 InstNumberT InstNumber = Inst->getNumber(); 280 InstNumberT InstNumber = Inst->getNumber();
270 Variable *Dest = Inst->getDest(); 281 Variable *Dest = Inst->getDest();
(...skipping 23 matching lines...) Expand all
294 } 305 }
295 } 306 }
296 } 307 }
297 } 308 }
298 } 309 }
299 return Valid; 310 return Valid;
300 } 311 }
301 312
302 void Cfg::doBranchOpt() { 313 void Cfg::doBranchOpt() {
303 static TimerIdT IDdoBranchOpt = GlobalContext::getTimerID("doBranchOpt"); 314 static TimerIdT IDdoBranchOpt = GlobalContext::getTimerID("doBranchOpt");
304 TimerMarker T(IDdoBranchOpt, getContext()); 315 TimerMarker T(IDdoBranchOpt, this);
305 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) { 316 for (auto I = Nodes.begin(), E = Nodes.end(); I != E; ++I) {
306 auto NextNode = I; 317 auto NextNode = I;
307 ++NextNode; 318 ++NextNode;
308 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode); 319 (*I)->doBranchOpt(NextNode == E ? NULL : *NextNode);
309 } 320 }
310 } 321 }
311 322
312 // ======================== Dump routines ======================== // 323 // ======================== Dump routines ======================== //
313 324
314 void Cfg::emit() { 325 void Cfg::emit() {
315 static TimerIdT IDemit = GlobalContext::getTimerID("emit"); 326 static TimerIdT IDemit = GlobalContext::getTimerID("emit");
316 TimerMarker T(IDemit, getContext()); 327 TimerMarker T(IDemit, this);
317 Ostream &Str = Ctx->getStrEmit(); 328 Ostream &Str = Ctx->getStrEmit();
318 if (!Ctx->testAndSetHasEmittedFirstMethod()) { 329 if (!Ctx->testAndSetHasEmittedFirstMethod()) {
319 // Print a helpful command for assembling the output. 330 // Print a helpful command for assembling the output.
320 // TODO: have the Target emit the header 331 // TODO: have the Target emit the header
321 // TODO: need a per-file emit in addition to per-CFG 332 // TODO: need a per-file emit in addition to per-CFG
322 Str << "# $LLVM_BIN_PATH/llvm-mc" 333 Str << "# $LLVM_BIN_PATH/llvm-mc"
323 << " -arch=x86" 334 << " -arch=x86"
324 << " -x86-asm-syntax=intel" 335 << " -x86-asm-syntax=intel"
325 << " -filetype=obj" 336 << " -filetype=obj"
326 << " -o=MyObj.o" 337 << " -o=MyObj.o"
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 } 391 }
381 } 392 }
382 // Print each basic block 393 // Print each basic block
383 for (CfgNode *Node : Nodes) 394 for (CfgNode *Node : Nodes)
384 Node->dump(this); 395 Node->dump(this);
385 if (getContext()->isVerbose(IceV_Instructions)) 396 if (getContext()->isVerbose(IceV_Instructions))
386 Str << "}\n"; 397 Str << "}\n";
387 } 398 }
388 399
389 } // end of namespace Ice 400 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceCfg.h ('k') | src/IceCfgNode.cpp » ('j') | src/IceGlobalContext.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698