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 |
| 11 // subclasses, primarily for the methods of the Variable class. | 11 // subclasses, primarily for the methods of the Variable class. |
| 12 // | 12 // |
| 13 //===----------------------------------------------------------------------===// | 13 //===----------------------------------------------------------------------===// |
| 14 | 14 |
| 15 #include "IceCfg.h" | 15 #include "IceCfg.h" |
| 16 #include "IceCfgNode.h" | |
| 16 #include "IceInst.h" | 17 #include "IceInst.h" |
| 17 #include "IceOperand.h" | 18 #include "IceOperand.h" |
| 18 #include "IceTargetLowering.h" // dumping stack/frame pointer register | 19 #include "IceTargetLowering.h" // dumping stack/frame pointer register |
| 19 | 20 |
| 20 namespace Ice { | 21 namespace Ice { |
| 21 | 22 |
| 22 bool operator<(const RelocatableTuple &A, const RelocatableTuple &B) { | 23 bool operator<(const RelocatableTuple &A, const RelocatableTuple &B) { |
| 23 if (A.Offset != B.Offset) | 24 if (A.Offset != B.Offset) |
| 24 return A.Offset < B.Offset; | 25 return A.Offset < B.Offset; |
| 25 if (A.SuppressMangling != B.SuppressMangling) | 26 if (A.SuppressMangling != B.SuppressMangling) |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 131 // calculation. | 132 // calculation. |
| 132 bool LiveRange::containsValue(InstNumberT Value) const { | 133 bool LiveRange::containsValue(InstNumberT Value) const { |
| 133 for (RangeType::const_iterator I = Range.begin(), E = Range.end(); I != E; | 134 for (RangeType::const_iterator I = Range.begin(), E = Range.end(); I != E; |
| 134 ++I) { | 135 ++I) { |
| 135 if (I->first <= Value && Value <= I->second) | 136 if (I->first <= Value && Value <= I->second) |
| 136 return true; | 137 return true; |
| 137 } | 138 } |
| 138 return false; | 139 return false; |
| 139 } | 140 } |
| 140 | 141 |
| 141 void Variable::setUse(const Inst *Inst, const CfgNode *Node) { | |
| 142 if (DefNode == NULL) | |
| 143 return; | |
| 144 if (llvm::isa<InstPhi>(Inst) || Node != DefNode) | |
| 145 DefNode = NULL; | |
| 146 } | |
| 147 | |
| 148 void Variable::setDefinition(Inst *Inst, const CfgNode *Node) { | |
| 149 if (DefInst && !DefInst->isDeleted() && DefInst != Inst) { | |
| 150 // Detect when a variable is being defined multiple times, | |
| 151 // particularly for Phi instruction lowering. If this happens, we | |
| 152 // need to lock DefInst to NULL. | |
| 153 DefInst = NULL; | |
| 154 DefNode = NULL; | |
| 155 return; | |
| 156 } | |
| 157 if (DefNode == NULL) | |
| 158 return; | |
| 159 DefInst = Inst; | |
| 160 if (Node != DefNode) | |
| 161 DefNode = NULL; | |
| 162 } | |
| 163 | |
| 164 void Variable::replaceDefinition(Inst *Inst, const CfgNode *Node) { | |
| 165 DefInst = NULL; | |
| 166 setDefinition(Inst, Node); | |
| 167 } | |
| 168 | |
| 169 void Variable::setIsArg(Cfg *Func, bool IsArg) { | |
| 170 if (IsArg) { | |
| 171 IsArgument = true; | |
| 172 if (DefNode == NULL) | |
| 173 return; | |
| 174 CfgNode *Entry = Func->getEntryNode(); | |
| 175 if (DefNode == Entry) | |
| 176 return; | |
| 177 DefNode = NULL; | |
| 178 } else { | |
| 179 IsArgument = false; | |
| 180 } | |
| 181 } | |
| 182 | |
| 183 IceString Variable::getName() const { | 142 IceString Variable::getName() const { |
| 184 if (!Name.empty()) | 143 if (!Name.empty()) |
| 185 return Name; | 144 return Name; |
| 186 char buf[30]; | 145 char buf[30]; |
| 187 snprintf(buf, llvm::array_lengthof(buf), "__%u", getIndex()); | 146 snprintf(buf, llvm::array_lengthof(buf), "__%u", getIndex()); |
| 188 return buf; | 147 return buf; |
| 189 } | 148 } |
| 190 | 149 |
| 191 Variable Variable::asType(Type Ty) { | 150 Variable Variable::asType(Type Ty) { |
| 192 // Note: This returns a Variable, even if the "this" object is a | 151 // Note: This returns a Variable, even if the "this" object is a |
| 193 // subclass of Variable. | 152 // subclass of Variable. |
| 194 Variable V(kVariable, Ty, DefNode, Number, Name); | 153 Variable V(kVariable, Ty, Number, Name); |
| 195 V.RegNum = RegNum; | 154 V.RegNum = RegNum; |
| 196 V.StackOffset = StackOffset; | 155 V.StackOffset = StackOffset; |
| 197 return V; | 156 return V; |
| 198 } | 157 } |
| 199 | 158 |
| 159 void VariableTracking::markUse(const Inst *Instr, const CfgNode *Node, | |
| 160 bool IsFromDef, bool IsImplicit) { | |
| 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 | |
| 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 | |
| 165 // of the block that actually uses a Variable. | |
| 166 assert(Node); | |
| 167 bool MakeMulti = false; | |
| 168 // A phi source variable conservatively needs to be marked as | |
| 169 // multi-block, even if its definition is in the same block. This | |
| 170 // is because there can be additional control flow before branching | |
| 171 // back to this node, and the variable is live throughout those | |
| 172 // nodes. | |
| 173 if (IsImplicit) | |
| 174 MakeMulti = true; | |
| 175 if (!IsFromDef && Instr && llvm::isa<InstPhi>(Instr)) | |
| 176 MakeMulti = true; | |
| 177 | |
| 178 if (!MakeMulti) { | |
| 179 switch (MultiBlock) { | |
| 180 case MBS_Unknown: | |
| 181 MultiBlock = MBS_SingleBlock; | |
| 182 SingleUseNode = Node; | |
| 183 break; | |
| 184 case MBS_SingleBlock: | |
| 185 if (SingleUseNode != Node) | |
| 186 MakeMulti = true; | |
| 187 break; | |
| 188 case MBS_MultiBlock: | |
| 189 break; | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 if (MakeMulti) { | |
| 194 MultiBlock = MBS_MultiBlock; | |
| 195 SingleUseNode = NULL; | |
| 196 } | |
| 197 } | |
| 198 | |
| 199 void VariableTracking::markDef(const Inst *Instr, const CfgNode *Node) { | |
| 200 // TODO(stichnot): If the definition occurs in the last instruction | |
| 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 | |
| 203 // markUse() both use this optimization. | |
| 204 const bool IsFromDef = true; | |
| 205 const bool IsImplicit = false; | |
| 206 markUse(Instr, Node, IsFromDef, IsImplicit); | |
| 207 switch (MultiDef) { | |
| 208 case MDS_Unknown: | |
| 209 MultiDef = MDS_SingleDef; | |
| 210 SingleDefInst = Instr; | |
| 211 break; | |
| 212 case MDS_SingleDef: | |
| 213 MultiDef = MDS_MultiDef; | |
| 214 SingleDefInst = NULL; | |
| 215 break; | |
| 216 case MDS_MultiDef: | |
| 217 break; | |
| 218 } | |
| 219 } | |
| 220 | |
| 221 void VariablesMetadata::init() { | |
| 222 Metadata.clear(); | |
| 223 Metadata.resize(Func->getNumVariables()); | |
| 224 const Inst *NoInst = NULL; | |
| 225 const CfgNode *EntryNode = Func->getEntryNode(); | |
| 226 const bool IsFromDef = false; | |
| 227 | |
| 228 // Mark args as being used in the entry node. | |
| 229 const VarList &ArgList = Func->getArgs(); | |
| 230 for (VarList::const_iterator I = ArgList.begin(), E = ArgList.end(); I != E; | |
|
jvoung (off chromium)
2014/09/22 21:48:03
Hmm, actually, split64() also creates new variable
Jim Stichnoth
2014/09/22 22:25:07
Interesting. I guess I was over-zealous in markin
| |
| 231 ++I) { | |
| 232 const Variable *Var = *I; | |
| 233 const bool IsImplicit = false; | |
| 234 Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit); | |
| 235 } | |
| 236 | |
| 237 // Also mark implicit args as being used in the entry node. | |
| 238 const VarList &ImplicitArgList = Func->getImplicitArgs(); | |
| 239 for (VarList::const_iterator I = ImplicitArgList.begin(), | |
| 240 E = ImplicitArgList.end(); | |
| 241 I != E; ++I) { | |
| 242 const Variable *Var = *I; | |
| 243 const bool IsImplicit = true; | |
| 244 Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit); | |
| 245 } | |
| 246 | |
| 247 SizeT NumNodes = Func->getNumNodes(); | |
| 248 for (SizeT N = 0; N < NumNodes; ++N) { | |
| 249 CfgNode *Node = Func->getNodes()[N]; | |
| 250 const InstList &Insts = Node->getInsts(); | |
| 251 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E; | |
| 252 ++I) { | |
| 253 if ((*I)->isDeleted()) | |
| 254 continue; | |
| 255 if (Variable *Dest = (*I)->getDest()) { | |
| 256 SizeT DestNum = Dest->getIndex(); | |
| 257 assert(DestNum < Metadata.size()); | |
| 258 Metadata[DestNum].markDef(*I, Node); | |
| 259 } | |
| 260 for (SizeT SrcNum = 0; SrcNum < (*I)->getSrcSize(); ++SrcNum) { | |
| 261 Operand *Src = (*I)->getSrc(SrcNum); | |
| 262 SizeT NumVars = Src->getNumVars(); | |
| 263 for (SizeT J = 0; J < NumVars; ++J) { | |
| 264 const Variable *Var = Src->getVar(J); | |
| 265 SizeT VarNum = Var->getIndex(); | |
| 266 assert(VarNum < Metadata.size()); | |
| 267 const bool IsFromDef = false; | |
| 268 const bool IsImplicit = false; | |
| 269 Metadata[VarNum].markUse(*I, Node, IsFromDef, IsImplicit); | |
| 270 } | |
| 271 } | |
| 272 } | |
| 273 } | |
| 274 } | |
| 275 | |
| 276 bool VariablesMetadata::isMultiDef(const Variable *Var) const { | |
| 277 if (Var->getIsArg()) | |
| 278 return false; | |
| 279 if (!isTracked(Var)) | |
| 280 return true; // conservative answer | |
| 281 SizeT VarNum = Var->getIndex(); | |
| 282 // Conservatively return true if the state is unknown. | |
| 283 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef; | |
| 284 } | |
| 285 | |
| 286 bool VariablesMetadata::isMultiBlock(const Variable *Var) const { | |
| 287 if (getDefinition(Var) == NULL) | |
| 288 return true; | |
| 289 SizeT VarNum = Var->getIndex(); | |
| 290 // Conservatively return true if the state is unknown. | |
| 291 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock; | |
| 292 } | |
| 293 | |
| 294 const Inst *VariablesMetadata::getDefinition(const Variable *Var) const { | |
| 295 if (!isTracked(Var)) | |
| 296 return NULL; // conservative answer | |
| 297 SizeT VarNum = Var->getIndex(); | |
| 298 return Metadata[VarNum].getDefinition(); | |
| 299 } | |
| 300 | |
| 301 const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { | |
| 302 if (!isTracked(Var)) | |
| 303 return NULL; // conservative answer | |
| 304 SizeT VarNum = Var->getIndex(); | |
| 305 return Metadata[VarNum].getNode(); | |
| 306 } | |
| 307 | |
| 200 // ======================== dump routines ======================== // | 308 // ======================== dump routines ======================== // |
| 201 | 309 |
| 202 void Variable::emit(const Cfg *Func) const { | 310 void Variable::emit(const Cfg *Func) const { |
| 203 Func->getTarget()->emitVariable(this, Func); | 311 Func->getTarget()->emitVariable(this); |
| 204 } | 312 } |
| 205 | 313 |
| 206 void Variable::dump(const Cfg *Func, Ostream &Str) const { | 314 void Variable::dump(const Cfg *Func, Ostream &Str) const { |
| 207 if (Func == NULL) { | 315 if (Func == NULL) { |
| 208 Str << "%" << getName(); | 316 Str << "%" << getName(); |
| 209 return; | 317 return; |
| 210 } | 318 } |
| 211 const CfgNode *CurrentNode = Func->getCurrentNode(); | |
| 212 (void)CurrentNode; // used only in assert() | |
| 213 assert(CurrentNode == NULL || DefNode == NULL || DefNode == CurrentNode); | |
| 214 if (Func->getContext()->isVerbose(IceV_RegOrigins) || | 319 if (Func->getContext()->isVerbose(IceV_RegOrigins) || |
| 215 (!hasReg() && !Func->getTarget()->hasComputedFrame())) | 320 (!hasReg() && !Func->getTarget()->hasComputedFrame())) |
| 216 Str << "%" << getName(); | 321 Str << "%" << getName(); |
| 217 if (hasReg()) { | 322 if (hasReg()) { |
| 218 if (Func->getContext()->isVerbose(IceV_RegOrigins)) | 323 if (Func->getContext()->isVerbose(IceV_RegOrigins)) |
| 219 Str << ":"; | 324 Str << ":"; |
| 220 Str << Func->getTarget()->getRegName(RegNum, getType()); | 325 Str << Func->getTarget()->getRegName(RegNum, getType()); |
| 221 } else if (Func->getTarget()->hasComputedFrame()) { | 326 } else if (Func->getTarget()->hasComputedFrame()) { |
| 222 if (Func->getContext()->isVerbose(IceV_RegOrigins)) | 327 if (Func->getContext()->isVerbose(IceV_RegOrigins)) |
| 223 Str << ":"; | 328 Str << ":"; |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 269 | 374 |
| 270 Ostream &operator<<(Ostream &Str, const RegWeight &W) { | 375 Ostream &operator<<(Ostream &Str, const RegWeight &W) { |
| 271 if (W.getWeight() == RegWeight::Inf) | 376 if (W.getWeight() == RegWeight::Inf) |
| 272 Str << "Inf"; | 377 Str << "Inf"; |
| 273 else | 378 else |
| 274 Str << W.getWeight(); | 379 Str << W.getWeight(); |
| 275 return Str; | 380 return Str; |
| 276 } | 381 } |
| 277 | 382 |
| 278 } // end of namespace Ice | 383 } // end of namespace Ice |
| OLD | NEW |