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