| OLD | NEW |
| 1 //===- subzero/src/IceInstARM32.h - ARM32 machine instructions --*- C++ -*-===// | 1 //===- subzero/src/IceInstARM32.h - ARM32 machine 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 InstARM32 and OperandARM32 classes and | 10 // This file declares the InstARM32 and OperandARM32 classes and |
| 11 // their subclasses. This represents the machine instructions and | 11 // their subclasses. This represents the machine instructions and |
| 12 // operands used for ARM32 code selection. | 12 // operands used for ARM32 code selection. |
| 13 // | 13 // |
| 14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
| 15 | 15 |
| 16 #ifndef SUBZERO_SRC_ICEINSTARM32_H | 16 #ifndef SUBZERO_SRC_ICEINSTARM32_H |
| 17 #define SUBZERO_SRC_ICEINSTARM32_H | 17 #define SUBZERO_SRC_ICEINSTARM32_H |
| 18 | 18 |
| 19 #include "IceConditionCodesARM32.h" |
| 19 #include "IceDefs.h" | 20 #include "IceDefs.h" |
| 20 #include "IceInst.h" | 21 #include "IceInst.h" |
| 21 #include "IceInstARM32.def" | 22 #include "IceInstARM32.def" |
| 22 #include "IceOperand.h" | 23 #include "IceOperand.h" |
| 23 | 24 |
| 24 namespace Ice { | 25 namespace Ice { |
| 25 | 26 |
| 26 class TargetARM32; | 27 class TargetARM32; |
| 27 | 28 |
| 28 // OperandARM32 extends the Operand hierarchy. Its subclasses are | 29 // OperandARM32 extends the Operand hierarchy. Its subclasses are |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 private: | 231 private: |
| 231 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, | 232 OperandARM32FlexReg(Cfg *Func, Type Ty, Variable *Reg, ShiftKind ShiftOp, |
| 232 Operand *ShiftAmt); | 233 Operand *ShiftAmt); |
| 233 ~OperandARM32FlexReg() override {} | 234 ~OperandARM32FlexReg() override {} |
| 234 | 235 |
| 235 Variable *Reg; | 236 Variable *Reg; |
| 236 ShiftKind ShiftOp; | 237 ShiftKind ShiftOp; |
| 237 Operand *ShiftAmt; | 238 Operand *ShiftAmt; |
| 238 }; | 239 }; |
| 239 | 240 |
| 241 // Base class for ARM instructions. While most ARM instructions can be |
| 242 // conditionally executed, a few of them are not predicable (halt, |
| 243 // memory barriers, etc.). |
| 240 class InstARM32 : public InstTarget { | 244 class InstARM32 : public InstTarget { |
| 241 InstARM32() = delete; | 245 InstARM32() = delete; |
| 242 InstARM32(const InstARM32 &) = delete; | 246 InstARM32(const InstARM32 &) = delete; |
| 243 InstARM32 &operator=(const InstARM32 &) = delete; | 247 InstARM32 &operator=(const InstARM32 &) = delete; |
| 244 | 248 |
| 245 public: | 249 public: |
| 246 enum InstKindARM32 { | 250 enum InstKindARM32 { |
| 247 k__Start = Inst::Target, | 251 k__Start = Inst::Target, |
| 248 Adc, | 252 Adc, |
| 249 Add, | 253 Add, |
| 250 And, | 254 And, |
| 255 Br, |
| 256 Call, |
| 257 Cmp, |
| 251 Eor, | 258 Eor, |
| 252 Ldr, | 259 Ldr, |
| 260 Lsl, |
| 253 Mla, | 261 Mla, |
| 254 Mov, | 262 Mov, |
| 255 Movt, | 263 Movt, |
| 256 Movw, | 264 Movw, |
| 257 Mul, | 265 Mul, |
| 258 Mvn, | 266 Mvn, |
| 259 Orr, | 267 Orr, |
| 260 Ret, | 268 Ret, |
| 261 Sbc, | 269 Sbc, |
| 262 Sub, | 270 Sub, |
| 263 Umull | 271 Umull |
| 264 }; | 272 }; |
| 265 | 273 |
| 266 static const char *getWidthString(Type Ty); | 274 static const char *getWidthString(Type Ty); |
| 275 static CondARM32::Cond getOppositeCondition(CondARM32::Cond Cond); |
| 267 | 276 |
| 268 void dump(const Cfg *Func) const override; | 277 void dump(const Cfg *Func) const override; |
| 269 | 278 |
| 270 protected: | 279 protected: |
| 271 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) | 280 InstARM32(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest) |
| 272 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} | 281 : InstTarget(Func, static_cast<InstKind>(Kind), Maxsrcs, Dest) {} |
| 273 ~InstARM32() override {} | 282 ~InstARM32() override {} |
| 274 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { | 283 static bool isClassof(const Inst *Inst, InstKindARM32 MyKind) { |
| 275 return Inst->getKind() == static_cast<InstKind>(MyKind); | 284 return Inst->getKind() == static_cast<InstKind>(MyKind); |
| 276 } | 285 } |
| 277 }; | 286 }; |
| 278 | 287 |
| 279 void emitTwoAddr(const char *Opcode, const Inst *Inst, const Cfg *Func); | 288 // A predicable ARM instruction. |
| 280 void emitThreeAddr(const char *Opcode, const Inst *Inst, const Cfg *Func, | 289 class InstARM32Pred : public InstARM32 { |
| 281 bool SetFlags); | 290 InstARM32Pred() = delete; |
| 291 InstARM32Pred(const InstARM32Pred &) = delete; |
| 292 InstARM32Pred &operator=(const InstARM32Pred &) = delete; |
| 282 | 293 |
| 283 // TODO(jvoung): add condition codes if instruction can be predicated. | 294 public: |
| 295 InstARM32Pred(Cfg *Func, InstKindARM32 Kind, SizeT Maxsrcs, Variable *Dest, |
| 296 CondARM32::Cond Predicate) |
| 297 : InstARM32(Func, Kind, Maxsrcs, Dest), Predicate(Predicate) {} |
| 298 |
| 299 CondARM32::Cond getPredicate() const { return Predicate; } |
| 300 void setPredicate(CondARM32::Cond Pred) { Predicate = Pred; } |
| 301 |
| 302 static const char *predString(CondARM32::Cond Predicate); |
| 303 void dumpOpcodePred(Ostream &Str, const char *Opcode, Type Ty) const; |
| 304 |
| 305 // Shared emit routines for common forms of instructions. |
| 306 static void emitTwoAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 307 const Cfg *Func); |
| 308 static void emitThreeAddr(const char *Opcode, const InstARM32Pred *Inst, |
| 309 const Cfg *Func, bool SetFlags); |
| 310 |
| 311 protected: |
| 312 CondARM32::Cond Predicate; |
| 313 }; |
| 314 |
| 315 template <typename StreamType> |
| 316 inline StreamType &operator<<(StreamType &Stream, CondARM32::Cond Predicate) { |
| 317 Stream << InstARM32Pred::predString(Predicate); |
| 318 return Stream; |
| 319 } |
| 284 | 320 |
| 285 // Instructions of the form x := op(y). | 321 // Instructions of the form x := op(y). |
| 286 template <InstARM32::InstKindARM32 K> | 322 template <InstARM32::InstKindARM32 K> |
| 287 class InstARM32UnaryopGPR : public InstARM32 { | 323 class InstARM32UnaryopGPR : public InstARM32Pred { |
| 288 InstARM32UnaryopGPR() = delete; | 324 InstARM32UnaryopGPR() = delete; |
| 289 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; | 325 InstARM32UnaryopGPR(const InstARM32UnaryopGPR &) = delete; |
| 290 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; | 326 InstARM32UnaryopGPR &operator=(const InstARM32UnaryopGPR &) = delete; |
| 291 | 327 |
| 292 public: | 328 public: |
| 293 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { | 329 static InstARM32UnaryopGPR *create(Cfg *Func, Variable *Dest, Operand *Src, |
| 330 CondARM32::Cond Predicate) { |
| 294 return new (Func->allocate<InstARM32UnaryopGPR>()) | 331 return new (Func->allocate<InstARM32UnaryopGPR>()) |
| 295 InstARM32UnaryopGPR(Func, Dest, Src); | 332 InstARM32UnaryopGPR(Func, Dest, Src, Predicate); |
| 296 } | 333 } |
| 297 void emit(const Cfg *Func) const override { | 334 void emit(const Cfg *Func) const override { |
| 298 if (!ALLOW_DUMP) | 335 if (!ALLOW_DUMP) |
| 299 return; | 336 return; |
| 300 Ostream &Str = Func->getContext()->getStrEmit(); | 337 Ostream &Str = Func->getContext()->getStrEmit(); |
| 301 assert(getSrcSize() == 1); | 338 assert(getSrcSize() == 1); |
| 302 Str << "\t" << Opcode << "\t"; | 339 Str << "\t" << Opcode << "\t"; |
| 303 getDest()->emit(Func); | 340 getDest()->emit(Func); |
| 304 Str << ", "; | 341 Str << ", "; |
| 305 getSrc(0)->emit(Func); | 342 getSrc(0)->emit(Func); |
| 306 } | 343 } |
| 307 void emitIAS(const Cfg *Func) const override { | 344 void emitIAS(const Cfg *Func) const override { |
| 308 (void)Func; | 345 (void)Func; |
| 309 llvm_unreachable("Not yet implemented"); | 346 llvm_unreachable("Not yet implemented"); |
| 310 } | 347 } |
| 311 void dump(const Cfg *Func) const override { | 348 void dump(const Cfg *Func) const override { |
| 312 if (!ALLOW_DUMP) | 349 if (!ALLOW_DUMP) |
| 313 return; | 350 return; |
| 314 Ostream &Str = Func->getContext()->getStrDump(); | 351 Ostream &Str = Func->getContext()->getStrDump(); |
| 315 dumpDest(Func); | 352 dumpDest(Func); |
| 316 Str << " = " << Opcode << "." << getDest()->getType() << " "; | 353 Str << " = "; |
| 354 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 355 Str << " "; |
| 317 dumpSources(Func); | 356 dumpSources(Func); |
| 318 } | 357 } |
| 319 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 358 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 320 | 359 |
| 321 private: | 360 private: |
| 322 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src) | 361 InstARM32UnaryopGPR(Cfg *Func, Variable *Dest, Operand *Src, |
| 323 : InstARM32(Func, K, 1, Dest) { | 362 CondARM32::Cond Predicate) |
| 363 : InstARM32Pred(Func, K, 1, Dest, Predicate) { |
| 324 addSource(Src); | 364 addSource(Src); |
| 325 } | 365 } |
| 326 ~InstARM32UnaryopGPR() override {} | 366 ~InstARM32UnaryopGPR() override {} |
| 327 static const char *Opcode; | 367 static const char *Opcode; |
| 328 }; | 368 }; |
| 329 | 369 |
| 330 // Instructions of the form x := x op y. | 370 // Instructions of the form x := x op y. |
| 331 template <InstARM32::InstKindARM32 K> | 371 template <InstARM32::InstKindARM32 K> |
| 332 class InstARM32TwoAddrGPR : public InstARM32 { | 372 class InstARM32TwoAddrGPR : public InstARM32Pred { |
| 333 InstARM32TwoAddrGPR() = delete; | 373 InstARM32TwoAddrGPR() = delete; |
| 334 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; | 374 InstARM32TwoAddrGPR(const InstARM32TwoAddrGPR &) = delete; |
| 335 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; | 375 InstARM32TwoAddrGPR &operator=(const InstARM32TwoAddrGPR &) = delete; |
| 336 | 376 |
| 337 public: | 377 public: |
| 338 // Dest must be a register. | 378 // Dest must be a register. |
| 339 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src) { | 379 static InstARM32TwoAddrGPR *create(Cfg *Func, Variable *Dest, Operand *Src, |
| 380 CondARM32::Cond Predicate) { |
| 340 return new (Func->allocate<InstARM32TwoAddrGPR>()) | 381 return new (Func->allocate<InstARM32TwoAddrGPR>()) |
| 341 InstARM32TwoAddrGPR(Func, Dest, Src); | 382 InstARM32TwoAddrGPR(Func, Dest, Src, Predicate); |
| 342 } | 383 } |
| 343 void emit(const Cfg *Func) const override { | 384 void emit(const Cfg *Func) const override { |
| 344 if (!ALLOW_DUMP) | 385 if (!ALLOW_DUMP) |
| 345 return; | 386 return; |
| 346 emitTwoAddr(Opcode, this, Func); | 387 emitTwoAddr(Opcode, this, Func); |
| 347 } | 388 } |
| 348 void emitIAS(const Cfg *Func) const override { | 389 void emitIAS(const Cfg *Func) const override { |
| 349 (void)Func; | 390 (void)Func; |
| 350 llvm::report_fatal_error("Not yet implemented"); | 391 llvm::report_fatal_error("Not yet implemented"); |
| 351 } | 392 } |
| 352 void dump(const Cfg *Func) const override { | 393 void dump(const Cfg *Func) const override { |
| 353 if (!ALLOW_DUMP) | 394 if (!ALLOW_DUMP) |
| 354 return; | 395 return; |
| 355 Ostream &Str = Func->getContext()->getStrDump(); | 396 Ostream &Str = Func->getContext()->getStrDump(); |
| 356 dumpDest(Func); | 397 dumpDest(Func); |
| 357 Str << " = " << Opcode << "." << getDest()->getType() << " "; | 398 Str << " = "; |
| 399 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 400 Str << " "; |
| 358 dumpSources(Func); | 401 dumpSources(Func); |
| 359 } | 402 } |
| 360 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 403 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 361 | 404 |
| 362 private: | 405 private: |
| 363 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src) | 406 InstARM32TwoAddrGPR(Cfg *Func, Variable *Dest, Operand *Src, |
| 364 : InstARM32(Func, K, 2, Dest) { | 407 CondARM32::Cond Predicate) |
| 408 : InstARM32Pred(Func, K, 2, Dest, Predicate) { |
| 365 addSource(Dest); | 409 addSource(Dest); |
| 366 addSource(Src); | 410 addSource(Src); |
| 367 } | 411 } |
| 368 ~InstARM32TwoAddrGPR() override {} | 412 ~InstARM32TwoAddrGPR() override {} |
| 369 static const char *Opcode; | 413 static const char *Opcode; |
| 370 }; | 414 }; |
| 371 | 415 |
| 372 // Base class for assignment instructions. | 416 // Base class for assignment instructions. |
| 373 // These can be tested for redundancy (and elided if redundant). | 417 // These can be tested for redundancy (and elided if redundant). |
| 374 template <InstARM32::InstKindARM32 K> | 418 template <InstARM32::InstKindARM32 K> |
| 375 class InstARM32Movlike : public InstARM32 { | 419 class InstARM32Movlike : public InstARM32Pred { |
| 376 InstARM32Movlike() = delete; | 420 InstARM32Movlike() = delete; |
| 377 InstARM32Movlike(const InstARM32Movlike &) = delete; | 421 InstARM32Movlike(const InstARM32Movlike &) = delete; |
| 378 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete; | 422 InstARM32Movlike &operator=(const InstARM32Movlike &) = delete; |
| 379 | 423 |
| 380 public: | 424 public: |
| 381 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source) { | 425 static InstARM32Movlike *create(Cfg *Func, Variable *Dest, Operand *Source, |
| 426 CondARM32::Cond Predicate) { |
| 382 return new (Func->allocate<InstARM32Movlike>()) | 427 return new (Func->allocate<InstARM32Movlike>()) |
| 383 InstARM32Movlike(Func, Dest, Source); | 428 InstARM32Movlike(Func, Dest, Source, Predicate); |
| 384 } | 429 } |
| 385 bool isRedundantAssign() const override { | 430 bool isRedundantAssign() const override { |
| 386 return checkForRedundantAssign(getDest(), getSrc(0)); | 431 return checkForRedundantAssign(getDest(), getSrc(0)); |
| 387 } | 432 } |
| 388 bool isSimpleAssign() const override { return true; } | 433 bool isSimpleAssign() const override { return true; } |
| 389 void emit(const Cfg *Func) const override; | 434 void emit(const Cfg *Func) const override; |
| 390 void emitIAS(const Cfg *Func) const override; | 435 void emitIAS(const Cfg *Func) const override; |
| 391 void dump(const Cfg *Func) const override { | 436 void dump(const Cfg *Func) const override { |
| 392 if (!ALLOW_DUMP) | 437 if (!ALLOW_DUMP) |
| 393 return; | 438 return; |
| 394 Ostream &Str = Func->getContext()->getStrDump(); | 439 Ostream &Str = Func->getContext()->getStrDump(); |
| 395 Str << Opcode << "." << getDest()->getType() << " "; | 440 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 441 Str << " "; |
| 396 dumpDest(Func); | 442 dumpDest(Func); |
| 397 Str << ", "; | 443 Str << ", "; |
| 398 dumpSources(Func); | 444 dumpSources(Func); |
| 399 } | 445 } |
| 400 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 446 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 401 | 447 |
| 402 private: | 448 private: |
| 403 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source) | 449 InstARM32Movlike(Cfg *Func, Variable *Dest, Operand *Source, |
| 404 : InstARM32(Func, K, 1, Dest) { | 450 CondARM32::Cond Predicate) |
| 451 : InstARM32Pred(Func, K, 1, Dest, Predicate) { |
| 405 addSource(Source); | 452 addSource(Source); |
| 406 } | 453 } |
| 407 ~InstARM32Movlike() override {} | 454 ~InstARM32Movlike() override {} |
| 408 | 455 |
| 409 static const char *Opcode; | 456 static const char *Opcode; |
| 410 }; | 457 }; |
| 411 | 458 |
| 412 // Instructions of the form x := y op z. May have the side-effect of setting | 459 // Instructions of the form x := y op z. May have the side-effect of setting |
| 413 // status flags. | 460 // status flags. |
| 414 template <InstARM32::InstKindARM32 K> | 461 template <InstARM32::InstKindARM32 K> |
| 415 class InstARM32ThreeAddrGPR : public InstARM32 { | 462 class InstARM32ThreeAddrGPR : public InstARM32Pred { |
| 416 InstARM32ThreeAddrGPR() = delete; | 463 InstARM32ThreeAddrGPR() = delete; |
| 417 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; | 464 InstARM32ThreeAddrGPR(const InstARM32ThreeAddrGPR &) = delete; |
| 418 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; | 465 InstARM32ThreeAddrGPR &operator=(const InstARM32ThreeAddrGPR &) = delete; |
| 419 | 466 |
| 420 public: | 467 public: |
| 421 // Create an ordinary binary-op instruction like add, and sub. | 468 // Create an ordinary binary-op instruction like add, and sub. |
| 422 // Dest and Src1 must be registers. | 469 // Dest and Src1 must be registers. |
| 423 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, | 470 static InstARM32ThreeAddrGPR *create(Cfg *Func, Variable *Dest, |
| 424 Variable *Src1, Operand *Src2, | 471 Variable *Src1, Operand *Src2, |
| 472 CondARM32::Cond Predicate, |
| 425 bool SetFlags = false) { | 473 bool SetFlags = false) { |
| 426 return new (Func->allocate<InstARM32ThreeAddrGPR>()) | 474 return new (Func->allocate<InstARM32ThreeAddrGPR>()) |
| 427 InstARM32ThreeAddrGPR(Func, Dest, Src1, Src2, SetFlags); | 475 InstARM32ThreeAddrGPR(Func, Dest, Src1, Src2, Predicate, SetFlags); |
| 428 } | 476 } |
| 429 void emit(const Cfg *Func) const override { | 477 void emit(const Cfg *Func) const override { |
| 430 if (!ALLOW_DUMP) | 478 if (!ALLOW_DUMP) |
| 431 return; | 479 return; |
| 432 emitThreeAddr(Opcode, this, Func, SetFlags); | 480 emitThreeAddr(Opcode, this, Func, SetFlags); |
| 433 } | 481 } |
| 434 void emitIAS(const Cfg *Func) const override { | 482 void emitIAS(const Cfg *Func) const override { |
| 435 (void)Func; | 483 (void)Func; |
| 436 llvm::report_fatal_error("Not yet implemented"); | 484 llvm::report_fatal_error("Not yet implemented"); |
| 437 } | 485 } |
| 438 void dump(const Cfg *Func) const override { | 486 void dump(const Cfg *Func) const override { |
| 439 if (!ALLOW_DUMP) | 487 if (!ALLOW_DUMP) |
| 440 return; | 488 return; |
| 441 Ostream &Str = Func->getContext()->getStrDump(); | 489 Ostream &Str = Func->getContext()->getStrDump(); |
| 442 dumpDest(Func); | 490 dumpDest(Func); |
| 443 Str << " = " << Opcode << (SetFlags ? "s" : "") << "." | 491 Str << " = "; |
| 444 << getDest()->getType() << " "; | 492 dumpOpcodePred(Str, Opcode, getDest()->getType()); |
| 493 Str << (SetFlags ? ".s " : " "); |
| 445 dumpSources(Func); | 494 dumpSources(Func); |
| 446 } | 495 } |
| 447 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } | 496 static bool classof(const Inst *Inst) { return isClassof(Inst, K); } |
| 448 | 497 |
| 449 private: | 498 private: |
| 450 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src1, | 499 InstARM32ThreeAddrGPR(Cfg *Func, Variable *Dest, Variable *Src1, |
| 451 Operand *Src2, bool SetFlags) | 500 Operand *Src2, CondARM32::Cond Predicate, bool SetFlags) |
| 452 : InstARM32(Func, K, 2, Dest), SetFlags(SetFlags) { | 501 : InstARM32Pred(Func, K, 2, Dest, Predicate), SetFlags(SetFlags) { |
| 453 addSource(Src1); | 502 addSource(Src1); |
| 454 addSource(Src2); | 503 addSource(Src2); |
| 455 } | 504 } |
| 456 ~InstARM32ThreeAddrGPR() override {} | 505 ~InstARM32ThreeAddrGPR() override {} |
| 457 static const char *Opcode; | 506 static const char *Opcode; |
| 458 bool SetFlags; | 507 bool SetFlags; |
| 459 }; | 508 }; |
| 460 | 509 |
| 461 typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc; | 510 typedef InstARM32ThreeAddrGPR<InstARM32::Adc> InstARM32Adc; |
| 462 typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add; | 511 typedef InstARM32ThreeAddrGPR<InstARM32::Add> InstARM32Add; |
| 463 typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And; | 512 typedef InstARM32ThreeAddrGPR<InstARM32::And> InstARM32And; |
| 464 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; | 513 typedef InstARM32ThreeAddrGPR<InstARM32::Eor> InstARM32Eor; |
| 514 typedef InstARM32ThreeAddrGPR<InstARM32::Lsl> InstARM32Lsl; |
| 465 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul; | 515 typedef InstARM32ThreeAddrGPR<InstARM32::Mul> InstARM32Mul; |
| 466 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr; | 516 typedef InstARM32ThreeAddrGPR<InstARM32::Orr> InstARM32Orr; |
| 467 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc; | 517 typedef InstARM32ThreeAddrGPR<InstARM32::Sbc> InstARM32Sbc; |
| 468 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub; | 518 typedef InstARM32ThreeAddrGPR<InstARM32::Sub> InstARM32Sub; |
| 469 // Move instruction (variable <- flex). This is more of a pseudo-inst. | 519 // Move instruction (variable <- flex). This is more of a pseudo-inst. |
| 470 // If var is a register, then we use "mov". If var is stack, then we use | 520 // If var is a register, then we use "mov". If var is stack, then we use |
| 471 // "str" to store to the stack. | 521 // "str" to store to the stack. |
| 472 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; | 522 typedef InstARM32Movlike<InstARM32::Mov> InstARM32Mov; |
| 473 // MovT leaves the bottom bits alone so dest is also a source. | 523 // MovT leaves the bottom bits alone so dest is also a source. |
| 474 // This helps indicate that a previous MovW setting dest is not dead code. | 524 // This helps indicate that a previous MovW setting dest is not dead code. |
| 475 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; | 525 typedef InstARM32TwoAddrGPR<InstARM32::Movt> InstARM32Movt; |
| 476 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; | 526 typedef InstARM32UnaryopGPR<InstARM32::Movw> InstARM32Movw; |
| 477 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; | 527 typedef InstARM32UnaryopGPR<InstARM32::Mvn> InstARM32Mvn; |
| 478 | 528 |
| 529 // Direct branch instruction. |
| 530 class InstARM32Br : public InstARM32Pred { |
| 531 InstARM32Br() = delete; |
| 532 InstARM32Br(const InstARM32Br &) = delete; |
| 533 InstARM32Br &operator=(const InstARM32Br &) = delete; |
| 534 |
| 535 public: |
| 536 // Create a conditional branch to one of two nodes. |
| 537 static InstARM32Br *create(Cfg *Func, CfgNode *TargetTrue, |
| 538 CfgNode *TargetFalse, CondARM32::Cond Predicate) { |
| 539 assert(Predicate != CondARM32::AL); |
| 540 return new (Func->allocate<InstARM32Br>()) |
| 541 InstARM32Br(Func, TargetTrue, TargetFalse, Predicate); |
| 542 } |
| 543 // Create an unconditional branch to a node. |
| 544 static InstARM32Br *create(Cfg *Func, CfgNode *Target) { |
| 545 const CfgNode *NoCondTarget = nullptr; |
| 546 return new (Func->allocate<InstARM32Br>()) |
| 547 InstARM32Br(Func, NoCondTarget, Target, CondARM32::AL); |
| 548 } |
| 549 // Create a non-terminator conditional branch to a node, with a |
| 550 // fallthrough to the next instruction in the current node. This is |
| 551 // used for switch lowering. |
| 552 static InstARM32Br *create(Cfg *Func, CfgNode *Target, |
| 553 CondARM32::Cond Predicate) { |
| 554 assert(Predicate != CondARM32::AL); |
| 555 const CfgNode *NoUncondTarget = nullptr; |
| 556 return new (Func->allocate<InstARM32Br>()) |
| 557 InstARM32Br(Func, Target, NoUncondTarget, Predicate); |
| 558 } |
| 559 const CfgNode *getTargetTrue() const { return TargetTrue; } |
| 560 const CfgNode *getTargetFalse() const { return TargetFalse; } |
| 561 bool optimizeBranch(const CfgNode *NextNode); |
| 562 uint32_t getEmitInstCount() const override { |
| 563 uint32_t Sum = 0; |
| 564 if (getTargetTrue()) |
| 565 ++Sum; |
| 566 if (getTargetFalse()) |
| 567 ++Sum; |
| 568 return Sum; |
| 569 } |
| 570 bool isUnconditionalBranch() const override { |
| 571 return getPredicate() == CondARM32::AL; |
| 572 } |
| 573 bool repointEdge(CfgNode *OldNode, CfgNode *NewNode) override; |
| 574 void emit(const Cfg *Func) const override; |
| 575 void emitIAS(const Cfg *Func) const override; |
| 576 void dump(const Cfg *Func) const override; |
| 577 static bool classof(const Inst *Inst) { return isClassof(Inst, Br); } |
| 578 |
| 579 private: |
| 580 InstARM32Br(Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, |
| 581 CondARM32::Cond Predicate); |
| 582 ~InstARM32Br() override {} |
| 583 const CfgNode *TargetTrue; |
| 584 const CfgNode *TargetFalse; |
| 585 }; |
| 586 |
| 587 // Call instruction (bl/blx). Arguments should have already been pushed. |
| 588 // Technically bl and the register form of blx can be predicated, but we'll |
| 589 // leave that out until needed. |
| 590 class InstARM32Call : public InstARM32 { |
| 591 InstARM32Call() = delete; |
| 592 InstARM32Call(const InstARM32Call &) = delete; |
| 593 InstARM32Call &operator=(const InstARM32Call &) = delete; |
| 594 |
| 595 public: |
| 596 static InstARM32Call *create(Cfg *Func, Variable *Dest, Operand *CallTarget) { |
| 597 return new (Func->allocate<InstARM32Call>()) |
| 598 InstARM32Call(Func, Dest, CallTarget); |
| 599 } |
| 600 Operand *getCallTarget() const { return getSrc(0); } |
| 601 void emit(const Cfg *Func) const override; |
| 602 void emitIAS(const Cfg *Func) const override; |
| 603 void dump(const Cfg *Func) const override; |
| 604 static bool classof(const Inst *Inst) { return isClassof(Inst, Call); } |
| 605 |
| 606 private: |
| 607 InstARM32Call(Cfg *Func, Variable *Dest, Operand *CallTarget); |
| 608 ~InstARM32Call() override {} |
| 609 }; |
| 610 |
| 611 // Integer compare instruction. |
| 612 class InstARM32Cmp : public InstARM32Pred { |
| 613 InstARM32Cmp() = delete; |
| 614 InstARM32Cmp(const InstARM32Cmp &) = delete; |
| 615 InstARM32Cmp &operator=(const InstARM32Cmp &) = delete; |
| 616 |
| 617 public: |
| 618 static InstARM32Cmp *create(Cfg *Func, Variable *Src1, Operand *Src2, |
| 619 CondARM32::Cond Predicate) { |
| 620 return new (Func->allocate<InstARM32Cmp>()) |
| 621 InstARM32Cmp(Func, Src1, Src2, Predicate); |
| 622 } |
| 623 void emit(const Cfg *Func) const override; |
| 624 void emitIAS(const Cfg *Func) const override; |
| 625 void dump(const Cfg *Func) const override; |
| 626 static bool classof(const Inst *Inst) { return isClassof(Inst, Cmp); } |
| 627 |
| 628 private: |
| 629 InstARM32Cmp(Cfg *Func, Variable *Src1, Operand *Src2, |
| 630 CondARM32::Cond Predicate); |
| 631 ~InstARM32Cmp() override {} |
| 632 }; |
| 633 |
| 479 // Load instruction. | 634 // Load instruction. |
| 480 class InstARM32Ldr : public InstARM32 { | 635 class InstARM32Ldr : public InstARM32Pred { |
| 481 InstARM32Ldr() = delete; | 636 InstARM32Ldr() = delete; |
| 482 InstARM32Ldr(const InstARM32Ldr &) = delete; | 637 InstARM32Ldr(const InstARM32Ldr &) = delete; |
| 483 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; | 638 InstARM32Ldr &operator=(const InstARM32Ldr &) = delete; |
| 484 | 639 |
| 485 public: | 640 public: |
| 486 // Dest must be a register. | 641 // Dest must be a register. |
| 487 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem) { | 642 static InstARM32Ldr *create(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, |
| 488 return new (Func->allocate<InstARM32Ldr>()) InstARM32Ldr(Func, Dest, Mem); | 643 CondARM32::Cond Predicate) { |
| 644 return new (Func->allocate<InstARM32Ldr>()) |
| 645 InstARM32Ldr(Func, Dest, Mem, Predicate); |
| 489 } | 646 } |
| 490 void emit(const Cfg *Func) const override; | 647 void emit(const Cfg *Func) const override; |
| 491 void emitIAS(const Cfg *Func) const override; | 648 void emitIAS(const Cfg *Func) const override; |
| 492 void dump(const Cfg *Func) const override; | 649 void dump(const Cfg *Func) const override; |
| 493 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } | 650 static bool classof(const Inst *Inst) { return isClassof(Inst, Ldr); } |
| 494 | 651 |
| 495 private: | 652 private: |
| 496 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem); | 653 InstARM32Ldr(Cfg *Func, Variable *Dest, OperandARM32Mem *Mem, |
| 654 CondARM32::Cond Predicate); |
| 497 ~InstARM32Ldr() override {} | 655 ~InstARM32Ldr() override {} |
| 498 }; | 656 }; |
| 499 | 657 |
| 500 // Multiply Accumulate: d := x * y + a | 658 // Multiply Accumulate: d := x * y + a |
| 501 class InstARM32Mla : public InstARM32 { | 659 class InstARM32Mla : public InstARM32Pred { |
| 502 InstARM32Mla() = delete; | 660 InstARM32Mla() = delete; |
| 503 InstARM32Mla(const InstARM32Mla &) = delete; | 661 InstARM32Mla(const InstARM32Mla &) = delete; |
| 504 InstARM32Mla &operator=(const InstARM32Mla &) = delete; | 662 InstARM32Mla &operator=(const InstARM32Mla &) = delete; |
| 505 | 663 |
| 506 public: | 664 public: |
| 507 // Everything must be a register. | 665 // Everything must be a register. |
| 508 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0, | 666 static InstARM32Mla *create(Cfg *Func, Variable *Dest, Variable *Src0, |
| 509 Variable *Src1, Variable *Acc) { | 667 Variable *Src1, Variable *Acc, |
| 668 CondARM32::Cond Predicate) { |
| 510 return new (Func->allocate<InstARM32Mla>()) | 669 return new (Func->allocate<InstARM32Mla>()) |
| 511 InstARM32Mla(Func, Dest, Src0, Src1, Acc); | 670 InstARM32Mla(Func, Dest, Src0, Src1, Acc, Predicate); |
| 512 } | 671 } |
| 513 void emit(const Cfg *Func) const override; | 672 void emit(const Cfg *Func) const override; |
| 514 void emitIAS(const Cfg *Func) const override; | 673 void emitIAS(const Cfg *Func) const override; |
| 515 void dump(const Cfg *Func) const override; | 674 void dump(const Cfg *Func) const override; |
| 516 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); } | 675 static bool classof(const Inst *Inst) { return isClassof(Inst, Mla); } |
| 517 | 676 |
| 518 private: | 677 private: |
| 519 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1, | 678 InstARM32Mla(Cfg *Func, Variable *Dest, Variable *Src0, Variable *Src1, |
| 520 Variable *Acc); | 679 Variable *Acc, CondARM32::Cond Predicate); |
| 521 ~InstARM32Mla() override {} | 680 ~InstARM32Mla() override {} |
| 522 }; | 681 }; |
| 523 | 682 |
| 524 // Ret pseudo-instruction. This is actually a "bx" instruction with | 683 // Ret pseudo-instruction. This is actually a "bx" instruction with |
| 525 // an "lr" register operand, but epilogue lowering will search for a Ret | 684 // an "lr" register operand, but epilogue lowering will search for a Ret |
| 526 // instead of a generic "bx". This instruction also takes a Source | 685 // instead of a generic "bx". This instruction also takes a Source |
| 527 // operand (for non-void returning functions) for liveness analysis, though | 686 // operand (for non-void returning functions) for liveness analysis, though |
| 528 // a FakeUse before the ret would do just as well. | 687 // a FakeUse before the ret would do just as well. |
| 688 // |
| 689 // NOTE: Even though "bx" can be predicated, for now leave out the predication |
| 690 // since it's not yet known to be useful for Ret. That may complicate finding |
| 691 // the terminator instruction if it's not guaranteed to be executed. |
| 529 class InstARM32Ret : public InstARM32 { | 692 class InstARM32Ret : public InstARM32 { |
| 530 InstARM32Ret() = delete; | 693 InstARM32Ret() = delete; |
| 531 InstARM32Ret(const InstARM32Ret &) = delete; | 694 InstARM32Ret(const InstARM32Ret &) = delete; |
| 532 InstARM32Ret &operator=(const InstARM32Ret &) = delete; | 695 InstARM32Ret &operator=(const InstARM32Ret &) = delete; |
| 533 | 696 |
| 534 public: | 697 public: |
| 535 static InstARM32Ret *create(Cfg *Func, Variable *LR, | 698 static InstARM32Ret *create(Cfg *Func, Variable *LR, |
| 536 Variable *Source = nullptr) { | 699 Variable *Source = nullptr) { |
| 537 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); | 700 return new (Func->allocate<InstARM32Ret>()) InstARM32Ret(Func, LR, Source); |
| 538 } | 701 } |
| 539 void emit(const Cfg *Func) const override; | 702 void emit(const Cfg *Func) const override; |
| 540 void emitIAS(const Cfg *Func) const override; | 703 void emitIAS(const Cfg *Func) const override; |
| 541 void dump(const Cfg *Func) const override; | 704 void dump(const Cfg *Func) const override; |
| 542 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } | 705 static bool classof(const Inst *Inst) { return isClassof(Inst, Ret); } |
| 543 | 706 |
| 544 private: | 707 private: |
| 545 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); | 708 InstARM32Ret(Cfg *Func, Variable *LR, Variable *Source); |
| 546 ~InstARM32Ret() override {} | 709 ~InstARM32Ret() override {} |
| 547 }; | 710 }; |
| 548 | 711 |
| 549 // Unsigned Multiply Long: d.lo, d.hi := x * y | 712 // Unsigned Multiply Long: d.lo, d.hi := x * y |
| 550 class InstARM32Umull : public InstARM32 { | 713 class InstARM32Umull : public InstARM32Pred { |
| 551 InstARM32Umull() = delete; | 714 InstARM32Umull() = delete; |
| 552 InstARM32Umull(const InstARM32Umull &) = delete; | 715 InstARM32Umull(const InstARM32Umull &) = delete; |
| 553 InstARM32Umull &operator=(const InstARM32Umull &) = delete; | 716 InstARM32Umull &operator=(const InstARM32Umull &) = delete; |
| 554 | 717 |
| 555 public: | 718 public: |
| 556 // Everything must be a register. | 719 // Everything must be a register. |
| 557 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, | 720 static InstARM32Umull *create(Cfg *Func, Variable *DestLo, Variable *DestHi, |
| 558 Variable *Src0, Variable *Src1) { | 721 Variable *Src0, Variable *Src1, |
| 722 CondARM32::Cond Predicate) { |
| 559 return new (Func->allocate<InstARM32Umull>()) | 723 return new (Func->allocate<InstARM32Umull>()) |
| 560 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1); | 724 InstARM32Umull(Func, DestLo, DestHi, Src0, Src1, Predicate); |
| 561 } | 725 } |
| 562 void emit(const Cfg *Func) const override; | 726 void emit(const Cfg *Func) const override; |
| 563 void emitIAS(const Cfg *Func) const override; | 727 void emitIAS(const Cfg *Func) const override; |
| 564 void dump(const Cfg *Func) const override; | 728 void dump(const Cfg *Func) const override; |
| 565 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } | 729 static bool classof(const Inst *Inst) { return isClassof(Inst, Umull); } |
| 566 | 730 |
| 567 private: | 731 private: |
| 568 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, | 732 InstARM32Umull(Cfg *Func, Variable *DestLo, Variable *DestHi, Variable *Src0, |
| 569 Variable *Src1); | 733 Variable *Src1, CondARM32::Cond Predicate); |
| 570 ~InstARM32Umull() override {} | 734 ~InstARM32Umull() override {} |
| 571 Variable *DestHi; | 735 Variable *DestHi; |
| 572 }; | 736 }; |
| 573 | 737 |
| 574 // Declare partial template specializations of emit() methods that | 738 // Declare partial template specializations of emit() methods that |
| 575 // already have default implementations. Without this, there is the | 739 // already have default implementations. Without this, there is the |
| 576 // possibility of ODR violations and link errors. | 740 // possibility of ODR violations and link errors. |
| 577 | 741 |
| 578 template <> void InstARM32Movw::emit(const Cfg *Func) const; | 742 template <> void InstARM32Movw::emit(const Cfg *Func) const; |
| 579 template <> void InstARM32Movt::emit(const Cfg *Func) const; | 743 template <> void InstARM32Movt::emit(const Cfg *Func) const; |
| 580 | 744 |
| 581 } // end of namespace Ice | 745 } // end of namespace Ice |
| 582 | 746 |
| 583 #endif // SUBZERO_SRC_ICEINSTARM32_H | 747 #endif // SUBZERO_SRC_ICEINSTARM32_H |
| OLD | NEW |