OLD | NEW |
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 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 | 178 |
179 Variable Variable::asType(Type Ty) { | 179 Variable Variable::asType(Type Ty) { |
180 // Note: This returns a Variable, even if the "this" object is a | 180 // Note: This returns a Variable, even if the "this" object is a |
181 // subclass of Variable. | 181 // subclass of Variable. |
182 Variable V(kVariable, Ty, Number, Name); | 182 Variable V(kVariable, Ty, Number, Name); |
183 V.RegNum = RegNum; | 183 V.RegNum = RegNum; |
184 V.StackOffset = StackOffset; | 184 V.StackOffset = StackOffset; |
185 return V; | 185 return V; |
186 } | 186 } |
187 | 187 |
188 void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node, | 188 void VariableTracking::markUse(MetadataKind TrackingKind, const Inst *Instr, |
189 bool IsFromDef, bool IsImplicit) { | 189 const CfgNode *Node, bool IsFromDef, |
| 190 bool IsImplicit) { |
| 191 (void)TrackingKind; |
190 if (MultiBlock == MBS_MultiBlock) | 192 if (MultiBlock == MBS_MultiBlock) |
191 return; | 193 return; |
192 // TODO(stichnot): If the use occurs as a source operand in the | 194 // TODO(stichnot): If the use occurs as a source operand in the |
193 // first instruction of the block, and its definition is in this | 195 // first instruction of the block, and its definition is in this |
194 // block's only predecessor, we might consider not marking this as a | 196 // block's only predecessor, we might consider not marking this as a |
195 // separate use. This may also apply if it's the first instruction | 197 // separate use. This may also apply if it's the first instruction |
196 // of the block that actually uses a Variable. | 198 // of the block that actually uses a Variable. |
197 assert(Node); | 199 assert(Node); |
198 bool MakeMulti = false; | 200 bool MakeMulti = false; |
199 if (IsImplicit) | 201 if (IsImplicit) |
(...skipping 20 matching lines...) Expand all Loading... |
220 break; | 222 break; |
221 } | 223 } |
222 } | 224 } |
223 | 225 |
224 if (MakeMulti) { | 226 if (MakeMulti) { |
225 MultiBlock = MBS_MultiBlock; | 227 MultiBlock = MBS_MultiBlock; |
226 SingleUseNode = NULL; | 228 SingleUseNode = NULL; |
227 } | 229 } |
228 } | 230 } |
229 | 231 |
230 void VariableTracking::markDef(const Inst *Instr, const CfgNode *Node) { | 232 void VariableTracking::markDef(MetadataKind TrackingKind, const Inst *Instr, |
| 233 const CfgNode *Node) { |
231 // TODO(stichnot): If the definition occurs in the last instruction | 234 // TODO(stichnot): If the definition occurs in the last instruction |
232 // of the block, consider not marking this as a separate use. But | 235 // of the block, consider not marking this as a separate use. But |
233 // be careful not to omit all uses of the variable if markDef() and | 236 // be careful not to omit all uses of the variable if markDef() and |
234 // markUse() both use this optimization. | 237 // markUse() both use this optimization. |
235 assert(Node); | 238 assert(Node); |
236 // Verify that instructions are added in increasing order. | 239 // Verify that instructions are added in increasing order. |
237 assert(Definitions.empty() || | 240 #ifndef NDEBUG |
238 Instr->getNumber() >= Definitions.back()->getNumber()); | 241 if (TrackingKind == VMK_All) { |
239 Definitions.push_back(Instr); | 242 const Inst *LastInstruction = |
| 243 Definitions.empty() ? FirstOrSingleDefinition : Definitions.back(); |
| 244 assert(LastInstruction == NULL || |
| 245 Instr->getNumber() >= LastInstruction->getNumber()); |
| 246 } |
| 247 #endif |
240 const bool IsFromDef = true; | 248 const bool IsFromDef = true; |
241 const bool IsImplicit = false; | 249 const bool IsImplicit = false; |
242 markUse(Instr, Node, IsFromDef, IsImplicit); | 250 markUse(TrackingKind, Instr, Node, IsFromDef, IsImplicit); |
| 251 if (TrackingKind == VMK_Uses) |
| 252 return; |
| 253 if (FirstOrSingleDefinition == NULL) |
| 254 FirstOrSingleDefinition = Instr; |
| 255 else if (TrackingKind == VMK_All) |
| 256 Definitions.push_back(Instr); |
243 switch (MultiDef) { | 257 switch (MultiDef) { |
244 case MDS_Unknown: | 258 case MDS_Unknown: |
245 assert(SingleDefNode == NULL); | 259 assert(SingleDefNode == NULL); |
246 MultiDef = MDS_SingleDef; | 260 MultiDef = MDS_SingleDef; |
247 SingleDefNode = Node; | 261 SingleDefNode = Node; |
248 break; | 262 break; |
249 case MDS_SingleDef: | 263 case MDS_SingleDef: |
250 assert(SingleDefNode); | 264 assert(SingleDefNode); |
251 if (Node == SingleDefNode) { | 265 if (Node == SingleDefNode) { |
252 MultiDef = MDS_MultiDefSingleBlock; | 266 MultiDef = MDS_MultiDefSingleBlock; |
(...skipping 15 matching lines...) Expand all Loading... |
268 } | 282 } |
269 } | 283 } |
270 | 284 |
271 const Inst *VariableTracking::getFirstDefinition() const { | 285 const Inst *VariableTracking::getFirstDefinition() const { |
272 switch (MultiDef) { | 286 switch (MultiDef) { |
273 case MDS_Unknown: | 287 case MDS_Unknown: |
274 case MDS_MultiDefMultiBlock: | 288 case MDS_MultiDefMultiBlock: |
275 return NULL; | 289 return NULL; |
276 case MDS_SingleDef: | 290 case MDS_SingleDef: |
277 case MDS_MultiDefSingleBlock: | 291 case MDS_MultiDefSingleBlock: |
278 assert(!Definitions.empty()); | 292 assert(FirstOrSingleDefinition); |
279 return Definitions[0]; | 293 return FirstOrSingleDefinition; |
280 } | 294 } |
281 } | 295 } |
282 | 296 |
283 const Inst *VariableTracking::getSingleDefinition() const { | 297 const Inst *VariableTracking::getSingleDefinition() const { |
284 switch (MultiDef) { | 298 switch (MultiDef) { |
285 case MDS_Unknown: | 299 case MDS_Unknown: |
286 case MDS_MultiDefMultiBlock: | 300 case MDS_MultiDefMultiBlock: |
287 case MDS_MultiDefSingleBlock: | 301 case MDS_MultiDefSingleBlock: |
288 return NULL; | 302 return NULL; |
289 case MDS_SingleDef: | 303 case MDS_SingleDef: |
290 assert(!Definitions.empty()); | 304 assert(FirstOrSingleDefinition); |
291 return Definitions[0]; | 305 return FirstOrSingleDefinition; |
292 } | 306 } |
293 } | 307 } |
294 | 308 |
295 void VariablesMetadata::init() { | 309 void VariablesMetadata::init(MetadataKind TrackingKind) { |
296 TimerMarker T(TimerStack::TT_vmetadata, Func); | 310 TimerMarker T(TimerStack::TT_vmetadata, Func); |
| 311 Kind = TrackingKind; |
297 Metadata.clear(); | 312 Metadata.clear(); |
298 Metadata.resize(Func->getNumVariables()); | 313 Metadata.resize(Func->getNumVariables()); |
299 | 314 |
300 // Mark implicit args as being used in the entry node. | 315 // Mark implicit args as being used in the entry node. |
301 for (Variable *Var : Func->getImplicitArgs()) { | 316 for (Variable *Var : Func->getImplicitArgs()) { |
302 const Inst *NoInst = NULL; | 317 const Inst *NoInst = NULL; |
303 const CfgNode *EntryNode = Func->getEntryNode(); | 318 const CfgNode *EntryNode = Func->getEntryNode(); |
304 const bool IsFromDef = false; | 319 const bool IsFromDef = false; |
305 const bool IsImplicit = true; | 320 const bool IsImplicit = true; |
306 Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit); | 321 Metadata[Var->getIndex()] |
| 322 .markUse(Kind, NoInst, EntryNode, IsFromDef, IsImplicit); |
307 } | 323 } |
308 | 324 |
309 for (CfgNode *Node : Func->getNodes()) { | 325 for (CfgNode *Node : Func->getNodes()) { |
310 for (Inst *I : Node->getInsts()) { | 326 for (Inst *I : Node->getInsts()) { |
311 if (I->isDeleted()) | 327 if (I->isDeleted()) |
312 continue; | 328 continue; |
313 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(I)) { | 329 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(I)) { |
314 // A FakeKill instruction indicates certain Variables (usually | 330 // A FakeKill instruction indicates certain Variables (usually |
315 // physical scratch registers) are redefined, so we register | 331 // physical scratch registers) are redefined, so we register |
316 // them as defs. | 332 // them as defs. |
317 for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) { | 333 for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) { |
318 Variable *Var = llvm::cast<Variable>(I->getSrc(SrcNum)); | 334 Variable *Var = llvm::cast<Variable>(I->getSrc(SrcNum)); |
319 SizeT VarNum = Var->getIndex(); | 335 SizeT VarNum = Var->getIndex(); |
320 assert(VarNum < Metadata.size()); | 336 assert(VarNum < Metadata.size()); |
321 Metadata[VarNum].markDef(Kill, Node); | 337 Metadata[VarNum].markDef(Kind, Kill, Node); |
322 } | 338 } |
323 continue; // no point in executing the rest | 339 continue; // no point in executing the rest |
324 } | 340 } |
325 if (Variable *Dest = I->getDest()) { | 341 if (Variable *Dest = I->getDest()) { |
326 SizeT DestNum = Dest->getIndex(); | 342 SizeT DestNum = Dest->getIndex(); |
327 assert(DestNum < Metadata.size()); | 343 assert(DestNum < Metadata.size()); |
328 Metadata[DestNum].markDef(I, Node); | 344 Metadata[DestNum].markDef(Kind, I, Node); |
329 } | 345 } |
330 for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) { | 346 for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) { |
331 Operand *Src = I->getSrc(SrcNum); | 347 Operand *Src = I->getSrc(SrcNum); |
332 SizeT NumVars = Src->getNumVars(); | 348 SizeT NumVars = Src->getNumVars(); |
333 for (SizeT J = 0; J < NumVars; ++J) { | 349 for (SizeT J = 0; J < NumVars; ++J) { |
334 const Variable *Var = Src->getVar(J); | 350 const Variable *Var = Src->getVar(J); |
335 SizeT VarNum = Var->getIndex(); | 351 SizeT VarNum = Var->getIndex(); |
336 assert(VarNum < Metadata.size()); | 352 assert(VarNum < Metadata.size()); |
337 const bool IsFromDef = false; | 353 const bool IsFromDef = false; |
338 const bool IsImplicit = false; | 354 const bool IsImplicit = false; |
339 Metadata[VarNum].markUse(I, Node, IsFromDef, IsImplicit); | 355 Metadata[VarNum].markUse(Kind, I, Node, IsFromDef, IsImplicit); |
340 } | 356 } |
341 } | 357 } |
342 } | 358 } |
343 } | 359 } |
344 } | 360 } |
345 | 361 |
346 bool VariablesMetadata::isMultiDef(const Variable *Var) const { | 362 bool VariablesMetadata::isMultiDef(const Variable *Var) const { |
| 363 assert(Kind != VMK_Uses); |
347 if (Var->getIsArg()) | 364 if (Var->getIsArg()) |
348 return false; | 365 return false; |
349 if (!isTracked(Var)) | 366 if (!isTracked(Var)) |
350 return true; // conservative answer | 367 return true; // conservative answer |
351 SizeT VarNum = Var->getIndex(); | 368 SizeT VarNum = Var->getIndex(); |
352 // Conservatively return true if the state is unknown. | 369 // Conservatively return true if the state is unknown. |
353 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef; | 370 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef; |
354 } | 371 } |
355 | 372 |
356 bool VariablesMetadata::isMultiBlock(const Variable *Var) const { | 373 bool VariablesMetadata::isMultiBlock(const Variable *Var) const { |
357 if (Var->getIsArg()) | 374 if (Var->getIsArg()) |
358 return true; | 375 return true; |
359 if (!isTracked(Var)) | 376 if (!isTracked(Var)) |
360 return true; // conservative answer | 377 return true; // conservative answer |
361 SizeT VarNum = Var->getIndex(); | 378 SizeT VarNum = Var->getIndex(); |
362 // Conservatively return true if the state is unknown. | 379 // Conservatively return true if the state is unknown. |
363 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock; | 380 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock; |
364 } | 381 } |
365 | 382 |
366 const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const { | 383 const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const { |
| 384 assert(Kind != VMK_Uses); |
367 if (!isTracked(Var)) | 385 if (!isTracked(Var)) |
368 return NULL; // conservative answer | 386 return NULL; // conservative answer |
369 SizeT VarNum = Var->getIndex(); | 387 SizeT VarNum = Var->getIndex(); |
370 return Metadata[VarNum].getFirstDefinition(); | 388 return Metadata[VarNum].getFirstDefinition(); |
371 } | 389 } |
372 | 390 |
373 const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const { | 391 const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const { |
| 392 assert(Kind != VMK_Uses); |
374 if (!isTracked(Var)) | 393 if (!isTracked(Var)) |
375 return NULL; // conservative answer | 394 return NULL; // conservative answer |
376 SizeT VarNum = Var->getIndex(); | 395 SizeT VarNum = Var->getIndex(); |
377 return Metadata[VarNum].getSingleDefinition(); | 396 return Metadata[VarNum].getSingleDefinition(); |
378 } | 397 } |
379 | 398 |
380 const InstDefList & | 399 const InstDefList & |
381 VariablesMetadata::getDefinitions(const Variable *Var) const { | 400 VariablesMetadata::getLatterDefinitions(const Variable *Var) const { |
| 401 assert(Kind == VMK_All); |
382 if (!isTracked(Var)) | 402 if (!isTracked(Var)) |
383 return NoDefinitions; | 403 return NoDefinitions; |
384 SizeT VarNum = Var->getIndex(); | 404 SizeT VarNum = Var->getIndex(); |
385 return Metadata[VarNum].getDefinitions(); | 405 return Metadata[VarNum].getLatterDefinitions(); |
386 } | 406 } |
387 | 407 |
388 const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { | 408 const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { |
389 if (!isTracked(Var)) | 409 if (!isTracked(Var)) |
390 return NULL; // conservative answer | 410 return NULL; // conservative answer |
391 SizeT VarNum = Var->getIndex(); | 411 SizeT VarNum = Var->getIndex(); |
392 return Metadata[VarNum].getNode(); | 412 return Metadata[VarNum].getNode(); |
393 } | 413 } |
394 | 414 |
395 const InstDefList VariablesMetadata::NoDefinitions; | 415 const InstDefList VariablesMetadata::NoDefinitions; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 | 484 |
465 Ostream &operator<<(Ostream &Str, const RegWeight &W) { | 485 Ostream &operator<<(Ostream &Str, const RegWeight &W) { |
466 if (W.getWeight() == RegWeight::Inf) | 486 if (W.getWeight() == RegWeight::Inf) |
467 Str << "Inf"; | 487 Str << "Inf"; |
468 else | 488 else |
469 Str << W.getWeight(); | 489 Str << W.getWeight(); |
470 return Str; | 490 return Str; |
471 } | 491 } |
472 | 492 |
473 } // end of namespace Ice | 493 } // end of namespace Ice |
OLD | NEW |