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 |
| 225 // Mark implicit args as being used in the entry node. |
| 226 const VarList &ImplicitArgList = Func->getImplicitArgs(); |
| 227 for (VarList::const_iterator I = ImplicitArgList.begin(), |
| 228 E = ImplicitArgList.end(); |
| 229 I != E; ++I) { |
| 230 const Variable *Var = *I; |
| 231 const Inst *NoInst = NULL; |
| 232 const CfgNode *EntryNode = Func->getEntryNode(); |
| 233 const bool IsFromDef = false; |
| 234 const bool IsImplicit = true; |
| 235 Metadata[Var->getIndex()].markUse(NoInst, EntryNode, IsFromDef, IsImplicit); |
| 236 } |
| 237 |
| 238 SizeT NumNodes = Func->getNumNodes(); |
| 239 for (SizeT N = 0; N < NumNodes; ++N) { |
| 240 CfgNode *Node = Func->getNodes()[N]; |
| 241 const InstList &Insts = Node->getInsts(); |
| 242 for (InstList::const_iterator I = Insts.begin(), E = Insts.end(); I != E; |
| 243 ++I) { |
| 244 if ((*I)->isDeleted()) |
| 245 continue; |
| 246 if (Variable *Dest = (*I)->getDest()) { |
| 247 SizeT DestNum = Dest->getIndex(); |
| 248 assert(DestNum < Metadata.size()); |
| 249 Metadata[DestNum].markDef(*I, Node); |
| 250 } |
| 251 for (SizeT SrcNum = 0; SrcNum < (*I)->getSrcSize(); ++SrcNum) { |
| 252 Operand *Src = (*I)->getSrc(SrcNum); |
| 253 SizeT NumVars = Src->getNumVars(); |
| 254 for (SizeT J = 0; J < NumVars; ++J) { |
| 255 const Variable *Var = Src->getVar(J); |
| 256 SizeT VarNum = Var->getIndex(); |
| 257 assert(VarNum < Metadata.size()); |
| 258 const bool IsFromDef = false; |
| 259 const bool IsImplicit = false; |
| 260 Metadata[VarNum].markUse(*I, Node, IsFromDef, IsImplicit); |
| 261 } |
| 262 } |
| 263 } |
| 264 } |
| 265 } |
| 266 |
| 267 bool VariablesMetadata::isMultiDef(const Variable *Var) const { |
| 268 if (Var->getIsArg()) |
| 269 return false; |
| 270 if (!isTracked(Var)) |
| 271 return true; // conservative answer |
| 272 SizeT VarNum = Var->getIndex(); |
| 273 // Conservatively return true if the state is unknown. |
| 274 return Metadata[VarNum].getMultiDef() != VariableTracking::MDS_SingleDef; |
| 275 } |
| 276 |
| 277 bool VariablesMetadata::isMultiBlock(const Variable *Var) const { |
| 278 if (getDefinition(Var) == NULL) |
| 279 return true; |
| 280 SizeT VarNum = Var->getIndex(); |
| 281 // Conservatively return true if the state is unknown. |
| 282 return Metadata[VarNum].getMultiBlock() != VariableTracking::MBS_SingleBlock; |
| 283 } |
| 284 |
| 285 const Inst *VariablesMetadata::getDefinition(const Variable *Var) const { |
| 286 if (!isTracked(Var)) |
| 287 return NULL; // conservative answer |
| 288 SizeT VarNum = Var->getIndex(); |
| 289 return Metadata[VarNum].getDefinition(); |
| 290 } |
| 291 |
| 292 const CfgNode *VariablesMetadata::getLocalUseNode(const Variable *Var) const { |
| 293 if (!isTracked(Var)) |
| 294 return NULL; // conservative answer |
| 295 SizeT VarNum = Var->getIndex(); |
| 296 return Metadata[VarNum].getNode(); |
| 297 } |
| 298 |
200 // ======================== dump routines ======================== // | 299 // ======================== dump routines ======================== // |
201 | 300 |
202 void Variable::emit(const Cfg *Func) const { | 301 void Variable::emit(const Cfg *Func) const { |
203 Func->getTarget()->emitVariable(this, Func); | 302 Func->getTarget()->emitVariable(this); |
204 } | 303 } |
205 | 304 |
206 void Variable::dump(const Cfg *Func, Ostream &Str) const { | 305 void Variable::dump(const Cfg *Func, Ostream &Str) const { |
207 if (Func == NULL) { | 306 if (Func == NULL) { |
208 Str << "%" << getName(); | 307 Str << "%" << getName(); |
209 return; | 308 return; |
210 } | 309 } |
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) || | 310 if (Func->getContext()->isVerbose(IceV_RegOrigins) || |
215 (!hasReg() && !Func->getTarget()->hasComputedFrame())) | 311 (!hasReg() && !Func->getTarget()->hasComputedFrame())) |
216 Str << "%" << getName(); | 312 Str << "%" << getName(); |
217 if (hasReg()) { | 313 if (hasReg()) { |
218 if (Func->getContext()->isVerbose(IceV_RegOrigins)) | 314 if (Func->getContext()->isVerbose(IceV_RegOrigins)) |
219 Str << ":"; | 315 Str << ":"; |
220 Str << Func->getTarget()->getRegName(RegNum, getType()); | 316 Str << Func->getTarget()->getRegName(RegNum, getType()); |
221 } else if (Func->getTarget()->hasComputedFrame()) { | 317 } else if (Func->getTarget()->hasComputedFrame()) { |
222 if (Func->getContext()->isVerbose(IceV_RegOrigins)) | 318 if (Func->getContext()->isVerbose(IceV_RegOrigins)) |
223 Str << ":"; | 319 Str << ":"; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 | 365 |
270 Ostream &operator<<(Ostream &Str, const RegWeight &W) { | 366 Ostream &operator<<(Ostream &Str, const RegWeight &W) { |
271 if (W.getWeight() == RegWeight::Inf) | 367 if (W.getWeight() == RegWeight::Inf) |
272 Str << "Inf"; | 368 Str << "Inf"; |
273 else | 369 else |
274 Str << W.getWeight(); | 370 Str << W.getWeight(); |
275 return Str; | 371 return Str; |
276 } | 372 } |
277 | 373 |
278 } // end of namespace Ice | 374 } // end of namespace Ice |
OLD | NEW |