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 |