| OLD | NEW |
| 1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=// | 1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 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 /// \file | 10 /// \file |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 87 : InstX86Base(Func, InstX86Base::Shrd, 3, Dest) { | 87 : InstX86Base(Func, InstX86Base::Shrd, 3, Dest) { |
| 88 this->addSource(Dest); | 88 this->addSource(Dest); |
| 89 this->addSource(Source1); | 89 this->addSource(Source1); |
| 90 this->addSource(Source2); | 90 this->addSource(Source2); |
| 91 } | 91 } |
| 92 | 92 |
| 93 template <typename TraitsType> | 93 template <typename TraitsType> |
| 94 InstImpl<TraitsType>::InstX86Label::InstX86Label(Cfg *Func, | 94 InstImpl<TraitsType>::InstX86Label::InstX86Label(Cfg *Func, |
| 95 TargetLowering *Target) | 95 TargetLowering *Target) |
| 96 : InstX86Base(Func, InstX86Base::Label, 0, nullptr), | 96 : InstX86Base(Func, InstX86Base::Label, 0, nullptr), |
| 97 Number(Target->makeNextLabelNumber()) {} | 97 LabelNumber(Target->makeNextLabelNumber()) { |
| 98 | 98 if (BuildDefs::dump()) { |
| 99 template <typename TraitsType> | 99 Name = GlobalString::createWithString( |
| 100 IceString InstImpl<TraitsType>::InstX86Label::getName(const Cfg *Func) const { | 100 Func->getContext(), ".L" + Func->getFunctionName() + "$local$__" + |
| 101 // TODO(stichnot): Returning an empty string in a non-DUMP build can cause a | 101 std::to_string(LabelNumber)); |
| 102 // huge degradation in ConstantRelocatable hashing. Investigate and fix, but | 102 } else { |
| 103 // for now return something reasonably unique. | 103 Name = GlobalString::createWithoutString(Func->getContext()); |
| 104 if (!BuildDefs::dump()) | 104 } |
| 105 return Func->getFunctionName() + std::to_string(Number); | |
| 106 return ".L" + Func->getFunctionName() + "$local$__" + std::to_string(Number); | |
| 107 } | 105 } |
| 108 | 106 |
| 109 template <typename TraitsType> | 107 template <typename TraitsType> |
| 110 InstImpl<TraitsType>::InstX86Br::InstX86Br( | 108 InstImpl<TraitsType>::InstX86Br::InstX86Br( |
| 111 Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, | 109 Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, |
| 112 const InstImpl<TraitsType>::InstX86Label *Label, BrCond Condition, | 110 const InstImpl<TraitsType>::InstX86Label *Label, BrCond Condition, |
| 113 Mode Kind) | 111 Mode Kind) |
| 114 : InstX86Base(Func, InstX86Base::Br, 0, nullptr), Condition(Condition), | 112 : InstX86Base(Func, InstX86Base::Br, 0, nullptr), Condition(Condition), |
| 115 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label), | 113 TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label), |
| 116 Kind(Kind) {} | 114 Kind(Kind) {} |
| (...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 434 Ostream &Str = Func->getContext()->getStrDump(); | 432 Ostream &Str = Func->getContext()->getStrDump(); |
| 435 this->getDest()->dump(Func); | 433 this->getDest()->dump(Func); |
| 436 Str << " = call getIP"; | 434 Str << " = call getIP"; |
| 437 } | 435 } |
| 438 | 436 |
| 439 template <typename TraitsType> | 437 template <typename TraitsType> |
| 440 void InstImpl<TraitsType>::InstX86Label::emit(const Cfg *Func) const { | 438 void InstImpl<TraitsType>::InstX86Label::emit(const Cfg *Func) const { |
| 441 if (!BuildDefs::dump()) | 439 if (!BuildDefs::dump()) |
| 442 return; | 440 return; |
| 443 Ostream &Str = Func->getContext()->getStrEmit(); | 441 Ostream &Str = Func->getContext()->getStrEmit(); |
| 444 Str << getName(Func) << ":"; | 442 Str << getLabelName() << ":"; |
| 445 } | 443 } |
| 446 | 444 |
| 447 template <typename TraitsType> | 445 template <typename TraitsType> |
| 448 void InstImpl<TraitsType>::InstX86Label::emitIAS(const Cfg *Func) const { | 446 void InstImpl<TraitsType>::InstX86Label::emitIAS(const Cfg *Func) const { |
| 449 Assembler *Asm = Func->getAssembler<Assembler>(); | 447 Assembler *Asm = Func->getAssembler<Assembler>(); |
| 450 Asm->bindLocalLabel(Number); | 448 Asm->bindLocalLabel(LabelNumber); |
| 451 if (OffsetReloc != nullptr) { | 449 if (OffsetReloc != nullptr) { |
| 452 Asm->bindRelocOffset(OffsetReloc); | 450 Asm->bindRelocOffset(OffsetReloc); |
| 453 } | 451 } |
| 454 } | 452 } |
| 455 | 453 |
| 456 template <typename TraitsType> | 454 template <typename TraitsType> |
| 457 void InstImpl<TraitsType>::InstX86Label::dump(const Cfg *Func) const { | 455 void InstImpl<TraitsType>::InstX86Label::dump(const Cfg *Func) const { |
| 458 if (!BuildDefs::dump()) | 456 if (!BuildDefs::dump()) |
| 459 return; | 457 return; |
| 460 Ostream &Str = Func->getContext()->getStrDump(); | 458 Ostream &Str = Func->getContext()->getStrDump(); |
| 461 Str << getName(Func) << ":"; | 459 Str << getLabelName() << ":"; |
| 462 } | 460 } |
| 463 | 461 |
| 464 template <typename TraitsType> | 462 template <typename TraitsType> |
| 465 void InstImpl<TraitsType>::InstX86Br::emit(const Cfg *Func) const { | 463 void InstImpl<TraitsType>::InstX86Br::emit(const Cfg *Func) const { |
| 466 if (!BuildDefs::dump()) | 464 if (!BuildDefs::dump()) |
| 467 return; | 465 return; |
| 468 Ostream &Str = Func->getContext()->getStrEmit(); | 466 Ostream &Str = Func->getContext()->getStrEmit(); |
| 469 Str << "\t"; | 467 Str << "\t"; |
| 470 | 468 |
| 471 if (Condition == Cond::Br_None) { | 469 if (Condition == Cond::Br_None) { |
| 472 Str << "jmp"; | 470 Str << "jmp"; |
| 473 } else { | 471 } else { |
| 474 Str << Traits::InstBrAttributes[Condition].EmitString; | 472 Str << Traits::InstBrAttributes[Condition].EmitString; |
| 475 } | 473 } |
| 476 | 474 |
| 477 if (Label) { | 475 if (Label) { |
| 478 Str << "\t" << Label->getName(Func); | 476 Str << "\t" << Label->getLabelName(); |
| 479 } else { | 477 } else { |
| 480 if (Condition == Cond::Br_None) { | 478 if (Condition == Cond::Br_None) { |
| 481 Str << "\t" << getTargetFalse()->getAsmName(); | 479 Str << "\t" << getTargetFalse()->getAsmName(); |
| 482 } else { | 480 } else { |
| 483 Str << "\t" << getTargetTrue()->getAsmName(); | 481 Str << "\t" << getTargetTrue()->getAsmName(); |
| 484 if (getTargetFalse()) { | 482 if (getTargetFalse()) { |
| 485 Str << "\n\t" | 483 Str << "\n\t" |
| 486 "jmp\t" << getTargetFalse()->getAsmName(); | 484 "jmp\t" << getTargetFalse()->getAsmName(); |
| 487 } | 485 } |
| 488 } | 486 } |
| 489 } | 487 } |
| 490 } | 488 } |
| 491 | 489 |
| 492 template <typename TraitsType> | 490 template <typename TraitsType> |
| 493 void InstImpl<TraitsType>::InstX86Br::emitIAS(const Cfg *Func) const { | 491 void InstImpl<TraitsType>::InstX86Br::emitIAS(const Cfg *Func) const { |
| 494 Assembler *Asm = Func->getAssembler<Assembler>(); | 492 Assembler *Asm = Func->getAssembler<Assembler>(); |
| 495 if (Label) { | 493 if (Label) { |
| 496 auto *L = Asm->getOrCreateLocalLabel(Label->getNumber()); | 494 auto *L = Asm->getOrCreateLocalLabel(Label->getLabelNumber()); |
| 497 if (Condition == Cond::Br_None) { | 495 if (Condition == Cond::Br_None) { |
| 498 Asm->jmp(L, isNear()); | 496 Asm->jmp(L, isNear()); |
| 499 } else { | 497 } else { |
| 500 Asm->j(Condition, L, isNear()); | 498 Asm->j(Condition, L, isNear()); |
| 501 } | 499 } |
| 502 } else { | 500 } else { |
| 503 if (Condition == Cond::Br_None) { | 501 if (Condition == Cond::Br_None) { |
| 504 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); | 502 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
| 505 assert(!getTargetTrue()); | 503 assert(!getTargetTrue()); |
| 506 Asm->jmp(L, isNear()); | 504 Asm->jmp(L, isNear()); |
| 507 } else { | 505 } else { |
| 508 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()); | 506 auto *L = Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex()); |
| 509 Asm->j(Condition, L, isNear()); | 507 Asm->j(Condition, L, isNear()); |
| 510 if (getTargetFalse()) { | 508 if (getTargetFalse()) { |
| 511 auto *L2 = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); | 509 auto *L2 = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex()); |
| 512 Asm->jmp(L2, isNear()); | 510 Asm->jmp(L2, isNear()); |
| 513 } | 511 } |
| 514 } | 512 } |
| 515 } | 513 } |
| 516 } | 514 } |
| 517 | 515 |
| 518 template <typename TraitsType> | 516 template <typename TraitsType> |
| 519 void InstImpl<TraitsType>::InstX86Br::dump(const Cfg *Func) const { | 517 void InstImpl<TraitsType>::InstX86Br::dump(const Cfg *Func) const { |
| 520 if (!BuildDefs::dump()) | 518 if (!BuildDefs::dump()) |
| 521 return; | 519 return; |
| 522 Ostream &Str = Func->getContext()->getStrDump(); | 520 Ostream &Str = Func->getContext()->getStrDump(); |
| 523 Str << "br "; | 521 Str << "br "; |
| 524 | 522 |
| 525 if (Condition == Cond::Br_None) { | 523 if (Condition == Cond::Br_None) { |
| 526 Str << "label %" | 524 if (Label) { |
| 527 << (Label ? Label->getName(Func) : getTargetFalse()->getName()); | 525 Str << "label %" << Label->getLabelName(); |
| 526 } else { |
| 527 Str << "label %" << getTargetFalse()->getName(); |
| 528 } |
| 528 return; | 529 return; |
| 529 } | 530 } |
| 530 | 531 |
| 531 Str << Traits::InstBrAttributes[Condition].DisplayString; | 532 Str << Traits::InstBrAttributes[Condition].DisplayString; |
| 532 if (Label) { | 533 if (Label) { |
| 533 Str << ", label %" << Label->getName(Func); | 534 Str << ", label %" << Label->getLabelName(); |
| 534 } else { | 535 } else { |
| 535 Str << ", label %" << getTargetTrue()->getName(); | 536 Str << ", label %" << getTargetTrue()->getName(); |
| 536 if (getTargetFalse()) { | 537 if (getTargetFalse()) { |
| 537 Str << ", label %" << getTargetFalse()->getName(); | 538 Str << ", label %" << getTargetFalse()->getName(); |
| 538 } | 539 } |
| 539 } | 540 } |
| 540 | 541 |
| 541 Str << " // (" << (isNear() ? "near" : "far") << " jump)"; | 542 Str << " // (" << (isNear() ? "near" : "far") << " jump)"; |
| 542 } | 543 } |
| 543 | 544 |
| (...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 return; | 655 return; |
| 655 Ostream &Str = Func->getContext()->getStrDump(); | 656 Ostream &Str = Func->getContext()->getStrDump(); |
| 656 if (this->getDest()) { | 657 if (this->getDest()) { |
| 657 this->dumpDest(Func); | 658 this->dumpDest(Func); |
| 658 Str << " = "; | 659 Str << " = "; |
| 659 } | 660 } |
| 660 Str << "call "; | 661 Str << "call "; |
| 661 getCallTarget()->dump(Func); | 662 getCallTarget()->dump(Func); |
| 662 } | 663 } |
| 663 | 664 |
| 664 // The this->Opcode parameter needs to be char* and not IceString because of | 665 // The this->Opcode parameter needs to be char* and not std::string because of |
| 665 // template issues. | 666 // template issues. |
| 666 template <typename TraitsType> | 667 template <typename TraitsType> |
| 667 void InstImpl<TraitsType>::InstX86Base::emitTwoAddress( | 668 void InstImpl<TraitsType>::InstX86Base::emitTwoAddress( |
| 668 const Cfg *Func, const char *Opcode, const char *Suffix) const { | 669 const Cfg *Func, const char *Opcode, const char *Suffix) const { |
| 669 if (!BuildDefs::dump()) | 670 if (!BuildDefs::dump()) |
| 670 return; | 671 return; |
| 671 Ostream &Str = Func->getContext()->getStrEmit(); | 672 Ostream &Str = Func->getContext()->getStrEmit(); |
| 672 assert(getSrcSize() == 2); | 673 assert(getSrcSize() == 2); |
| 673 Operand *Dest = getDest(); | 674 Operand *Dest = getDest(); |
| 674 if (Dest == nullptr) | 675 if (Dest == nullptr) |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 727 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar); | 728 Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar); |
| 728 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); | 729 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr); |
| 729 } | 730 } |
| 730 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) { | 731 } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) { |
| 731 Mem->emitSegmentOverride(Asm); | 732 Mem->emitSegmentOverride(Asm); |
| 732 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, | 733 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, |
| 733 Mem->toAsmAddress(Asm, Target, IsLea)); | 734 Mem->toAsmAddress(Asm, Target, IsLea)); |
| 734 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | 735 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
| 735 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue())); | 736 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue())); |
| 736 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { | 737 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
| 737 const auto FixupKind = Reloc->getName() == GlobalOffsetTable | 738 const auto FixupKind = (Reloc->getName().hasStdString() && |
| 739 Reloc->getName().toString() == GlobalOffsetTable) |
| 738 ? Traits::FK_GotPC | 740 ? Traits::FK_GotPC |
| 739 : Traits::TargetLowering::getAbsFixup(); | 741 : Traits::TargetLowering::getAbsFixup(); |
| 740 AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc); | 742 AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc); |
| 741 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Fixup)); | 743 (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Fixup)); |
| 742 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) { | 744 } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) { |
| 743 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); | 745 (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func)); |
| 744 } else { | 746 } else { |
| 745 llvm_unreachable("Unexpected operand type"); | 747 llvm_unreachable("Unexpected operand type"); |
| 746 } | 748 } |
| 747 } | 749 } |
| 748 | 750 |
| 749 template <typename TraitsType> | 751 template <typename TraitsType> |
| 750 void InstImpl<TraitsType>::emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, | 752 void InstImpl<TraitsType>::emitIASAddrOpTyGPR(const Cfg *Func, Type Ty, |
| 751 const Address &Addr, | 753 const Address &Addr, |
| 752 const Operand *Src, | 754 const Operand *Src, |
| 753 const GPREmitterAddrOp &Emitter) { | 755 const GPREmitterAddrOp &Emitter) { |
| 754 Assembler *Asm = Func->getAssembler<Assembler>(); | 756 Assembler *Asm = Func->getAssembler<Assembler>(); |
| 755 // Src can only be Reg or AssemblerImmediate. | 757 // Src can only be Reg or AssemblerImmediate. |
| 756 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { | 758 if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { |
| 757 assert(SrcVar->hasReg()); | 759 assert(SrcVar->hasReg()); |
| 758 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum()); | 760 GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum()); |
| 759 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); | 761 (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg); |
| 760 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { | 762 } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { |
| 761 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue())); | 763 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue())); |
| 762 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { | 764 } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) { |
| 763 const auto FixupKind = Reloc->getName() == GlobalOffsetTable | 765 const auto FixupKind = (Reloc->getName().hasStdString() && |
| 766 Reloc->getName().toString() == GlobalOffsetTable) |
| 764 ? Traits::FK_GotPC | 767 ? Traits::FK_GotPC |
| 765 : Traits::TargetLowering::getAbsFixup(); | 768 : Traits::TargetLowering::getAbsFixup(); |
| 766 AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc); | 769 AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc); |
| 767 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup)); | 770 (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup)); |
| 768 } else { | 771 } else { |
| 769 llvm_unreachable("Unexpected operand type"); | 772 llvm_unreachable("Unexpected operand type"); |
| 770 } | 773 } |
| 771 } | 774 } |
| 772 | 775 |
| 773 template <typename TraitsType> | 776 template <typename TraitsType> |
| (...skipping 1211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1985 Ostream &Str = Func->getContext()->getStrEmit(); | 1988 Ostream &Str = Func->getContext()->getStrEmit(); |
| 1986 assert(this->getSrcSize() == 1); | 1989 assert(this->getSrcSize() == 1); |
| 1987 assert(this->getDest()->hasReg()); | 1990 assert(this->getDest()->hasReg()); |
| 1988 Str << "\t" | 1991 Str << "\t" |
| 1989 "lea" << this->getWidthString(this->getDest()->getType()) << "\t"; | 1992 "lea" << this->getWidthString(this->getDest()->getType()) << "\t"; |
| 1990 Operand *Src0 = this->getSrc(0); | 1993 Operand *Src0 = this->getSrc(0); |
| 1991 if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) { | 1994 if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) { |
| 1992 Type Ty = Src0Var->getType(); | 1995 Type Ty = Src0Var->getType(); |
| 1993 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an | 1996 // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an |
| 1994 // acceptable type. | 1997 // acceptable type. |
| 1995 Src0Var->asType(isVectorType(Ty) ? IceType_i32 : Ty, RegNumT())->emit(Func); | 1998 Src0Var->asType(Func, isVectorType(Ty) ? IceType_i32 : Ty, RegNumT()) |
| 1999 ->emit(Func); |
| 1996 } else { | 2000 } else { |
| 1997 Src0->emit(Func); | 2001 Src0->emit(Func); |
| 1998 } | 2002 } |
| 1999 Str << ", "; | 2003 Str << ", "; |
| 2000 this->getDest()->emit(Func); | 2004 this->getDest()->emit(Func); |
| 2001 } | 2005 } |
| 2002 | 2006 |
| 2003 template <typename TraitsType> | 2007 template <typename TraitsType> |
| 2004 void InstImpl<TraitsType>::InstX86Mov::emit(const Cfg *Func) const { | 2008 void InstImpl<TraitsType>::InstX86Mov::emit(const Cfg *Func) const { |
| 2005 if (!BuildDefs::dump()) | 2009 if (!BuildDefs::dump()) |
| (...skipping 20 matching lines...) Expand all Loading... |
| 2026 // point value between a vector and a scalar (which movss is used for). Clean | 2030 // point value between a vector and a scalar (which movss is used for). Clean |
| 2027 // this up. | 2031 // this up. |
| 2028 assert(InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(DestTy) == | 2032 assert(InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(DestTy) == |
| 2029 InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy)); | 2033 InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy)); |
| 2030 const Operand *NewSrc = Src; | 2034 const Operand *NewSrc = Src; |
| 2031 if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { | 2035 if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) { |
| 2032 RegNumT NewRegNum; | 2036 RegNumT NewRegNum; |
| 2033 if (SrcVar->hasReg()) | 2037 if (SrcVar->hasReg()) |
| 2034 NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum()); | 2038 NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum()); |
| 2035 if (SrcTy != DestTy) | 2039 if (SrcTy != DestTy) |
| 2036 NewSrc = SrcVar->asType(DestTy, NewRegNum); | 2040 NewSrc = SrcVar->asType(Func, DestTy, NewRegNum); |
| 2037 } | 2041 } |
| 2038 NewSrc->emit(Func); | 2042 NewSrc->emit(Func); |
| 2039 Str << ", "; | 2043 Str << ", "; |
| 2040 this->getDest()->emit(Func); | 2044 this->getDest()->emit(Func); |
| 2041 } | 2045 } |
| 2042 | 2046 |
| 2043 template <typename TraitsType> | 2047 template <typename TraitsType> |
| 2044 void InstImpl<TraitsType>::InstX86Mov::emitIAS(const Cfg *Func) const { | 2048 void InstImpl<TraitsType>::InstX86Mov::emitIAS(const Cfg *Func) const { |
| 2045 assert(this->getSrcSize() == 1); | 2049 assert(this->getSrcSize() == 1); |
| 2046 const Variable *Dest = this->getDest(); | 2050 const Variable *Dest = this->getDest(); |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2304 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) { | 2308 if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) { |
| 2305 Ostream &Str = Func->getContext()->getStrEmit(); | 2309 Ostream &Str = Func->getContext()->getStrEmit(); |
| 2306 if (mayBeElided(Dest, Src)) { | 2310 if (mayBeElided(Dest, Src)) { |
| 2307 Str << "\t/* elided movzx */"; | 2311 Str << "\t/* elided movzx */"; |
| 2308 } else { | 2312 } else { |
| 2309 Str << "\t" | 2313 Str << "\t" |
| 2310 "mov" | 2314 "mov" |
| 2311 "\t"; | 2315 "\t"; |
| 2312 Src->emit(Func); | 2316 Src->emit(Func); |
| 2313 Str << ", "; | 2317 Str << ", "; |
| 2314 Dest->asType(IceType_i32, | 2318 Dest->asType(Func, IceType_i32, |
| 2315 Traits::getGprForType(IceType_i32, Dest->getRegNum())) | 2319 Traits::getGprForType(IceType_i32, Dest->getRegNum())) |
| 2316 ->emit(Func); | 2320 ->emit(Func); |
| 2317 Str << " /* movzx */"; | 2321 Str << " /* movzx */"; |
| 2318 } | 2322 } |
| 2319 return; | 2323 return; |
| 2320 } | 2324 } |
| 2321 } | 2325 } |
| 2322 InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func); | 2326 InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func); |
| 2323 } | 2327 } |
| 2324 | 2328 |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2512 << Traits::TypeAttributes[this->getSrc(0)->getType()].PackString << "\t"; | 2516 << Traits::TypeAttributes[this->getSrc(0)->getType()].PackString << "\t"; |
| 2513 this->getSrc(1)->emit(Func); | 2517 this->getSrc(1)->emit(Func); |
| 2514 Str << ", "; | 2518 Str << ", "; |
| 2515 this->getSrc(0)->emit(Func); | 2519 this->getSrc(0)->emit(Func); |
| 2516 Str << ", "; | 2520 Str << ", "; |
| 2517 Variable *Dest = this->getDest(); | 2521 Variable *Dest = this->getDest(); |
| 2518 // pextrw must take a register dest. There is an SSE4.1 version that takes a | 2522 // pextrw must take a register dest. There is an SSE4.1 version that takes a |
| 2519 // memory dest, but we aren't using it. For uniformity, just restrict them | 2523 // memory dest, but we aren't using it. For uniformity, just restrict them |
| 2520 // all to have a register dest for now. | 2524 // all to have a register dest for now. |
| 2521 assert(Dest->hasReg()); | 2525 assert(Dest->hasReg()); |
| 2522 Dest->asType(IceType_i32, Dest->getRegNum())->emit(Func); | 2526 Dest->asType(Func, IceType_i32, Dest->getRegNum())->emit(Func); |
| 2523 } | 2527 } |
| 2524 | 2528 |
| 2525 template <typename TraitsType> | 2529 template <typename TraitsType> |
| 2526 void InstImpl<TraitsType>::InstX86Pextr::emitIAS(const Cfg *Func) const { | 2530 void InstImpl<TraitsType>::InstX86Pextr::emitIAS(const Cfg *Func) const { |
| 2527 assert(this->getSrcSize() == 2); | 2531 assert(this->getSrcSize() == 2); |
| 2528 // pextrb and pextrd are SSE4.1 instructions. | 2532 // pextrb and pextrd are SSE4.1 instructions. |
| 2529 const Variable *Dest = this->getDest(); | 2533 const Variable *Dest = this->getDest(); |
| 2530 Type DispatchTy = Traits::getInVectorElementType(this->getSrc(0)->getType()); | 2534 Type DispatchTy = Traits::getInVectorElementType(this->getSrc(0)->getType()); |
| 2531 // pextrw must take a register dest. There is an SSE4.1 version that takes a | 2535 // pextrw must take a register dest. There is an SSE4.1 version that takes a |
| 2532 // memory dest, but we aren't using it. For uniformity, just restrict them | 2536 // memory dest, but we aren't using it. For uniformity, just restrict them |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2549 assert(this->getSrcSize() == 3); | 2553 assert(this->getSrcSize() == 3); |
| 2550 Str << "\t" << this->Opcode | 2554 Str << "\t" << this->Opcode |
| 2551 << Traits::TypeAttributes[this->getDest()->getType()].PackString << "\t"; | 2555 << Traits::TypeAttributes[this->getDest()->getType()].PackString << "\t"; |
| 2552 this->getSrc(2)->emit(Func); | 2556 this->getSrc(2)->emit(Func); |
| 2553 Str << ", "; | 2557 Str << ", "; |
| 2554 Operand *Src1 = this->getSrc(1); | 2558 Operand *Src1 = this->getSrc(1); |
| 2555 if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) { | 2559 if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) { |
| 2556 // If src1 is a register, it should always be r32. | 2560 // If src1 is a register, it should always be r32. |
| 2557 if (Src1Var->hasReg()) { | 2561 if (Src1Var->hasReg()) { |
| 2558 const auto NewRegNum = Traits::getBaseReg(Src1Var->getRegNum()); | 2562 const auto NewRegNum = Traits::getBaseReg(Src1Var->getRegNum()); |
| 2559 const Variable *NewSrc = Src1Var->asType(IceType_i32, NewRegNum); | 2563 const Variable *NewSrc = Src1Var->asType(Func, IceType_i32, NewRegNum); |
| 2560 NewSrc->emit(Func); | 2564 NewSrc->emit(Func); |
| 2561 } else { | 2565 } else { |
| 2562 Src1Var->emit(Func); | 2566 Src1Var->emit(Func); |
| 2563 } | 2567 } |
| 2564 } else { | 2568 } else { |
| 2565 Src1->emit(Func); | 2569 Src1->emit(Func); |
| 2566 } | 2570 } |
| 2567 Str << ", "; | 2571 Str << ", "; |
| 2568 this->getDest()->emit(Func); | 2572 this->getDest()->emit(Func); |
| 2569 } | 2573 } |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2893 return; | 2897 return; |
| 2894 Ostream &Str = Func->getContext()->getStrDump(); | 2898 Ostream &Str = Func->getContext()->getStrDump(); |
| 2895 Str << "IACA_END"; | 2899 Str << "IACA_END"; |
| 2896 } | 2900 } |
| 2897 | 2901 |
| 2898 } // end of namespace X86NAMESPACE | 2902 } // end of namespace X86NAMESPACE |
| 2899 | 2903 |
| 2900 } // end of namespace Ice | 2904 } // end of namespace Ice |
| 2901 | 2905 |
| 2902 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H | 2906 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H |
| OLD | NEW |