| 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 |