| 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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 | 158 |
| 159 void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node, | 159 void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node, |
| 160 bool IsFromDef, bool IsImplicit) { | 160 bool IsFromDef, bool IsImplicit) { |
| 161 // TODO(stichnot): If the use occurs as a source operand in the | 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 | 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 | 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 | 164 // separate use. This may also apply if it's the first instruction |
| 165 // of the block that actually uses a Variable. | 165 // of the block that actually uses a Variable. |
| 166 assert(Node); | 166 assert(Node); |
| 167 bool MakeMulti = false; | 167 bool MakeMulti = false; |
| 168 if (IsImplicit) |
| 169 MakeMulti = true; |
| 168 // A phi source variable conservatively needs to be marked as | 170 // A phi source variable conservatively needs to be marked as |
| 169 // multi-block, even if its definition is in the same block. This | 171 // multi-block, even if its definition is in the same block. This |
| 170 // is because there can be additional control flow before branching | 172 // is because there can be additional control flow before branching |
| 171 // back to this node, and the variable is live throughout those | 173 // back to this node, and the variable is live throughout those |
| 172 // nodes. | 174 // nodes. |
| 173 if (IsImplicit) | |
| 174 MakeMulti = true; | |
| 175 if (!IsFromDef && Instr && llvm::isa<InstPhi>(Instr)) | 175 if (!IsFromDef && Instr && llvm::isa<InstPhi>(Instr)) |
| 176 MakeMulti = true; | 176 MakeMulti = true; |
| 177 | 177 |
| 178 if (!MakeMulti) { | 178 if (!MakeMulti) { |
| 179 switch (MultiBlock) { | 179 switch (MultiBlock) { |
| 180 case MBS_Unknown: | 180 case MBS_Unknown: |
| 181 MultiBlock = MBS_SingleBlock; | 181 MultiBlock = MBS_SingleBlock; |
| 182 SingleUseNode = Node; | 182 SingleUseNode = Node; |
| 183 break; | 183 break; |
| 184 case MBS_SingleBlock: | 184 case MBS_SingleBlock: |
| 185 if (SingleUseNode != Node) | 185 if (SingleUseNode != Node) |
| 186 MakeMulti = true; | 186 MakeMulti = true; |
| 187 break; | 187 break; |
| 188 case MBS_MultiBlock: | 188 case MBS_MultiBlock: |
| 189 break; | 189 break; |
| 190 } | 190 } |
| 191 } | 191 } |
| 192 | 192 |
| 193 if (MakeMulti) { | 193 if (MakeMulti) { |
| 194 MultiBlock = MBS_MultiBlock; | 194 MultiBlock = MBS_MultiBlock; |
| 195 SingleUseNode = NULL; | 195 SingleUseNode = NULL; |
| 196 } | 196 } |
| 197 } | 197 } |
| 198 | 198 |
| 199 void VariableTracking::markDef(const Inst *Instr, const CfgNode *Node) { | 199 void VariableTracking::markDef(const Inst *Instr, const CfgNode *Node) { |
| 200 // TODO(stichnot): If the definition occurs in the last instruction | 200 // TODO(stichnot): If the definition occurs in the last instruction |
| 201 // of the block, consider not marking this as a separate use. But | 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 | 202 // be careful not to omit all uses of the variable if markDef() and |
| 203 // markUse() both use this optimization. | 203 // markUse() both use this optimization. |
| 204 assert(Node); |
| 205 Definitions.push_back(Instr); |
| 204 const bool IsFromDef = true; | 206 const bool IsFromDef = true; |
| 205 const bool IsImplicit = false; | 207 const bool IsImplicit = false; |
| 206 markUse(Instr, Node, IsFromDef, IsImplicit); | 208 markUse(Instr, Node, IsFromDef, IsImplicit); |
| 207 switch (MultiDef) { | 209 switch (MultiDef) { |
| 208 case MDS_Unknown: | 210 case MDS_Unknown: |
| 211 assert(SingleDefNode == NULL); |
| 209 MultiDef = MDS_SingleDef; | 212 MultiDef = MDS_SingleDef; |
| 210 SingleDefInst = Instr; | 213 SingleDefNode = Node; |
| 211 break; | 214 break; |
| 212 case MDS_SingleDef: | 215 case MDS_SingleDef: |
| 213 MultiDef = MDS_MultiDef; | 216 assert(SingleDefNode); |
| 214 SingleDefInst = NULL; | 217 if (Node == SingleDefNode) { |
| 218 MultiDef = MDS_MultiDefSingleBlock; |
| 219 } else { |
| 220 MultiDef = MDS_MultiDefMultiBlock; |
| 221 SingleDefNode = NULL; |
| 222 } |
| 215 break; | 223 break; |
| 216 case MDS_MultiDef: | 224 case MDS_MultiDefSingleBlock: |
| 225 assert(SingleDefNode); |
| 226 if (Node != SingleDefNode) { |
| 227 MultiDef = MDS_MultiDefMultiBlock; |
| 228 SingleDefNode = NULL; |
| 229 } |
| 217 break; | 230 break; |
| 231 case MDS_MultiDefMultiBlock: |
| 232 assert(SingleDefNode == NULL); |
| 233 break; |
| 234 } |
| 235 } |
| 236 |
| 237 const Inst *VariableTracking::getFirstDefinition() const { |
| 238 switch (MultiDef) { |
| 239 case MDS_Unknown: |
| 240 case MDS_MultiDefMultiBlock: |
| 241 return NULL; |
| 242 case MDS_SingleDef: |
| 243 case MDS_MultiDefSingleBlock: |
| 244 assert(!Definitions.empty()); |
| 245 return Definitions[0]; |
| 246 } |
| 247 } |
| 248 |
| 249 const Inst *VariableTracking::getSingleDefinition() const { |
| 250 switch (MultiDef) { |
| 251 case MDS_Unknown: |
| 252 case MDS_MultiDefMultiBlock: |
| 253 case MDS_MultiDefSingleBlock: |
| 254 return NULL; |
| 255 case MDS_SingleDef: |
| 256 assert(!Definitions.empty()); |
| 257 return Definitions[0]; |
| 218 } | 258 } |
| 219 } | 259 } |
| 220 | 260 |
| 221 void VariablesMetadata::init() { | 261 void VariablesMetadata::init() { |
| 222 Metadata.clear(); | 262 Metadata.clear(); |
| 223 Metadata.resize(Func->getNumVariables()); | 263 Metadata.resize(Func->getNumVariables()); |
| 224 | 264 |
| 225 // Mark implicit args as being used in the entry node. | 265 // Mark implicit args as being used in the entry node. |
| 226 const VarList &ImplicitArgList = Func->getImplicitArgs(); | 266 const VarList &ImplicitArgList = Func->getImplicitArgs(); |
| 227 for (VarList::const_iterator I = ImplicitArgList.begin(), | 267 for (VarList::const_iterator I = ImplicitArgList.begin(), |
| 228 E = ImplicitArgList.end(); | 268 E = ImplicitArgList.end(); |
| 229 I != E; ++I) { | 269 I != E; ++I) { |
| 230 const Variable *Var = *I; | 270 const Variable *Var = *I; |
| 231 const Inst *NoInst = NULL; | 271 const Inst *NoInst = NULL; |
| 232 const CfgNode *EntryNode = Func->getEntryNode(); | 272 const CfgNode *EntryNode = Func->getEntryNode(); |
| 233 const bool IsFromDef = false; | 273 const bool IsFromDef = false; |
| 234 const bool IsImplicit = true; | 274 const bool IsImplicit = true; |
| 235 Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit); | 275 Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit); |
| 236 } | 276 } |
| 237 | 277 |
| 238 SizeT NumNodes = Func->getNumNodes(); | 278 SizeT NumNodes = Func->getNumNodes(); |
| 239 for (SizeT N = 0; N < NumNodes; ++N) { | 279 for (SizeT N = 0; N < NumNodes; ++N) { |
| 240 CfgNode *Node = Func->getNodes()[N]; | 280 CfgNode *Node = Func->getNodes()[N]; |
| 241 const InstList &Insts = Node->getInsts(); | 281 const InstList &Insts = Node->getInsts(); |
| 242 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E; | 282 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E; |
| 243 ++I) { | 283 ++I) { |
| 244 if ((*I)->isDeleted()) | 284 if ((*I)->isDeleted()) |
| 245 continue; | 285 continue; |
| 286 if (InstFakeKill *Kill = llvm::dyn_cast<InstFakeKill>(*I)) { |
| 287 // A FakeKill instruction indicates certain Variables (usually |
| 288 // physical scratch registers) are redefined, so we register |
| 289 // them as defs. |
| 290 for (SizeT SrcNum = 0; SrcNum < (*I)->getSrcSize(); ++SrcNum) { |
| 291 Variable *Var = llvm::cast<Variable>((*I)->getSrc(SrcNum)); |
| 292 SizeT VarNum = Var->getIndex(); |
| 293 assert(VarNum < Metadata.size()); |
| 294 Metadata[VarNum].markDef(Kill, Node); |
| 295 } |
| 296 continue; // no point in executing the rest |
| 297 } |
| 246 if (Variable *Dest = (*I)->getDest()) { | 298 if (Variable *Dest = (*I)->getDest()) { |
| 247 SizeT DestNum = Dest->getIndex(); | 299 SizeT DestNum = Dest->getIndex(); |
| 248 assert(DestNum < Metadata.size()); | 300 assert(DestNum < Metadata.size()); |
| 249 Metadata[DestNum].markDef(*I, Node); | 301 Metadata[DestNum].markDef(*I, Node); |
| 250 } | 302 } |
| 251 for (SizeT SrcNum = 0; SrcNum < (*I)->getSrcSize(); ++SrcNum) { | 303 for (SizeT SrcNum = 0; SrcNum < (*I)->getSrcSize(); ++SrcNum) { |
| 252 Operand *Src = (*I)->getSrc(SrcNum); | 304 Operand *Src = (*I)->getSrc(SrcNum); |
| 253 SizeT NumVars = Src->getNumVars(); | 305 SizeT NumVars = Src->getNumVars(); |
| 254 for (SizeT J = 0; J < NumVars; ++J) { | 306 for (SizeT J = 0; J < NumVars; ++J) { |
| 255 const Variable *Var = Src->getVar(J); | 307 const Variable *Var = Src->getVar(J); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 268 if (Var->getIsArg()) | 320 if (Var->getIsArg()) |
| 269 return false; | 321 return false; |
| 270 if (!isTracked(Var)) | 322 if (!isTracked(Var)) |
| 271 return true; // conservative answer | 323 return true; // conservative answer |
| 272 SizeT VarNum = Var->getIndex(); | 324 SizeT VarNum = Var->getIndex(); |
| 273 // Conservatively return true if the state is unknown. | 325 // Conservatively return true if the state is unknown. |
| 274 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef; | 326 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef; |
| 275 } | 327 } |
| 276 | 328 |
| 277 bool VariablesMetadata::isMultiBlock(const Variable *Var) const { | 329 bool VariablesMetadata::isMultiBlock(const Variable *Var) const { |
| 278 if (getDefinition(Var) == NULL) | 330 if (Var->getIsArg()) |
| 279 return true; | 331 return true; |
| 332 if (!isTracked(Var)) |
| 333 return true; // conservative answer |
| 280 SizeT VarNum = Var->getIndex(); | 334 SizeT VarNum = Var->getIndex(); |
| 281 // Conservatively return true if the state is unknown. | 335 // Conservatively return true if the state is unknown. |
| 282 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock; | 336 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock; |
| 283 } | 337 } |
| 284 | 338 |
| 285 const Inst *VariablesMetadata::getDefinition(const Variable *Var) const { | 339 const Inst *VariablesMetadata::getFirstDefinition(const Variable *Var) const { |
| 286 if (!isTracked(Var)) | 340 if (!isTracked(Var)) |
| 287 return NULL; // conservative answer | 341 return NULL; // conservative answer |
| 288 SizeT VarNum = Var->getIndex(); | 342 SizeT VarNum = Var->getIndex(); |
| 289 return Metadata[VarNum].getDefinition(); | 343 return Metadata[VarNum].getFirstDefinition(); |
| 344 } |
| 345 |
| 346 const Inst *VariablesMetadata::getSingleDefinition(const Variable *Var) const { |
| 347 if (!isTracked(Var)) |
| 348 return NULL; // conservative answer |
| 349 SizeT VarNum = Var->getIndex(); |
| 350 return Metadata[VarNum].getSingleDefinition(); |
| 351 } |
| 352 |
| 353 const InstDefList & |
| 354 VariablesMetadata::getDefinitions(const Variable *Var) const { |
| 355 if (!isTracked(Var)) |
| 356 return NoDefinitions; |
| 357 SizeT VarNum = Var->getIndex(); |
| 358 return Metadata[VarNum].getDefinitions(); |
| 290 } | 359 } |
| 291 | 360 |
| 292 const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { | 361 const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { |
| 293 if (!isTracked(Var)) | 362 if (!isTracked(Var)) |
| 294 return NULL; // conservative answer | 363 return NULL; // conservative answer |
| 295 SizeT VarNum = Var->getIndex(); | 364 SizeT VarNum = Var->getIndex(); |
| 296 return Metadata[VarNum].getNode(); | 365 return Metadata[VarNum].getNode(); |
| 297 } | 366 } |
| 298 | 367 |
| 368 const InstDefList VariablesMetadata::NoDefinitions; |
| 369 |
| 299 // ======================== dump routines ======================== // | 370 // ======================== dump routines ======================== // |
| 300 | 371 |
| 301 void Variable::emit(const Cfg *Func) const { | 372 void Variable::emit(const Cfg *Func) const { |
| 302 Func->getTarget()->emitVariable(this); | 373 Func->getTarget()->emitVariable(this); |
| 303 } | 374 } |
| 304 | 375 |
| 305 void Variable::dump(const Cfg *Func, Ostream &Str) const { | 376 void Variable::dump(const Cfg *Func, Ostream &Str) const { |
| 306 if (Func == NULL) { | 377 if (Func == NULL) { |
| 307 Str << "%" << getName(); | 378 Str << "%" << getName(); |
| 308 return; | 379 return; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 | 436 |
| 366 Ostream &operator<<(Ostream &Str, const RegWeight &W) { | 437 Ostream &operator<<(Ostream &Str, const RegWeight &W) { |
| 367 if (W.getWeight() == RegWeight::Inf) | 438 if (W.getWeight() == RegWeight::Inf) |
| 368 Str << "Inf"; | 439 Str << "Inf"; |
| 369 else | 440 else |
| 370 Str << W.getWeight(); | 441 Str << W.getWeight(); |
| 371 return Str; | 442 return Str; |
| 372 } | 443 } |
| 373 | 444 |
| 374 } // end of namespace Ice | 445 } // end of namespace Ice |
| OLD | NEW |