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

Side by Side Diff: src/IceOperand.cpp

Issue 589003002: Subzero: Refactor tracking of Defs and block-local Variables. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: "Mark args as being used in the entry node" was unnecessary. 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/IceOperand.h ('k') | src/IceTargetLowering.h » ('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/IceOperand.cpp - High-level operand implementation -----===// 1 //===- subzero/src/IceOperand.cpp - High-level operand 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 Operand class and its target-independent 10 // This file implements the Operand class and its target-independent
11 // subclasses, primarily for the methods of the Variable class. 11 // subclasses, primarily for the methods of the Variable class.
12 // 12 //
13 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
14 14
15 #include "IceCfg.h" 15 #include "IceCfg.h"
16 #include "IceCfgNode.h"
16 #include "IceInst.h" 17 #include "IceInst.h"
17 #include "IceOperand.h" 18 #include "IceOperand.h"
18 #include "IceTargetLowering.h" // dumping stack/frame pointer register 19 #include "IceTargetLowering.h" // dumping stack/frame pointer register
19 20
20 namespace Ice { 21 namespace Ice {
21 22
22 bool operator<(const RelocatableTuple &A, const RelocatableTuple &B) { 23 bool operator<(const RelocatableTuple &A, const RelocatableTuple &B) {
23 if (A.Offset != B.Offset) 24 if (A.Offset != B.Offset)
24 return A.Offset < B.Offset; 25 return A.Offset < B.Offset;
25 if (A.SuppressMangling != B.SuppressMangling) 26 if (A.SuppressMangling != B.SuppressMangling)
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 // calculation. 132 // calculation.
132 bool LiveRange::containsValue(InstNumberT Value) const { 133 bool LiveRange::containsValue(InstNumberT Value) const {
133 for (RangeType::const_iterator I = Range.begin(), E = Range.end(); I != E; 134 for (RangeType::const_iterator I = Range.begin(), E = Range.end(); I != E;
134 ++I) { 135 ++I) {
135 if (I->first <= Value && Value <= I->second) 136 if (I->first <= Value && Value <= I->second)
136 return true; 137 return true;
137 } 138 }
138 return false; 139 return false;
139 } 140 }
140 141
141 void Variable::setUse(const Inst *Inst, const CfgNode *Node) {
142 if (DefNode == NULL)
143 return;
144 if (llvm::isa<InstPhi>(Inst) || Node != DefNode)
145 DefNode = NULL;
146 }
147
148 void Variable::setDefinition(Inst *Inst, const CfgNode *Node) {
149 if (DefInst && !DefInst->isDeleted() && DefInst != Inst) {
150 // Detect when a variable is being defined multiple times,
151 // particularly for Phi instruction lowering. If this happens, we
152 // need to lock DefInst to NULL.
153 DefInst = NULL;
154 DefNode = NULL;
155 return;
156 }
157 if (DefNode == NULL)
158 return;
159 DefInst = Inst;
160 if (Node != DefNode)
161 DefNode = NULL;
162 }
163
164 void Variable::replaceDefinition(Inst *Inst, const CfgNode *Node) {
165 DefInst = NULL;
166 setDefinition(Inst, Node);
167 }
168
169 void Variable::setIsArg(Cfg *Func, bool IsArg) {
170 if (IsArg) {
171 IsArgument = true;
172 if (DefNode == NULL)
173 return;
174 CfgNode *Entry = Func->getEntryNode();
175 if (DefNode == Entry)
176 return;
177 DefNode = NULL;
178 } else {
179 IsArgument = false;
180 }
181 }
182
183 IceString Variable::getName() const { 142 IceString Variable::getName() const {
184 if (!Name.empty()) 143 if (!Name.empty())
185 return Name; 144 return Name;
186 char buf[30]; 145 char buf[30];
187 snprintf(buf, llvm::array_lengthof(buf), "__%u", getIndex()); 146 snprintf(buf, llvm::array_lengthof(buf), "__%u", getIndex());
188 return buf; 147 return buf;
189 } 148 }
190 149
191 Variable Variable::asType(Type Ty) { 150 Variable Variable::asType(Type Ty) {
192 // Note: This returns a Variable, even if the "this" object is a 151 // Note: This returns a Variable, even if the "this" object is a
193 // subclass of Variable. 152 // subclass of Variable.
194 Variable V(kVariable, Ty, DefNode, Number, Name); 153 Variable V(kVariable, Ty, Number, Name);
195 V.RegNum = RegNum; 154 V.RegNum = RegNum;
196 V.StackOffset = StackOffset; 155 V.StackOffset = StackOffset;
197 return V; 156 return V;
198 } 157 }
199 158
159 void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node,
160 bool IsFromDef, bool IsImplicit) {
161 // TODO(stichnot): If the use occurs as a source operand in the
162 // first instruction of the block, and its definition is in this
163 // block's only predecessor, we might consider not marking this as a
164 // separate use. This may also apply if it's the first instruction
165 // of the block that actually uses a Variable.
166 assert(Node);
167 bool MakeMulti = false;
168 // A phi source variable conservatively needs to be marked as
169 // multi-block, even if its definition is in the same block. This
170 // is because there can be additional control flow before branching
171 // back to this node, and the variable is live throughout those
172 // nodes.
173 if (IsImplicit)
174 MakeMulti = true;
175 if (!IsFromDef && Instr && llvm::isa<InstPhi>(Instr))
176 MakeMulti = true;
177
178 if (!MakeMulti) {
179 switch (MultiBlock) {
180 case MBS_Unknown:
181 MultiBlock = MBS_SingleBlock;
182 SingleUseNode = Node;
183 break;
184 case MBS_SingleBlock:
185 if (SingleUseNode != Node)
186 MakeMulti = true;
187 break;
188 case MBS_MultiBlock:
189 break;
190 }
191 }
192
193 if (MakeMulti) {
194 MultiBlock = MBS_MultiBlock;
195 SingleUseNode = NULL;
196 }
197 }
198
199 void VariableTracking::markDef(const Inst *Instr, const CfgNode *Node) {
200 // TODO(stichnot): If the definition occurs in the last instruction
201 // of the block, consider not marking this as a separate use. But
202 // be careful not to omit all uses of the variable if markDef() and
203 // markUse() both use this optimization.
204 const bool IsFromDef = true;
205 const bool IsImplicit = false;
206 markUse(Instr, Node, IsFromDef, IsImplicit);
207 switch (MultiDef) {
208 case MDS_Unknown:
209 MultiDef = MDS_SingleDef;
210 SingleDefInst = Instr;
211 break;
212 case MDS_SingleDef:
213 MultiDef = MDS_MultiDef;
214 SingleDefInst = NULL;
215 break;
216 case MDS_MultiDef:
217 break;
218 }
219 }
220
221 void VariablesMetadata::init() {
222 Metadata.clear();
223 Metadata.resize(Func->getNumVariables());
224
225 // Mark implicit args as being used in the entry node.
226 const VarList &ImplicitArgList = Func->getImplicitArgs();
227 for (VarList::const_iterator I = ImplicitArgList.begin(),
228 E = ImplicitArgList.end();
229 I != E; ++I) {
230 const Variable *Var = *I;
231 const Inst *NoInst = NULL;
232 const CfgNode *EntryNode = Func->getEntryNode();
233 const bool IsFromDef = false;
234 const bool IsImplicit = true;
235 Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit);
236 }
237
238 SizeT NumNodes = Func->getNumNodes();
239 for (SizeT N = 0; N < NumNodes; ++N) {
240 CfgNode *Node = Func->getNodes()[N];
241 const InstList &Insts = Node->getInsts();
242 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E;
243 ++I) {
244 if ((*I)->isDeleted())
245 continue;
246 if (Variable *Dest = (*I)->getDest()) {
247 SizeT DestNum = Dest->getIndex();
248 assert(DestNum < Metadata.size());
249 Metadata[DestNum].markDef(*I, Node);
250 }
251 for (SizeT SrcNum = 0; SrcNum < (*I)->getSrcSize(); ++SrcNum) {
252 Operand *Src = (*I)->getSrc(SrcNum);
253 SizeT NumVars = Src->getNumVars();
254 for (SizeT J = 0; J < NumVars; ++J) {
255 const Variable *Var = Src->getVar(J);
256 SizeT VarNum = Var->getIndex();
257 assert(VarNum < Metadata.size());
258 const bool IsFromDef = false;
259 const bool IsImplicit = false;
260 Metadata[VarNum].markUse(*I, Node, IsFromDef, IsImplicit);
261 }
262 }
263 }
264 }
265 }
266
267 bool VariablesMetadata::isMultiDef(const Variable *Var) const {
268 if (Var->getIsArg())
269 return false;
270 if (!isTracked(Var))
271 return true; // conservative answer
272 SizeT VarNum = Var->getIndex();
273 // Conservatively return true if the state is unknown.
274 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef;
275 }
276
277 bool VariablesMetadata::isMultiBlock(const Variable *Var) const {
278 if (getDefinition(Var) == NULL)
279 return true;
280 SizeT VarNum = Var->getIndex();
281 // Conservatively return true if the state is unknown.
282 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock;
283 }
284
285 const Inst *VariablesMetadata::getDefinition(const Variable *Var) const {
286 if (!isTracked(Var))
287 return NULL; // conservative answer
288 SizeT VarNum = Var->getIndex();
289 return Metadata[VarNum].getDefinition();
290 }
291
292 const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const {
293 if (!isTracked(Var))
294 return NULL; // conservative answer
295 SizeT VarNum = Var->getIndex();
296 return Metadata[VarNum].getNode();
297 }
298
200 // ======================== dump routines ======================== // 299 // ======================== dump routines ======================== //
201 300
202 void Variable::emit(const Cfg *Func) const { 301 void Variable::emit(const Cfg *Func) const {
203 Func->getTarget()->emitVariable(this, Func); 302 Func->getTarget()->emitVariable(this);
204 } 303 }
205 304
206 void Variable::dump(const Cfg *Func, Ostream &Str) const { 305 void Variable::dump(const Cfg *Func, Ostream &Str) const {
207 if (Func == NULL) { 306 if (Func == NULL) {
208 Str << "%" << getName(); 307 Str << "%" << getName();
209 return; 308 return;
210 } 309 }
211 const CfgNode *CurrentNode = Func->getCurrentNode();
212 (void)CurrentNode; // used only in assert()
213 assert(CurrentNode == NULL || DefNode == NULL || DefNode == CurrentNode);
214 if (Func->getContext()->isVerbose(IceV_RegOrigins) || 310 if (Func->getContext()->isVerbose(IceV_RegOrigins) ||
215 (!hasReg() && !Func->getTarget()->hasComputedFrame())) 311 (!hasReg() && !Func->getTarget()->hasComputedFrame()))
216 Str << "%" << getName(); 312 Str << "%" << getName();
217 if (hasReg()) { 313 if (hasReg()) {
218 if (Func->getContext()->isVerbose(IceV_RegOrigins)) 314 if (Func->getContext()->isVerbose(IceV_RegOrigins))
219 Str << ":"; 315 Str << ":";
220 Str << Func->getTarget()->getRegName(RegNum, getType()); 316 Str << Func->getTarget()->getRegName(RegNum, getType());
221 } else if (Func->getTarget()->hasComputedFrame()) { 317 } else if (Func->getTarget()->hasComputedFrame()) {
222 if (Func->getContext()->isVerbose(IceV_RegOrigins)) 318 if (Func->getContext()->isVerbose(IceV_RegOrigins))
223 Str << ":"; 319 Str << ":";
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
269 365
270 Ostream &operator<<(Ostream &Str, const RegWeight &W) { 366 Ostream &operator<<(Ostream &Str, const RegWeight &W) {
271 if (W.getWeight() == RegWeight::Inf) 367 if (W.getWeight() == RegWeight::Inf)
272 Str << "Inf"; 368 Str << "Inf";
273 else 369 else
274 Str << W.getWeight(); 370 Str << W.getWeight();
275 return Str; 371 return Str;
276 } 372 }
277 373
278 } // end of namespace Ice 374 } // end of namespace Ice
OLDNEW
« no previous file with comments | « src/IceOperand.h ('k') | src/IceTargetLowering.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698