Chromium Code Reviews| 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 if (TrackingKind == VMK_All) { |
| 238 Instr->getNumber() >= Definitions.back()->getNumber()); | 241 assert(Definitions.empty() || |
| 239 Definitions.push_back(Instr); | 242 Instr->getNumber() >= Definitions.back()->getNumber()); |
| 243 } | |
| 240 const bool IsFromDef = true; | 244 const bool IsFromDef = true; |
| 241 const bool IsImplicit = false; | 245 const bool IsImplicit = false; |
| 242 markUse(Instr, Node, IsFromDef, IsImplicit); | 246 markUse(TrackingKind, Instr, Node, IsFromDef, IsImplicit); |
| 247 if (TrackingKind == VMK_Uses) | |
| 248 return; | |
| 249 if (FirstDefinition == NULL) | |
|
jvoung (off chromium)
2014/10/15 17:44:54
Looks like this could be put under "if (TrackingKi
Jim Stichnoth
2014/10/15 21:29:43
Renamed the field to FirstOrSingleDefinition to cl
| |
| 250 FirstDefinition = Instr; | |
| 251 if (TrackingKind == VMK_All) | |
| 252 Definitions.push_back(Instr); | |
| 243 switch (MultiDef) { | 253 switch (MultiDef) { |
| 244 case MDS_Unknown: | 254 case MDS_Unknown: |
| 245 assert(SingleDefNode == NULL); | 255 assert(SingleDefNode == NULL); |
| 246 MultiDef = MDS_SingleDef; | 256 MultiDef = MDS_SingleDef; |
| 247 SingleDefNode = Node; | 257 SingleDefNode = Node; |
| 248 break; | 258 break; |
| 249 case MDS_SingleDef: | 259 case MDS_SingleDef: |
| 250 assert(SingleDefNode); | 260 assert(SingleDefNode); |
| 251 if (Node == SingleDefNode) { | 261 if (Node == SingleDefNode) { |
| 252 MultiDef = MDS_MultiDefSingleBlock; | 262 MultiDef = MDS_MultiDefSingleBlock; |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 268 } | 278 } |
| 269 } | 279 } |
| 270 | 280 |
| 271 const Inst *VariableTracking::getFirstDefinition() const { | 281 const Inst *VariableTracking::getFirstDefinition() const { |
| 272 switch (MultiDef) { | 282 switch (MultiDef) { |
| 273 case MDS_Unknown: | 283 case MDS_Unknown: |
| 274 case MDS_MultiDefMultiBlock: | 284 case MDS_MultiDefMultiBlock: |
| 275 return NULL; | 285 return NULL; |
| 276 case MDS_SingleDef: | 286 case MDS_SingleDef: |
| 277 case MDS_MultiDefSingleBlock: | 287 case MDS_MultiDefSingleBlock: |
| 278 assert(!Definitions.empty()); | 288 assert(FirstDefinition); |
| 279 return Definitions[0]; | 289 return FirstDefinition; |
| 280 } | 290 } |
| 281 } | 291 } |
| 282 | 292 |
| 283 const Inst *VariableTracking::getSingleDefinition() const { | 293 const Inst *VariableTracking::getSingleDefinition() const { |
| 284 switch (MultiDef) { | 294 switch (MultiDef) { |
| 285 case MDS_Unknown: | 295 case MDS_Unknown: |
| 286 case MDS_MultiDefMultiBlock: | 296 case MDS_MultiDefMultiBlock: |
| 287 case MDS_MultiDefSingleBlock: | 297 case MDS_MultiDefSingleBlock: |
| 288 return NULL; | 298 return NULL; |
| 289 case MDS_SingleDef: | 299 case MDS_SingleDef: |
| 290 assert(!Definitions.empty()); | 300 assert(FirstDefinition); |
| 291 return Definitions[0]; | 301 return FirstDefinition; |
| 292 } | 302 } |
| 293 } | 303 } |
| 294 | 304 |
| 295 void VariablesMetadata::init() { | 305 void VariablesMetadata::init(MetadataKind TrackingKind) { |
| 296 TimerMarker T(TimerStack::TT_vmetadata, Func); | 306 TimerMarker T(TimerStack::TT_vmetadata, Func); |
| 307 Kind = TrackingKind; | |
| 297 Metadata.clear(); | 308 Metadata.clear(); |
| 298 Metadata.resize(Func->getNumVariables()); | 309 Metadata.resize(Func->getNumVariables()); |
| 299 | 310 |
| 300 // Mark implicit args as being used in the entry node. | 311 // Mark implicit args as being used in the entry node. |
| 301 for (Variable *Var : Func->getImplicitArgs()) { | 312 for (Variable *Var : Func->getImplicitArgs()) { |
| 302 const Inst *NoInst = NULL; | 313 const Inst *NoInst = NULL; |
| 303 const CfgNode *EntryNode = Func->getEntryNode(); | 314 const CfgNode *EntryNode = Func->getEntryNode(); |
| 304 const bool IsFromDef = false; | 315 const bool IsFromDef = false; |
| 305 const bool IsImplicit = true; | 316 const bool IsImplicit = true; |
| 306 Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit); | 317 Metadata[Var->getIndex()] |
| 318 .markUse(Kind, NoInst, EntryNode, IsFromDef, IsImplicit); | |
| 307 } | 319 } |
| 308 | 320 |
| 309 for (CfgNode *Node : Func->getNodes()) { | 321 for (CfgNode *Node : Func->getNodes()) { |
| 310 for (Inst *I : Node->getInsts()) { | 322 for (Inst *I : Node->getInsts()) { |
| 311 if (I->isDeleted()) | 323 if (I->isDeleted()) |
| 312 continue; | 324 continue; |
| 313 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(I)) { | 325 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(I)) { |
| 314 // A FakeKill instruction indicates certain Variables (usually | 326 // A FakeKill instruction indicates certain Variables (usually |
| 315 // physical scratch registers) are redefined, so we register | 327 // physical scratch registers) are redefined, so we register |
| 316 // them as defs. | 328 // them as defs. |
| 317 for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) { | 329 for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) { |
| 318 Variable *Var = llvm::cast<Variable>(I->getSrc(SrcNum)); | 330 Variable *Var = llvm::cast<Variable>(I->getSrc(SrcNum)); |
| 319 SizeT VarNum = Var->getIndex(); | 331 SizeT VarNum = Var->getIndex(); |
| 320 assert(VarNum < Metadata.size()); | 332 assert(VarNum < Metadata.size()); |
| 321 Metadata[VarNum].markDef(Kill, Node); | 333 Metadata[VarNum].markDef(Kind, Kill, Node); |
| 322 } | 334 } |
| 323 continue; // no point in executing the rest | 335 continue; // no point in executing the rest |
| 324 } | 336 } |
| 325 if (Variable *Dest = I->getDest()) { | 337 if (Variable *Dest = I->getDest()) { |
| 326 SizeT DestNum = Dest->getIndex(); | 338 SizeT DestNum = Dest->getIndex(); |
| 327 assert(DestNum < Metadata.size()); | 339 assert(DestNum < Metadata.size()); |
| 328 Metadata[DestNum].markDef(I, Node); | 340 Metadata[DestNum].markDef(Kind, I, Node); |
| 329 } | 341 } |
| 330 for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) { | 342 for (SizeT SrcNum = 0; SrcNum < I->getSrcSize(); ++SrcNum) { |
| 331 Operand *Src = I->getSrc(SrcNum); | 343 Operand *Src = I->getSrc(SrcNum); |
| 332 SizeT NumVars = Src->getNumVars(); | 344 SizeT NumVars = Src->getNumVars(); |
| 333 for (SizeT J = 0; J < NumVars; ++J) { | 345 for (SizeT J = 0; J < NumVars; ++J) { |
| 334 const Variable *Var = Src->getVar(J); | 346 const Variable *Var = Src->getVar(J); |
| 335 SizeT VarNum = Var->getIndex(); | 347 SizeT VarNum = Var->getIndex(); |
| 336 assert(VarNum < Metadata.size()); | 348 assert(VarNum < Metadata.size()); |
| 337 const bool IsFromDef = false; | 349 const bool IsFromDef = false; |
| 338 const bool IsImplicit = false; | 350 const bool IsImplicit = false; |
| 339 Metadata[VarNum].markUse(I, Node, IsFromDef, IsImplicit); | 351 Metadata[VarNum].markUse(Kind, I, Node, IsFromDef, IsImplicit); |
| 340 } | 352 } |
| 341 } | 353 } |
| 342 } | 354 } |
| 343 } | 355 } |
| 344 } | 356 } |
| 345 | 357 |
| 346 bool VariablesMetadata::isMultiDef(const Variable *Var) const { | 358 bool VariablesMetadata::isMultiDef(const Variable *Var) const { |
| 359 assert(Kind != VMK_Uses); | |
| 347 if (Var->getIsArg()) | 360 if (Var->getIsArg()) |
| 348 return false; | 361 return false; |
| 349 if (!isTracked(Var)) | 362 if (!isTracked(Var)) |
| 350 return true; // conservative answer | 363 return true; // conservative answer |
| 351 SizeT VarNum = Var->getIndex(); | 364 SizeT VarNum = Var->getIndex(); |
| 352 // Conservatively return true if the state is unknown. | 365 // Conservatively return true if the state is unknown. |
| 353 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef; | 366 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef; |
| 354 } | 367 } |
| 355 | 368 |
| 356 bool VariablesMetadata::isMultiBlock(const Variable *Var) const { | 369 bool VariablesMetadata::isMultiBlock(const Variable *Var) const { |
| 357 if (Var->getIsArg()) | 370 if (Var->getIsArg()) |
| 358 return true; | 371 return true; |
| 359 if (!isTracked(Var)) | 372 if (!isTracked(Var)) |
| 360 return true; // conservative answer | 373 return true; // conservative answer |
| 361 SizeT VarNum = Var->getIndex(); | 374 SizeT VarNum = Var->getIndex(); |
| 362 // Conservatively return true if the state is unknown. | 375 // Conservatively return true if the state is unknown. |
| 363 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock; | 376 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock; |
| 364 } | 377 } |
| 365 | 378 |
| 366 const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const { | 379 const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const { |
| 380 assert(Kind == VMK_All); | |
| 367 if (!isTracked(Var)) | 381 if (!isTracked(Var)) |
| 368 return NULL; // conservative answer | 382 return NULL; // conservative answer |
| 369 SizeT VarNum = Var->getIndex(); | 383 SizeT VarNum = Var->getIndex(); |
| 370 return Metadata[VarNum].getFirstDefinition(); | 384 return Metadata[VarNum].getFirstDefinition(); |
| 371 } | 385 } |
| 372 | 386 |
| 373 const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const { | 387 const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const { |
| 388 assert(Kind != VMK_Uses); | |
| 374 if (!isTracked(Var)) | 389 if (!isTracked(Var)) |
| 375 return NULL; // conservative answer | 390 return NULL; // conservative answer |
| 376 SizeT VarNum = Var->getIndex(); | 391 SizeT VarNum = Var->getIndex(); |
| 377 return Metadata[VarNum].getSingleDefinition(); | 392 return Metadata[VarNum].getSingleDefinition(); |
| 378 } | 393 } |
| 379 | 394 |
| 380 const InstDefList & | 395 const InstDefList & |
| 381 VariablesMetadata::getDefinitions(const Variable *Var) const { | 396 VariablesMetadata::getDefinitions(const Variable *Var) const { |
| 397 assert(Kind == VMK_All); | |
| 382 if (!isTracked(Var)) | 398 if (!isTracked(Var)) |
| 383 return NoDefinitions; | 399 return NoDefinitions; |
| 384 SizeT VarNum = Var->getIndex(); | 400 SizeT VarNum = Var->getIndex(); |
| 385 return Metadata[VarNum].getDefinitions(); | 401 return Metadata[VarNum].getDefinitions(); |
| 386 } | 402 } |
| 387 | 403 |
| 388 const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { | 404 const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { |
| 389 if (!isTracked(Var)) | 405 if (!isTracked(Var)) |
| 390 return NULL; // conservative answer | 406 return NULL; // conservative answer |
| 391 SizeT VarNum = Var->getIndex(); | 407 SizeT VarNum = Var->getIndex(); |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 464 | 480 |
| 465 Ostream &operator<<(Ostream &Str, const RegWeight &W) { | 481 Ostream &operator<<(Ostream &Str, const RegWeight &W) { |
| 466 if (W.getWeight() == RegWeight::Inf) | 482 if (W.getWeight() == RegWeight::Inf) |
| 467 Str << "Inf"; | 483 Str << "Inf"; |
| 468 else | 484 else |
| 469 Str << W.getWeight(); | 485 Str << W.getWeight(); |
| 470 return Str; | 486 return Str; |
| 471 } | 487 } |
| 472 | 488 |
| 473 } // end of namespace Ice | 489 } // end of namespace Ice |
| OLD | NEW |