OLD | NEW |
---|---|
1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// | 1 //===- subzero/src/IceInst.h - High-level instructions ----------*- C++ -*-===// |
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 declares the Inst class and its target-independent | 10 // This file declares the Inst class and its target-independent |
(...skipping 17 matching lines...) Expand all Loading... | |
28 // We need a list of everything that should be validated, and tests | 28 // We need a list of everything that should be validated, and tests |
29 // for each. | 29 // for each. |
30 | 30 |
31 namespace Ice { | 31 namespace Ice { |
32 | 32 |
33 // Base instruction class for ICE. Inst has two subclasses: | 33 // Base instruction class for ICE. Inst has two subclasses: |
34 // InstHighLevel and InstTarget. High-level ICE instructions inherit | 34 // InstHighLevel and InstTarget. High-level ICE instructions inherit |
35 // from InstHighLevel, and low-level (target-specific) ICE | 35 // from InstHighLevel, and low-level (target-specific) ICE |
36 // instructions inherit from InstTarget. | 36 // instructions inherit from InstTarget. |
37 class Inst { | 37 class Inst { |
38 Inst(const Inst &) = delete; | |
39 Inst &operator=(const Inst &) = delete; | |
40 | |
38 public: | 41 public: |
39 enum InstKind { | 42 enum InstKind { |
40 // Arbitrary (alphabetical) order, except put Unreachable first. | 43 // Arbitrary (alphabetical) order, except put Unreachable first. |
41 Unreachable, | 44 Unreachable, |
42 Alloca, | 45 Alloca, |
43 Arithmetic, | 46 Arithmetic, |
44 Assign, // not part of LLVM/PNaCl bitcode | 47 Assign, // not part of LLVM/PNaCl bitcode |
45 Br, | 48 Br, |
46 Call, | 49 Call, |
47 Cast, | 50 Cast, |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 // instruction. An instruction can have an arbitrary number of | 165 // instruction. An instruction can have an arbitrary number of |
163 // source operands (e.g. a call instruction), and each source | 166 // source operands (e.g. a call instruction), and each source |
164 // operand can contain 0 or 1 Variable (and target-specific operands | 167 // operand can contain 0 or 1 Variable (and target-specific operands |
165 // could contain more than 1 Variable). All the variables in an | 168 // could contain more than 1 Variable). All the variables in an |
166 // instruction are conceptually flattened and each variable is | 169 // instruction are conceptually flattened and each variable is |
167 // mapped to one bit position of the LiveRangesEnded bit vector. | 170 // mapped to one bit position of the LiveRangesEnded bit vector. |
168 // Only the first CHAR_BIT * sizeof(LREndedBits) variables are | 171 // Only the first CHAR_BIT * sizeof(LREndedBits) variables are |
169 // tracked this way. | 172 // tracked this way. |
170 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry | 173 typedef uint32_t LREndedBits; // only first 32 src operands tracked, sorry |
171 LREndedBits LiveRangesEnded; | 174 LREndedBits LiveRangesEnded; |
172 | |
173 private: | |
174 Inst(const Inst &) = delete; | |
175 Inst &operator=(const Inst &) = delete; | |
176 }; | 175 }; |
177 | 176 |
178 class InstHighLevel : public Inst { | 177 class InstHighLevel : public Inst { |
179 InstHighLevel(const InstHighLevel &) = delete; | 178 InstHighLevel(const InstHighLevel &) = delete; |
180 InstHighLevel &operator=(const InstHighLevel &) = delete; | 179 InstHighLevel &operator=(const InstHighLevel &) = delete; |
181 | 180 |
182 protected: | 181 protected: |
183 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 182 InstHighLevel(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
184 : Inst(Func, Kind, MaxSrcs, Dest) {} | 183 : Inst(Func, Kind, MaxSrcs, Dest) {} |
Karl
2014/10/15 19:59:12
Is there a reason this doesn't have a create metho
Jim Stichnoth
2014/10/15 20:23:43
This is the base class for the high-level ICE inst
Karl
2014/10/15 20:29:12
I see. I didn't notice it was protected, and hence
| |
185 void emit(const Cfg * /*Func*/) const override { | 184 void emit(const Cfg * /*Func*/) const override { |
186 llvm_unreachable("emit() called on a non-lowered instruction"); | 185 llvm_unreachable("emit() called on a non-lowered instruction"); |
187 } | 186 } |
188 void emitIAS(const Cfg * /*Func*/) const override { | 187 void emitIAS(const Cfg * /*Func*/) const override { |
189 llvm_unreachable("emitIAS() called on a non-lowered instruction"); | 188 llvm_unreachable("emitIAS() called on a non-lowered instruction"); |
190 } | 189 } |
191 ~InstHighLevel() override {} | 190 ~InstHighLevel() override {} |
192 }; | 191 }; |
193 | 192 |
194 // Alloca instruction. This captures the size in bytes as getSrc(0), | 193 // Alloca instruction. This captures the size in bytes as getSrc(0), |
195 // and the required alignment in bytes. The alignment must be either | 194 // and the required alignment in bytes. The alignment must be either |
196 // 0 (no alignment required) or a power of 2. | 195 // 0 (no alignment required) or a power of 2. |
197 class InstAlloca : public InstHighLevel { | 196 class InstAlloca : public InstHighLevel { |
197 InstAlloca(const InstAlloca &) = delete; | |
198 InstAlloca &operator=(const InstAlloca &) = delete; | |
199 | |
198 public: | 200 public: |
199 static InstAlloca *create(Cfg *Func, Operand *ByteCount, | 201 static InstAlloca *create(Cfg *Func, Operand *ByteCount, |
200 uint32_t AlignInBytes, Variable *Dest) { | 202 uint32_t AlignInBytes, Variable *Dest) { |
201 return new (Func->allocateInst<InstAlloca>()) | 203 return new (Func->allocateInst<InstAlloca>()) |
202 InstAlloca(Func, ByteCount, AlignInBytes, Dest); | 204 InstAlloca(Func, ByteCount, AlignInBytes, Dest); |
203 } | 205 } |
204 uint32_t getAlignInBytes() const { return AlignInBytes; } | 206 uint32_t getAlignInBytes() const { return AlignInBytes; } |
205 Operand *getSizeInBytes() const { return getSrc(0); } | 207 Operand *getSizeInBytes() const { return getSrc(0); } |
206 void dump(const Cfg *Func) const override; | 208 void dump(const Cfg *Func) const override; |
207 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } | 209 static bool classof(const Inst *Inst) { return Inst->getKind() == Alloca; } |
208 | 210 |
209 private: | 211 private: |
210 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, | 212 InstAlloca(Cfg *Func, Operand *ByteCount, uint32_t AlignInBytes, |
211 Variable *Dest); | 213 Variable *Dest); |
212 InstAlloca(const InstAlloca &) = delete; | |
213 InstAlloca &operator=(const InstAlloca &) = delete; | |
214 ~InstAlloca() override {} | 214 ~InstAlloca() override {} |
215 const uint32_t AlignInBytes; | 215 const uint32_t AlignInBytes; |
216 }; | 216 }; |
217 | 217 |
218 // Binary arithmetic instruction. The source operands are captured in | 218 // Binary arithmetic instruction. The source operands are captured in |
219 // getSrc(0) and getSrc(1). | 219 // getSrc(0) and getSrc(1). |
220 class InstArithmetic : public InstHighLevel { | 220 class InstArithmetic : public InstHighLevel { |
221 InstArithmetic(const InstArithmetic &) = delete; | |
222 InstArithmetic &operator=(const InstArithmetic &) = delete; | |
223 | |
221 public: | 224 public: |
222 enum OpKind { | 225 enum OpKind { |
223 #define X(tag, str, commutative) tag, | 226 #define X(tag, str, commutative) tag, |
224 ICEINSTARITHMETIC_TABLE | 227 ICEINSTARITHMETIC_TABLE |
225 #undef X | 228 #undef X |
226 _num | 229 _num |
227 }; | 230 }; |
228 | 231 |
229 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, | 232 static InstArithmetic *create(Cfg *Func, OpKind Op, Variable *Dest, |
230 Operand *Source1, Operand *Source2) { | 233 Operand *Source1, Operand *Source2) { |
231 return new (Func->allocateInst<InstArithmetic>()) | 234 return new (Func->allocateInst<InstArithmetic>()) |
232 InstArithmetic(Func, Op, Dest, Source1, Source2); | 235 InstArithmetic(Func, Op, Dest, Source1, Source2); |
233 } | 236 } |
234 OpKind getOp() const { return Op; } | 237 OpKind getOp() const { return Op; } |
235 static const char *getOpName(OpKind Op); | 238 static const char *getOpName(OpKind Op); |
236 bool isCommutative() const; | 239 bool isCommutative() const; |
237 void dump(const Cfg *Func) const override; | 240 void dump(const Cfg *Func) const override; |
238 static bool classof(const Inst *Inst) { | 241 static bool classof(const Inst *Inst) { |
239 return Inst->getKind() == Arithmetic; | 242 return Inst->getKind() == Arithmetic; |
240 } | 243 } |
241 | 244 |
242 private: | 245 private: |
243 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, | 246 InstArithmetic(Cfg *Func, OpKind Op, Variable *Dest, Operand *Source1, |
244 Operand *Source2); | 247 Operand *Source2); |
245 InstArithmetic(const InstArithmetic &) = delete; | |
246 InstArithmetic &operator=(const InstArithmetic &) = delete; | |
247 ~InstArithmetic() override {} | 248 ~InstArithmetic() override {} |
248 | 249 |
249 const OpKind Op; | 250 const OpKind Op; |
250 }; | 251 }; |
251 | 252 |
252 // Assignment instruction. The source operand is captured in | 253 // Assignment instruction. The source operand is captured in |
253 // getSrc(0). This is not part of the LLVM bitcode, but is a useful | 254 // getSrc(0). This is not part of the LLVM bitcode, but is a useful |
254 // abstraction for some of the lowering. E.g., if Phi instruction | 255 // abstraction for some of the lowering. E.g., if Phi instruction |
255 // lowering happens before target lowering, or for representing an | 256 // lowering happens before target lowering, or for representing an |
256 // Inttoptr instruction, or as an intermediate step for lowering a | 257 // Inttoptr instruction, or as an intermediate step for lowering a |
257 // Load instruction. | 258 // Load instruction. |
258 class InstAssign : public InstHighLevel { | 259 class InstAssign : public InstHighLevel { |
260 InstAssign(const InstAssign &) = delete; | |
261 InstAssign &operator=(const InstAssign &) = delete; | |
262 | |
259 public: | 263 public: |
260 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { | 264 static InstAssign *create(Cfg *Func, Variable *Dest, Operand *Source) { |
261 return new (Func->allocateInst<InstAssign>()) | 265 return new (Func->allocateInst<InstAssign>()) |
262 InstAssign(Func, Dest, Source); | 266 InstAssign(Func, Dest, Source); |
263 } | 267 } |
264 bool isSimpleAssign() const override { return true; } | 268 bool isSimpleAssign() const override { return true; } |
265 void dump(const Cfg *Func) const override; | 269 void dump(const Cfg *Func) const override; |
266 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } | 270 static bool classof(const Inst *Inst) { return Inst->getKind() == Assign; } |
267 | 271 |
268 private: | 272 private: |
269 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); | 273 InstAssign(Cfg *Func, Variable *Dest, Operand *Source); |
270 InstAssign(const InstAssign &) = delete; | |
271 InstAssign &operator=(const InstAssign &) = delete; | |
272 ~InstAssign() override {} | 274 ~InstAssign() override {} |
273 }; | 275 }; |
274 | 276 |
275 // Branch instruction. This represents both conditional and | 277 // Branch instruction. This represents both conditional and |
276 // unconditional branches. | 278 // unconditional branches. |
277 class InstBr : public InstHighLevel { | 279 class InstBr : public InstHighLevel { |
280 InstBr(const InstBr &) = delete; | |
281 InstBr &operator=(const InstBr &) = delete; | |
282 | |
278 public: | 283 public: |
279 // Create a conditional branch. If TargetTrue==TargetFalse, it is | 284 // Create a conditional branch. If TargetTrue==TargetFalse, it is |
280 // optimized to an unconditional branch. | 285 // optimized to an unconditional branch. |
281 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, | 286 static InstBr *create(Cfg *Func, Operand *Source, CfgNode *TargetTrue, |
282 CfgNode *TargetFalse) { | 287 CfgNode *TargetFalse) { |
283 return new (Func->allocateInst<InstBr>()) | 288 return new (Func->allocateInst<InstBr>()) |
284 InstBr(Func, Source, TargetTrue, TargetFalse); | 289 InstBr(Func, Source, TargetTrue, TargetFalse); |
285 } | 290 } |
286 // Create an unconditional branch. | 291 // Create an unconditional branch. |
287 static InstBr *create(Cfg *Func, CfgNode *Target) { | 292 static InstBr *create(Cfg *Func, CfgNode *Target) { |
(...skipping 12 matching lines...) Expand all Loading... | |
300 } | 305 } |
301 NodeList getTerminatorEdges() const override; | 306 NodeList getTerminatorEdges() const override; |
302 void dump(const Cfg *Func) const override; | 307 void dump(const Cfg *Func) const override; |
303 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; } | 308 static bool classof(const Inst *Inst) { return Inst->getKind() == Br; } |
304 | 309 |
305 private: | 310 private: |
306 // Conditional branch | 311 // Conditional branch |
307 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); | 312 InstBr(Cfg *Func, Operand *Source, CfgNode *TargetTrue, CfgNode *TargetFalse); |
308 // Unconditional branch | 313 // Unconditional branch |
309 InstBr(Cfg *Func, CfgNode *Target); | 314 InstBr(Cfg *Func, CfgNode *Target); |
310 InstBr(const InstBr &) = delete; | |
311 InstBr &operator=(const InstBr &) = delete; | |
312 ~InstBr() override {} | 315 ~InstBr() override {} |
313 | 316 |
314 CfgNode *const TargetFalse; // Doubles as unconditional branch target | 317 CfgNode *const TargetFalse; // Doubles as unconditional branch target |
315 CfgNode *const TargetTrue; // NULL if unconditional branch | 318 CfgNode *const TargetTrue; // NULL if unconditional branch |
316 }; | 319 }; |
317 | 320 |
318 // Call instruction. The call target is captured as getSrc(0), and | 321 // Call instruction. The call target is captured as getSrc(0), and |
319 // arg I is captured as getSrc(I+1). | 322 // arg I is captured as getSrc(I+1). |
320 class InstCall : public InstHighLevel { | 323 class InstCall : public InstHighLevel { |
324 InstCall(const InstCall &) = delete; | |
325 InstCall &operator=(const InstCall &) = delete; | |
326 | |
321 public: | 327 public: |
322 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, | 328 static InstCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, |
323 Operand *CallTarget, bool HasTailCall) { | 329 Operand *CallTarget, bool HasTailCall) { |
324 // Set HasSideEffects to true so that the call instruction can't be | 330 // Set HasSideEffects to true so that the call instruction can't be |
325 // dead-code eliminated. IntrinsicCalls can override this if the | 331 // dead-code eliminated. IntrinsicCalls can override this if the |
326 // particular intrinsic is deletable and has no side-effects. | 332 // particular intrinsic is deletable and has no side-effects. |
327 const bool HasSideEffects = true; | 333 const bool HasSideEffects = true; |
328 const InstKind Kind = Inst::Call; | 334 const InstKind Kind = Inst::Call; |
329 return new (Func->allocateInst<InstCall>()) InstCall( | 335 return new (Func->allocateInst<InstCall>()) InstCall( |
330 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind); | 336 Func, NumArgs, Dest, CallTarget, HasTailCall, HasSideEffects, Kind); |
(...skipping 11 matching lines...) Expand all Loading... | |
342 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, | 348 InstCall(Cfg *Func, SizeT NumArgs, Variable *Dest, Operand *CallTarget, |
343 bool HasTailCall, bool HasSideEff, InstKind Kind) | 349 bool HasTailCall, bool HasSideEff, InstKind Kind) |
344 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) { | 350 : InstHighLevel(Func, Kind, NumArgs + 1, Dest), HasTailCall(HasTailCall) { |
345 HasSideEffects = HasSideEff; | 351 HasSideEffects = HasSideEff; |
346 addSource(CallTarget); | 352 addSource(CallTarget); |
347 } | 353 } |
348 ~InstCall() override {} | 354 ~InstCall() override {} |
349 | 355 |
350 private: | 356 private: |
351 bool HasTailCall; | 357 bool HasTailCall; |
352 InstCall(const InstCall &) = delete; | |
353 InstCall &operator=(const InstCall &) = delete; | |
354 }; | 358 }; |
355 | 359 |
356 // Cast instruction (a.k.a. conversion operation). | 360 // Cast instruction (a.k.a. conversion operation). |
357 class InstCast : public InstHighLevel { | 361 class InstCast : public InstHighLevel { |
362 InstCast(const InstCast &) = delete; | |
363 InstCast &operator=(const InstCast &) = delete; | |
364 | |
358 public: | 365 public: |
359 enum OpKind { | 366 enum OpKind { |
360 #define X(tag, str) tag, | 367 #define X(tag, str) tag, |
361 ICEINSTCAST_TABLE | 368 ICEINSTCAST_TABLE |
362 #undef X | 369 #undef X |
363 _num | 370 _num |
364 }; | 371 }; |
365 | 372 |
366 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, | 373 static InstCast *create(Cfg *Func, OpKind CastKind, Variable *Dest, |
367 Operand *Source) { | 374 Operand *Source) { |
368 return new (Func->allocateInst<InstCast>()) | 375 return new (Func->allocateInst<InstCast>()) |
369 InstCast(Func, CastKind, Dest, Source); | 376 InstCast(Func, CastKind, Dest, Source); |
370 } | 377 } |
371 OpKind getCastKind() const { return CastKind; } | 378 OpKind getCastKind() const { return CastKind; } |
372 void dump(const Cfg *Func) const override; | 379 void dump(const Cfg *Func) const override; |
373 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } | 380 static bool classof(const Inst *Inst) { return Inst->getKind() == Cast; } |
374 | 381 |
375 private: | 382 private: |
376 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); | 383 InstCast(Cfg *Func, OpKind CastKind, Variable *Dest, Operand *Source); |
377 InstCast(const InstCast &) = delete; | |
378 InstCast &operator=(const InstCast &) = delete; | |
379 ~InstCast() override {} | 384 ~InstCast() override {} |
380 const OpKind CastKind; | 385 const OpKind CastKind; |
381 }; | 386 }; |
382 | 387 |
383 // ExtractElement instruction. | 388 // ExtractElement instruction. |
384 class InstExtractElement : public InstHighLevel { | 389 class InstExtractElement : public InstHighLevel { |
390 InstExtractElement(const InstExtractElement &) = delete; | |
391 InstExtractElement &operator=(const InstExtractElement &) = delete; | |
392 | |
385 public: | 393 public: |
386 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 394 static InstExtractElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
387 Operand *Source2) { | 395 Operand *Source2) { |
388 return new (Func->allocateInst<InstExtractElement>()) | 396 return new (Func->allocateInst<InstExtractElement>()) |
389 InstExtractElement(Func, Dest, Source1, Source2); | 397 InstExtractElement(Func, Dest, Source1, Source2); |
390 } | 398 } |
391 | 399 |
392 void dump(const Cfg *Func) const override; | 400 void dump(const Cfg *Func) const override; |
393 static bool classof(const Inst *Inst) { | 401 static bool classof(const Inst *Inst) { |
394 return Inst->getKind() == ExtractElement; | 402 return Inst->getKind() == ExtractElement; |
395 } | 403 } |
396 | 404 |
397 private: | 405 private: |
398 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, | 406 InstExtractElement(Cfg *Func, Variable *Dest, Operand *Source1, |
399 Operand *Source2); | 407 Operand *Source2); |
400 InstExtractElement(const InstExtractElement &) = delete; | |
401 InstExtractElement &operator=(const InstExtractElement &) = delete; | |
402 ~InstExtractElement() override {} | 408 ~InstExtractElement() override {} |
403 }; | 409 }; |
404 | 410 |
405 // Floating-point comparison instruction. The source operands are | 411 // Floating-point comparison instruction. The source operands are |
406 // captured in getSrc(0) and getSrc(1). | 412 // captured in getSrc(0) and getSrc(1). |
407 class InstFcmp : public InstHighLevel { | 413 class InstFcmp : public InstHighLevel { |
414 InstFcmp(const InstFcmp &) = delete; | |
415 InstFcmp &operator=(const InstFcmp &) = delete; | |
416 | |
408 public: | 417 public: |
409 enum FCond { | 418 enum FCond { |
410 #define X(tag, str) tag, | 419 #define X(tag, str) tag, |
411 ICEINSTFCMP_TABLE | 420 ICEINSTFCMP_TABLE |
412 #undef X | 421 #undef X |
413 _num | 422 _num |
414 }; | 423 }; |
415 | 424 |
416 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, | 425 static InstFcmp *create(Cfg *Func, FCond Condition, Variable *Dest, |
417 Operand *Source1, Operand *Source2) { | 426 Operand *Source1, Operand *Source2) { |
418 return new (Func->allocateInst<InstFcmp>()) | 427 return new (Func->allocateInst<InstFcmp>()) |
419 InstFcmp(Func, Condition, Dest, Source1, Source2); | 428 InstFcmp(Func, Condition, Dest, Source1, Source2); |
420 } | 429 } |
421 FCond getCondition() const { return Condition; } | 430 FCond getCondition() const { return Condition; } |
422 void dump(const Cfg *Func) const override; | 431 void dump(const Cfg *Func) const override; |
423 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } | 432 static bool classof(const Inst *Inst) { return Inst->getKind() == Fcmp; } |
424 | 433 |
425 private: | 434 private: |
426 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, | 435 InstFcmp(Cfg *Func, FCond Condition, Variable *Dest, Operand *Source1, |
427 Operand *Source2); | 436 Operand *Source2); |
428 InstFcmp(const InstFcmp &) = delete; | |
429 InstFcmp &operator=(const InstFcmp &) = delete; | |
430 ~InstFcmp() override {} | 437 ~InstFcmp() override {} |
431 const FCond Condition; | 438 const FCond Condition; |
432 }; | 439 }; |
433 | 440 |
434 // Integer comparison instruction. The source operands are captured | 441 // Integer comparison instruction. The source operands are captured |
435 // in getSrc(0) and getSrc(1). | 442 // in getSrc(0) and getSrc(1). |
436 class InstIcmp : public InstHighLevel { | 443 class InstIcmp : public InstHighLevel { |
444 InstIcmp(const InstIcmp &) = delete; | |
445 InstIcmp &operator=(const InstIcmp &) = delete; | |
446 | |
437 public: | 447 public: |
438 enum ICond { | 448 enum ICond { |
439 #define X(tag, str) tag, | 449 #define X(tag, str) tag, |
440 ICEINSTICMP_TABLE | 450 ICEINSTICMP_TABLE |
441 #undef X | 451 #undef X |
442 _num | 452 _num |
443 }; | 453 }; |
444 | 454 |
445 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, | 455 static InstIcmp *create(Cfg *Func, ICond Condition, Variable *Dest, |
446 Operand *Source1, Operand *Source2) { | 456 Operand *Source1, Operand *Source2) { |
447 return new (Func->allocateInst<InstIcmp>()) | 457 return new (Func->allocateInst<InstIcmp>()) |
448 InstIcmp(Func, Condition, Dest, Source1, Source2); | 458 InstIcmp(Func, Condition, Dest, Source1, Source2); |
449 } | 459 } |
450 ICond getCondition() const { return Condition; } | 460 ICond getCondition() const { return Condition; } |
451 void dump(const Cfg *Func) const override; | 461 void dump(const Cfg *Func) const override; |
452 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } | 462 static bool classof(const Inst *Inst) { return Inst->getKind() == Icmp; } |
453 | 463 |
454 private: | 464 private: |
455 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, | 465 InstIcmp(Cfg *Func, ICond Condition, Variable *Dest, Operand *Source1, |
456 Operand *Source2); | 466 Operand *Source2); |
457 InstIcmp(const InstIcmp &) = delete; | |
458 InstIcmp &operator=(const InstIcmp &) = delete; | |
459 ~InstIcmp() override {} | 467 ~InstIcmp() override {} |
460 const ICond Condition; | 468 const ICond Condition; |
461 }; | 469 }; |
462 | 470 |
463 // InsertElement instruction. | 471 // InsertElement instruction. |
464 class InstInsertElement : public InstHighLevel { | 472 class InstInsertElement : public InstHighLevel { |
473 InstInsertElement(const InstInsertElement &) = delete; | |
474 InstInsertElement &operator=(const InstInsertElement &) = delete; | |
475 | |
465 public: | 476 public: |
466 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, | 477 static InstInsertElement *create(Cfg *Func, Variable *Dest, Operand *Source1, |
467 Operand *Source2, Operand *Source3) { | 478 Operand *Source2, Operand *Source3) { |
468 return new (Func->allocateInst<InstInsertElement>()) | 479 return new (Func->allocateInst<InstInsertElement>()) |
469 InstInsertElement(Func, Dest, Source1, Source2, Source3); | 480 InstInsertElement(Func, Dest, Source1, Source2, Source3); |
470 } | 481 } |
471 | 482 |
472 void dump(const Cfg *Func) const override; | 483 void dump(const Cfg *Func) const override; |
473 static bool classof(const Inst *Inst) { | 484 static bool classof(const Inst *Inst) { |
474 return Inst->getKind() == InsertElement; | 485 return Inst->getKind() == InsertElement; |
475 } | 486 } |
476 | 487 |
477 private: | 488 private: |
478 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, | 489 InstInsertElement(Cfg *Func, Variable *Dest, Operand *Source1, |
479 Operand *Source2, Operand *Source3); | 490 Operand *Source2, Operand *Source3); |
480 InstInsertElement(const InstInsertElement &) = delete; | |
481 InstInsertElement &operator=(const InstInsertElement &) = delete; | |
482 ~InstInsertElement() override {} | 491 ~InstInsertElement() override {} |
483 }; | 492 }; |
484 | 493 |
485 // Call to an intrinsic function. The call target is captured as getSrc(0), | 494 // Call to an intrinsic function. The call target is captured as getSrc(0), |
486 // and arg I is captured as getSrc(I+1). | 495 // and arg I is captured as getSrc(I+1). |
487 class InstIntrinsicCall : public InstCall { | 496 class InstIntrinsicCall : public InstCall { |
497 InstIntrinsicCall(const InstIntrinsicCall &) = delete; | |
498 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; | |
499 | |
488 public: | 500 public: |
489 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, | 501 static InstIntrinsicCall *create(Cfg *Func, SizeT NumArgs, Variable *Dest, |
490 Operand *CallTarget, | 502 Operand *CallTarget, |
491 const Intrinsics::IntrinsicInfo &Info) { | 503 const Intrinsics::IntrinsicInfo &Info) { |
492 return new (Func->allocateInst<InstIntrinsicCall>()) | 504 return new (Func->allocateInst<InstIntrinsicCall>()) |
493 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); | 505 InstIntrinsicCall(Func, NumArgs, Dest, CallTarget, Info); |
494 } | 506 } |
495 static bool classof(const Inst *Inst) { | 507 static bool classof(const Inst *Inst) { |
496 return Inst->getKind() == IntrinsicCall; | 508 return Inst->getKind() == IntrinsicCall; |
497 } | 509 } |
498 | 510 |
499 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } | 511 Intrinsics::IntrinsicInfo getIntrinsicInfo() const { return Info; } |
500 | 512 |
501 private: | 513 private: |
502 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, | 514 InstIntrinsicCall(Cfg *Func, SizeT NumArgs, Variable *Dest, |
503 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) | 515 Operand *CallTarget, const Intrinsics::IntrinsicInfo &Info) |
504 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, | 516 : InstCall(Func, NumArgs, Dest, CallTarget, false, Info.HasSideEffects, |
505 Inst::IntrinsicCall), | 517 Inst::IntrinsicCall), |
506 Info(Info) {} | 518 Info(Info) {} |
507 InstIntrinsicCall(const InstIntrinsicCall &) = delete; | |
508 InstIntrinsicCall &operator=(const InstIntrinsicCall &) = delete; | |
509 ~InstIntrinsicCall() override {} | 519 ~InstIntrinsicCall() override {} |
510 const Intrinsics::IntrinsicInfo Info; | 520 const Intrinsics::IntrinsicInfo Info; |
511 }; | 521 }; |
512 | 522 |
513 // Load instruction. The source address is captured in getSrc(0). | 523 // Load instruction. The source address is captured in getSrc(0). |
514 class InstLoad : public InstHighLevel { | 524 class InstLoad : public InstHighLevel { |
525 InstLoad(const InstLoad &) = delete; | |
526 InstLoad &operator=(const InstLoad &) = delete; | |
527 | |
515 public: | 528 public: |
516 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, | 529 static InstLoad *create(Cfg *Func, Variable *Dest, Operand *SourceAddr, |
517 uint32_t Align = 1) { | 530 uint32_t Align = 1) { |
518 // TODO(kschimpf) Stop ignoring alignment specification. | 531 // TODO(kschimpf) Stop ignoring alignment specification. |
519 (void)Align; | 532 (void)Align; |
520 return new (Func->allocateInst<InstLoad>()) | 533 return new (Func->allocateInst<InstLoad>()) |
521 InstLoad(Func, Dest, SourceAddr); | 534 InstLoad(Func, Dest, SourceAddr); |
522 } | 535 } |
523 Operand *getSourceAddress() const { return getSrc(0); } | 536 Operand *getSourceAddress() const { return getSrc(0); } |
524 void dump(const Cfg *Func) const override; | 537 void dump(const Cfg *Func) const override; |
525 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } | 538 static bool classof(const Inst *Inst) { return Inst->getKind() == Load; } |
526 | 539 |
527 private: | 540 private: |
528 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); | 541 InstLoad(Cfg *Func, Variable *Dest, Operand *SourceAddr); |
529 InstLoad(const InstLoad &) = delete; | |
530 InstLoad &operator=(const InstLoad &) = delete; | |
531 ~InstLoad() override {} | 542 ~InstLoad() override {} |
532 }; | 543 }; |
533 | 544 |
534 // Phi instruction. For incoming edge I, the node is Labels[I] and | 545 // Phi instruction. For incoming edge I, the node is Labels[I] and |
535 // the Phi source operand is getSrc(I). | 546 // the Phi source operand is getSrc(I). |
536 class InstPhi : public InstHighLevel { | 547 class InstPhi : public InstHighLevel { |
548 InstPhi(const InstPhi &) = delete; | |
549 InstPhi &operator=(const InstPhi &) = delete; | |
550 | |
537 public: | 551 public: |
538 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { | 552 static InstPhi *create(Cfg *Func, SizeT MaxSrcs, Variable *Dest) { |
539 return new (Func->allocateInst<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); | 553 return new (Func->allocateInst<InstPhi>()) InstPhi(Func, MaxSrcs, Dest); |
540 } | 554 } |
541 void addArgument(Operand *Source, CfgNode *Label); | 555 void addArgument(Operand *Source, CfgNode *Label); |
542 Operand *getOperandForTarget(CfgNode *Target) const; | 556 Operand *getOperandForTarget(CfgNode *Target) const; |
543 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, | 557 void livenessPhiOperand(LivenessBV &Live, CfgNode *Target, |
544 Liveness *Liveness); | 558 Liveness *Liveness); |
545 Inst *lower(Cfg *Func); | 559 Inst *lower(Cfg *Func); |
546 void dump(const Cfg *Func) const override; | 560 void dump(const Cfg *Func) const override; |
547 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } | 561 static bool classof(const Inst *Inst) { return Inst->getKind() == Phi; } |
548 | 562 |
549 private: | 563 private: |
550 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); | 564 InstPhi(Cfg *Func, SizeT MaxSrcs, Variable *Dest); |
551 InstPhi(const InstPhi &) = delete; | |
552 InstPhi &operator=(const InstPhi &) = delete; | |
553 void destroy(Cfg *Func) override { | 565 void destroy(Cfg *Func) override { |
554 Func->deallocateArrayOf<CfgNode *>(Labels); | 566 Func->deallocateArrayOf<CfgNode *>(Labels); |
555 Inst::destroy(Func); | 567 Inst::destroy(Func); |
556 } | 568 } |
557 ~InstPhi() override {} | 569 ~InstPhi() override {} |
558 | 570 |
559 // Labels[] duplicates the InEdges[] information in the enclosing | 571 // Labels[] duplicates the InEdges[] information in the enclosing |
560 // CfgNode, but the Phi instruction is created before InEdges[] | 572 // CfgNode, but the Phi instruction is created before InEdges[] |
561 // is available, so it's more complicated to share the list. | 573 // is available, so it's more complicated to share the list. |
562 CfgNode **Labels; | 574 CfgNode **Labels; |
563 }; | 575 }; |
564 | 576 |
565 // Ret instruction. The return value is captured in getSrc(0), but if | 577 // Ret instruction. The return value is captured in getSrc(0), but if |
566 // there is no return value (void-type function), then | 578 // there is no return value (void-type function), then |
567 // getSrcSize()==0 and hasRetValue()==false. | 579 // getSrcSize()==0 and hasRetValue()==false. |
568 class InstRet : public InstHighLevel { | 580 class InstRet : public InstHighLevel { |
581 InstRet(const InstRet &) = delete; | |
582 InstRet &operator=(const InstRet &) = delete; | |
583 | |
569 public: | 584 public: |
570 static InstRet *create(Cfg *Func, Operand *RetValue = NULL) { | 585 static InstRet *create(Cfg *Func, Operand *RetValue = NULL) { |
571 return new (Func->allocateInst<InstRet>()) InstRet(Func, RetValue); | 586 return new (Func->allocateInst<InstRet>()) InstRet(Func, RetValue); |
572 } | 587 } |
573 bool hasRetValue() const { return getSrcSize(); } | 588 bool hasRetValue() const { return getSrcSize(); } |
574 Operand *getRetValue() const { | 589 Operand *getRetValue() const { |
575 assert(hasRetValue()); | 590 assert(hasRetValue()); |
576 return getSrc(0); | 591 return getSrc(0); |
577 } | 592 } |
578 NodeList getTerminatorEdges() const override { return NodeList(); } | 593 NodeList getTerminatorEdges() const override { return NodeList(); } |
579 void dump(const Cfg *Func) const override; | 594 void dump(const Cfg *Func) const override; |
580 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } | 595 static bool classof(const Inst *Inst) { return Inst->getKind() == Ret; } |
581 | 596 |
582 private: | 597 private: |
583 InstRet(Cfg *Func, Operand *RetValue); | 598 InstRet(Cfg *Func, Operand *RetValue); |
584 InstRet(const InstRet &) = delete; | |
585 InstRet &operator=(const InstRet &) = delete; | |
586 ~InstRet() override {} | 599 ~InstRet() override {} |
587 }; | 600 }; |
588 | 601 |
589 // Select instruction. The condition, true, and false operands are captured. | 602 // Select instruction. The condition, true, and false operands are captured. |
590 class InstSelect : public InstHighLevel { | 603 class InstSelect : public InstHighLevel { |
604 InstSelect(const InstSelect &) = delete; | |
605 InstSelect &operator=(const InstSelect &) = delete; | |
606 | |
591 public: | 607 public: |
592 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, | 608 static InstSelect *create(Cfg *Func, Variable *Dest, Operand *Condition, |
593 Operand *SourceTrue, Operand *SourceFalse) { | 609 Operand *SourceTrue, Operand *SourceFalse) { |
594 return new (Func->allocateInst<InstSelect>()) | 610 return new (Func->allocateInst<InstSelect>()) |
595 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); | 611 InstSelect(Func, Dest, Condition, SourceTrue, SourceFalse); |
596 } | 612 } |
597 Operand *getCondition() const { return getSrc(0); } | 613 Operand *getCondition() const { return getSrc(0); } |
598 Operand *getTrueOperand() const { return getSrc(1); } | 614 Operand *getTrueOperand() const { return getSrc(1); } |
599 Operand *getFalseOperand() const { return getSrc(2); } | 615 Operand *getFalseOperand() const { return getSrc(2); } |
600 void dump(const Cfg *Func) const override; | 616 void dump(const Cfg *Func) const override; |
601 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } | 617 static bool classof(const Inst *Inst) { return Inst->getKind() == Select; } |
602 | 618 |
603 private: | 619 private: |
604 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, | 620 InstSelect(Cfg *Func, Variable *Dest, Operand *Condition, Operand *Source1, |
605 Operand *Source2); | 621 Operand *Source2); |
606 InstSelect(const InstSelect &) = delete; | |
607 InstSelect &operator=(const InstSelect &) = delete; | |
608 ~InstSelect() override {} | 622 ~InstSelect() override {} |
609 }; | 623 }; |
610 | 624 |
611 // Store instruction. The address operand is captured, along with the | 625 // Store instruction. The address operand is captured, along with the |
612 // data operand to be stored into the address. | 626 // data operand to be stored into the address. |
613 class InstStore : public InstHighLevel { | 627 class InstStore : public InstHighLevel { |
628 InstStore(const InstStore &) = delete; | |
629 InstStore &operator=(const InstStore &) = delete; | |
630 | |
614 public: | 631 public: |
615 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, | 632 static InstStore *create(Cfg *Func, Operand *Data, Operand *Addr, |
616 uint32_t align = 1) { | 633 uint32_t align = 1) { |
617 // TODO(kschimpf) Stop ignoring alignment specification. | 634 // TODO(kschimpf) Stop ignoring alignment specification. |
618 (void)align; | 635 (void)align; |
619 return new (Func->allocateInst<InstStore>()) InstStore(Func, Data, Addr); | 636 return new (Func->allocateInst<InstStore>()) InstStore(Func, Data, Addr); |
620 } | 637 } |
621 Operand *getAddr() const { return getSrc(1); } | 638 Operand *getAddr() const { return getSrc(1); } |
622 Operand *getData() const { return getSrc(0); } | 639 Operand *getData() const { return getSrc(0); } |
623 void dump(const Cfg *Func) const override; | 640 void dump(const Cfg *Func) const override; |
624 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } | 641 static bool classof(const Inst *Inst) { return Inst->getKind() == Store; } |
625 | 642 |
626 private: | 643 private: |
627 InstStore(Cfg *Func, Operand *Data, Operand *Addr); | 644 InstStore(Cfg *Func, Operand *Data, Operand *Addr); |
628 InstStore(const InstStore &) = delete; | |
629 InstStore &operator=(const InstStore &) = delete; | |
630 ~InstStore() override {} | 645 ~InstStore() override {} |
631 }; | 646 }; |
632 | 647 |
633 // Switch instruction. The single source operand is captured as | 648 // Switch instruction. The single source operand is captured as |
634 // getSrc(0). | 649 // getSrc(0). |
635 class InstSwitch : public InstHighLevel { | 650 class InstSwitch : public InstHighLevel { |
651 InstSwitch(const InstSwitch &) = delete; | |
652 InstSwitch &operator=(const InstSwitch &) = delete; | |
653 | |
636 public: | 654 public: |
637 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, | 655 static InstSwitch *create(Cfg *Func, SizeT NumCases, Operand *Source, |
638 CfgNode *LabelDefault) { | 656 CfgNode *LabelDefault) { |
639 return new (Func->allocateInst<InstSwitch>()) | 657 return new (Func->allocateInst<InstSwitch>()) |
640 InstSwitch(Func, NumCases, Source, LabelDefault); | 658 InstSwitch(Func, NumCases, Source, LabelDefault); |
641 } | 659 } |
642 Operand *getComparison() const { return getSrc(0); } | 660 Operand *getComparison() const { return getSrc(0); } |
643 CfgNode *getLabelDefault() const { return LabelDefault; } | 661 CfgNode *getLabelDefault() const { return LabelDefault; } |
644 SizeT getNumCases() const { return NumCases; } | 662 SizeT getNumCases() const { return NumCases; } |
645 uint64_t getValue(SizeT I) const { | 663 uint64_t getValue(SizeT I) const { |
646 assert(I < NumCases); | 664 assert(I < NumCases); |
647 return Values[I]; | 665 return Values[I]; |
648 } | 666 } |
649 CfgNode *getLabel(SizeT I) const { | 667 CfgNode *getLabel(SizeT I) const { |
650 assert(I < NumCases); | 668 assert(I < NumCases); |
651 return Labels[I]; | 669 return Labels[I]; |
652 } | 670 } |
653 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); | 671 void addBranch(SizeT CaseIndex, uint64_t Value, CfgNode *Label); |
654 NodeList getTerminatorEdges() const override; | 672 NodeList getTerminatorEdges() const override; |
655 void dump(const Cfg *Func) const override; | 673 void dump(const Cfg *Func) const override; |
656 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; } | 674 static bool classof(const Inst *Inst) { return Inst->getKind() == Switch; } |
657 | 675 |
658 private: | 676 private: |
659 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); | 677 InstSwitch(Cfg *Func, SizeT NumCases, Operand *Source, CfgNode *LabelDefault); |
660 InstSwitch(const InstSwitch &) = delete; | |
661 InstSwitch &operator=(const InstSwitch &) = delete; | |
662 void destroy(Cfg *Func) override { | 678 void destroy(Cfg *Func) override { |
663 Func->deallocateArrayOf<uint64_t>(Values); | 679 Func->deallocateArrayOf<uint64_t>(Values); |
664 Func->deallocateArrayOf<CfgNode *>(Labels); | 680 Func->deallocateArrayOf<CfgNode *>(Labels); |
665 Inst::destroy(Func); | 681 Inst::destroy(Func); |
666 } | 682 } |
667 ~InstSwitch() override {} | 683 ~InstSwitch() override {} |
668 | 684 |
669 CfgNode *LabelDefault; | 685 CfgNode *LabelDefault; |
670 SizeT NumCases; // not including the default case | 686 SizeT NumCases; // not including the default case |
671 uint64_t *Values; // size is NumCases | 687 uint64_t *Values; // size is NumCases |
672 CfgNode **Labels; // size is NumCases | 688 CfgNode **Labels; // size is NumCases |
673 }; | 689 }; |
674 | 690 |
675 // Unreachable instruction. This is a terminator instruction with no | 691 // Unreachable instruction. This is a terminator instruction with no |
676 // operands. | 692 // operands. |
677 class InstUnreachable : public InstHighLevel { | 693 class InstUnreachable : public InstHighLevel { |
694 InstUnreachable(const InstUnreachable &) = delete; | |
695 InstUnreachable &operator=(const InstUnreachable &) = delete; | |
696 | |
678 public: | 697 public: |
679 static InstUnreachable *create(Cfg *Func) { | 698 static InstUnreachable *create(Cfg *Func) { |
680 return new (Func->allocateInst<InstUnreachable>()) InstUnreachable(Func); | 699 return new (Func->allocateInst<InstUnreachable>()) InstUnreachable(Func); |
681 } | 700 } |
682 NodeList getTerminatorEdges() const override { return NodeList(); } | 701 NodeList getTerminatorEdges() const override { return NodeList(); } |
683 void dump(const Cfg *Func) const override; | 702 void dump(const Cfg *Func) const override; |
684 static bool classof(const Inst *Inst) { | 703 static bool classof(const Inst *Inst) { |
685 return Inst->getKind() == Unreachable; | 704 return Inst->getKind() == Unreachable; |
686 } | 705 } |
687 | 706 |
688 private: | 707 private: |
689 InstUnreachable(Cfg *Func); | 708 InstUnreachable(Cfg *Func); |
690 InstUnreachable(const InstUnreachable &) = delete; | |
691 InstUnreachable &operator=(const InstUnreachable &) = delete; | |
692 ~InstUnreachable() override {} | 709 ~InstUnreachable() override {} |
693 }; | 710 }; |
694 | 711 |
695 // FakeDef instruction. This creates a fake definition of a variable, | 712 // FakeDef instruction. This creates a fake definition of a variable, |
696 // which is how we represent the case when an instruction produces | 713 // which is how we represent the case when an instruction produces |
697 // multiple results. This doesn't happen with high-level ICE | 714 // multiple results. This doesn't happen with high-level ICE |
698 // instructions, but might with lowered instructions. For example, | 715 // instructions, but might with lowered instructions. For example, |
699 // this would be a way to represent condition flags being modified by | 716 // this would be a way to represent condition flags being modified by |
700 // an instruction. | 717 // an instruction. |
701 // | 718 // |
702 // It's generally useful to set the optional source operand to be the | 719 // It's generally useful to set the optional source operand to be the |
703 // dest variable of the instruction that actually produces the FakeDef | 720 // dest variable of the instruction that actually produces the FakeDef |
704 // dest. Otherwise, the original instruction could be dead-code | 721 // dest. Otherwise, the original instruction could be dead-code |
705 // eliminated if its dest operand is unused, and therefore the FakeDef | 722 // eliminated if its dest operand is unused, and therefore the FakeDef |
706 // dest wouldn't be properly initialized. | 723 // dest wouldn't be properly initialized. |
707 class InstFakeDef : public InstHighLevel { | 724 class InstFakeDef : public InstHighLevel { |
725 InstFakeDef(const InstFakeDef &) = delete; | |
726 InstFakeDef &operator=(const InstFakeDef &) = delete; | |
727 | |
708 public: | 728 public: |
709 static InstFakeDef *create(Cfg *Func, Variable *Dest, Variable *Src = NULL) { | 729 static InstFakeDef *create(Cfg *Func, Variable *Dest, Variable *Src = NULL) { |
710 return new (Func->allocateInst<InstFakeDef>()) InstFakeDef(Func, Dest, Src); | 730 return new (Func->allocateInst<InstFakeDef>()) InstFakeDef(Func, Dest, Src); |
711 } | 731 } |
712 void emit(const Cfg *Func) const override; | 732 void emit(const Cfg *Func) const override; |
713 void emitIAS(const Cfg *Func) const override { emit(Func); } | 733 void emitIAS(const Cfg *Func) const override { emit(Func); } |
714 void dump(const Cfg *Func) const override; | 734 void dump(const Cfg *Func) const override; |
715 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } | 735 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeDef; } |
716 | 736 |
717 private: | 737 private: |
718 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); | 738 InstFakeDef(Cfg *Func, Variable *Dest, Variable *Src); |
719 InstFakeDef(const InstFakeDef &) = delete; | |
720 InstFakeDef &operator=(const InstFakeDef &) = delete; | |
721 ~InstFakeDef() override {} | 739 ~InstFakeDef() override {} |
722 }; | 740 }; |
723 | 741 |
724 // FakeUse instruction. This creates a fake use of a variable, to | 742 // FakeUse instruction. This creates a fake use of a variable, to |
725 // keep the instruction that produces that variable from being | 743 // keep the instruction that produces that variable from being |
726 // dead-code eliminated. This is useful in a variety of lowering | 744 // dead-code eliminated. This is useful in a variety of lowering |
727 // situations. The FakeUse instruction has no dest, so it can itself | 745 // situations. The FakeUse instruction has no dest, so it can itself |
728 // never be dead-code eliminated. | 746 // never be dead-code eliminated. |
729 class InstFakeUse : public InstHighLevel { | 747 class InstFakeUse : public InstHighLevel { |
748 InstFakeUse(const InstFakeUse &) = delete; | |
749 InstFakeUse &operator=(const InstFakeUse &) = delete; | |
750 | |
730 public: | 751 public: |
731 static InstFakeUse *create(Cfg *Func, Variable *Src) { | 752 static InstFakeUse *create(Cfg *Func, Variable *Src) { |
732 return new (Func->allocateInst<InstFakeUse>()) InstFakeUse(Func, Src); | 753 return new (Func->allocateInst<InstFakeUse>()) InstFakeUse(Func, Src); |
733 } | 754 } |
734 void emit(const Cfg *Func) const override; | 755 void emit(const Cfg *Func) const override; |
735 void emitIAS(const Cfg *Func) const override { emit(Func); } | 756 void emitIAS(const Cfg *Func) const override { emit(Func); } |
736 void dump(const Cfg *Func) const override; | 757 void dump(const Cfg *Func) const override; |
737 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } | 758 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeUse; } |
738 | 759 |
739 private: | 760 private: |
740 InstFakeUse(Cfg *Func, Variable *Src); | 761 InstFakeUse(Cfg *Func, Variable *Src); |
741 InstFakeUse(const InstFakeUse &) = delete; | |
742 InstFakeUse &operator=(const InstFakeUse &) = delete; | |
743 ~InstFakeUse() override {} | 762 ~InstFakeUse() override {} |
744 }; | 763 }; |
745 | 764 |
746 // FakeKill instruction. This "kills" a set of variables by adding a | 765 // FakeKill instruction. This "kills" a set of variables by adding a |
747 // trivial live range at this instruction to each variable. The | 766 // trivial live range at this instruction to each variable. The |
748 // primary use is to indicate that scratch registers are killed after | 767 // primary use is to indicate that scratch registers are killed after |
749 // a call, so that the register allocator won't assign a scratch | 768 // a call, so that the register allocator won't assign a scratch |
750 // register to a variable whose live range spans a call. | 769 // register to a variable whose live range spans a call. |
751 // | 770 // |
752 // The FakeKill instruction also holds a pointer to the instruction | 771 // The FakeKill instruction also holds a pointer to the instruction |
753 // that kills the set of variables, so that if that linked instruction | 772 // that kills the set of variables, so that if that linked instruction |
754 // gets dead-code eliminated, the FakeKill instruction will as well. | 773 // gets dead-code eliminated, the FakeKill instruction will as well. |
755 class InstFakeKill : public InstHighLevel { | 774 class InstFakeKill : public InstHighLevel { |
775 InstFakeKill(const InstFakeKill &) = delete; | |
776 InstFakeKill &operator=(const InstFakeKill &) = delete; | |
777 | |
756 public: | 778 public: |
757 static InstFakeKill *create(Cfg *Func, const VarList &KilledRegs, | 779 static InstFakeKill *create(Cfg *Func, const VarList &KilledRegs, |
758 const Inst *Linked) { | 780 const Inst *Linked) { |
759 return new (Func->allocateInst<InstFakeKill>()) | 781 return new (Func->allocateInst<InstFakeKill>()) |
760 InstFakeKill(Func, KilledRegs, Linked); | 782 InstFakeKill(Func, KilledRegs, Linked); |
761 } | 783 } |
762 const Inst *getLinked() const { return Linked; } | 784 const Inst *getLinked() const { return Linked; } |
763 void emit(const Cfg *Func) const override; | 785 void emit(const Cfg *Func) const override; |
764 void emitIAS(const Cfg *Func) const override { emit(Func); } | 786 void emitIAS(const Cfg *Func) const override { emit(Func); } |
765 void dump(const Cfg *Func) const override; | 787 void dump(const Cfg *Func) const override; |
766 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } | 788 static bool classof(const Inst *Inst) { return Inst->getKind() == FakeKill; } |
767 | 789 |
768 private: | 790 private: |
769 InstFakeKill(Cfg *Func, const VarList &KilledRegs, const Inst *Linked); | 791 InstFakeKill(Cfg *Func, const VarList &KilledRegs, const Inst *Linked); |
770 InstFakeKill(const InstFakeKill &) = delete; | |
771 InstFakeKill &operator=(const InstFakeKill &) = delete; | |
772 ~InstFakeKill() override {} | 792 ~InstFakeKill() override {} |
773 | 793 |
774 // This instruction is ignored if Linked->isDeleted() is true. | 794 // This instruction is ignored if Linked->isDeleted() is true. |
775 const Inst *Linked; | 795 const Inst *Linked; |
776 }; | 796 }; |
777 | 797 |
778 // The Target instruction is the base class for all target-specific | 798 // The Target instruction is the base class for all target-specific |
779 // instructions. | 799 // instructions. |
780 class InstTarget : public Inst { | 800 class InstTarget : public Inst { |
781 InstTarget(const InstTarget &) = delete; | 801 InstTarget(const InstTarget &) = delete; |
782 InstTarget &operator=(const InstTarget &) = delete; | 802 InstTarget &operator=(const InstTarget &) = delete; |
783 | 803 |
784 public: | 804 public: |
785 uint32_t getEmitInstCount() const override { return 1; } | 805 uint32_t getEmitInstCount() const override { return 1; } |
786 void dump(const Cfg *Func) const override; | 806 void dump(const Cfg *Func) const override; |
787 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } | 807 static bool classof(const Inst *Inst) { return Inst->getKind() >= Target; } |
788 | 808 |
789 protected: | 809 protected: |
790 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) | 810 InstTarget(Cfg *Func, InstKind Kind, SizeT MaxSrcs, Variable *Dest) |
791 : Inst(Func, Kind, MaxSrcs, Dest) { | 811 : Inst(Func, Kind, MaxSrcs, Dest) { |
792 assert(Kind >= Target); | 812 assert(Kind >= Target); |
793 } | 813 } |
794 void emitIAS(const Cfg *Func) const override { emit(Func); } | 814 void emitIAS(const Cfg *Func) const override { emit(Func); } |
795 ~InstTarget() override {} | 815 ~InstTarget() override {} |
796 }; | 816 }; |
797 | 817 |
798 } // end of namespace Ice | 818 } // end of namespace Ice |
799 | 819 |
800 #endif // SUBZERO_SRC_ICEINST_H | 820 #endif // SUBZERO_SRC_ICEINST_H |
OLD | NEW |