| 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) {} |
| 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 |