Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(977)

Side by Side Diff: src/IceInstX86BaseImpl.h

Issue 1341423002: Reflow comments to use the full width. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Fix spelling and rebase Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceInstX86Base.h ('k') | src/IceIntrinsics.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 InstX86Br<Machine>::InstX86Br( 105 InstX86Br<Machine>::InstX86Br(
106 Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse, 106 Cfg *Func, const CfgNode *TargetTrue, const CfgNode *TargetFalse,
107 const InstX86Label<Machine> *Label, 107 const InstX86Label<Machine> *Label,
108 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, Mode Kind) 108 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition, Mode Kind)
109 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Br, 0, nullptr), 109 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Br, 0, nullptr),
110 Condition(Condition), TargetTrue(TargetTrue), TargetFalse(TargetFalse), 110 Condition(Condition), TargetTrue(TargetTrue), TargetFalse(TargetFalse),
111 Label(Label), Kind(Kind) {} 111 Label(Label), Kind(Kind) {}
112 112
113 template <class Machine> 113 template <class Machine>
114 bool InstX86Br<Machine>::optimizeBranch(const CfgNode *NextNode) { 114 bool InstX86Br<Machine>::optimizeBranch(const CfgNode *NextNode) {
115 // If there is no next block, then there can be no fallthrough to 115 // If there is no next block, then there can be no fallthrough to optimize.
116 // optimize.
117 if (NextNode == nullptr) 116 if (NextNode == nullptr)
118 return false; 117 return false;
119 // Intra-block conditional branches can't be optimized. 118 // Intra-block conditional branches can't be optimized.
120 if (Label) 119 if (Label)
121 return false; 120 return false;
122 // If there is no fallthrough node, such as a non-default case label 121 // If there is no fallthrough node, such as a non-default case label for a
123 // for a switch instruction, then there is no opportunity to 122 // switch instruction, then there is no opportunity to optimize.
124 // optimize.
125 if (getTargetFalse() == nullptr) 123 if (getTargetFalse() == nullptr)
126 return false; 124 return false;
127 125
128 // Unconditional branch to the next node can be removed. 126 // Unconditional branch to the next node can be removed.
129 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None && 127 if (Condition == InstX86Base<Machine>::Traits::Cond::Br_None &&
130 getTargetFalse() == NextNode) { 128 getTargetFalse() == NextNode) {
131 assert(getTargetTrue() == nullptr); 129 assert(getTargetTrue() == nullptr);
132 this->setDeleted(); 130 this->setDeleted();
133 return true; 131 return true;
134 } 132 }
135 // If the fallthrough is to the next node, set fallthrough to nullptr 133 // If the fallthrough is to the next node, set fallthrough to nullptr to
136 // to indicate. 134 // indicate.
137 if (getTargetFalse() == NextNode) { 135 if (getTargetFalse() == NextNode) {
138 TargetFalse = nullptr; 136 TargetFalse = nullptr;
139 return true; 137 return true;
140 } 138 }
141 // If TargetTrue is the next node, and TargetFalse is not nullptr 139 // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
142 // (which was already tested above), then invert the branch 140 // already tested above), then invert the branch condition, swap the targets,
143 // condition, swap the targets, and set new fallthrough to nullptr. 141 // and set new fallthrough to nullptr.
144 if (getTargetTrue() == NextNode) { 142 if (getTargetTrue() == NextNode) {
145 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None); 143 assert(Condition != InstX86Base<Machine>::Traits::Cond::Br_None);
146 Condition = this->getOppositeCondition(Condition); 144 Condition = this->getOppositeCondition(Condition);
147 TargetTrue = getTargetFalse(); 145 TargetTrue = getTargetFalse();
148 TargetFalse = nullptr; 146 TargetFalse = nullptr;
149 return true; 147 return true;
150 } 148 }
151 return false; 149 return false;
152 } 150 }
153 151
(...skipping 24 matching lines...) Expand all
178 this->HasSideEffects = true; 176 this->HasSideEffects = true;
179 this->addSource(CallTarget); 177 this->addSource(CallTarget);
180 } 178 }
181 179
182 template <class Machine> 180 template <class Machine>
183 InstX86Cmov<Machine>::InstX86Cmov( 181 InstX86Cmov<Machine>::InstX86Cmov(
184 Cfg *Func, Variable *Dest, Operand *Source, 182 Cfg *Func, Variable *Dest, Operand *Source,
185 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition) 183 typename InstX86Base<Machine>::Traits::Cond::BrCond Condition)
186 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmov, 2, Dest), 184 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmov, 2, Dest),
187 Condition(Condition) { 185 Condition(Condition) {
188 // The final result is either the original Dest, or Source, so mark 186 // The final result is either the original Dest, or Source, so mark both as
189 // both as sources. 187 // sources.
190 this->addSource(Dest); 188 this->addSource(Dest);
191 this->addSource(Source); 189 this->addSource(Source);
192 } 190 }
193 191
194 template <class Machine> 192 template <class Machine>
195 InstX86Cmpps<Machine>::InstX86Cmpps( 193 InstX86Cmpps<Machine>::InstX86Cmpps(
196 Cfg *Func, Variable *Dest, Operand *Source, 194 Cfg *Func, Variable *Dest, Operand *Source,
197 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition) 195 typename InstX86Base<Machine>::Traits::Cond::CmppsCond Condition)
198 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmpps, 2, Dest), 196 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Cmpps, 2, Dest),
199 Condition(Condition) { 197 Condition(Condition) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 this->addSource(Src); 311 this->addSource(Src);
314 } 312 }
315 313
316 template <class Machine> 314 template <class Machine>
317 InstX86Fstp<Machine>::InstX86Fstp(Cfg *Func, Variable *Dest) 315 InstX86Fstp<Machine>::InstX86Fstp(Cfg *Func, Variable *Dest)
318 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fstp, 0, Dest) {} 316 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Fstp, 0, Dest) {}
319 317
320 template <class Machine> 318 template <class Machine>
321 InstX86Pop<Machine>::InstX86Pop(Cfg *Func, Variable *Dest) 319 InstX86Pop<Machine>::InstX86Pop(Cfg *Func, Variable *Dest)
322 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Pop, 0, Dest) { 320 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Pop, 0, Dest) {
323 // A pop instruction affects the stack pointer and so it should not 321 // A pop instruction affects the stack pointer and so it should not be
324 // be allowed to be automatically dead-code eliminated. (The 322 // allowed to be automatically dead-code eliminated. (The corresponding push
325 // corresponding push instruction doesn't need this treatment 323 // instruction doesn't need this treatment because it has no dest variable
326 // because it has no dest variable and therefore won't be dead-code 324 // and therefore won't be dead-code eliminated.) This is needed for
327 // eliminated.) This is needed for late-stage liveness analysis 325 // late-stage liveness analysis (e.g. asm-verbose mode).
328 // (e.g. asm-verbose mode).
329 this->HasSideEffects = true; 326 this->HasSideEffects = true;
330 } 327 }
331 328
332 template <class Machine> 329 template <class Machine>
333 InstX86Push<Machine>::InstX86Push(Cfg *Func, Variable *Source) 330 InstX86Push<Machine>::InstX86Push(Cfg *Func, Variable *Source)
334 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Push, 1, nullptr) { 331 : InstX86Base<Machine>(Func, InstX86Base<Machine>::Push, 1, nullptr) {
335 this->addSource(Source); 332 this->addSource(Source);
336 } 333 }
337 334
338 template <class Machine> 335 template <class Machine>
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 void InstX86Jmp<Machine>::emitIAS(const Cfg *Func) const { 519 void InstX86Jmp<Machine>::emitIAS(const Cfg *Func) const {
523 // Note: Adapted (mostly copied) from InstX86Call<Machine>::emitIAS(). 520 // Note: Adapted (mostly copied) from InstX86Call<Machine>::emitIAS().
524 typename InstX86Base<Machine>::Traits::Assembler *Asm = 521 typename InstX86Base<Machine>::Traits::Assembler *Asm =
525 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 522 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
526 Operand *Target = getJmpTarget(); 523 Operand *Target = getJmpTarget();
527 if (const auto Var = llvm::dyn_cast<Variable>(Target)) { 524 if (const auto Var = llvm::dyn_cast<Variable>(Target)) {
528 if (Var->hasReg()) { 525 if (Var->hasReg()) {
529 Asm->jmp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR( 526 Asm->jmp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedGPR(
530 Var->getRegNum())); 527 Var->getRegNum()));
531 } else { 528 } else {
532 // The jmp instruction with a memory operand should be possible 529 // The jmp instruction with a memory operand should be possible to
533 // to encode, but it isn't a valid sandboxed instruction, and 530 // encode, but it isn't a valid sandboxed instruction, and there
534 // there shouldn't be a register allocation issue to jump 531 // shouldn't be a register allocation issue to jump through a scratch
535 // through a scratch register, so we don't really need to bother 532 // register, so we don't really need to bother implementing it.
536 // implementing it.
537 llvm::report_fatal_error("Assembler can't jmp to memory operand"); 533 llvm::report_fatal_error("Assembler can't jmp to memory operand");
538 } 534 }
539 } else if (const auto Mem = llvm::dyn_cast< 535 } else if (const auto Mem = llvm::dyn_cast<
540 typename InstX86Base<Machine>::Traits::X86OperandMem>( 536 typename InstX86Base<Machine>::Traits::X86OperandMem>(
541 Target)) { 537 Target)) {
542 (void)Mem; 538 (void)Mem;
543 assert(Mem->getSegmentRegister() == 539 assert(Mem->getSegmentRegister() ==
544 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment); 540 InstX86Base<Machine>::Traits::X86OperandMem::DefaultSegment);
545 llvm::report_fatal_error("Assembler can't jmp to memory operand"); 541 llvm::report_fatal_error("Assembler can't jmp to memory operand");
546 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) { 542 } else if (const auto CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
547 assert(CR->getOffset() == 0 && "We only support jumping to a function"); 543 assert(CR->getOffset() == 0 && "We only support jumping to a function");
548 Asm->jmp(CR); 544 Asm->jmp(CR);
549 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) { 545 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
550 // NaCl trampoline calls refer to an address within the sandbox directly. 546 // NaCl trampoline calls refer to an address within the sandbox directly.
551 // This is usually only needed for non-IRT builds and otherwise not 547 // This is usually only needed for non-IRT builds and otherwise not very
552 // very portable or stable. Usually this is only done for "calls" 548 // portable or stable. Usually this is only done for "calls" and not jumps.
553 // and not jumps. 549 // TODO(jvoung): Support this when there is a lowering that actually
554 // TODO(jvoung): Support this when there is a lowering that 550 // triggers this case.
555 // actually triggers this case.
556 (void)Imm; 551 (void)Imm;
557 llvm::report_fatal_error("Unexpected jmp to absolute address"); 552 llvm::report_fatal_error("Unexpected jmp to absolute address");
558 } else { 553 } else {
559 llvm::report_fatal_error("Unexpected operand type"); 554 llvm::report_fatal_error("Unexpected operand type");
560 } 555 }
561 } 556 }
562 557
563 template <class Machine> void InstX86Jmp<Machine>::dump(const Cfg *Func) const { 558 template <class Machine> void InstX86Jmp<Machine>::dump(const Cfg *Func) const {
564 if (!BuildDefs::dump()) 559 if (!BuildDefs::dump())
565 return; 560 return;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
626 return; 621 return;
627 Ostream &Str = Func->getContext()->getStrDump(); 622 Ostream &Str = Func->getContext()->getStrDump();
628 if (this->getDest()) { 623 if (this->getDest()) {
629 this->dumpDest(Func); 624 this->dumpDest(Func);
630 Str << " = "; 625 Str << " = ";
631 } 626 }
632 Str << "call "; 627 Str << "call ";
633 getCallTarget()->dump(Func); 628 getCallTarget()->dump(Func);
634 } 629 }
635 630
636 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for 631 // The ShiftHack parameter is used to emit "cl" instead of "ecx" for shift
637 // shift instructions, in order to be syntactically valid. The 632 // instructions, in order to be syntactically valid. The this->Opcode parameter
638 // this->Opcode parameter needs to be char* and not IceString because of 633 // needs to be char* and not IceString because of template issues.
639 // template issues.
640 template <class Machine> 634 template <class Machine>
641 void InstX86Base<Machine>::emitTwoAddress(const char *Opcode, const Inst *Inst, 635 void InstX86Base<Machine>::emitTwoAddress(const char *Opcode, const Inst *Inst,
642 const Cfg *Func, bool ShiftHack) { 636 const Cfg *Func, bool ShiftHack) {
643 if (!BuildDefs::dump()) 637 if (!BuildDefs::dump())
644 return; 638 return;
645 Ostream &Str = Func->getContext()->getStrEmit(); 639 Ostream &Str = Func->getContext()->getStrEmit();
646 assert(Inst->getSrcSize() == 2); 640 assert(Inst->getSrcSize() == 2);
647 Operand *Dest = Inst->getDest(); 641 Operand *Dest = Inst->getDest();
648 if (Dest == nullptr) 642 if (Dest == nullptr)
649 Dest = Inst->getSrc(0); 643 Dest = Inst->getSrc(0);
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
795 } 789 }
796 } 790 }
797 791
798 template <class Machine> 792 template <class Machine>
799 void InstX86Base<Machine>::emitIASGPRShift( 793 void InstX86Base<Machine>::emitIASGPRShift(
800 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src, 794 const Cfg *Func, Type Ty, const Variable *Var, const Operand *Src,
801 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp 795 const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterShiftOp
802 &Emitter) { 796 &Emitter) {
803 typename InstX86Base<Machine>::Traits::Assembler *Asm = 797 typename InstX86Base<Machine>::Traits::Assembler *Asm =
804 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 798 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
805 // Technically, the Dest Var can be mem as well, but we only use Reg. 799 // Technically, the Dest Var can be mem as well, but we only use Reg. We can
806 // We can extend this to check Dest if we decide to use that form. 800 // extend this to check Dest if we decide to use that form.
807 assert(Var->hasReg()); 801 assert(Var->hasReg());
808 // We cheat a little and use GPRRegister even for byte operations. 802 // We cheat a little and use GPRRegister even for byte operations.
809 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg = 803 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister VarReg =
810 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR( 804 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
811 Ty, Var->getRegNum()); 805 Ty, Var->getRegNum());
812 // Src must be reg == ECX or an Imm8. 806 // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
813 // This is asserted by the assembler.
814 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) { 807 if (const auto SrcVar = llvm::dyn_cast<Variable>(Src)) {
815 assert(SrcVar->hasReg()); 808 assert(SrcVar->hasReg());
816 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg = 809 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister SrcReg =
817 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR( 810 InstX86Base<Machine>::Traits::RegisterSet::getEncodedByteRegOrGPR(
818 Ty, SrcVar->getRegNum()); 811 Ty, SrcVar->getRegNum());
819 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg); 812 (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
820 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) { 813 } else if (const auto Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
821 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue())); 814 (Asm->*(Emitter.GPRImm))(Ty, VarReg, Immediate(Imm->getValue()));
822 } else { 815 } else {
823 llvm_unreachable("Unexpected operand type"); 816 llvm_unreachable("Unexpected operand type");
(...skipping 506 matching lines...) Expand 10 before | Expand all | Expand 10 after
1330 (void)Src0Var; 1323 (void)Src0Var;
1331 assert(Src0Var && 1324 assert(Src0Var &&
1332 Src0Var->getRegNum() == 1325 Src0Var->getRegNum() ==
1333 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax); 1326 InstX86Base<Machine>::Traits::RegisterSet::Reg_eax);
1334 static const typename InstX86Base< 1327 static const typename InstX86Base<
1335 Machine>::Traits::Assembler::GPREmitterOneOp Emitter = { 1328 Machine>::Traits::Assembler::GPREmitterOneOp Emitter = {
1336 &InstX86Base<Machine>::Traits::Assembler::imul, 1329 &InstX86Base<Machine>::Traits::Assembler::imul,
1337 &InstX86Base<Machine>::Traits::Assembler::imul}; 1330 &InstX86Base<Machine>::Traits::Assembler::imul};
1338 emitIASOpTyGPR<Machine>(Func, Ty, this->getSrc(1), Emitter); 1331 emitIASOpTyGPR<Machine>(Func, Ty, this->getSrc(1), Emitter);
1339 } else { 1332 } else {
1340 // We only use imul as a two-address instruction even though 1333 // We only use imul as a two-address instruction even though there is a 3
1341 // there is a 3 operand version when one of the operands is a constant. 1334 // operand version when one of the operands is a constant.
1342 assert(Var == this->getSrc(0)); 1335 assert(Var == this->getSrc(0));
1343 static const typename InstX86Base< 1336 static const typename InstX86Base<
1344 Machine>::Traits::Assembler::GPREmitterRegOp Emitter = { 1337 Machine>::Traits::Assembler::GPREmitterRegOp Emitter = {
1345 &InstX86Base<Machine>::Traits::Assembler::imul, 1338 &InstX86Base<Machine>::Traits::Assembler::imul,
1346 &InstX86Base<Machine>::Traits::Assembler::imul, 1339 &InstX86Base<Machine>::Traits::Assembler::imul,
1347 &InstX86Base<Machine>::Traits::Assembler::imul}; 1340 &InstX86Base<Machine>::Traits::Assembler::imul};
1348 emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter); 1341 emitIASRegOpTyGPR<Machine>(Func, Ty, Var, Src, Emitter);
1349 } 1342 }
1350 } 1343 }
1351 1344
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after
1671 Str << ", "; 1664 Str << ", ";
1672 this->getDest()->emit(Func); 1665 this->getDest()->emit(Func);
1673 } 1666 }
1674 1667
1675 template <class Machine> 1668 template <class Machine>
1676 void InstX86Cmpps<Machine>::emitIAS(const Cfg *Func) const { 1669 void InstX86Cmpps<Machine>::emitIAS(const Cfg *Func) const {
1677 typename InstX86Base<Machine>::Traits::Assembler *Asm = 1670 typename InstX86Base<Machine>::Traits::Assembler *Asm =
1678 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 1671 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
1679 assert(this->getSrcSize() == 2); 1672 assert(this->getSrcSize() == 2);
1680 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid); 1673 assert(Condition < InstX86Base<Machine>::Traits::Cond::Cmpps_Invalid);
1681 // Assuming there isn't any load folding for cmpps, and vector constants 1674 // Assuming there isn't any load folding for cmpps, and vector constants are
1682 // are not allowed in PNaCl. 1675 // not allowed in PNaCl.
1683 assert(llvm::isa<Variable>(this->getSrc(1))); 1676 assert(llvm::isa<Variable>(this->getSrc(1)));
1684 const auto SrcVar = llvm::cast<Variable>(this->getSrc(1)); 1677 const auto SrcVar = llvm::cast<Variable>(this->getSrc(1));
1685 if (SrcVar->hasReg()) { 1678 if (SrcVar->hasReg()) {
1686 Asm->cmpps(InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm( 1679 Asm->cmpps(InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1687 this->getDest()->getRegNum()), 1680 this->getDest()->getRegNum()),
1688 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm( 1681 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
1689 SrcVar->getRegNum()), 1682 SrcVar->getRegNum()),
1690 Condition); 1683 Condition);
1691 } else { 1684 } else {
1692 typename InstX86Base<Machine>::Traits::Address SrcStackAddr = 1685 typename InstX86Base<Machine>::Traits::Address SrcStackAddr =
(...skipping 288 matching lines...) Expand 10 before | Expand all | Expand 10 after
1981 ->getType()] 1974 ->getType()]
1982 .SdSsString << "\t"; 1975 .SdSsString << "\t";
1983 this->getSrc(1)->emit(Func); 1976 this->getSrc(1)->emit(Func);
1984 Str << ", "; 1977 Str << ", ";
1985 this->getSrc(0)->emit(Func); 1978 this->getSrc(0)->emit(Func);
1986 } 1979 }
1987 1980
1988 template <class Machine> 1981 template <class Machine>
1989 void InstX86Ucomiss<Machine>::emitIAS(const Cfg *Func) const { 1982 void InstX86Ucomiss<Machine>::emitIAS(const Cfg *Func) const {
1990 assert(this->getSrcSize() == 2); 1983 assert(this->getSrcSize() == 2);
1991 // Currently src0 is always a variable by convention, to avoid having 1984 // Currently src0 is always a variable by convention, to avoid having two
1992 // two memory operands. 1985 // memory operands.
1993 assert(llvm::isa<Variable>(this->getSrc(0))); 1986 assert(llvm::isa<Variable>(this->getSrc(0)));
1994 const auto Src0Var = llvm::cast<Variable>(this->getSrc(0)); 1987 const auto Src0Var = llvm::cast<Variable>(this->getSrc(0));
1995 Type Ty = Src0Var->getType(); 1988 Type Ty = Src0Var->getType();
1996 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp 1989 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
1997 Emitter = {&InstX86Base<Machine>::Traits::Assembler::ucomiss, 1990 Emitter = {&InstX86Base<Machine>::Traits::Assembler::ucomiss,
1998 &InstX86Base<Machine>::Traits::Assembler::ucomiss}; 1991 &InstX86Base<Machine>::Traits::Assembler::ucomiss};
1999 emitIASRegOpTyXMM<Machine>(Func, Ty, Src0Var, this->getSrc(1), Emitter); 1992 emitIASRegOpTyXMM<Machine>(Func, Ty, Src0Var, this->getSrc(1), Emitter);
2000 } 1993 }
2001 1994
2002 template <class Machine> 1995 template <class Machine>
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
2284 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 && 2277 if (InstX86Base<Machine>::Traits::Is64Bit && DestTy == IceType_i64 &&
2285 isIntegerConstant(Src)) { 2278 isIntegerConstant(Src)) {
2286 Str << "\tmovabs\t"; 2279 Str << "\tmovabs\t";
2287 } else { 2280 } else {
2288 Str << "\tmov" 2281 Str << "\tmov"
2289 << (!isScalarFloatingType(DestTy) 2282 << (!isScalarFloatingType(DestTy)
2290 ? this->getWidthString(SrcTy) 2283 ? this->getWidthString(SrcTy)
2291 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy] 2284 : InstX86Base<Machine>::Traits::TypeAttributes[DestTy]
2292 .SdSsString) << "\t"; 2285 .SdSsString) << "\t";
2293 } 2286 }
2294 // For an integer truncation operation, src is wider than dest. 2287 // For an integer truncation operation, src is wider than dest. Ideally, we
2295 // Ideally, we use a mov instruction whose data width matches the 2288 // use a mov instruction whose data width matches the narrower dest. This is
2296 // narrower dest. This is a problem if e.g. src is a register like 2289 // a problem if e.g. src is a register like esi or si where there is no 8-bit
2297 // esi or si where there is no 8-bit version of the register. To be 2290 // version of the register. To be safe, we instead widen the dest to match
2298 // safe, we instead widen the dest to match src. This works even 2291 // src. This works even for stack-allocated dest variables because
2299 // for stack-allocated dest variables because typeWidthOnStack() 2292 // typeWidthOnStack() pads to a 4-byte boundary even if only a lower portion
2300 // pads to a 4-byte boundary even if only a lower portion is used. 2293 // is used.
2301 // TODO: This assert disallows usages such as copying a floating point 2294 // TODO: This assert disallows usages such as copying a floating
2302 // value between a vector and a scalar (which movss is used for). 2295 // point value between a vector and a scalar (which movss is used for). Clean
2303 // Clean this up. 2296 // this up.
2304 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) == 2297 assert(Func->getTarget()->typeWidthInBytesOnStack(DestTy) ==
2305 Func->getTarget()->typeWidthInBytesOnStack(SrcTy)); 2298 Func->getTarget()->typeWidthInBytesOnStack(SrcTy));
2306 Src->emit(Func); 2299 Src->emit(Func);
2307 Str << ", "; 2300 Str << ", ";
2308 this->getDest()->asType(SrcTy)->emit(Func); 2301 this->getDest()->asType(SrcTy)->emit(Func);
2309 } 2302 }
2310 2303
2311 template <class Machine> 2304 template <class Machine>
2312 void InstX86Mov<Machine>::emitIAS(const Cfg *Func) const { 2305 void InstX86Mov<Machine>::emitIAS(const Cfg *Func) const {
2313 assert(this->getSrcSize() == 1); 2306 assert(this->getSrcSize() == 1);
2314 const Variable *Dest = this->getDest(); 2307 const Variable *Dest = this->getDest();
2315 const Operand *Src = this->getSrc(0); 2308 const Operand *Src = this->getSrc(0);
2316 Type DestTy = Dest->getType(); 2309 Type DestTy = Dest->getType();
2317 Type SrcTy = Src->getType(); 2310 Type SrcTy = Src->getType();
2318 // Mov can be used for GPRs or XMM registers. Also, the type does not 2311 // Mov can be used for GPRs or XMM registers. Also, the type does not
2319 // necessarily match (Mov can be used for bitcasts). However, when 2312 // necessarily match (Mov can be used for bitcasts). However, when the type
2320 // the type does not match, one of the operands must be a register. 2313 // does not match, one of the operands must be a register. Thus, the strategy
2321 // Thus, the strategy is to find out if Src or Dest are a register, 2314 // is to find out if Src or Dest are a register, then use that register's
2322 // then use that register's type to decide on which emitter set to use. 2315 // type to decide on which emitter set to use. The emitter set will include
2323 // The emitter set will include reg-reg movs, but that case should 2316 // reg-reg movs, but that case should be unused when the types don't match.
2324 // be unused when the types don't match.
2325 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp 2317 static const typename InstX86Base<Machine>::Traits::Assembler::XmmEmitterRegOp
2326 XmmRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::movss, 2318 XmmRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::movss,
2327 &InstX86Base<Machine>::Traits::Assembler::movss}; 2319 &InstX86Base<Machine>::Traits::Assembler::movss};
2328 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp 2320 static const typename InstX86Base<Machine>::Traits::Assembler::GPREmitterRegOp
2329 GPRRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::mov, 2321 GPRRegEmitter = {&InstX86Base<Machine>::Traits::Assembler::mov,
2330 &InstX86Base<Machine>::Traits::Assembler::mov, 2322 &InstX86Base<Machine>::Traits::Assembler::mov,
2331 &InstX86Base<Machine>::Traits::Assembler::mov}; 2323 &InstX86Base<Machine>::Traits::Assembler::mov};
2332 static const typename InstX86Base< 2324 static const typename InstX86Base<
2333 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = { 2325 Machine>::Traits::Assembler::GPREmitterAddrOp GPRAddrEmitter = {
2334 &InstX86Base<Machine>::Traits::Assembler::mov, 2326 &InstX86Base<Machine>::Traits::Assembler::mov,
2335 &InstX86Base<Machine>::Traits::Assembler::mov}; 2327 &InstX86Base<Machine>::Traits::Assembler::mov};
2336 // For an integer truncation operation, src is wider than dest. 2328 // For an integer truncation operation, src is wider than dest. Ideally, we
2337 // Ideally, we use a mov instruction whose data width matches the 2329 // use a mov instruction whose data width matches the narrower dest. This is
2338 // narrower dest. This is a problem if e.g. src is a register like 2330 // a problem if e.g. src is a register like esi or si where there is no 8-bit
2339 // esi or si where there is no 8-bit version of the register. To be 2331 // version of the register. To be safe, we instead widen the dest to match
2340 // safe, we instead widen the dest to match src. This works even 2332 // src. This works even for stack-allocated dest variables because
2341 // for stack-allocated dest variables because typeWidthOnStack() 2333 // typeWidthOnStack() pads to a 4-byte boundary even if only a lower portion
2342 // pads to a 4-byte boundary even if only a lower portion is used. 2334 // is used.
2343 // TODO: This assert disallows usages such as copying a floating point 2335 // TODO: This assert disallows usages such as copying a floating
2344 // value between a vector and a scalar (which movss is used for). 2336 // point value between a vector and a scalar (which movss is used for). Clean
2345 // Clean this up. 2337 // this up.
2346 assert( 2338 assert(
2347 Func->getTarget()->typeWidthInBytesOnStack(this->getDest()->getType()) == 2339 Func->getTarget()->typeWidthInBytesOnStack(this->getDest()->getType()) ==
2348 Func->getTarget()->typeWidthInBytesOnStack(Src->getType())); 2340 Func->getTarget()->typeWidthInBytesOnStack(Src->getType()));
2349 if (Dest->hasReg()) { 2341 if (Dest->hasReg()) {
2350 if (isScalarFloatingType(DestTy)) { 2342 if (isScalarFloatingType(DestTy)) {
2351 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter); 2343 emitIASRegOpTyXMM<Machine>(Func, DestTy, Dest, Src, XmmRegEmitter);
2352 return; 2344 return;
2353 } else { 2345 } else {
2354 assert(isScalarIntegerType(DestTy)); 2346 assert(isScalarIntegerType(DestTy));
2355 // Widen DestTy for truncation (see above note). We should only do this 2347 // Widen DestTy for truncation (see above note). We should only do this
(...skipping 12 matching lines...) Expand all
2368 Value); 2360 Value);
2369 return; 2361 return;
2370 } 2362 }
2371 if (isScalarIntegerType(SrcTy)) { 2363 if (isScalarIntegerType(SrcTy)) {
2372 DestTy = SrcTy; 2364 DestTy = SrcTy;
2373 } 2365 }
2374 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter); 2366 emitIASRegOpTyGPR<Machine>(Func, DestTy, Dest, Src, GPRRegEmitter);
2375 return; 2367 return;
2376 } 2368 }
2377 } else { 2369 } else {
2378 // Dest must be Stack and Src *could* be a register. Use Src's type 2370 // Dest must be Stack and Src *could* be a register. Use Src's type to
2379 // to decide on the emitters. 2371 // decide on the emitters.
2380 typename InstX86Base<Machine>::Traits::Address StackAddr( 2372 typename InstX86Base<Machine>::Traits::Address StackAddr(
2381 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>( 2373 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2382 Func->getTarget()) 2374 Func->getTarget())
2383 ->stackVarToAsmOperand(Dest)); 2375 ->stackVarToAsmOperand(Dest));
2384 if (isScalarFloatingType(SrcTy)) { 2376 if (isScalarFloatingType(SrcTy)) {
2385 // Src must be a register. 2377 // Src must be a register.
2386 const auto SrcVar = llvm::cast<Variable>(Src); 2378 const auto SrcVar = llvm::cast<Variable>(Src);
2387 assert(SrcVar->hasReg()); 2379 assert(SrcVar->hasReg());
2388 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2380 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2389 Func->getAssembler< 2381 Func->getAssembler<
(...skipping 12 matching lines...) Expand all
2402 } 2394 }
2403 } 2395 }
2404 2396
2405 template <class Machine> 2397 template <class Machine>
2406 void InstX86Movd<Machine>::emitIAS(const Cfg *Func) const { 2398 void InstX86Movd<Machine>::emitIAS(const Cfg *Func) const {
2407 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2399 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2408 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 2400 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2409 assert(this->getSrcSize() == 1); 2401 assert(this->getSrcSize() == 1);
2410 const Variable *Dest = this->getDest(); 2402 const Variable *Dest = this->getDest();
2411 const auto SrcVar = llvm::cast<Variable>(this->getSrc(0)); 2403 const auto SrcVar = llvm::cast<Variable>(this->getSrc(0));
2412 // For insert/extract element (one of Src/Dest is an Xmm vector and 2404 // For insert/extract element (one of Src/Dest is an Xmm vector and the other
2413 // the other is an int type). 2405 // is an int type).
2414 if (SrcVar->getType() == IceType_i32 || 2406 if (SrcVar->getType() == IceType_i32 ||
2415 (InstX86Base<Machine>::Traits::Is64Bit && 2407 (InstX86Base<Machine>::Traits::Is64Bit &&
2416 SrcVar->getType() == IceType_i64)) { 2408 SrcVar->getType() == IceType_i64)) {
2417 assert(isVectorType(Dest->getType()) || 2409 assert(isVectorType(Dest->getType()) ||
2418 (isScalarFloatingType(Dest->getType()) && 2410 (isScalarFloatingType(Dest->getType()) &&
2419 typeWidthInBytes(SrcVar->getType()) == 2411 typeWidthInBytes(SrcVar->getType()) ==
2420 typeWidthInBytes(Dest->getType()))); 2412 typeWidthInBytes(Dest->getType())));
2421 assert(Dest->hasReg()); 2413 assert(Dest->hasReg());
2422 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg = 2414 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister DestReg =
2423 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm( 2415 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2457 ->stackVarToAsmOperand(Dest)); 2449 ->stackVarToAsmOperand(Dest));
2458 Asm->movd(Dest->getType(), StackAddr, SrcReg); 2450 Asm->movd(Dest->getType(), StackAddr, SrcReg);
2459 } 2451 }
2460 } 2452 }
2461 } 2453 }
2462 2454
2463 template <class Machine> 2455 template <class Machine>
2464 void InstX86Movp<Machine>::emit(const Cfg *Func) const { 2456 void InstX86Movp<Machine>::emit(const Cfg *Func) const {
2465 if (!BuildDefs::dump()) 2457 if (!BuildDefs::dump())
2466 return; 2458 return;
2467 // TODO(wala,stichnot): movups works with all vector operands, but 2459 // TODO(wala,stichnot): movups works with all vector operands, but there
2468 // there exist other instructions (movaps, movdqa, movdqu) that may 2460 // exist other instructions (movaps, movdqa, movdqu) that may perform better,
2469 // perform better, depending on the data type and alignment of the 2461 // depending on the data type and alignment of the operands.
2470 // operands.
2471 Ostream &Str = Func->getContext()->getStrEmit(); 2462 Ostream &Str = Func->getContext()->getStrEmit();
2472 assert(this->getSrcSize() == 1); 2463 assert(this->getSrcSize() == 1);
2473 Str << "\tmovups\t"; 2464 Str << "\tmovups\t";
2474 this->getSrc(0)->emit(Func); 2465 this->getSrc(0)->emit(Func);
2475 Str << ", "; 2466 Str << ", ";
2476 this->getDest()->emit(Func); 2467 this->getDest()->emit(Func);
2477 } 2468 }
2478 2469
2479 template <class Machine> 2470 template <class Machine>
2480 void InstX86Movp<Machine>::emitIAS(const Cfg *Func) const { 2471 void InstX86Movp<Machine>::emitIAS(const Cfg *Func) const {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
2514 static const typename InstX86Base< 2505 static const typename InstX86Base<
2515 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = { 2506 Machine>::Traits::Assembler::XmmEmitterMovOps Emitter = {
2516 &InstX86Base<Machine>::Traits::Assembler::movq, 2507 &InstX86Base<Machine>::Traits::Assembler::movq,
2517 &InstX86Base<Machine>::Traits::Assembler::movq, 2508 &InstX86Base<Machine>::Traits::Assembler::movq,
2518 &InstX86Base<Machine>::Traits::Assembler::movq}; 2509 &InstX86Base<Machine>::Traits::Assembler::movq};
2519 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter); 2510 emitIASMovlikeXMM<Machine>(Func, Dest, Src, Emitter);
2520 } 2511 }
2521 2512
2522 template <class Machine> 2513 template <class Machine>
2523 void InstX86MovssRegs<Machine>::emitIAS(const Cfg *Func) const { 2514 void InstX86MovssRegs<Machine>::emitIAS(const Cfg *Func) const {
2524 // This is Binop variant is only intended to be used for reg-reg moves 2515 // This is Binop variant is only intended to be used for reg-reg moves where
2525 // where part of the Dest register is untouched. 2516 // part of the Dest register is untouched.
2526 assert(this->getSrcSize() == 2); 2517 assert(this->getSrcSize() == 2);
2527 const Variable *Dest = this->getDest(); 2518 const Variable *Dest = this->getDest();
2528 assert(Dest == this->getSrc(0)); 2519 assert(Dest == this->getSrc(0));
2529 const auto SrcVar = llvm::cast<Variable>(this->getSrc(1)); 2520 const auto SrcVar = llvm::cast<Variable>(this->getSrc(1));
2530 assert(Dest->hasReg() && SrcVar->hasReg()); 2521 assert(Dest->hasReg() && SrcVar->hasReg());
2531 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2522 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2532 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 2523 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2533 Asm->movss(IceType_f32, 2524 Asm->movss(IceType_f32,
2534 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm( 2525 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2535 Dest->getRegNum()), 2526 Dest->getRegNum()),
2536 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm( 2527 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2537 SrcVar->getRegNum())); 2528 SrcVar->getRegNum()));
2538 } 2529 }
2539 2530
2540 template <class Machine> 2531 template <class Machine>
2541 void InstX86Movsx<Machine>::emitIAS(const Cfg *Func) const { 2532 void InstX86Movsx<Machine>::emitIAS(const Cfg *Func) const {
2542 assert(this->getSrcSize() == 1); 2533 assert(this->getSrcSize() == 1);
2543 const Variable *Dest = this->getDest(); 2534 const Variable *Dest = this->getDest();
2544 const Operand *Src = this->getSrc(0); 2535 const Operand *Src = this->getSrc(0);
2545 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice 2536 // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
2546 // we just use the full register for Dest to avoid having an 2537 // use the full register for Dest to avoid having an OperandSizeOverride
2547 // OperandSizeOverride prefix. It also allows us to only dispatch on SrcTy. 2538 // prefix. It also allows us to only dispatch on SrcTy.
2548 Type SrcTy = Src->getType(); 2539 Type SrcTy = Src->getType();
2549 assert(typeWidthInBytes(Dest->getType()) > 1); 2540 assert(typeWidthInBytes(Dest->getType()) > 1);
2550 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy)); 2541 assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
2551 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src, 2542 emitIASRegOpTyGPR<Machine, false, true>(Func, SrcTy, Dest, Src,
2552 this->Emitter); 2543 this->Emitter);
2553 } 2544 }
2554 2545
2555 template <class Machine> 2546 template <class Machine>
2556 void InstX86Movzx<Machine>::emitIAS(const Cfg *Func) const { 2547 void InstX86Movzx<Machine>::emitIAS(const Cfg *Func) const {
2557 assert(this->getSrcSize() == 1); 2548 assert(this->getSrcSize() == 1);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
2589 2580
2590 template <class Machine> void InstX86Fld<Machine>::emit(const Cfg *Func) const { 2581 template <class Machine> void InstX86Fld<Machine>::emit(const Cfg *Func) const {
2591 if (!BuildDefs::dump()) 2582 if (!BuildDefs::dump())
2592 return; 2583 return;
2593 Ostream &Str = Func->getContext()->getStrEmit(); 2584 Ostream &Str = Func->getContext()->getStrEmit();
2594 assert(this->getSrcSize() == 1); 2585 assert(this->getSrcSize() == 1);
2595 Type Ty = this->getSrc(0)->getType(); 2586 Type Ty = this->getSrc(0)->getType();
2596 SizeT Width = typeWidthInBytes(Ty); 2587 SizeT Width = typeWidthInBytes(Ty);
2597 const auto Var = llvm::dyn_cast<Variable>(this->getSrc(0)); 2588 const auto Var = llvm::dyn_cast<Variable>(this->getSrc(0));
2598 if (Var && Var->hasReg()) { 2589 if (Var && Var->hasReg()) {
2599 // This is a physical xmm register, so we need to spill it to a 2590 // This is a physical xmm register, so we need to spill it to a temporary
2600 // temporary stack slot. 2591 // stack slot.
2601 Str << "\tsubl\t$" << Width << ", %esp" 2592 Str << "\tsubl\t$" << Width << ", %esp"
2602 << "\n"; 2593 << "\n";
2603 Str << "\tmov" 2594 Str << "\tmov"
2604 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t"; 2595 << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString << "\t";
2605 Var->emit(Func); 2596 Var->emit(Func);
2606 Str << ", (%esp)\n"; 2597 Str << ", (%esp)\n";
2607 Str << "\tfld" << this->getFldString(Ty) << "\t" 2598 Str << "\tfld" << this->getFldString(Ty) << "\t"
2608 << "(%esp)\n"; 2599 << "(%esp)\n";
2609 Str << "\taddl\t$" << Width << ", %esp"; 2600 Str << "\taddl\t$" << Width << ", %esp";
2610 return; 2601 return;
2611 } 2602 }
2612 Str << "\tfld" << this->getFldString(Ty) << "\t"; 2603 Str << "\tfld" << this->getFldString(Ty) << "\t";
2613 this->getSrc(0)->emit(Func); 2604 this->getSrc(0)->emit(Func);
2614 } 2605 }
2615 2606
2616 template <class Machine> 2607 template <class Machine>
2617 void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const { 2608 void InstX86Fld<Machine>::emitIAS(const Cfg *Func) const {
2618 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2609 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2619 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 2610 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2620 assert(this->getSrcSize() == 1); 2611 assert(this->getSrcSize() == 1);
2621 const Operand *Src = this->getSrc(0); 2612 const Operand *Src = this->getSrc(0);
2622 Type Ty = Src->getType(); 2613 Type Ty = Src->getType();
2623 if (const auto Var = llvm::dyn_cast<Variable>(Src)) { 2614 if (const auto Var = llvm::dyn_cast<Variable>(Src)) {
2624 if (Var->hasReg()) { 2615 if (Var->hasReg()) {
2625 // This is a physical xmm register, so we need to spill it to a 2616 // This is a physical xmm register, so we need to spill it to a temporary
2626 // temporary stack slot. 2617 // stack slot.
2627 Immediate Width(typeWidthInBytes(Ty)); 2618 Immediate Width(typeWidthInBytes(Ty));
2628 Asm->sub(IceType_i32, 2619 Asm->sub(IceType_i32,
2629 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 2620 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp,
2630 Width); 2621 Width);
2631 typename InstX86Base<Machine>::Traits::Address StackSlot = 2622 typename InstX86Base<Machine>::Traits::Address StackSlot =
2632 typename InstX86Base<Machine>::Traits::Address( 2623 typename InstX86Base<Machine>::Traits::Address(
2633 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0); 2624 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0);
2634 Asm->movss(Ty, StackSlot, 2625 Asm->movss(Ty, StackSlot,
2635 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm( 2626 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2636 Var->getRegNum())); 2627 Var->getRegNum()));
(...skipping 28 matching lines...) Expand all
2665 this->dumpSources(Func); 2656 this->dumpSources(Func);
2666 } 2657 }
2667 2658
2668 template <class Machine> 2659 template <class Machine>
2669 void InstX86Fstp<Machine>::emit(const Cfg *Func) const { 2660 void InstX86Fstp<Machine>::emit(const Cfg *Func) const {
2670 if (!BuildDefs::dump()) 2661 if (!BuildDefs::dump())
2671 return; 2662 return;
2672 Ostream &Str = Func->getContext()->getStrEmit(); 2663 Ostream &Str = Func->getContext()->getStrEmit();
2673 assert(this->getSrcSize() == 0); 2664 assert(this->getSrcSize() == 0);
2674 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to 2665 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2675 // "partially" delete the fstp if the Dest is unused. 2666 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2676 // Even if Dest is unused, the fstp should be kept for the SideEffects 2667 // the fstp should be kept for the SideEffects of popping the stack.
2677 // of popping the stack.
2678 if (!this->getDest()) { 2668 if (!this->getDest()) {
2679 Str << "\tfstp\tst(0)"; 2669 Str << "\tfstp\tst(0)";
2680 return; 2670 return;
2681 } 2671 }
2682 Type Ty = this->getDest()->getType(); 2672 Type Ty = this->getDest()->getType();
2683 size_t Width = typeWidthInBytes(Ty); 2673 size_t Width = typeWidthInBytes(Ty);
2684 if (!this->getDest()->hasReg()) { 2674 if (!this->getDest()->hasReg()) {
2685 Str << "\tfstp" << this->getFldString(Ty) << "\t"; 2675 Str << "\tfstp" << this->getFldString(Ty) << "\t";
2686 this->getDest()->emit(Func); 2676 this->getDest()->emit(Func);
2687 return; 2677 return;
2688 } 2678 }
2689 // Dest is a physical (xmm) register, so st(0) needs to go through 2679 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
2690 // memory. Hack this by creating a temporary stack slot, spilling 2680 // Hack this by creating a temporary stack slot, spilling st(0) there,
2691 // st(0) there, loading it into the xmm register, and deallocating 2681 // loading it into the xmm register, and deallocating the stack slot.
2692 // the stack slot.
2693 Str << "\tsubl\t$" << Width << ", %esp\n"; 2682 Str << "\tsubl\t$" << Width << ", %esp\n";
2694 Str << "\tfstp" << this->getFldString(Ty) << "\t" 2683 Str << "\tfstp" << this->getFldString(Ty) << "\t"
2695 << "(%esp)\n"; 2684 << "(%esp)\n";
2696 Str << "\tmov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString 2685 Str << "\tmov" << InstX86Base<Machine>::Traits::TypeAttributes[Ty].SdSsString
2697 << "\t" 2686 << "\t"
2698 << "(%esp), "; 2687 << "(%esp), ";
2699 this->getDest()->emit(Func); 2688 this->getDest()->emit(Func);
2700 Str << "\n"; 2689 Str << "\n";
2701 Str << "\taddl\t$" << Width << ", %esp"; 2690 Str << "\taddl\t$" << Width << ", %esp";
2702 } 2691 }
2703 2692
2704 template <class Machine> 2693 template <class Machine>
2705 void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const { 2694 void InstX86Fstp<Machine>::emitIAS(const Cfg *Func) const {
2706 typename InstX86Base<Machine>::Traits::Assembler *Asm = 2695 typename InstX86Base<Machine>::Traits::Assembler *Asm =
2707 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>(); 2696 Func->getAssembler<typename InstX86Base<Machine>::Traits::Assembler>();
2708 assert(this->getSrcSize() == 0); 2697 assert(this->getSrcSize() == 0);
2709 const Variable *Dest = this->getDest(); 2698 const Variable *Dest = this->getDest();
2710 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to 2699 // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
2711 // "partially" delete the fstp if the Dest is unused. 2700 // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
2712 // Even if Dest is unused, the fstp should be kept for the SideEffects 2701 // the fstp should be kept for the SideEffects of popping the stack.
2713 // of popping the stack.
2714 if (!Dest) { 2702 if (!Dest) {
2715 Asm->fstp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedSTReg(0)); 2703 Asm->fstp(InstX86Base<Machine>::Traits::RegisterSet::getEncodedSTReg(0));
2716 return; 2704 return;
2717 } 2705 }
2718 Type Ty = Dest->getType(); 2706 Type Ty = Dest->getType();
2719 if (!Dest->hasReg()) { 2707 if (!Dest->hasReg()) {
2720 typename InstX86Base<Machine>::Traits::Address StackAddr( 2708 typename InstX86Base<Machine>::Traits::Address StackAddr(
2721 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>( 2709 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2722 Func->getTarget()) 2710 Func->getTarget())
2723 ->stackVarToAsmOperand(Dest)); 2711 ->stackVarToAsmOperand(Dest));
2724 Asm->fstp(Ty, StackAddr); 2712 Asm->fstp(Ty, StackAddr);
2725 } else { 2713 } else {
2726 // Dest is a physical (xmm) register, so st(0) needs to go through 2714 // Dest is a physical (xmm) register, so st(0) needs to go through memory.
2727 // memory. Hack this by creating a temporary stack slot, spilling 2715 // Hack this by creating a temporary stack slot, spilling st(0) there,
2728 // st(0) there, loading it into the xmm register, and deallocating 2716 // loading it into the xmm register, and deallocating the stack slot.
2729 // the stack slot.
2730 Immediate Width(typeWidthInBytes(Ty)); 2717 Immediate Width(typeWidthInBytes(Ty));
2731 Asm->sub(IceType_i32, 2718 Asm->sub(IceType_i32,
2732 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width); 2719 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, Width);
2733 typename InstX86Base<Machine>::Traits::Address StackSlot = 2720 typename InstX86Base<Machine>::Traits::Address StackSlot =
2734 typename InstX86Base<Machine>::Traits::Address( 2721 typename InstX86Base<Machine>::Traits::Address(
2735 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0); 2722 InstX86Base<Machine>::Traits::RegisterSet::Encoded_Reg_esp, 0);
2736 Asm->fstp(Ty, StackSlot); 2723 Asm->fstp(Ty, StackSlot);
2737 Asm->movss(Ty, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm( 2724 Asm->movss(Ty, InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm(
2738 Dest->getRegNum()), 2725 Dest->getRegNum()),
2739 StackSlot); 2726 StackSlot);
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2789 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1); 2776 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2790 Str << "\t" << this->Opcode 2777 Str << "\t" << this->Opcode
2791 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0) 2778 << InstX86Base<Machine>::Traits::TypeAttributes[this->getSrc(0)
2792 ->getType()] 2779 ->getType()]
2793 .PackString << "\t"; 2780 .PackString << "\t";
2794 this->getSrc(1)->emit(Func); 2781 this->getSrc(1)->emit(Func);
2795 Str << ", "; 2782 Str << ", ";
2796 this->getSrc(0)->emit(Func); 2783 this->getSrc(0)->emit(Func);
2797 Str << ", "; 2784 Str << ", ";
2798 Variable *Dest = this->getDest(); 2785 Variable *Dest = this->getDest();
2799 // pextrw must take a register dest. There is an SSE4.1 version that takes 2786 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2800 // a memory dest, but we aren't using it. For uniformity, just restrict 2787 // memory dest, but we aren't using it. For uniformity, just restrict them
2801 // them all to have a register dest for now. 2788 // all to have a register dest for now.
2802 assert(Dest->hasReg()); 2789 assert(Dest->hasReg());
2803 Dest->asType(IceType_i32)->emit(Func); 2790 Dest->asType(IceType_i32)->emit(Func);
2804 } 2791 }
2805 2792
2806 template <class Machine> 2793 template <class Machine>
2807 void InstX86Pextr<Machine>::emitIAS(const Cfg *Func) const { 2794 void InstX86Pextr<Machine>::emitIAS(const Cfg *Func) const {
2808 assert(this->getSrcSize() == 2); 2795 assert(this->getSrcSize() == 2);
2809 // pextrb and pextrd are SSE4.1 instructions. 2796 // pextrb and pextrd are SSE4.1 instructions.
2810 const Variable *Dest = this->getDest(); 2797 const Variable *Dest = this->getDest();
2811 Type DispatchTy = Dest->getType(); 2798 Type DispatchTy = Dest->getType();
2812 assert(DispatchTy == IceType_i16 || 2799 assert(DispatchTy == IceType_i16 ||
2813 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>( 2800 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2814 Func->getTarget()) 2801 Func->getTarget())
2815 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1); 2802 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2816 // pextrw must take a register dest. There is an SSE4.1 version that takes 2803 // pextrw must take a register dest. There is an SSE4.1 version that takes a
2817 // a memory dest, but we aren't using it. For uniformity, just restrict 2804 // memory dest, but we aren't using it. For uniformity, just restrict them
2818 // them all to have a register dest for now. 2805 // all to have a register dest for now.
2819 assert(Dest->hasReg()); 2806 assert(Dest->hasReg());
2820 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2). 2807 // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
2821 assert(llvm::cast<Variable>(this->getSrc(0))->hasReg()); 2808 assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
2822 static const typename InstX86Base<Machine>::Traits::Assembler:: 2809 static const typename InstX86Base<Machine>::Traits::Assembler::
2823 template ThreeOpImmEmitter< 2810 template ThreeOpImmEmitter<
2824 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister, 2811 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2825 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister> 2812 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister>
2826 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pextr, nullptr}; 2813 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pextr, nullptr};
2827 emitIASThreeOpImmOps< 2814 emitIASThreeOpImmOps<
2828 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister, 2815 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
2869 void InstX86Pinsr<Machine>::emitIAS(const Cfg *Func) const { 2856 void InstX86Pinsr<Machine>::emitIAS(const Cfg *Func) const {
2870 assert(this->getSrcSize() == 3); 2857 assert(this->getSrcSize() == 3);
2871 assert(this->getDest() == this->getSrc(0)); 2858 assert(this->getDest() == this->getSrc(0));
2872 // pinsrb and pinsrd are SSE4.1 instructions. 2859 // pinsrb and pinsrd are SSE4.1 instructions.
2873 const Operand *Src0 = this->getSrc(1); 2860 const Operand *Src0 = this->getSrc(1);
2874 Type DispatchTy = Src0->getType(); 2861 Type DispatchTy = Src0->getType();
2875 assert(DispatchTy == IceType_i16 || 2862 assert(DispatchTy == IceType_i16 ||
2876 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>( 2863 static_cast<typename InstX86Base<Machine>::Traits::TargetLowering *>(
2877 Func->getTarget()) 2864 Func->getTarget())
2878 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1); 2865 ->getInstructionSet() >= InstX86Base<Machine>::Traits::SSE4_1);
2879 // If src1 is a register, it should always be r32 (this should fall out 2866 // If src1 is a register, it should always be r32 (this should fall out from
2880 // from the encodings for ByteRegs overlapping the encodings for r32), 2867 // the encodings for ByteRegs overlapping the encodings for r32), but we have
2881 // but we have to trust the regalloc to not choose "ah", where it 2868 // to trust the regalloc to not choose "ah", where it doesn't overlap.
2882 // doesn't overlap.
2883 static const typename InstX86Base<Machine>::Traits::Assembler:: 2869 static const typename InstX86Base<Machine>::Traits::Assembler::
2884 template ThreeOpImmEmitter< 2870 template ThreeOpImmEmitter<
2885 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister, 2871 typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2886 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister> 2872 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister>
2887 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pinsr, 2873 Emitter = {&InstX86Base<Machine>::Traits::Assembler::pinsr,
2888 &InstX86Base<Machine>::Traits::Assembler::pinsr}; 2874 &InstX86Base<Machine>::Traits::Assembler::pinsr};
2889 emitIASThreeOpImmOps< 2875 emitIASThreeOpImmOps<
2890 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister, 2876 Machine, typename InstX86Base<Machine>::Traits::RegisterSet::XmmRegister,
2891 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister, 2877 typename InstX86Base<Machine>::Traits::RegisterSet::GPRRegister,
2892 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm, 2878 InstX86Base<Machine>::Traits::RegisterSet::getEncodedXmm,
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after
3287 return; 3273 return;
3288 Ostream &Str = Func->getContext()->getStrDump(); 3274 Ostream &Str = Func->getContext()->getStrDump();
3289 Str << "IACA_END"; 3275 Str << "IACA_END";
3290 } 3276 }
3291 3277
3292 } // end of namespace X86Internal 3278 } // end of namespace X86Internal
3293 3279
3294 } // end of namespace Ice 3280 } // end of namespace Ice
3295 3281
3296 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H 3282 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H
OLDNEW
« no previous file with comments | « src/IceInstX86Base.h ('k') | src/IceIntrinsics.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698