Home | History | Annotate | Download | only in src
      1 //===- subzero/src/IceInstX86BaseImpl.h - Generic X86 instructions -*- C++ -*=//
      2 //
      3 //                        The Subzero Code Generator
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 ///
     10 /// \file
     11 /// \brief Implements the InstX86Base class and its descendants.
     12 ///
     13 //===----------------------------------------------------------------------===//
     14 
     15 #ifndef SUBZERO_SRC_ICEINSTX86BASEIMPL_H
     16 #define SUBZERO_SRC_ICEINSTX86BASEIMPL_H
     17 
     18 #include "IceInstX86Base.h"
     19 
     20 #include "IceAssemblerX86Base.h"
     21 #include "IceCfg.h"
     22 #include "IceCfgNode.h"
     23 #include "IceDefs.h"
     24 #include "IceInst.h"
     25 #include "IceOperand.h"
     26 #include "IceTargetLowering.h"
     27 #include "IceTargetLoweringX86Base.h"
     28 
     29 namespace Ice {
     30 
     31 namespace X86NAMESPACE {
     32 
     33 template <typename TraitsType>
     34 const char *InstImpl<TraitsType>::InstX86Base::getWidthString(Type Ty) {
     35   return Traits::TypeAttributes[Ty].WidthString;
     36 }
     37 
     38 template <typename TraitsType>
     39 const char *InstImpl<TraitsType>::InstX86Base::getFldString(Type Ty) {
     40   return Traits::TypeAttributes[Ty].FldString;
     41 }
     42 
     43 template <typename TraitsType>
     44 typename InstImpl<TraitsType>::Cond::BrCond
     45 InstImpl<TraitsType>::InstX86Base::getOppositeCondition(BrCond Cond) {
     46   return Traits::InstBrAttributes[Cond].Opposite;
     47 }
     48 
     49 template <typename TraitsType>
     50 InstImpl<TraitsType>::InstX86FakeRMW::InstX86FakeRMW(Cfg *Func, Operand *Data,
     51                                                      Operand *Addr,
     52                                                      InstArithmetic::OpKind Op,
     53                                                      Variable *Beacon)
     54     : InstX86Base(Func, InstX86Base::FakeRMW, 3, nullptr), Op(Op) {
     55   this->addSource(Data);
     56   this->addSource(Addr);
     57   this->addSource(Beacon);
     58 }
     59 
     60 template <typename TraitsType>
     61 InstImpl<TraitsType>::InstX86GetIP::InstX86GetIP(Cfg *Func, Variable *Dest)
     62     : InstX86Base(Func, InstX86Base::GetIP, 0, Dest) {}
     63 
     64 template <typename TraitsType>
     65 InstImpl<TraitsType>::InstX86Mul::InstX86Mul(Cfg *Func, Variable *Dest,
     66                                              Variable *Source1,
     67                                              Operand *Source2)
     68     : InstX86Base(Func, InstX86Base::Mul, 2, Dest) {
     69   this->addSource(Source1);
     70   this->addSource(Source2);
     71 }
     72 
     73 template <typename TraitsType>
     74 InstImpl<TraitsType>::InstX86Shld::InstX86Shld(Cfg *Func, Variable *Dest,
     75                                                Variable *Source1,
     76                                                Operand *Source2)
     77     : InstX86Base(Func, InstX86Base::Shld, 3, Dest) {
     78   this->addSource(Dest);
     79   this->addSource(Source1);
     80   this->addSource(Source2);
     81 }
     82 
     83 template <typename TraitsType>
     84 InstImpl<TraitsType>::InstX86Shrd::InstX86Shrd(Cfg *Func, Variable *Dest,
     85                                                Variable *Source1,
     86                                                Operand *Source2)
     87     : InstX86Base(Func, InstX86Base::Shrd, 3, Dest) {
     88   this->addSource(Dest);
     89   this->addSource(Source1);
     90   this->addSource(Source2);
     91 }
     92 
     93 template <typename TraitsType>
     94 InstImpl<TraitsType>::InstX86Label::InstX86Label(Cfg *Func,
     95                                                  TargetLowering *Target)
     96     : InstX86Base(Func, InstX86Base::Label, 0, nullptr),
     97       LabelNumber(Target->makeNextLabelNumber()) {
     98   if (BuildDefs::dump()) {
     99     Name = GlobalString::createWithString(
    100         Func->getContext(), ".L" + Func->getFunctionName() + "$local$__" +
    101                                 std::to_string(LabelNumber));
    102   } else {
    103     Name = GlobalString::createWithoutString(Func->getContext());
    104   }
    105 }
    106 
    107 template <typename TraitsType>
    108 InstImpl<TraitsType>::InstX86Br::InstX86Br(Cfg *Func, const CfgNode *TargetTrue,
    109                                            const CfgNode *TargetFalse,
    110                                            const InstX86Label *Label,
    111                                            BrCond Condition, Mode Kind)
    112     : InstX86Base(Func, InstX86Base::Br, 0, nullptr), Condition(Condition),
    113       TargetTrue(TargetTrue), TargetFalse(TargetFalse), Label(Label),
    114       Kind(Kind) {}
    115 
    116 template <typename TraitsType>
    117 bool InstImpl<TraitsType>::InstX86Br::optimizeBranch(const CfgNode *NextNode) {
    118   // If there is no next block, then there can be no fallthrough to optimize.
    119   if (NextNode == nullptr)
    120     return false;
    121   // Intra-block conditional branches can't be optimized.
    122   if (Label)
    123     return false;
    124   // If there is no fallthrough node, such as a non-default case label for a
    125   // switch instruction, then there is no opportunity to optimize.
    126   if (getTargetFalse() == nullptr)
    127     return false;
    128 
    129   // Unconditional branch to the next node can be removed.
    130   if (Condition == Cond::Br_None && getTargetFalse() == NextNode) {
    131     assert(getTargetTrue() == nullptr);
    132     this->setDeleted();
    133     return true;
    134   }
    135   // If the fallthrough is to the next node, set fallthrough to nullptr to
    136   // indicate.
    137   if (getTargetFalse() == NextNode) {
    138     TargetFalse = nullptr;
    139     return true;
    140   }
    141   // If TargetTrue is the next node, and TargetFalse is not nullptr (which was
    142   // already tested above), then invert the branch condition, swap the targets,
    143   // and set new fallthrough to nullptr.
    144   if (getTargetTrue() == NextNode) {
    145     assert(Condition != Cond::Br_None);
    146     Condition = this->getOppositeCondition(Condition);
    147     TargetTrue = getTargetFalse();
    148     TargetFalse = nullptr;
    149     return true;
    150   }
    151   return false;
    152 }
    153 
    154 template <typename TraitsType>
    155 bool InstImpl<TraitsType>::InstX86Br::repointEdges(CfgNode *OldNode,
    156                                                    CfgNode *NewNode) {
    157   bool Found = false;
    158   if (TargetFalse == OldNode) {
    159     TargetFalse = NewNode;
    160     Found = true;
    161   }
    162   if (TargetTrue == OldNode) {
    163     TargetTrue = NewNode;
    164     Found = true;
    165   }
    166   return Found;
    167 }
    168 
    169 template <typename TraitsType>
    170 InstImpl<TraitsType>::InstX86Jmp::InstX86Jmp(Cfg *Func, Operand *Target)
    171     : InstX86Base(Func, InstX86Base::Jmp, 1, nullptr) {
    172   this->addSource(Target);
    173 }
    174 
    175 template <typename TraitsType>
    176 InstImpl<TraitsType>::InstX86Call::InstX86Call(Cfg *Func, Variable *Dest,
    177                                                Operand *CallTarget)
    178     : InstX86Base(Func, InstX86Base::Call, 1, Dest) {
    179   this->HasSideEffects = true;
    180   this->addSource(CallTarget);
    181 }
    182 
    183 template <typename TraitsType>
    184 InstImpl<TraitsType>::InstX86Movmsk::InstX86Movmsk(Cfg *Func, Variable *Dest,
    185                                                    Operand *Source)
    186     : InstX86Base(Func, InstX86Base::Movmsk, 1, Dest) {
    187   this->addSource(Source);
    188 }
    189 
    190 template <typename TraitsType>
    191 InstImpl<TraitsType>::InstX86Cmov::InstX86Cmov(Cfg *Func, Variable *Dest,
    192                                                Operand *Source,
    193                                                BrCond Condition)
    194     : InstX86Base(Func, InstX86Base::Cmov, 2, Dest), Condition(Condition) {
    195   // The final result is either the original Dest, or Source, so mark both as
    196   // sources.
    197   this->addSource(Dest);
    198   this->addSource(Source);
    199 }
    200 
    201 template <typename TraitsType>
    202 InstImpl<TraitsType>::InstX86Cmpps::InstX86Cmpps(Cfg *Func, Variable *Dest,
    203                                                  Operand *Source,
    204                                                  CmppsCond Condition)
    205     : InstX86Base(Func, InstX86Base::Cmpps, 2, Dest), Condition(Condition) {
    206   this->addSource(Dest);
    207   this->addSource(Source);
    208 }
    209 
    210 template <typename TraitsType>
    211 InstImpl<TraitsType>::InstX86Cmpxchg::InstX86Cmpxchg(Cfg *Func,
    212                                                      Operand *DestOrAddr,
    213                                                      Variable *Eax,
    214                                                      Variable *Desired,
    215                                                      bool Locked)
    216     : InstImpl<TraitsType>::InstX86BaseLockable(
    217           Func, InstX86Base::Cmpxchg, 3, llvm::dyn_cast<Variable>(DestOrAddr),
    218           Locked) {
    219   constexpr uint16_t Encoded_rAX = 0;
    220   (void)Encoded_rAX;
    221   assert(Traits::getEncodedGPR(Eax->getRegNum()) == Encoded_rAX);
    222   this->addSource(DestOrAddr);
    223   this->addSource(Eax);
    224   this->addSource(Desired);
    225 }
    226 
    227 template <typename TraitsType>
    228 InstImpl<TraitsType>::InstX86Cmpxchg8b::InstX86Cmpxchg8b(
    229     Cfg *Func, X86OperandMem *Addr, Variable *Edx, Variable *Eax, Variable *Ecx,
    230     Variable *Ebx, bool Locked)
    231     : InstImpl<TraitsType>::InstX86BaseLockable(Func, InstX86Base::Cmpxchg, 5,
    232                                                 nullptr, Locked) {
    233   assert(Edx->getRegNum() == RegisterSet::Reg_edx);
    234   assert(Eax->getRegNum() == RegisterSet::Reg_eax);
    235   assert(Ecx->getRegNum() == RegisterSet::Reg_ecx);
    236   assert(Ebx->getRegNum() == RegisterSet::Reg_ebx);
    237   this->addSource(Addr);
    238   this->addSource(Edx);
    239   this->addSource(Eax);
    240   this->addSource(Ecx);
    241   this->addSource(Ebx);
    242 }
    243 
    244 template <typename TraitsType>
    245 InstImpl<TraitsType>::InstX86Cvt::InstX86Cvt(Cfg *Func, Variable *Dest,
    246                                              Operand *Source,
    247                                              CvtVariant Variant)
    248     : InstX86Base(Func, InstX86Base::Cvt, 1, Dest), Variant(Variant) {
    249   this->addSource(Source);
    250 }
    251 
    252 template <typename TraitsType>
    253 InstImpl<TraitsType>::InstX86Icmp::InstX86Icmp(Cfg *Func, Operand *Src0,
    254                                                Operand *Src1)
    255     : InstX86Base(Func, InstX86Base::Icmp, 2, nullptr) {
    256   this->addSource(Src0);
    257   this->addSource(Src1);
    258 }
    259 
    260 template <typename TraitsType>
    261 InstImpl<TraitsType>::InstX86Ucomiss::InstX86Ucomiss(Cfg *Func, Operand *Src0,
    262                                                      Operand *Src1)
    263     : InstX86Base(Func, InstX86Base::Ucomiss, 2, nullptr) {
    264   this->addSource(Src0);
    265   this->addSource(Src1);
    266 }
    267 
    268 template <typename TraitsType>
    269 InstImpl<TraitsType>::InstX86UD2::InstX86UD2(Cfg *Func)
    270     : InstX86Base(Func, InstX86Base::UD2, 0, nullptr) {}
    271 
    272 template <typename TraitsType>
    273 InstImpl<TraitsType>::InstX86Int3::InstX86Int3(Cfg *Func)
    274     : InstX86Base(Func, InstX86Base::Int3, 0, nullptr) {}
    275 
    276 template <typename TraitsType>
    277 InstImpl<TraitsType>::InstX86Test::InstX86Test(Cfg *Func, Operand *Src1,
    278                                                Operand *Src2)
    279     : InstX86Base(Func, InstX86Base::Test, 2, nullptr) {
    280   this->addSource(Src1);
    281   this->addSource(Src2);
    282 }
    283 
    284 template <typename TraitsType>
    285 InstImpl<TraitsType>::InstX86Mfence::InstX86Mfence(Cfg *Func)
    286     : InstX86Base(Func, InstX86Base::Mfence, 0, nullptr) {
    287   this->HasSideEffects = true;
    288 }
    289 
    290 template <typename TraitsType>
    291 InstImpl<TraitsType>::InstX86Store::InstX86Store(Cfg *Func, Operand *Value,
    292                                                  X86Operand *Mem)
    293     : InstX86Base(Func, InstX86Base::Store, 2, nullptr) {
    294   this->addSource(Value);
    295   this->addSource(Mem);
    296 }
    297 
    298 template <typename TraitsType>
    299 InstImpl<TraitsType>::InstX86StoreP::InstX86StoreP(Cfg *Func, Variable *Value,
    300                                                    X86OperandMem *Mem)
    301     : InstX86Base(Func, InstX86Base::StoreP, 2, nullptr) {
    302   this->addSource(Value);
    303   this->addSource(Mem);
    304 }
    305 
    306 template <typename TraitsType>
    307 InstImpl<TraitsType>::InstX86StoreQ::InstX86StoreQ(Cfg *Func, Operand *Value,
    308                                                    X86OperandMem *Mem)
    309     : InstX86Base(Func, InstX86Base::StoreQ, 2, nullptr) {
    310   this->addSource(Value);
    311   this->addSource(Mem);
    312 }
    313 
    314 template <typename TraitsType>
    315 InstImpl<TraitsType>::InstX86StoreD::InstX86StoreD(Cfg *Func, Operand *Value,
    316                                                    X86OperandMem *Mem)
    317     : InstX86Base(Func, InstX86Base::StoreD, 2, nullptr) {
    318   this->addSource(Value);
    319   this->addSource(Mem);
    320 }
    321 
    322 template <typename TraitsType>
    323 InstImpl<TraitsType>::InstX86Nop::InstX86Nop(Cfg *Func, NopVariant Variant)
    324     : InstX86Base(Func, InstX86Base::Nop, 0, nullptr), Variant(Variant) {}
    325 
    326 template <typename TraitsType>
    327 InstImpl<TraitsType>::InstX86Fld::InstX86Fld(Cfg *Func, Operand *Src)
    328     : InstX86Base(Func, InstX86Base::Fld, 1, nullptr) {
    329   this->addSource(Src);
    330 }
    331 
    332 template <typename TraitsType>
    333 InstImpl<TraitsType>::InstX86Fstp::InstX86Fstp(Cfg *Func, Variable *Dest)
    334     : InstX86Base(Func, InstX86Base::Fstp, 0, Dest) {}
    335 
    336 template <typename TraitsType>
    337 InstImpl<TraitsType>::InstX86Pop::InstX86Pop(Cfg *Func, Variable *Dest)
    338     : InstX86Base(Func, InstX86Base::Pop, 0, Dest) {
    339   // A pop instruction affects the stack pointer and so it should not be
    340   // allowed to be automatically dead-code eliminated. (The corresponding push
    341   // instruction doesn't need this treatment because it has no dest variable
    342   // and therefore won't be dead-code eliminated.) This is needed for
    343   // late-stage liveness analysis (e.g. asm-verbose mode).
    344   this->HasSideEffects = true;
    345 }
    346 
    347 template <typename TraitsType>
    348 InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, Operand *Source)
    349     : InstX86Base(Func, InstX86Base::Push, 1, nullptr) {
    350   this->addSource(Source);
    351 }
    352 
    353 template <typename TraitsType>
    354 InstImpl<TraitsType>::InstX86Push::InstX86Push(Cfg *Func, InstX86Label *L)
    355     : InstX86Base(Func, InstX86Base::Push, 0, nullptr), Label(L) {}
    356 
    357 template <typename TraitsType>
    358 InstImpl<TraitsType>::InstX86Ret::InstX86Ret(Cfg *Func, Variable *Source)
    359     : InstX86Base(Func, InstX86Base::Ret, Source ? 1 : 0, nullptr) {
    360   if (Source)
    361     this->addSource(Source);
    362 }
    363 
    364 template <typename TraitsType>
    365 InstImpl<TraitsType>::InstX86Setcc::InstX86Setcc(Cfg *Func, Variable *Dest,
    366                                                  BrCond Cond)
    367     : InstX86Base(Func, InstX86Base::Setcc, 0, Dest), Condition(Cond) {}
    368 
    369 template <typename TraitsType>
    370 InstImpl<TraitsType>::InstX86Xadd::InstX86Xadd(Cfg *Func, Operand *Dest,
    371                                                Variable *Source, bool Locked)
    372     : InstImpl<TraitsType>::InstX86BaseLockable(
    373           Func, InstX86Base::Xadd, 2, llvm::dyn_cast<Variable>(Dest), Locked) {
    374   this->addSource(Dest);
    375   this->addSource(Source);
    376 }
    377 
    378 template <typename TraitsType>
    379 InstImpl<TraitsType>::InstX86Xchg::InstX86Xchg(Cfg *Func, Operand *Dest,
    380                                                Variable *Source)
    381     : InstX86Base(Func, InstX86Base::Xchg, 2, llvm::dyn_cast<Variable>(Dest)) {
    382   this->addSource(Dest);
    383   this->addSource(Source);
    384 }
    385 
    386 template <typename TraitsType>
    387 InstImpl<TraitsType>::InstX86IacaStart::InstX86IacaStart(Cfg *Func)
    388     : InstX86Base(Func, InstX86Base::IacaStart, 0, nullptr) {
    389   assert(getFlags().getAllowIacaMarks());
    390 }
    391 
    392 template <typename TraitsType>
    393 InstImpl<TraitsType>::InstX86IacaEnd::InstX86IacaEnd(Cfg *Func)
    394     : InstX86Base(Func, InstX86Base::IacaEnd, 0, nullptr) {
    395   assert(getFlags().getAllowIacaMarks());
    396 }
    397 
    398 // ======================== Dump routines ======================== //
    399 
    400 template <typename TraitsType>
    401 void InstImpl<TraitsType>::InstX86Base::dump(const Cfg *Func) const {
    402   if (!BuildDefs::dump())
    403     return;
    404   Ostream &Str = Func->getContext()->getStrDump();
    405   Str << "[" << Traits::TargetName << "] ";
    406   Inst::dump(Func);
    407 }
    408 
    409 template <typename TraitsType>
    410 void InstImpl<TraitsType>::InstX86FakeRMW::dump(const Cfg *Func) const {
    411   if (!BuildDefs::dump())
    412     return;
    413   Ostream &Str = Func->getContext()->getStrDump();
    414   Type Ty = getData()->getType();
    415   Str << "rmw " << InstArithmetic::getOpName(getOp()) << " " << Ty << " *";
    416   getAddr()->dump(Func);
    417   Str << ", ";
    418   getData()->dump(Func);
    419   Str << ", beacon=";
    420   getBeacon()->dump(Func);
    421 }
    422 
    423 template <typename TraitsType>
    424 void InstImpl<TraitsType>::InstX86GetIP::emit(const Cfg *Func) const {
    425   if (!BuildDefs::dump())
    426     return;
    427   const auto *Dest = this->getDest();
    428   assert(Dest->hasReg());
    429   Ostream &Str = Func->getContext()->getStrEmit();
    430   Str << "\t"
    431          "call"
    432          "\t";
    433   auto *Target = static_cast<TargetLowering *>(Func->getTarget());
    434   Target->emitWithoutPrefix(Target->createGetIPForRegister(Dest));
    435 }
    436 
    437 template <typename TraitsType>
    438 void InstImpl<TraitsType>::InstX86GetIP::emitIAS(const Cfg *Func) const {
    439   const auto *Dest = this->getDest();
    440   Assembler *Asm = Func->getAssembler<Assembler>();
    441   assert(Dest->hasReg());
    442   Asm->call(static_cast<TargetLowering *>(Func->getTarget())
    443                 ->createGetIPForRegister(Dest));
    444 }
    445 
    446 template <typename TraitsType>
    447 void InstImpl<TraitsType>::InstX86GetIP::dump(const Cfg *Func) const {
    448   if (!BuildDefs::dump())
    449     return;
    450   Ostream &Str = Func->getContext()->getStrDump();
    451   this->getDest()->dump(Func);
    452   Str << " = call getIP";
    453 }
    454 
    455 template <typename TraitsType>
    456 void InstImpl<TraitsType>::InstX86Label::emit(const Cfg *Func) const {
    457   if (!BuildDefs::dump())
    458     return;
    459   Ostream &Str = Func->getContext()->getStrEmit();
    460   Str << getLabelName() << ":";
    461 }
    462 
    463 template <typename TraitsType>
    464 void InstImpl<TraitsType>::InstX86Label::emitIAS(const Cfg *Func) const {
    465   Assembler *Asm = Func->getAssembler<Assembler>();
    466   Asm->bindLocalLabel(LabelNumber);
    467   if (OffsetReloc != nullptr) {
    468     Asm->bindRelocOffset(OffsetReloc);
    469   }
    470 }
    471 
    472 template <typename TraitsType>
    473 void InstImpl<TraitsType>::InstX86Label::dump(const Cfg *Func) const {
    474   if (!BuildDefs::dump())
    475     return;
    476   Ostream &Str = Func->getContext()->getStrDump();
    477   Str << getLabelName() << ":";
    478 }
    479 
    480 template <typename TraitsType>
    481 void InstImpl<TraitsType>::InstX86Br::emit(const Cfg *Func) const {
    482   if (!BuildDefs::dump())
    483     return;
    484   Ostream &Str = Func->getContext()->getStrEmit();
    485   Str << "\t";
    486 
    487   if (Condition == Cond::Br_None) {
    488     Str << "jmp";
    489   } else {
    490     Str << Traits::InstBrAttributes[Condition].EmitString;
    491   }
    492 
    493   if (Label) {
    494     Str << "\t" << Label->getLabelName();
    495   } else {
    496     if (Condition == Cond::Br_None) {
    497       Str << "\t" << getTargetFalse()->getAsmName();
    498     } else {
    499       Str << "\t" << getTargetTrue()->getAsmName();
    500       if (getTargetFalse()) {
    501         Str << "\n\t"
    502                "jmp\t" << getTargetFalse()->getAsmName();
    503       }
    504     }
    505   }
    506 }
    507 
    508 template <typename TraitsType>
    509 void InstImpl<TraitsType>::InstX86Br::emitIAS(const Cfg *Func) const {
    510   Assembler *Asm = Func->getAssembler<Assembler>();
    511   if (Label) {
    512     auto *L = Asm->getOrCreateLocalLabel(Label->getLabelNumber());
    513     if (Condition == Cond::Br_None) {
    514       Asm->jmp(L, isNear());
    515     } else {
    516       Asm->j(Condition, L, isNear());
    517     }
    518   } else {
    519     if (Condition == Cond::Br_None) {
    520       auto *L = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
    521       assert(!getTargetTrue());
    522       Asm->jmp(L, isNear());
    523     } else {
    524       auto *L = Asm->getOrCreateCfgNodeLabel(getTargetTrue()->getIndex());
    525       Asm->j(Condition, L, isNear());
    526       if (getTargetFalse()) {
    527         auto *L2 = Asm->getOrCreateCfgNodeLabel(getTargetFalse()->getIndex());
    528         Asm->jmp(L2, isNear());
    529       }
    530     }
    531   }
    532 }
    533 
    534 template <typename TraitsType>
    535 void InstImpl<TraitsType>::InstX86Br::dump(const Cfg *Func) const {
    536   if (!BuildDefs::dump())
    537     return;
    538   Ostream &Str = Func->getContext()->getStrDump();
    539   Str << "br ";
    540 
    541   if (Condition == Cond::Br_None) {
    542     if (Label) {
    543       Str << "label %" << Label->getLabelName();
    544     } else {
    545       Str << "label %" << getTargetFalse()->getName();
    546     }
    547     return;
    548   }
    549 
    550   Str << Traits::InstBrAttributes[Condition].DisplayString;
    551   if (Label) {
    552     Str << ", label %" << Label->getLabelName();
    553   } else {
    554     Str << ", label %" << getTargetTrue()->getName();
    555     if (getTargetFalse()) {
    556       Str << ", label %" << getTargetFalse()->getName();
    557     }
    558   }
    559 
    560   Str << " // (" << (isNear() ? "near" : "far") << " jump)";
    561 }
    562 
    563 template <typename TraitsType>
    564 void InstImpl<TraitsType>::InstX86Jmp::emit(const Cfg *Func) const {
    565   if (!BuildDefs::dump())
    566     return;
    567   Ostream &Str = Func->getContext()->getStrEmit();
    568   assert(this->getSrcSize() == 1);
    569   const Operand *Src = this->getSrc(0);
    570   if (Traits::Is64Bit) {
    571     if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
    572       Str << "\t"
    573              "jmp"
    574              "\t" << CR->getName();
    575       return;
    576     }
    577   }
    578   Str << "\t"
    579          "jmp"
    580          "\t*";
    581   getJmpTarget()->emit(Func);
    582 }
    583 
    584 template <typename TraitsType>
    585 void InstImpl<TraitsType>::InstX86Jmp::emitIAS(const Cfg *Func) const {
    586   // Note: Adapted (mostly copied) from
    587   // InstImpl<TraitsType>::InstX86Call::emitIAS().
    588   Assembler *Asm = Func->getAssembler<Assembler>();
    589   Operand *Target = getJmpTarget();
    590   if (const auto *Var = llvm::dyn_cast<Variable>(Target)) {
    591     if (Var->hasReg()) {
    592       Asm->jmp(Traits::getEncodedGPR(Var->getRegNum()));
    593     } else {
    594       // The jmp instruction with a memory operand should be possible to
    595       // encode, but it isn't a valid sandboxed instruction, and there
    596       // shouldn't be a register allocation issue to jump through a scratch
    597       // register, so we don't really need to bother implementing it.
    598       llvm::report_fatal_error("Assembler can't jmp to memory operand");
    599     }
    600   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Target)) {
    601     (void)Mem;
    602     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
    603     llvm::report_fatal_error("Assembler can't jmp to memory operand");
    604   } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(Target)) {
    605     Asm->jmp(CR);
    606   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Target)) {
    607     // NaCl trampoline calls refer to an address within the sandbox directly.
    608     // This is usually only needed for non-IRT builds and otherwise not very
    609     // portable or stable. Usually this is only done for "calls" and not jumps.
    610     Asm->jmp(AssemblerImmediate(Imm->getValue()));
    611   } else {
    612     llvm::report_fatal_error("Unexpected operand type");
    613   }
    614 }
    615 
    616 template <typename TraitsType>
    617 void InstImpl<TraitsType>::InstX86Jmp::dump(const Cfg *Func) const {
    618   if (!BuildDefs::dump())
    619     return;
    620   Ostream &Str = Func->getContext()->getStrDump();
    621   Str << "jmp ";
    622   getJmpTarget()->dump(Func);
    623 }
    624 
    625 template <typename TraitsType>
    626 void InstImpl<TraitsType>::InstX86Call::emit(const Cfg *Func) const {
    627   if (!BuildDefs::dump())
    628     return;
    629   Ostream &Str = Func->getContext()->getStrEmit();
    630   assert(this->getSrcSize() == 1);
    631   Str << "\t"
    632          "call\t";
    633   Operand *CallTarget = getCallTarget();
    634   auto *Target = InstX86Base::getTarget(Func);
    635   if (const auto *CI = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
    636     // Emit without a leading '$'.
    637     Str << CI->getValue();
    638   } else if (const auto DirectCallTarget =
    639                  llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
    640     DirectCallTarget->emitWithoutPrefix(Target);
    641   } else {
    642     Str << "*";
    643     CallTarget->emit(Func);
    644   }
    645 }
    646 
    647 template <typename TraitsType>
    648 void InstImpl<TraitsType>::InstX86Call::emitIAS(const Cfg *Func) const {
    649   Assembler *Asm = Func->getAssembler<Assembler>();
    650   Operand *CallTarget = getCallTarget();
    651   auto *Target = InstX86Base::getTarget(Func);
    652   if (const auto *Var = llvm::dyn_cast<Variable>(CallTarget)) {
    653     if (Var->hasReg()) {
    654       Asm->call(Traits::getEncodedGPR(Var->getRegNum()));
    655     } else {
    656       Asm->call(Target->stackVarToAsmOperand(Var));
    657     }
    658   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(CallTarget)) {
    659     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
    660     Asm->call(Mem->toAsmAddress(Asm, Target));
    661   } else if (const auto *CR = llvm::dyn_cast<ConstantRelocatable>(CallTarget)) {
    662     Asm->call(CR);
    663   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(CallTarget)) {
    664     Asm->call(AssemblerImmediate(Imm->getValue()));
    665   } else {
    666     llvm_unreachable("Unexpected operand type");
    667   }
    668 }
    669 
    670 template <typename TraitsType>
    671 void InstImpl<TraitsType>::InstX86Call::dump(const Cfg *Func) const {
    672   if (!BuildDefs::dump())
    673     return;
    674   Ostream &Str = Func->getContext()->getStrDump();
    675   if (this->getDest()) {
    676     this->dumpDest(Func);
    677     Str << " = ";
    678   }
    679   Str << "call ";
    680   getCallTarget()->dump(Func);
    681 }
    682 
    683 // The this->Opcode parameter needs to be char* and not std::string because of
    684 // template issues.
    685 template <typename TraitsType>
    686 void InstImpl<TraitsType>::InstX86Base::emitTwoAddress(
    687     const Cfg *Func, const char *Opcode, const char *Suffix) const {
    688   if (!BuildDefs::dump())
    689     return;
    690   Ostream &Str = Func->getContext()->getStrEmit();
    691   assert(getSrcSize() == 2);
    692   Operand *Dest = getDest();
    693   if (Dest == nullptr)
    694     Dest = getSrc(0);
    695   assert(Dest == getSrc(0));
    696   Operand *Src1 = getSrc(1);
    697   Str << "\t" << Opcode << Suffix
    698       << InstX86Base::getWidthString(Dest->getType()) << "\t";
    699   Src1->emit(Func);
    700   Str << ", ";
    701   Dest->emit(Func);
    702 }
    703 
    704 template <typename TraitsType>
    705 void InstImpl<TraitsType>::emitIASOpTyGPR(const Cfg *Func, Type Ty,
    706                                           const Operand *Op,
    707                                           const GPREmitterOneOp &Emitter) {
    708   auto *Target = InstX86Base::getTarget(Func);
    709   Assembler *Asm = Func->getAssembler<Assembler>();
    710   if (const auto *Var = llvm::dyn_cast<Variable>(Op)) {
    711     if (Var->hasReg()) {
    712       // We cheat a little and use GPRRegister even for byte operations.
    713       GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
    714       (Asm->*(Emitter.Reg))(Ty, VarReg);
    715     } else {
    716       Address StackAddr(Target->stackVarToAsmOperand(Var));
    717       (Asm->*(Emitter.Addr))(Ty, StackAddr);
    718     }
    719   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Op)) {
    720     Mem->emitSegmentOverride(Asm);
    721     (Asm->*(Emitter.Addr))(Ty, Mem->toAsmAddress(Asm, Target));
    722   } else {
    723     llvm_unreachable("Unexpected operand type");
    724   }
    725 }
    726 
    727 template <typename TraitsType>
    728 template <bool VarCanBeByte, bool SrcCanBeByte>
    729 void InstImpl<TraitsType>::emitIASRegOpTyGPR(const Cfg *Func, bool IsLea,
    730                                              Type Ty, const Variable *Var,
    731                                              const Operand *Src,
    732                                              const GPREmitterRegOp &Emitter) {
    733   auto *Target = InstX86Base::getTarget(Func);
    734   Assembler *Asm = Func->getAssembler<Assembler>();
    735   assert(Var->hasReg());
    736   // We cheat a little and use GPRRegister even for byte operations.
    737   GPRRegister VarReg = VarCanBeByte ? Traits::getEncodedGPR(Var->getRegNum())
    738                                     : Traits::getEncodedGPR(Var->getRegNum());
    739   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
    740     if (SrcVar->hasReg()) {
    741       GPRRegister SrcReg = SrcCanBeByte
    742                                ? Traits::getEncodedGPR(SrcVar->getRegNum())
    743                                : Traits::getEncodedGPR(SrcVar->getRegNum());
    744       (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
    745     } else {
    746       Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
    747       (Asm->*(Emitter.GPRAddr))(Ty, VarReg, SrcStackAddr);
    748     }
    749   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
    750     Mem->emitSegmentOverride(Asm);
    751     (Asm->*(Emitter.GPRAddr))(Ty, VarReg,
    752                               Mem->toAsmAddress(Asm, Target, IsLea));
    753   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
    754     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
    755   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
    756     assert(Traits::Is64Bit);
    757     assert(Utils::IsInt(32, Imm->getValue()));
    758     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
    759   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
    760     const auto FixupKind = (Reloc->getName().hasStdString() &&
    761                             Reloc->getName().toString() == GlobalOffsetTable)
    762                                ? Traits::FK_GotPC
    763                                : Traits::TargetLowering::getAbsFixup();
    764     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
    765     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Fixup));
    766   } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Src)) {
    767     (Asm->*(Emitter.GPRAddr))(Ty, VarReg, Split->toAsmAddress(Func));
    768   } else {
    769     llvm_unreachable("Unexpected operand type");
    770   }
    771 }
    772 
    773 template <typename TraitsType>
    774 void InstImpl<TraitsType>::emitIASAddrOpTyGPR(const Cfg *Func, Type Ty,
    775                                               const Address &Addr,
    776                                               const Operand *Src,
    777                                               const GPREmitterAddrOp &Emitter) {
    778   Assembler *Asm = Func->getAssembler<Assembler>();
    779   // Src can only be Reg or AssemblerImmediate.
    780   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
    781     assert(SrcVar->hasReg());
    782     GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
    783     (Asm->*(Emitter.AddrGPR))(Ty, Addr, SrcReg);
    784   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
    785     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
    786   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
    787     assert(Traits::Is64Bit);
    788     assert(Utils::IsInt(32, Imm->getValue()));
    789     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Imm->getValue()));
    790   } else if (const auto *Reloc = llvm::dyn_cast<ConstantRelocatable>(Src)) {
    791     const auto FixupKind = (Reloc->getName().hasStdString() &&
    792                             Reloc->getName().toString() == GlobalOffsetTable)
    793                                ? Traits::FK_GotPC
    794                                : Traits::TargetLowering::getAbsFixup();
    795     AssemblerFixup *Fixup = Asm->createFixup(FixupKind, Reloc);
    796     (Asm->*(Emitter.AddrImm))(Ty, Addr, AssemblerImmediate(Fixup));
    797   } else {
    798     llvm_unreachable("Unexpected operand type");
    799   }
    800 }
    801 
    802 template <typename TraitsType>
    803 void InstImpl<TraitsType>::emitIASAsAddrOpTyGPR(
    804     const Cfg *Func, Type Ty, const Operand *Op0, const Operand *Op1,
    805     const GPREmitterAddrOp &Emitter) {
    806   auto *Target = InstX86Base::getTarget(Func);
    807   if (const auto *Op0Var = llvm::dyn_cast<Variable>(Op0)) {
    808     assert(!Op0Var->hasReg());
    809     Address StackAddr(Target->stackVarToAsmOperand(Op0Var));
    810     emitIASAddrOpTyGPR(Func, Ty, StackAddr, Op1, Emitter);
    811   } else if (const auto *Op0Mem = llvm::dyn_cast<X86OperandMem>(Op0)) {
    812     Assembler *Asm = Func->getAssembler<Assembler>();
    813     Op0Mem->emitSegmentOverride(Asm);
    814     emitIASAddrOpTyGPR(Func, Ty, Op0Mem->toAsmAddress(Asm, Target), Op1,
    815                        Emitter);
    816   } else if (const auto *Split = llvm::dyn_cast<VariableSplit>(Op0)) {
    817     emitIASAddrOpTyGPR(Func, Ty, Split->toAsmAddress(Func), Op1, Emitter);
    818   } else {
    819     llvm_unreachable("Unexpected operand type");
    820   }
    821 }
    822 
    823 template <typename TraitsType>
    824 void InstImpl<TraitsType>::emitIASGPRShift(const Cfg *Func, Type Ty,
    825                                            const Variable *Var,
    826                                            const Operand *Src,
    827                                            const GPREmitterShiftOp &Emitter) {
    828   Assembler *Asm = Func->getAssembler<Assembler>();
    829   // Technically, the Dest Var can be mem as well, but we only use Reg. We can
    830   // extend this to check Dest if we decide to use that form.
    831   assert(Var->hasReg());
    832   // We cheat a little and use GPRRegister even for byte operations.
    833   GPRRegister VarReg = Traits::getEncodedGPR(Var->getRegNum());
    834   // Src must be reg == ECX or an Imm8. This is asserted by the assembler.
    835   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
    836     assert(SrcVar->hasReg());
    837     GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar->getRegNum());
    838     (Asm->*(Emitter.GPRGPR))(Ty, VarReg, SrcReg);
    839   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
    840     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
    841   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger64>(Src)) {
    842     assert(Traits::Is64Bit);
    843     assert(Utils::IsInt(32, Imm->getValue()));
    844     (Asm->*(Emitter.GPRImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
    845   } else {
    846     llvm_unreachable("Unexpected operand type");
    847   }
    848 }
    849 
    850 template <typename TraitsType>
    851 void InstImpl<TraitsType>::emitIASGPRShiftDouble(
    852     const Cfg *Func, const Variable *Dest, const Operand *Src1Op,
    853     const Operand *Src2Op, const GPREmitterShiftD &Emitter) {
    854   Assembler *Asm = Func->getAssembler<Assembler>();
    855   // Dest can be reg or mem, but we only use the reg variant.
    856   assert(Dest->hasReg());
    857   GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
    858   // SrcVar1 must be reg.
    859   const auto *SrcVar1 = llvm::cast<Variable>(Src1Op);
    860   assert(SrcVar1->hasReg());
    861   GPRRegister SrcReg = Traits::getEncodedGPR(SrcVar1->getRegNum());
    862   Type Ty = SrcVar1->getType();
    863   // Src2 can be the implicit CL register or an immediate.
    864   if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src2Op)) {
    865     (Asm->*(Emitter.GPRGPRImm))(Ty, DestReg, SrcReg,
    866                                 AssemblerImmediate(Imm->getValue()));
    867   } else {
    868     assert(llvm::cast<Variable>(Src2Op)->getRegNum() == RegisterSet::Reg_cl);
    869     (Asm->*(Emitter.GPRGPR))(Ty, DestReg, SrcReg);
    870   }
    871 }
    872 
    873 template <typename TraitsType>
    874 void InstImpl<TraitsType>::emitIASXmmShift(const Cfg *Func, Type Ty,
    875                                            const Variable *Var,
    876                                            const Operand *Src,
    877                                            const XmmEmitterShiftOp &Emitter) {
    878   auto *Target = InstX86Base::getTarget(Func);
    879   Assembler *Asm = Func->getAssembler<Assembler>();
    880   assert(Var->hasReg());
    881   XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
    882   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
    883     if (SrcVar->hasReg()) {
    884       XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
    885       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
    886     } else {
    887       Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
    888       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
    889     }
    890   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
    891     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
    892     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
    893   } else if (const auto *Imm = llvm::dyn_cast<ConstantInteger32>(Src)) {
    894     (Asm->*(Emitter.XmmImm))(Ty, VarReg, AssemblerImmediate(Imm->getValue()));
    895   } else {
    896     llvm_unreachable("Unexpected operand type");
    897   }
    898 }
    899 
    900 template <typename TraitsType>
    901 void InstImpl<TraitsType>::emitIASRegOpTyXMM(const Cfg *Func, Type Ty,
    902                                              const Variable *Var,
    903                                              const Operand *Src,
    904                                              const XmmEmitterRegOp &Emitter) {
    905   auto *Target = InstX86Base::getTarget(Func);
    906   Assembler *Asm = Func->getAssembler<Assembler>();
    907   assert(Var->hasReg());
    908   XmmRegister VarReg = Traits::getEncodedXmm(Var->getRegNum());
    909   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
    910     if (SrcVar->hasReg()) {
    911       XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
    912       (Asm->*(Emitter.XmmXmm))(Ty, VarReg, SrcReg);
    913     } else {
    914       Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
    915       (Asm->*(Emitter.XmmAddr))(Ty, VarReg, SrcStackAddr);
    916     }
    917   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
    918     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
    919     (Asm->*(Emitter.XmmAddr))(Ty, VarReg, Mem->toAsmAddress(Asm, Target));
    920   } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
    921     (Asm->*(Emitter.XmmAddr))(Ty, VarReg,
    922                               Traits::Address::ofConstPool(Asm, Imm));
    923   } else {
    924     llvm_unreachable("Unexpected operand type");
    925   }
    926 }
    927 
    928 template <typename TraitsType>
    929 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
    930           SReg_t (*srcEnc)(RegNumT)>
    931 void InstImpl<TraitsType>::emitIASCastRegOp(
    932     const Cfg *Func, Type DestTy, const Variable *Dest, Type SrcTy,
    933     const Operand *Src, const CastEmitterRegOp<DReg_t, SReg_t> &Emitter) {
    934   auto *Target = InstX86Base::getTarget(Func);
    935   Assembler *Asm = Func->getAssembler<Assembler>();
    936   assert(Dest->hasReg());
    937   DReg_t DestReg = destEnc(Dest->getRegNum());
    938   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
    939     if (SrcVar->hasReg()) {
    940       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
    941       (Asm->*(Emitter.RegReg))(DestTy, DestReg, SrcTy, SrcReg);
    942     } else {
    943       Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
    944       (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy, SrcStackAddr);
    945     }
    946   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
    947     Mem->emitSegmentOverride(Asm);
    948     (Asm->*(Emitter.RegAddr))(DestTy, DestReg, SrcTy,
    949                               Mem->toAsmAddress(Asm, Target));
    950   } else {
    951     llvm_unreachable("Unexpected operand type");
    952   }
    953 }
    954 
    955 template <typename TraitsType>
    956 template <typename DReg_t, typename SReg_t, DReg_t (*destEnc)(RegNumT),
    957           SReg_t (*srcEnc)(RegNumT)>
    958 void InstImpl<TraitsType>::emitIASThreeOpImmOps(
    959     const Cfg *Func, Type DispatchTy, const Variable *Dest, const Operand *Src0,
    960     const Operand *Src1, const ThreeOpImmEmitter<DReg_t, SReg_t> Emitter) {
    961   auto *Target = InstX86Base::getTarget(Func);
    962   Assembler *Asm = Func->getAssembler<Assembler>();
    963   // This only handles Dest being a register, and Src1 being an immediate.
    964   assert(Dest->hasReg());
    965   DReg_t DestReg = destEnc(Dest->getRegNum());
    966   AssemblerImmediate Imm(llvm::cast<ConstantInteger32>(Src1)->getValue());
    967   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src0)) {
    968     if (SrcVar->hasReg()) {
    969       SReg_t SrcReg = srcEnc(SrcVar->getRegNum());
    970       (Asm->*(Emitter.RegRegImm))(DispatchTy, DestReg, SrcReg, Imm);
    971     } else {
    972       Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
    973       (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg, SrcStackAddr, Imm);
    974     }
    975   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src0)) {
    976     Mem->emitSegmentOverride(Asm);
    977     (Asm->*(Emitter.RegAddrImm))(DispatchTy, DestReg,
    978                                  Mem->toAsmAddress(Asm, Target), Imm);
    979   } else {
    980     llvm_unreachable("Unexpected operand type");
    981   }
    982 }
    983 
    984 template <typename TraitsType>
    985 void InstImpl<TraitsType>::emitIASMovlikeXMM(const Cfg *Func,
    986                                              const Variable *Dest,
    987                                              const Operand *Src,
    988                                              const XmmEmitterMovOps Emitter) {
    989   auto *Target = InstX86Base::getTarget(Func);
    990   Assembler *Asm = Func->getAssembler<Assembler>();
    991   if (Dest->hasReg()) {
    992     XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
    993     if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
    994       if (SrcVar->hasReg()) {
    995         (Asm->*(Emitter.XmmXmm))(DestReg,
    996                                  Traits::getEncodedXmm(SrcVar->getRegNum()));
    997       } else {
    998         Address StackAddr(Target->stackVarToAsmOperand(SrcVar));
    999         (Asm->*(Emitter.XmmAddr))(DestReg, StackAddr);
   1000       }
   1001     } else if (const auto *SrcMem = llvm::dyn_cast<X86OperandMem>(Src)) {
   1002       assert(SrcMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   1003       (Asm->*(Emitter.XmmAddr))(DestReg, SrcMem->toAsmAddress(Asm, Target));
   1004     } else {
   1005       llvm_unreachable("Unexpected operand type");
   1006     }
   1007   } else {
   1008     Address StackAddr(Target->stackVarToAsmOperand(Dest));
   1009     // Src must be a register in this case.
   1010     const auto *SrcVar = llvm::cast<Variable>(Src);
   1011     assert(SrcVar->hasReg());
   1012     (Asm->*(Emitter.AddrXmm))(StackAddr,
   1013                               Traits::getEncodedXmm(SrcVar->getRegNum()));
   1014   }
   1015 }
   1016 
   1017 template <typename TraitsType>
   1018 void InstImpl<TraitsType>::InstX86Movmsk::dump(const Cfg *Func) const {
   1019   if (!BuildDefs::dump())
   1020     return;
   1021   Ostream &Str = Func->getContext()->getStrDump();
   1022   this->dumpDest(Func);
   1023   Str << " = movmsk." << this->getSrc(0)->getType() << " ";
   1024   this->dumpSources(Func);
   1025 }
   1026 
   1027 template <typename TraitsType>
   1028 void InstImpl<TraitsType>::InstX86Movmsk::emit(const Cfg *Func) const {
   1029   if (!BuildDefs::dump())
   1030     return;
   1031   Ostream &Str = Func->getContext()->getStrEmit();
   1032   assert(this->getSrcSize() == 1);
   1033   Type SrcTy = this->getSrc(0)->getType();
   1034   assert(isVectorType(SrcTy));
   1035   switch (SrcTy) {
   1036   case IceType_v16i8:
   1037     Str << "\t"
   1038            "pmovmskb"
   1039            "\t";
   1040     break;
   1041   case IceType_v4i32:
   1042   case IceType_v4f32:
   1043     Str << "\t"
   1044            "movmskps"
   1045            "\t";
   1046     break;
   1047   default:
   1048     llvm_unreachable("Unexpected operand type");
   1049   }
   1050   this->getSrc(0)->emit(Func);
   1051   Str << ", ";
   1052   this->getDest()->emit(Func);
   1053 }
   1054 
   1055 template <typename TraitsType>
   1056 void InstImpl<TraitsType>::InstX86Movmsk::emitIAS(const Cfg *Func) const {
   1057   assert(this->getSrcSize() == 1);
   1058   Assembler *Asm = Func->getAssembler<Assembler>();
   1059   const Variable *Dest = this->getDest();
   1060   const Variable *Src = llvm::cast<Variable>(this->getSrc(0));
   1061   const Type DestTy = Dest->getType();
   1062   (void)DestTy;
   1063   const Type SrcTy = Src->getType();
   1064   assert(isVectorType(SrcTy));
   1065   assert(isScalarIntegerType(DestTy));
   1066   if (Traits::Is64Bit) {
   1067     assert(DestTy == IceType_i32 || DestTy == IceType_i64);
   1068   } else {
   1069     assert(typeWidthInBytes(DestTy) <= 4);
   1070   }
   1071   XmmRegister SrcReg = Traits::getEncodedXmm(Src->getRegNum());
   1072   GPRRegister DestReg = Traits::getEncodedGPR(Dest->getRegNum());
   1073   Asm->movmsk(SrcTy, DestReg, SrcReg);
   1074 }
   1075 
   1076 template <typename TraitsType>
   1077 void InstImpl<TraitsType>::InstX86Sqrt::emit(const Cfg *Func) const {
   1078   if (!BuildDefs::dump())
   1079     return;
   1080   Ostream &Str = Func->getContext()->getStrEmit();
   1081   assert(this->getSrcSize() == 1);
   1082   Type Ty = this->getSrc(0)->getType();
   1083   assert(isScalarFloatingType(Ty));
   1084   Str << "\t"
   1085          "sqrt" << Traits::TypeAttributes[Ty].SpSdString << "\t";
   1086   this->getSrc(0)->emit(Func);
   1087   Str << ", ";
   1088   this->getDest()->emit(Func);
   1089 }
   1090 
   1091 template <typename TraitsType>
   1092 void InstImpl<TraitsType>::InstX86Div::emit(const Cfg *Func) const {
   1093   if (!BuildDefs::dump())
   1094     return;
   1095   Ostream &Str = Func->getContext()->getStrEmit();
   1096   assert(this->getSrcSize() == 3);
   1097   Operand *Src1 = this->getSrc(1);
   1098   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
   1099   Src1->emit(Func);
   1100 }
   1101 
   1102 template <typename TraitsType>
   1103 void InstImpl<TraitsType>::InstX86Div::emitIAS(const Cfg *Func) const {
   1104   assert(this->getSrcSize() == 3);
   1105   const Operand *Src = this->getSrc(1);
   1106   Type Ty = Src->getType();
   1107   static GPREmitterOneOp Emitter = {&Assembler::div, &Assembler::div};
   1108   emitIASOpTyGPR(Func, Ty, Src, Emitter);
   1109 }
   1110 
   1111 template <typename TraitsType>
   1112 void InstImpl<TraitsType>::InstX86Idiv::emit(const Cfg *Func) const {
   1113   if (!BuildDefs::dump())
   1114     return;
   1115   Ostream &Str = Func->getContext()->getStrEmit();
   1116   assert(this->getSrcSize() == 3);
   1117   Operand *Src1 = this->getSrc(1);
   1118   Str << "\t" << this->Opcode << this->getWidthString(Src1->getType()) << "\t";
   1119   Src1->emit(Func);
   1120 }
   1121 
   1122 template <typename TraitsType>
   1123 void InstImpl<TraitsType>::InstX86Idiv::emitIAS(const Cfg *Func) const {
   1124   assert(this->getSrcSize() == 3);
   1125   const Operand *Src = this->getSrc(1);
   1126   Type Ty = Src->getType();
   1127   static const GPREmitterOneOp Emitter = {&Assembler::idiv, &Assembler::idiv};
   1128   emitIASOpTyGPR(Func, Ty, Src, Emitter);
   1129 }
   1130 
   1131 // pblendvb and blendvps take xmm0 as a final implicit argument.
   1132 template <typename TraitsType>
   1133 void InstImpl<TraitsType>::emitVariableBlendInst(const char *Opcode,
   1134                                                  const Inst *Instr,
   1135                                                  const Cfg *Func) {
   1136   if (!BuildDefs::dump())
   1137     return;
   1138   Ostream &Str = Func->getContext()->getStrEmit();
   1139   assert(Instr->getSrcSize() == 3);
   1140   assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
   1141          RegisterSet::Reg_xmm0);
   1142   Str << "\t" << Opcode << "\t";
   1143   Instr->getSrc(1)->emit(Func);
   1144   Str << ", ";
   1145   Instr->getDest()->emit(Func);
   1146 }
   1147 
   1148 template <typename TraitsType>
   1149 void InstImpl<TraitsType>::emitIASVariableBlendInst(
   1150     const Inst *Instr, const Cfg *Func, const XmmEmitterRegOp &Emitter) {
   1151   assert(Instr->getSrcSize() == 3);
   1152   assert(llvm::cast<Variable>(Instr->getSrc(2))->getRegNum() ==
   1153          RegisterSet::Reg_xmm0);
   1154   const Variable *Dest = Instr->getDest();
   1155   const Operand *Src = Instr->getSrc(1);
   1156   emitIASRegOpTyXMM(Func, Dest->getType(), Dest, Src, Emitter);
   1157 }
   1158 
   1159 template <typename TraitsType>
   1160 void InstImpl<TraitsType>::InstX86Blendvps::emit(const Cfg *Func) const {
   1161   if (!BuildDefs::dump())
   1162     return;
   1163   emitVariableBlendInst(this->Opcode, this, Func);
   1164 }
   1165 
   1166 template <typename TraitsType>
   1167 void InstImpl<TraitsType>::InstX86Blendvps::emitIAS(const Cfg *Func) const {
   1168   static const XmmEmitterRegOp Emitter = {&Assembler::blendvps,
   1169                                           &Assembler::blendvps};
   1170   emitIASVariableBlendInst(this, Func, Emitter);
   1171 }
   1172 
   1173 template <typename TraitsType>
   1174 void InstImpl<TraitsType>::InstX86Pblendvb::emit(const Cfg *Func) const {
   1175   if (!BuildDefs::dump())
   1176     return;
   1177   emitVariableBlendInst(this->Opcode, this, Func);
   1178 }
   1179 
   1180 template <typename TraitsType>
   1181 void InstImpl<TraitsType>::InstX86Pblendvb::emitIAS(const Cfg *Func) const {
   1182   static const XmmEmitterRegOp Emitter = {&Assembler::pblendvb,
   1183                                           &Assembler::pblendvb};
   1184   emitIASVariableBlendInst(this, Func, Emitter);
   1185 }
   1186 
   1187 template <typename TraitsType>
   1188 void InstImpl<TraitsType>::InstX86Imul::emit(const Cfg *Func) const {
   1189   if (!BuildDefs::dump())
   1190     return;
   1191   Ostream &Str = Func->getContext()->getStrEmit();
   1192   assert(this->getSrcSize() == 2);
   1193   Variable *Dest = this->getDest();
   1194   if (isByteSizedArithType(Dest->getType())) {
   1195     // The 8-bit version of imul only allows the form "imul r/m8".
   1196     const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
   1197     (void)Src0Var;
   1198     assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
   1199     Str << "\t"
   1200            "imulb\t";
   1201     this->getSrc(1)->emit(Func);
   1202   } else if (llvm::isa<Constant>(this->getSrc(1))) {
   1203     Str << "\t"
   1204            "imul" << this->getWidthString(Dest->getType()) << "\t";
   1205     this->getSrc(1)->emit(Func);
   1206     Str << ", ";
   1207     this->getSrc(0)->emit(Func);
   1208     Str << ", ";
   1209     Dest->emit(Func);
   1210   } else {
   1211     this->emitTwoAddress(Func, this->Opcode);
   1212   }
   1213 }
   1214 
   1215 template <typename TraitsType>
   1216 void InstImpl<TraitsType>::InstX86Imul::emitIAS(const Cfg *Func) const {
   1217   assert(this->getSrcSize() == 2);
   1218   const Variable *Var = this->getDest();
   1219   Type Ty = Var->getType();
   1220   const Operand *Src = this->getSrc(1);
   1221   if (isByteSizedArithType(Ty)) {
   1222     // The 8-bit version of imul only allows the form "imul r/m8".
   1223     const auto *Src0Var = llvm::dyn_cast<Variable>(this->getSrc(0));
   1224     (void)Src0Var;
   1225     assert(Src0Var->getRegNum() == RegisterSet::Reg_al);
   1226     static const GPREmitterOneOp Emitter = {&Assembler::imul, &Assembler::imul};
   1227     emitIASOpTyGPR(Func, Ty, this->getSrc(1), Emitter);
   1228   } else {
   1229     // The two-address version is used when multiplying by a non-constant
   1230     // or doing an 8-bit multiply.
   1231     assert(Var == this->getSrc(0));
   1232     static const GPREmitterRegOp Emitter = {&Assembler::imul, &Assembler::imul,
   1233                                             &Assembler::imul};
   1234     constexpr bool NotLea = false;
   1235     emitIASRegOpTyGPR(Func, NotLea, Ty, Var, Src, Emitter);
   1236   }
   1237 }
   1238 
   1239 template <typename TraitsType>
   1240 void InstImpl<TraitsType>::InstX86ImulImm::emit(const Cfg *Func) const {
   1241   if (!BuildDefs::dump())
   1242     return;
   1243   Ostream &Str = Func->getContext()->getStrEmit();
   1244   assert(this->getSrcSize() == 2);
   1245   Variable *Dest = this->getDest();
   1246   assert(Dest->getType() == IceType_i16 || Dest->getType() == IceType_i32);
   1247   assert(llvm::isa<Constant>(this->getSrc(1)));
   1248   Str << "\t"
   1249          "imul" << this->getWidthString(Dest->getType()) << "\t";
   1250   this->getSrc(1)->emit(Func);
   1251   Str << ", ";
   1252   this->getSrc(0)->emit(Func);
   1253   Str << ", ";
   1254   Dest->emit(Func);
   1255 }
   1256 
   1257 template <typename TraitsType>
   1258 void InstImpl<TraitsType>::InstX86ImulImm::emitIAS(const Cfg *Func) const {
   1259   assert(this->getSrcSize() == 2);
   1260   const Variable *Dest = this->getDest();
   1261   Type Ty = Dest->getType();
   1262   assert(llvm::isa<Constant>(this->getSrc(1)));
   1263   static const ThreeOpImmEmitter<GPRRegister, GPRRegister> Emitter = {
   1264       &Assembler::imul, &Assembler::imul};
   1265   emitIASThreeOpImmOps<GPRRegister, GPRRegister, Traits::getEncodedGPR,
   1266                        Traits::getEncodedGPR>(Func, Ty, Dest, this->getSrc(0),
   1267                                               this->getSrc(1), Emitter);
   1268 }
   1269 
   1270 template <typename TraitsType>
   1271 void InstImpl<TraitsType>::InstX86Insertps::emitIAS(const Cfg *Func) const {
   1272   assert(this->getSrcSize() == 3);
   1273   assert(InstX86Base::getTarget(Func)->getInstructionSet() >= Traits::SSE4_1);
   1274   const Variable *Dest = this->getDest();
   1275   assert(Dest == this->getSrc(0));
   1276   Type Ty = Dest->getType();
   1277   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
   1278       &Assembler::insertps, &Assembler::insertps};
   1279   emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
   1280                        Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
   1281                                               this->getSrc(2), Emitter);
   1282 }
   1283 
   1284 template <typename TraitsType>
   1285 void InstImpl<TraitsType>::InstX86Cbwdq::emit(const Cfg *Func) const {
   1286   if (!BuildDefs::dump())
   1287     return;
   1288   Ostream &Str = Func->getContext()->getStrEmit();
   1289   assert(this->getSrcSize() == 1);
   1290   Operand *Src0 = this->getSrc(0);
   1291   const auto DestReg = this->getDest()->getRegNum();
   1292   const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
   1293   (void)DestReg;
   1294   (void)SrcReg;
   1295   switch (Src0->getType()) {
   1296   default:
   1297     llvm_unreachable("unexpected source type!");
   1298     break;
   1299   case IceType_i8:
   1300     assert(SrcReg == RegisterSet::Reg_al);
   1301     assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
   1302     Str << "\t"
   1303            "cbtw";
   1304     break;
   1305   case IceType_i16:
   1306     assert(SrcReg == RegisterSet::Reg_ax);
   1307     assert(DestReg == RegisterSet::Reg_dx);
   1308     Str << "\t"
   1309            "cwtd";
   1310     break;
   1311   case IceType_i32:
   1312     assert(SrcReg == RegisterSet::Reg_eax);
   1313     assert(DestReg == RegisterSet::Reg_edx);
   1314     Str << "\t"
   1315            "cltd";
   1316     break;
   1317   case IceType_i64:
   1318     assert(Traits::Is64Bit);
   1319     assert(SrcReg == Traits::getRaxOrDie());
   1320     assert(DestReg == Traits::getRdxOrDie());
   1321     Str << "\t"
   1322            "cqo";
   1323     break;
   1324   }
   1325 }
   1326 
   1327 template <typename TraitsType>
   1328 void InstImpl<TraitsType>::InstX86Cbwdq::emitIAS(const Cfg *Func) const {
   1329   Assembler *Asm = Func->getAssembler<Assembler>();
   1330   assert(this->getSrcSize() == 1);
   1331   Operand *Src0 = this->getSrc(0);
   1332   const auto DestReg = this->getDest()->getRegNum();
   1333   const auto SrcReg = llvm::cast<Variable>(Src0)->getRegNum();
   1334   (void)DestReg;
   1335   (void)SrcReg;
   1336   switch (Src0->getType()) {
   1337   default:
   1338     llvm_unreachable("unexpected source type!");
   1339     break;
   1340   case IceType_i8:
   1341     assert(SrcReg == RegisterSet::Reg_al);
   1342     assert(DestReg == RegisterSet::Reg_ax || DestReg == RegisterSet::Reg_ah);
   1343     Asm->cbw();
   1344     break;
   1345   case IceType_i16:
   1346     assert(SrcReg == RegisterSet::Reg_ax);
   1347     assert(DestReg == RegisterSet::Reg_dx);
   1348     Asm->cwd();
   1349     break;
   1350   case IceType_i32:
   1351     assert(SrcReg == RegisterSet::Reg_eax);
   1352     assert(DestReg == RegisterSet::Reg_edx);
   1353     Asm->cdq();
   1354     break;
   1355   case IceType_i64:
   1356     assert(Traits::Is64Bit);
   1357     assert(SrcReg == Traits::getRaxOrDie());
   1358     assert(DestReg == Traits::getRdxOrDie());
   1359     Asm->cqo();
   1360     break;
   1361   }
   1362 }
   1363 
   1364 template <typename TraitsType>
   1365 void InstImpl<TraitsType>::InstX86Mul::emit(const Cfg *Func) const {
   1366   if (!BuildDefs::dump())
   1367     return;
   1368   Ostream &Str = Func->getContext()->getStrEmit();
   1369   assert(this->getSrcSize() == 2);
   1370   assert(llvm::isa<Variable>(this->getSrc(0)));
   1371   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
   1372          RegisterSet::Reg_eax);
   1373   assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
   1374                                                                 // allow
   1375                                                                 // edx?
   1376   Str << "\t"
   1377          "mul" << this->getWidthString(this->getDest()->getType()) << "\t";
   1378   this->getSrc(1)->emit(Func);
   1379 }
   1380 
   1381 template <typename TraitsType>
   1382 void InstImpl<TraitsType>::InstX86Mul::emitIAS(const Cfg *Func) const {
   1383   assert(this->getSrcSize() == 2);
   1384   assert(llvm::isa<Variable>(this->getSrc(0)));
   1385   assert(llvm::cast<Variable>(this->getSrc(0))->getRegNum() ==
   1386          RegisterSet::Reg_eax);
   1387   assert(this->getDest()->getRegNum() == RegisterSet::Reg_eax); // TODO:
   1388                                                                 // allow
   1389                                                                 // edx?
   1390   const Operand *Src = this->getSrc(1);
   1391   Type Ty = Src->getType();
   1392   static const GPREmitterOneOp Emitter = {&Assembler::mul, &Assembler::mul};
   1393   emitIASOpTyGPR(Func, Ty, Src, Emitter);
   1394 }
   1395 
   1396 template <typename TraitsType>
   1397 void InstImpl<TraitsType>::InstX86Mul::dump(const Cfg *Func) const {
   1398   if (!BuildDefs::dump())
   1399     return;
   1400   Ostream &Str = Func->getContext()->getStrDump();
   1401   this->dumpDest(Func);
   1402   Str << " = mul." << this->getDest()->getType() << " ";
   1403   this->dumpSources(Func);
   1404 }
   1405 
   1406 template <typename TraitsType>
   1407 void InstImpl<TraitsType>::InstX86Shld::emit(const Cfg *Func) const {
   1408   if (!BuildDefs::dump())
   1409     return;
   1410   Ostream &Str = Func->getContext()->getStrEmit();
   1411   Variable *Dest = this->getDest();
   1412   assert(this->getSrcSize() == 3);
   1413   assert(Dest == this->getSrc(0));
   1414   Str << "\t"
   1415          "shld" << this->getWidthString(Dest->getType()) << "\t";
   1416   this->getSrc(2)->emit(Func);
   1417   Str << ", ";
   1418   this->getSrc(1)->emit(Func);
   1419   Str << ", ";
   1420   Dest->emit(Func);
   1421 }
   1422 
   1423 template <typename TraitsType>
   1424 void InstImpl<TraitsType>::InstX86Shld::emitIAS(const Cfg *Func) const {
   1425   assert(this->getSrcSize() == 3);
   1426   assert(this->getDest() == this->getSrc(0));
   1427   const Variable *Dest = this->getDest();
   1428   const Operand *Src1 = this->getSrc(1);
   1429   const Operand *Src2 = this->getSrc(2);
   1430   static const GPREmitterShiftD Emitter = {&Assembler::shld, &Assembler::shld};
   1431   emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
   1432 }
   1433 
   1434 template <typename TraitsType>
   1435 void InstImpl<TraitsType>::InstX86Shld::dump(const Cfg *Func) const {
   1436   if (!BuildDefs::dump())
   1437     return;
   1438   Ostream &Str = Func->getContext()->getStrDump();
   1439   this->dumpDest(Func);
   1440   Str << " = shld." << this->getDest()->getType() << " ";
   1441   this->dumpSources(Func);
   1442 }
   1443 
   1444 template <typename TraitsType>
   1445 void InstImpl<TraitsType>::InstX86Shrd::emit(const Cfg *Func) const {
   1446   if (!BuildDefs::dump())
   1447     return;
   1448   Ostream &Str = Func->getContext()->getStrEmit();
   1449   Variable *Dest = this->getDest();
   1450   assert(this->getSrcSize() == 3);
   1451   assert(Dest == this->getSrc(0));
   1452   Str << "\t"
   1453          "shrd" << this->getWidthString(Dest->getType()) << "\t";
   1454   this->getSrc(2)->emit(Func);
   1455   Str << ", ";
   1456   this->getSrc(1)->emit(Func);
   1457   Str << ", ";
   1458   Dest->emit(Func);
   1459 }
   1460 
   1461 template <typename TraitsType>
   1462 void InstImpl<TraitsType>::InstX86Shrd::emitIAS(const Cfg *Func) const {
   1463   assert(this->getSrcSize() == 3);
   1464   assert(this->getDest() == this->getSrc(0));
   1465   const Variable *Dest = this->getDest();
   1466   const Operand *Src1 = this->getSrc(1);
   1467   const Operand *Src2 = this->getSrc(2);
   1468   static const GPREmitterShiftD Emitter = {&Assembler::shrd, &Assembler::shrd};
   1469   emitIASGPRShiftDouble(Func, Dest, Src1, Src2, Emitter);
   1470 }
   1471 
   1472 template <typename TraitsType>
   1473 void InstImpl<TraitsType>::InstX86Shrd::dump(const Cfg *Func) const {
   1474   if (!BuildDefs::dump())
   1475     return;
   1476   Ostream &Str = Func->getContext()->getStrDump();
   1477   this->dumpDest(Func);
   1478   Str << " = shrd." << this->getDest()->getType() << " ";
   1479   this->dumpSources(Func);
   1480 }
   1481 
   1482 template <typename TraitsType>
   1483 void InstImpl<TraitsType>::InstX86Cmov::emit(const Cfg *Func) const {
   1484   if (!BuildDefs::dump())
   1485     return;
   1486   Ostream &Str = Func->getContext()->getStrEmit();
   1487   Variable *Dest = this->getDest();
   1488   Str << "\t";
   1489   assert(Condition != Cond::Br_None);
   1490   assert(this->getDest()->hasReg());
   1491   Str << "cmov" << Traits::InstBrAttributes[Condition].DisplayString
   1492       << this->getWidthString(Dest->getType()) << "\t";
   1493   this->getSrc(1)->emit(Func);
   1494   Str << ", ";
   1495   Dest->emit(Func);
   1496 }
   1497 
   1498 template <typename TraitsType>
   1499 void InstImpl<TraitsType>::InstX86Cmov::emitIAS(const Cfg *Func) const {
   1500   assert(Condition != Cond::Br_None);
   1501   assert(this->getDest()->hasReg());
   1502   assert(this->getSrcSize() == 2);
   1503   Operand *Src = this->getSrc(1);
   1504   Type SrcTy = Src->getType();
   1505   assert(SrcTy == IceType_i16 || SrcTy == IceType_i32 || (Traits::Is64Bit));
   1506   Assembler *Asm = Func->getAssembler<Assembler>();
   1507   auto *Target = InstX86Base::getTarget(Func);
   1508   if (const auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
   1509     if (SrcVar->hasReg()) {
   1510       Asm->cmov(SrcTy, Condition,
   1511                 Traits::getEncodedGPR(this->getDest()->getRegNum()),
   1512                 Traits::getEncodedGPR(SrcVar->getRegNum()));
   1513     } else {
   1514       Asm->cmov(SrcTy, Condition,
   1515                 Traits::getEncodedGPR(this->getDest()->getRegNum()),
   1516                 Target->stackVarToAsmOperand(SrcVar));
   1517     }
   1518   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
   1519     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   1520     Asm->cmov(SrcTy, Condition,
   1521               Traits::getEncodedGPR(this->getDest()->getRegNum()),
   1522               Mem->toAsmAddress(Asm, Target));
   1523   } else {
   1524     llvm_unreachable("Unexpected operand type");
   1525   }
   1526 }
   1527 
   1528 template <typename TraitsType>
   1529 void InstImpl<TraitsType>::InstX86Cmov::dump(const Cfg *Func) const {
   1530   if (!BuildDefs::dump())
   1531     return;
   1532   Ostream &Str = Func->getContext()->getStrDump();
   1533   Str << "cmov" << Traits::InstBrAttributes[Condition].DisplayString << ".";
   1534   Str << this->getDest()->getType() << " ";
   1535   this->dumpDest(Func);
   1536   Str << ", ";
   1537   this->dumpSources(Func);
   1538 }
   1539 
   1540 template <typename TraitsType>
   1541 void InstImpl<TraitsType>::InstX86Cmpps::emit(const Cfg *Func) const {
   1542   if (!BuildDefs::dump())
   1543     return;
   1544   Ostream &Str = Func->getContext()->getStrEmit();
   1545   assert(this->getSrcSize() == 2);
   1546   assert(Condition < Cond::Cmpps_Invalid);
   1547   Type DestTy = this->Dest->getType();
   1548   Str << "\t"
   1549          "cmp" << Traits::InstCmppsAttributes[Condition].EmitString
   1550       << Traits::TypeAttributes[DestTy].PdPsString << "\t";
   1551   this->getSrc(1)->emit(Func);
   1552   Str << ", ";
   1553   this->getDest()->emit(Func);
   1554 }
   1555 
   1556 template <typename TraitsType>
   1557 void InstImpl<TraitsType>::InstX86Cmpps::emitIAS(const Cfg *Func) const {
   1558   Assembler *Asm = Func->getAssembler<Assembler>();
   1559   assert(this->getSrcSize() == 2);
   1560   assert(Condition < Cond::Cmpps_Invalid);
   1561   // Assuming there isn't any load folding for cmpps, and vector constants are
   1562   // not allowed in PNaCl.
   1563   assert(llvm::isa<Variable>(this->getSrc(1)));
   1564   auto *Target = InstX86Base::getTarget(Func);
   1565   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
   1566   if (SrcVar->hasReg()) {
   1567     Asm->cmpps(this->getDest()->getType(),
   1568                Traits::getEncodedXmm(this->getDest()->getRegNum()),
   1569                Traits::getEncodedXmm(SrcVar->getRegNum()), Condition);
   1570   } else {
   1571     Address SrcStackAddr = Target->stackVarToAsmOperand(SrcVar);
   1572     Asm->cmpps(this->getDest()->getType(),
   1573                Traits::getEncodedXmm(this->getDest()->getRegNum()),
   1574                SrcStackAddr, Condition);
   1575   }
   1576 }
   1577 
   1578 template <typename TraitsType>
   1579 void InstImpl<TraitsType>::InstX86Cmpps::dump(const Cfg *Func) const {
   1580   if (!BuildDefs::dump())
   1581     return;
   1582   Ostream &Str = Func->getContext()->getStrDump();
   1583   assert(Condition < Cond::Cmpps_Invalid);
   1584   this->dumpDest(Func);
   1585   Str << " = cmp" << Traits::InstCmppsAttributes[Condition].EmitString << "ps"
   1586                                                                           "\t";
   1587   this->dumpSources(Func);
   1588 }
   1589 
   1590 template <typename TraitsType>
   1591 void InstImpl<TraitsType>::InstX86Cmpxchg::emit(const Cfg *Func) const {
   1592   if (!BuildDefs::dump())
   1593     return;
   1594   Ostream &Str = Func->getContext()->getStrEmit();
   1595   assert(this->getSrcSize() == 3);
   1596   if (this->Locked) {
   1597     Str << "\t"
   1598            "lock";
   1599   }
   1600   Str << "\t"
   1601          "cmpxchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
   1602   this->getSrc(2)->emit(Func);
   1603   Str << ", ";
   1604   this->getSrc(0)->emit(Func);
   1605 }
   1606 
   1607 template <typename TraitsType>
   1608 void InstImpl<TraitsType>::InstX86Cmpxchg::emitIAS(const Cfg *Func) const {
   1609   assert(this->getSrcSize() == 3);
   1610   Assembler *Asm = Func->getAssembler<Assembler>();
   1611   Type Ty = this->getSrc(0)->getType();
   1612   auto *Target = InstX86Base::getTarget(Func);
   1613   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
   1614   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   1615   const Address Addr = Mem->toAsmAddress(Asm, Target);
   1616   const auto *VarReg = llvm::cast<Variable>(this->getSrc(2));
   1617   assert(VarReg->hasReg());
   1618   const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
   1619   Asm->cmpxchg(Ty, Addr, Reg, this->Locked);
   1620 }
   1621 
   1622 template <typename TraitsType>
   1623 void InstImpl<TraitsType>::InstX86Cmpxchg::dump(const Cfg *Func) const {
   1624   if (!BuildDefs::dump())
   1625     return;
   1626   Ostream &Str = Func->getContext()->getStrDump();
   1627   if (this->Locked) {
   1628     Str << "lock ";
   1629   }
   1630   Str << "cmpxchg." << this->getSrc(0)->getType() << " ";
   1631   this->dumpSources(Func);
   1632 }
   1633 
   1634 template <typename TraitsType>
   1635 void InstImpl<TraitsType>::InstX86Cmpxchg8b::emit(const Cfg *Func) const {
   1636   if (!BuildDefs::dump())
   1637     return;
   1638   Ostream &Str = Func->getContext()->getStrEmit();
   1639   assert(this->getSrcSize() == 5);
   1640   if (this->Locked) {
   1641     Str << "\t"
   1642            "lock";
   1643   }
   1644   Str << "\t"
   1645          "cmpxchg8b\t";
   1646   this->getSrc(0)->emit(Func);
   1647 }
   1648 
   1649 template <typename TraitsType>
   1650 void InstImpl<TraitsType>::InstX86Cmpxchg8b::emitIAS(const Cfg *Func) const {
   1651   assert(this->getSrcSize() == 5);
   1652   Assembler *Asm = Func->getAssembler<Assembler>();
   1653   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
   1654   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   1655   auto *Target = InstX86Base::getTarget(Func);
   1656   const Address Addr = Mem->toAsmAddress(Asm, Target);
   1657   Asm->cmpxchg8b(Addr, this->Locked);
   1658 }
   1659 
   1660 template <typename TraitsType>
   1661 void InstImpl<TraitsType>::InstX86Cmpxchg8b::dump(const Cfg *Func) const {
   1662   if (!BuildDefs::dump())
   1663     return;
   1664   Ostream &Str = Func->getContext()->getStrDump();
   1665   if (this->Locked) {
   1666     Str << "lock ";
   1667   }
   1668   Str << "cmpxchg8b ";
   1669   this->dumpSources(Func);
   1670 }
   1671 
   1672 template <typename TraitsType>
   1673 void InstImpl<TraitsType>::InstX86Cvt::emit(const Cfg *Func) const {
   1674   if (!BuildDefs::dump())
   1675     return;
   1676   Ostream &Str = Func->getContext()->getStrEmit();
   1677   assert(this->getSrcSize() == 1);
   1678   Str << "\t"
   1679          "cvt";
   1680   if (isTruncating())
   1681     Str << "t";
   1682   Str << Traits::TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
   1683       << Traits::TypeAttributes[this->getDest()->getType()].CvtString << "\t";
   1684   this->getSrc(0)->emit(Func);
   1685   Str << ", ";
   1686   this->getDest()->emit(Func);
   1687 }
   1688 
   1689 template <typename TraitsType>
   1690 void InstImpl<TraitsType>::InstX86Cvt::emitIAS(const Cfg *Func) const {
   1691   assert(this->getSrcSize() == 1);
   1692   const Variable *Dest = this->getDest();
   1693   const Operand *Src = this->getSrc(0);
   1694   Type DestTy = Dest->getType();
   1695   Type SrcTy = Src->getType();
   1696   switch (Variant) {
   1697   case Si2ss: {
   1698     assert(isScalarIntegerType(SrcTy));
   1699     if (!Traits::Is64Bit) {
   1700       assert(typeWidthInBytes(SrcTy) <= 4);
   1701     } else {
   1702       assert(SrcTy == IceType_i32 || SrcTy == IceType_i64);
   1703     }
   1704     assert(isScalarFloatingType(DestTy));
   1705     static const CastEmitterRegOp<XmmRegister, GPRRegister> Emitter = {
   1706         &Assembler::cvtsi2ss, &Assembler::cvtsi2ss};
   1707     emitIASCastRegOp<XmmRegister, GPRRegister, Traits::getEncodedXmm,
   1708                      Traits::getEncodedGPR>(Func, DestTy, Dest, SrcTy, Src,
   1709                                             Emitter);
   1710     return;
   1711   }
   1712   case Tss2si: {
   1713     assert(isScalarFloatingType(SrcTy));
   1714     assert(isScalarIntegerType(DestTy));
   1715     if (Traits::Is64Bit) {
   1716       assert(DestTy == IceType_i32 || DestTy == IceType_i64);
   1717     } else {
   1718       assert(typeWidthInBytes(DestTy) <= 4);
   1719     }
   1720     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
   1721         &Assembler::cvttss2si, &Assembler::cvttss2si};
   1722     emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
   1723                      Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
   1724                                             Emitter);
   1725     return;
   1726   }
   1727   case Ss2si: {
   1728     assert(isScalarFloatingType(SrcTy));
   1729     assert(isScalarIntegerType(DestTy));
   1730     if (Traits::Is64Bit) {
   1731       assert(DestTy == IceType_i32 || DestTy == IceType_i64);
   1732     } else {
   1733       assert(typeWidthInBytes(DestTy) <= 4);
   1734     }
   1735     static const CastEmitterRegOp<GPRRegister, XmmRegister> Emitter = {
   1736         &Assembler::cvtss2si, &Assembler::cvtss2si};
   1737     emitIASCastRegOp<GPRRegister, XmmRegister, Traits::getEncodedGPR,
   1738                      Traits::getEncodedXmm>(Func, DestTy, Dest, SrcTy, Src,
   1739                                             Emitter);
   1740     return;
   1741   }
   1742   case Float2float: {
   1743     assert(isScalarFloatingType(SrcTy));
   1744     assert(isScalarFloatingType(DestTy));
   1745     assert(DestTy != SrcTy);
   1746     static const XmmEmitterRegOp Emitter = {&Assembler::cvtfloat2float,
   1747                                             &Assembler::cvtfloat2float};
   1748     emitIASRegOpTyXMM(Func, SrcTy, Dest, Src, Emitter);
   1749     return;
   1750   }
   1751   case Dq2ps: {
   1752     assert(isVectorIntegerType(SrcTy));
   1753     assert(isVectorFloatingType(DestTy));
   1754     static const XmmEmitterRegOp Emitter = {&Assembler::cvtdq2ps,
   1755                                             &Assembler::cvtdq2ps};
   1756     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
   1757     return;
   1758   }
   1759   case Tps2dq: {
   1760     assert(isVectorFloatingType(SrcTy));
   1761     assert(isVectorIntegerType(DestTy));
   1762     static const XmmEmitterRegOp Emitter = {&Assembler::cvttps2dq,
   1763                                             &Assembler::cvttps2dq};
   1764     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
   1765     return;
   1766   }
   1767   case Ps2dq: {
   1768     assert(isVectorFloatingType(SrcTy));
   1769     assert(isVectorIntegerType(DestTy));
   1770     static const XmmEmitterRegOp Emitter = {&Assembler::cvtps2dq,
   1771                                             &Assembler::cvtps2dq};
   1772     emitIASRegOpTyXMM(Func, DestTy, Dest, Src, Emitter);
   1773     return;
   1774   }
   1775   }
   1776 }
   1777 
   1778 template <typename TraitsType>
   1779 void InstImpl<TraitsType>::InstX86Cvt::dump(const Cfg *Func) const {
   1780   if (!BuildDefs::dump())
   1781     return;
   1782   Ostream &Str = Func->getContext()->getStrDump();
   1783   this->dumpDest(Func);
   1784   Str << " = cvt";
   1785   if (isTruncating())
   1786     Str << "t";
   1787   Str << Traits::TypeAttributes[this->getSrc(0)->getType()].CvtString << "2"
   1788       << Traits::TypeAttributes[this->getDest()->getType()].CvtString << " ";
   1789   this->dumpSources(Func);
   1790 }
   1791 
   1792 template <typename TraitsType>
   1793 void InstImpl<TraitsType>::InstX86Round::emit(const Cfg *Func) const {
   1794   if (!BuildDefs::dump())
   1795     return;
   1796   Ostream &Str = Func->getContext()->getStrEmit();
   1797   assert(this->getSrcSize() == 3);
   1798   Str << "\t" << this->Opcode
   1799       << Traits::TypeAttributes[this->getDest()->getType()].SpSdString << "\t";
   1800   this->getSrc(1)->emit(Func);
   1801   Str << ", ";
   1802   this->getSrc(0)->emit(Func);
   1803   Str << ", ";
   1804   this->getDest()->emit(Func);
   1805 }
   1806 
   1807 template <typename TraitsType>
   1808 void InstImpl<TraitsType>::InstX86Round::emitIAS(const Cfg *Func) const {
   1809   assert(this->getSrcSize() == 2);
   1810   assert(InstX86Base::getTarget(Func)->getInstructionSet() >= Traits::SSE4_1);
   1811   const Variable *Dest = this->getDest();
   1812   Type Ty = Dest->getType();
   1813   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
   1814       &Assembler::round, &Assembler::round};
   1815   emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
   1816                        Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
   1817                                               this->getSrc(1), Emitter);
   1818 }
   1819 
   1820 template <typename TraitsType>
   1821 void InstImpl<TraitsType>::InstX86Icmp::emit(const Cfg *Func) const {
   1822   if (!BuildDefs::dump())
   1823     return;
   1824   Ostream &Str = Func->getContext()->getStrEmit();
   1825   assert(this->getSrcSize() == 2);
   1826   Str << "\t"
   1827          "cmp" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
   1828   this->getSrc(1)->emit(Func);
   1829   Str << ", ";
   1830   this->getSrc(0)->emit(Func);
   1831 }
   1832 
   1833 template <typename TraitsType>
   1834 void InstImpl<TraitsType>::InstX86Icmp::emitIAS(const Cfg *Func) const {
   1835   assert(this->getSrcSize() == 2);
   1836   const Operand *Src0 = this->getSrc(0);
   1837   const Operand *Src1 = this->getSrc(1);
   1838   Type Ty = Src0->getType();
   1839   static const GPREmitterRegOp RegEmitter = {&Assembler::cmp, &Assembler::cmp,
   1840                                              &Assembler::cmp};
   1841   static const GPREmitterAddrOp AddrEmitter = {&Assembler::cmp,
   1842                                                &Assembler::cmp};
   1843   if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
   1844     if (SrcVar0->hasReg()) {
   1845       constexpr bool NotLea = false;
   1846       emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter);
   1847       return;
   1848     }
   1849   }
   1850   emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
   1851 }
   1852 
   1853 template <typename TraitsType>
   1854 void InstImpl<TraitsType>::InstX86Icmp::dump(const Cfg *Func) const {
   1855   if (!BuildDefs::dump())
   1856     return;
   1857   Ostream &Str = Func->getContext()->getStrDump();
   1858   Str << "cmp." << this->getSrc(0)->getType() << " ";
   1859   this->dumpSources(Func);
   1860 }
   1861 
   1862 template <typename TraitsType>
   1863 void InstImpl<TraitsType>::InstX86Ucomiss::emit(const Cfg *Func) const {
   1864   if (!BuildDefs::dump())
   1865     return;
   1866   Ostream &Str = Func->getContext()->getStrEmit();
   1867   assert(this->getSrcSize() == 2);
   1868   Str << "\t"
   1869          "ucomi"
   1870       << Traits::TypeAttributes[this->getSrc(0)->getType()].SdSsString << "\t";
   1871   this->getSrc(1)->emit(Func);
   1872   Str << ", ";
   1873   this->getSrc(0)->emit(Func);
   1874 }
   1875 
   1876 template <typename TraitsType>
   1877 void InstImpl<TraitsType>::InstX86Ucomiss::emitIAS(const Cfg *Func) const {
   1878   assert(this->getSrcSize() == 2);
   1879   // Currently src0 is always a variable by convention, to avoid having two
   1880   // memory operands.
   1881   assert(llvm::isa<Variable>(this->getSrc(0)));
   1882   const auto *Src0Var = llvm::cast<Variable>(this->getSrc(0));
   1883   Type Ty = Src0Var->getType();
   1884   static const XmmEmitterRegOp Emitter = {&Assembler::ucomiss,
   1885                                           &Assembler::ucomiss};
   1886   emitIASRegOpTyXMM(Func, Ty, Src0Var, this->getSrc(1), Emitter);
   1887 }
   1888 
   1889 template <typename TraitsType>
   1890 void InstImpl<TraitsType>::InstX86Ucomiss::dump(const Cfg *Func) const {
   1891   if (!BuildDefs::dump())
   1892     return;
   1893   Ostream &Str = Func->getContext()->getStrDump();
   1894   Str << "ucomiss." << this->getSrc(0)->getType() << " ";
   1895   this->dumpSources(Func);
   1896 }
   1897 
   1898 template <typename TraitsType>
   1899 void InstImpl<TraitsType>::InstX86UD2::emit(const Cfg *Func) const {
   1900   if (!BuildDefs::dump())
   1901     return;
   1902   Ostream &Str = Func->getContext()->getStrEmit();
   1903   assert(this->getSrcSize() == 0);
   1904   Str << "\t"
   1905          "ud2";
   1906 }
   1907 
   1908 template <typename TraitsType>
   1909 void InstImpl<TraitsType>::InstX86UD2::emitIAS(const Cfg *Func) const {
   1910   Assembler *Asm = Func->getAssembler<Assembler>();
   1911   Asm->ud2();
   1912 }
   1913 
   1914 template <typename TraitsType>
   1915 void InstImpl<TraitsType>::InstX86UD2::dump(const Cfg *Func) const {
   1916   if (!BuildDefs::dump())
   1917     return;
   1918   Ostream &Str = Func->getContext()->getStrDump();
   1919   Str << "ud2";
   1920 }
   1921 
   1922 template <typename TraitsType>
   1923 void InstImpl<TraitsType>::InstX86Int3::emit(const Cfg *Func) const {
   1924   if (!BuildDefs::dump())
   1925     return;
   1926   Ostream &Str = Func->getContext()->getStrEmit();
   1927   assert(this->getSrcSize() == 0);
   1928   Str << "\t"
   1929          "int 3";
   1930 }
   1931 
   1932 template <typename TraitsType>
   1933 void InstImpl<TraitsType>::InstX86Int3::emitIAS(const Cfg *Func) const {
   1934   Assembler *Asm = Func->getAssembler<Assembler>();
   1935   Asm->int3();
   1936 }
   1937 
   1938 template <typename TraitsType>
   1939 void InstImpl<TraitsType>::InstX86Int3::dump(const Cfg *Func) const {
   1940   if (!BuildDefs::dump())
   1941     return;
   1942   Ostream &Str = Func->getContext()->getStrDump();
   1943   Str << "int 3";
   1944 }
   1945 
   1946 template <typename TraitsType>
   1947 void InstImpl<TraitsType>::InstX86Test::emit(const Cfg *Func) const {
   1948   if (!BuildDefs::dump())
   1949     return;
   1950   Ostream &Str = Func->getContext()->getStrEmit();
   1951   assert(this->getSrcSize() == 2);
   1952   Str << "\t"
   1953          "test" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
   1954   this->getSrc(1)->emit(Func);
   1955   Str << ", ";
   1956   this->getSrc(0)->emit(Func);
   1957 }
   1958 
   1959 template <typename TraitsType>
   1960 void InstImpl<TraitsType>::InstX86Test::emitIAS(const Cfg *Func) const {
   1961   assert(this->getSrcSize() == 2);
   1962   const Operand *Src0 = this->getSrc(0);
   1963   const Operand *Src1 = this->getSrc(1);
   1964   Type Ty = Src0->getType();
   1965   // The Reg/Addr form of test is not encodeable.
   1966   static const GPREmitterRegOp RegEmitter = {&Assembler::test, nullptr,
   1967                                              &Assembler::test};
   1968   static const GPREmitterAddrOp AddrEmitter = {&Assembler::test,
   1969                                                &Assembler::test};
   1970   if (const auto *SrcVar0 = llvm::dyn_cast<Variable>(Src0)) {
   1971     if (SrcVar0->hasReg()) {
   1972       constexpr bool NotLea = false;
   1973       emitIASRegOpTyGPR(Func, NotLea, Ty, SrcVar0, Src1, RegEmitter);
   1974       return;
   1975     }
   1976   }
   1977   emitIASAsAddrOpTyGPR(Func, Ty, Src0, Src1, AddrEmitter);
   1978 }
   1979 
   1980 template <typename TraitsType>
   1981 void InstImpl<TraitsType>::InstX86Test::dump(const Cfg *Func) const {
   1982   if (!BuildDefs::dump())
   1983     return;
   1984   Ostream &Str = Func->getContext()->getStrDump();
   1985   Str << "test." << this->getSrc(0)->getType() << " ";
   1986   this->dumpSources(Func);
   1987 }
   1988 
   1989 template <typename TraitsType>
   1990 void InstImpl<TraitsType>::InstX86Mfence::emit(const Cfg *Func) const {
   1991   if (!BuildDefs::dump())
   1992     return;
   1993   Ostream &Str = Func->getContext()->getStrEmit();
   1994   assert(this->getSrcSize() == 0);
   1995   Str << "\t"
   1996          "mfence";
   1997 }
   1998 
   1999 template <typename TraitsType>
   2000 void InstImpl<TraitsType>::InstX86Mfence::emitIAS(const Cfg *Func) const {
   2001   Assembler *Asm = Func->getAssembler<Assembler>();
   2002   Asm->mfence();
   2003 }
   2004 
   2005 template <typename TraitsType>
   2006 void InstImpl<TraitsType>::InstX86Mfence::dump(const Cfg *Func) const {
   2007   if (!BuildDefs::dump())
   2008     return;
   2009   Ostream &Str = Func->getContext()->getStrDump();
   2010   Str << "mfence";
   2011 }
   2012 
   2013 template <typename TraitsType>
   2014 void InstImpl<TraitsType>::InstX86Store::emit(const Cfg *Func) const {
   2015   if (!BuildDefs::dump())
   2016     return;
   2017   Ostream &Str = Func->getContext()->getStrEmit();
   2018   assert(this->getSrcSize() == 2);
   2019   Type Ty = this->getSrc(0)->getType();
   2020   Str << "\t"
   2021          "mov" << this->getWidthString(Ty)
   2022       << Traits::TypeAttributes[Ty].SdSsString << "\t";
   2023   this->getSrc(0)->emit(Func);
   2024   Str << ", ";
   2025   this->getSrc(1)->emit(Func);
   2026 }
   2027 
   2028 template <typename TraitsType>
   2029 void InstImpl<TraitsType>::InstX86Store::emitIAS(const Cfg *Func) const {
   2030   assert(this->getSrcSize() == 2);
   2031   const Operand *Dest = this->getSrc(1);
   2032   const Operand *Src = this->getSrc(0);
   2033   Type DestTy = Dest->getType();
   2034   if (isScalarFloatingType(DestTy)) {
   2035     // Src must be a register, since Dest is a Mem operand of some kind.
   2036     const auto *SrcVar = llvm::cast<Variable>(Src);
   2037     assert(SrcVar->hasReg());
   2038     XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
   2039     Assembler *Asm = Func->getAssembler<Assembler>();
   2040     auto *Target = InstX86Base::getTarget(Func);
   2041     if (const auto *DestVar = llvm::dyn_cast<Variable>(Dest)) {
   2042       assert(!DestVar->hasReg());
   2043       Address StackAddr(Target->stackVarToAsmOperand(DestVar));
   2044       Asm->movss(DestTy, StackAddr, SrcReg);
   2045     } else {
   2046       const auto DestMem = llvm::cast<X86OperandMem>(Dest);
   2047       assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   2048       Asm->movss(DestTy, DestMem->toAsmAddress(Asm, Target), SrcReg);
   2049     }
   2050     return;
   2051   } else {
   2052     assert(isScalarIntegerType(DestTy));
   2053     static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
   2054                                                     &Assembler::mov};
   2055     emitIASAsAddrOpTyGPR(Func, DestTy, Dest, Src, GPRAddrEmitter);
   2056   }
   2057 }
   2058 
   2059 template <typename TraitsType>
   2060 void InstImpl<TraitsType>::InstX86Store::dump(const Cfg *Func) const {
   2061   if (!BuildDefs::dump())
   2062     return;
   2063   Ostream &Str = Func->getContext()->getStrDump();
   2064   Str << "mov." << this->getSrc(0)->getType() << " ";
   2065   this->getSrc(1)->dump(Func);
   2066   Str << ", ";
   2067   this->getSrc(0)->dump(Func);
   2068 }
   2069 
   2070 template <typename TraitsType>
   2071 void InstImpl<TraitsType>::InstX86StoreP::emit(const Cfg *Func) const {
   2072   if (!BuildDefs::dump())
   2073     return;
   2074   Ostream &Str = Func->getContext()->getStrEmit();
   2075   assert(this->getSrcSize() == 2);
   2076   assert(isVectorType(this->getSrc(1)->getType()));
   2077   Str << "\t"
   2078          "movups\t";
   2079   this->getSrc(0)->emit(Func);
   2080   Str << ", ";
   2081   this->getSrc(1)->emit(Func);
   2082 }
   2083 
   2084 template <typename TraitsType>
   2085 void InstImpl<TraitsType>::InstX86StoreP::emitIAS(const Cfg *Func) const {
   2086   Assembler *Asm = Func->getAssembler<Assembler>();
   2087   assert(this->getSrcSize() == 2);
   2088   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
   2089   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
   2090   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   2091   assert(SrcVar->hasReg());
   2092   auto *Target = InstX86Base::getTarget(Func);
   2093   Asm->movups(DestMem->toAsmAddress(Asm, Target),
   2094               Traits::getEncodedXmm(SrcVar->getRegNum()));
   2095 }
   2096 
   2097 template <typename TraitsType>
   2098 void InstImpl<TraitsType>::InstX86StoreP::dump(const Cfg *Func) const {
   2099   if (!BuildDefs::dump())
   2100     return;
   2101   Ostream &Str = Func->getContext()->getStrDump();
   2102   Str << "storep." << this->getSrc(0)->getType() << " ";
   2103   this->getSrc(1)->dump(Func);
   2104   Str << ", ";
   2105   this->getSrc(0)->dump(Func);
   2106 }
   2107 
   2108 template <typename TraitsType>
   2109 void InstImpl<TraitsType>::InstX86StoreQ::emit(const Cfg *Func) const {
   2110   if (!BuildDefs::dump())
   2111     return;
   2112   Ostream &Str = Func->getContext()->getStrEmit();
   2113   assert(this->getSrcSize() == 2);
   2114   assert(this->getSrc(1)->getType() == IceType_i64 ||
   2115          this->getSrc(1)->getType() == IceType_f64 ||
   2116          isVectorType(this->getSrc(1)->getType()));
   2117   Str << "\t"
   2118          "movq\t";
   2119   this->getSrc(0)->emit(Func);
   2120   Str << ", ";
   2121   this->getSrc(1)->emit(Func);
   2122 }
   2123 
   2124 template <typename TraitsType>
   2125 void InstImpl<TraitsType>::InstX86StoreQ::emitIAS(const Cfg *Func) const {
   2126   Assembler *Asm = Func->getAssembler<Assembler>();
   2127   assert(this->getSrcSize() == 2);
   2128   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
   2129   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
   2130   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   2131   assert(SrcVar->hasReg());
   2132   auto *Target = InstX86Base::getTarget(Func);
   2133   Asm->movq(DestMem->toAsmAddress(Asm, Target),
   2134             Traits::getEncodedXmm(SrcVar->getRegNum()));
   2135 }
   2136 
   2137 template <typename TraitsType>
   2138 void InstImpl<TraitsType>::InstX86StoreQ::dump(const Cfg *Func) const {
   2139   if (!BuildDefs::dump())
   2140     return;
   2141   Ostream &Str = Func->getContext()->getStrDump();
   2142   Str << "storeq." << this->getSrc(0)->getType() << " ";
   2143   this->getSrc(1)->dump(Func);
   2144   Str << ", ";
   2145   this->getSrc(0)->dump(Func);
   2146 }
   2147 
   2148 template <typename TraitsType>
   2149 void InstImpl<TraitsType>::InstX86StoreD::emit(const Cfg *Func) const {
   2150   if (!BuildDefs::dump())
   2151     return;
   2152   Ostream &Str = Func->getContext()->getStrEmit();
   2153   assert(this->getSrcSize() == 2);
   2154   assert(this->getSrc(1)->getType() == IceType_i64 ||
   2155          this->getSrc(1)->getType() == IceType_f64 ||
   2156          isVectorType(this->getSrc(1)->getType()));
   2157   Str << "\t"
   2158          "movd\t";
   2159   this->getSrc(0)->emit(Func);
   2160   Str << ", ";
   2161   this->getSrc(1)->emit(Func);
   2162 }
   2163 
   2164 template <typename TraitsType>
   2165 void InstImpl<TraitsType>::InstX86StoreD::emitIAS(const Cfg *Func) const {
   2166   Assembler *Asm = Func->getAssembler<Assembler>();
   2167   assert(this->getSrcSize() == 2);
   2168   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(0));
   2169   const auto DestMem = llvm::cast<X86OperandMem>(this->getSrc(1));
   2170   assert(DestMem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   2171   assert(SrcVar->hasReg());
   2172   auto *Target = InstX86Base::getTarget(Func);
   2173   Asm->movd(SrcVar->getType(), DestMem->toAsmAddress(Asm, Target),
   2174             Traits::getEncodedXmm(SrcVar->getRegNum()));
   2175 }
   2176 
   2177 template <typename TraitsType>
   2178 void InstImpl<TraitsType>::InstX86StoreD::dump(const Cfg *Func) const {
   2179   if (!BuildDefs::dump())
   2180     return;
   2181   Ostream &Str = Func->getContext()->getStrDump();
   2182   Str << "stored." << this->getSrc(0)->getType() << " ";
   2183   this->getSrc(1)->dump(Func);
   2184   Str << ", ";
   2185   this->getSrc(0)->dump(Func);
   2186 }
   2187 
   2188 template <typename TraitsType>
   2189 void InstImpl<TraitsType>::InstX86Lea::emit(const Cfg *Func) const {
   2190   if (!BuildDefs::dump())
   2191     return;
   2192   if (auto *Add = this->deoptLeaToAddOrNull(Func)) {
   2193     Add->emit(Func);
   2194     return;
   2195   }
   2196 
   2197   Ostream &Str = Func->getContext()->getStrEmit();
   2198   assert(this->getSrcSize() == 1);
   2199   assert(this->getDest()->hasReg());
   2200   Str << "\t"
   2201          "lea" << this->getWidthString(this->getDest()->getType()) << "\t";
   2202   Operand *Src0 = this->getSrc(0);
   2203   if (const auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
   2204     Type Ty = Src0Var->getType();
   2205     // lea on x86-32 doesn't accept mem128 operands, so cast VSrc0 to an
   2206     // acceptable type.
   2207     Src0Var->asType(Func, isVectorType(Ty) ? IceType_i32 : Ty, RegNumT())
   2208         ->emit(Func);
   2209   } else {
   2210     Src0->emit(Func);
   2211   }
   2212   Str << ", ";
   2213   this->getDest()->emit(Func);
   2214 }
   2215 
   2216 template <typename TraitsType>
   2217 void InstImpl<TraitsType>::InstX86Mov::emit(const Cfg *Func) const {
   2218   if (!BuildDefs::dump())
   2219     return;
   2220   Ostream &Str = Func->getContext()->getStrEmit();
   2221   assert(this->getSrcSize() == 1);
   2222   Operand *Src = this->getSrc(0);
   2223   Type SrcTy = Src->getType();
   2224   Type DestTy = this->getDest()->getType();
   2225   if (Traits::Is64Bit && DestTy == IceType_i64 &&
   2226       llvm::isa<ConstantInteger64>(Src) &&
   2227       !Utils::IsInt(32, llvm::cast<ConstantInteger64>(Src)->getValue())) {
   2228     Str << "\t"
   2229            "movabs"
   2230            "\t";
   2231   } else {
   2232     Str << "\t"
   2233            "mov" << (!isScalarFloatingType(DestTy)
   2234                          ? this->getWidthString(DestTy)
   2235                          : Traits::TypeAttributes[DestTy].SdSsString) << "\t";
   2236   }
   2237   // For an integer truncation operation, src is wider than dest. In this case,
   2238   // we use a mov instruction whose data width matches the narrower dest.
   2239   // TODO: This assert disallows usages such as copying a floating
   2240   // point value between a vector and a scalar (which movss is used for). Clean
   2241   // this up.
   2242   assert(InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(DestTy) ==
   2243          InstX86Base::getTarget(Func)->typeWidthInBytesOnStack(SrcTy));
   2244   const Operand *NewSrc = Src;
   2245   if (auto *SrcVar = llvm::dyn_cast<Variable>(Src)) {
   2246     RegNumT NewRegNum;
   2247     if (SrcVar->hasReg())
   2248       NewRegNum = Traits::getGprForType(DestTy, SrcVar->getRegNum());
   2249     if (SrcTy != DestTy)
   2250       NewSrc = SrcVar->asType(Func, DestTy, NewRegNum);
   2251   }
   2252   NewSrc->emit(Func);
   2253   Str << ", ";
   2254   this->getDest()->emit(Func);
   2255 }
   2256 
   2257 template <typename TraitsType>
   2258 void InstImpl<TraitsType>::InstX86Mov::emitIAS(const Cfg *Func) const {
   2259   assert(this->getSrcSize() == 1);
   2260   const Variable *Dest = this->getDest();
   2261   const Operand *Src = this->getSrc(0);
   2262   Type DestTy = Dest->getType();
   2263   Type SrcTy = Src->getType();
   2264   // Mov can be used for GPRs or XMM registers. Also, the type does not
   2265   // necessarily match (Mov can be used for bitcasts). However, when the type
   2266   // does not match, one of the operands must be a register. Thus, the strategy
   2267   // is to find out if Src or Dest are a register, then use that register's
   2268   // type to decide on which emitter set to use. The emitter set will include
   2269   // reg-reg movs, but that case should be unused when the types don't match.
   2270   static const XmmEmitterRegOp XmmRegEmitter = {&Assembler::movss,
   2271                                                 &Assembler::movss};
   2272   static const GPREmitterRegOp GPRRegEmitter = {
   2273       &Assembler::mov, &Assembler::mov, &Assembler::mov};
   2274   static const GPREmitterAddrOp GPRAddrEmitter = {&Assembler::mov,
   2275                                                   &Assembler::mov};
   2276   // For an integer truncation operation, src is wider than dest. In this case,
   2277   // we use a mov instruction whose data width matches the narrower dest.
   2278   // TODO: This assert disallows usages such as copying a floating
   2279   // point value between a vector and a scalar (which movss is used for). Clean
   2280   // this up.
   2281   auto *Target = InstX86Base::getTarget(Func);
   2282   assert(Target->typeWidthInBytesOnStack(this->getDest()->getType()) ==
   2283          Target->typeWidthInBytesOnStack(Src->getType()));
   2284   if (Dest->hasReg()) {
   2285     if (isScalarFloatingType(DestTy)) {
   2286       emitIASRegOpTyXMM(Func, DestTy, Dest, Src, XmmRegEmitter);
   2287       return;
   2288     } else {
   2289       assert(isScalarIntegerType(DestTy));
   2290       // Widen DestTy for truncation (see above note). We should only do this
   2291       // when both Src and Dest are integer types.
   2292       if (Traits::Is64Bit && DestTy == IceType_i64) {
   2293         if (const auto *C64 = llvm::dyn_cast<ConstantInteger64>(Src)) {
   2294           Func->getAssembler<Assembler>()->movabs(
   2295               Traits::getEncodedGPR(Dest->getRegNum()), C64->getValue());
   2296           return;
   2297         }
   2298       }
   2299       if (isScalarIntegerType(SrcTy)) {
   2300         SrcTy = DestTy;
   2301       }
   2302       constexpr bool NotLea = false;
   2303       emitIASRegOpTyGPR(Func, NotLea, DestTy, Dest, Src, GPRRegEmitter);
   2304       return;
   2305     }
   2306   } else {
   2307     // Dest must be Stack and Src *could* be a register. Use Src's type to
   2308     // decide on the emitters.
   2309     Address StackAddr(Target->stackVarToAsmOperand(Dest));
   2310     if (isScalarFloatingType(SrcTy)) {
   2311       // Src must be a register.
   2312       const auto *SrcVar = llvm::cast<Variable>(Src);
   2313       assert(SrcVar->hasReg());
   2314       Assembler *Asm = Func->getAssembler<Assembler>();
   2315       Asm->movss(SrcTy, StackAddr, Traits::getEncodedXmm(SrcVar->getRegNum()));
   2316       return;
   2317     } else {
   2318       // Src can be a register or immediate.
   2319       assert(isScalarIntegerType(SrcTy));
   2320       emitIASAddrOpTyGPR(Func, SrcTy, StackAddr, Src, GPRAddrEmitter);
   2321       return;
   2322     }
   2323     return;
   2324   }
   2325 }
   2326 
   2327 template <typename TraitsType>
   2328 void InstImpl<TraitsType>::InstX86Movd::emit(const Cfg *Func) const {
   2329   if (!BuildDefs::dump())
   2330     return;
   2331   assert(this->getSrcSize() == 1);
   2332   Variable *Dest = this->getDest();
   2333   Operand *Src = this->getSrc(0);
   2334 
   2335   if (Dest->getType() == IceType_i64 || Src->getType() == IceType_i64) {
   2336     assert(Dest->getType() == IceType_f64 || Src->getType() == IceType_f64);
   2337     assert(Dest->getType() != Src->getType());
   2338     Ostream &Str = Func->getContext()->getStrEmit();
   2339     Str << "\t"
   2340            "movq"
   2341            "\t";
   2342     Src->emit(Func);
   2343     Str << ", ";
   2344     Dest->emit(Func);
   2345     return;
   2346   }
   2347 
   2348   InstX86BaseUnaryopXmm<InstX86Base::Movd>::emit(Func);
   2349 }
   2350 
   2351 template <typename TraitsType>
   2352 void InstImpl<TraitsType>::InstX86Movd::emitIAS(const Cfg *Func) const {
   2353   Assembler *Asm = Func->getAssembler<Assembler>();
   2354   assert(this->getSrcSize() == 1);
   2355   const Variable *Dest = this->getDest();
   2356   auto *Target = InstX86Base::getTarget(Func);
   2357   // For insert/extract element (one of Src/Dest is an Xmm vector and the other
   2358   // is an int type).
   2359   if (const auto *SrcVar = llvm::dyn_cast<Variable>(this->getSrc(0))) {
   2360     if (SrcVar->getType() == IceType_i32 ||
   2361         (Traits::Is64Bit && SrcVar->getType() == IceType_i64)) {
   2362       assert(isVectorType(Dest->getType()) ||
   2363              (isScalarFloatingType(Dest->getType()) &&
   2364               typeWidthInBytes(SrcVar->getType()) ==
   2365                   typeWidthInBytes(Dest->getType())));
   2366       assert(Dest->hasReg());
   2367       XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
   2368       if (SrcVar->hasReg()) {
   2369         Asm->movd(SrcVar->getType(), DestReg,
   2370                   Traits::getEncodedGPR(SrcVar->getRegNum()));
   2371       } else {
   2372         Address StackAddr(Target->stackVarToAsmOperand(SrcVar));
   2373         Asm->movd(SrcVar->getType(), DestReg, StackAddr);
   2374       }
   2375     } else {
   2376       assert(isVectorType(SrcVar->getType()) ||
   2377              (isScalarFloatingType(SrcVar->getType()) &&
   2378               typeWidthInBytes(SrcVar->getType()) ==
   2379                   typeWidthInBytes(Dest->getType())));
   2380       assert(SrcVar->hasReg());
   2381       assert(Dest->getType() == IceType_i32 ||
   2382              (Traits::Is64Bit && Dest->getType() == IceType_i64));
   2383       XmmRegister SrcReg = Traits::getEncodedXmm(SrcVar->getRegNum());
   2384       if (Dest->hasReg()) {
   2385         Asm->movd(Dest->getType(), Traits::getEncodedGPR(Dest->getRegNum()),
   2386                   SrcReg);
   2387       } else {
   2388         Address StackAddr(Target->stackVarToAsmOperand(Dest));
   2389         Asm->movd(Dest->getType(), StackAddr, SrcReg);
   2390       }
   2391     }
   2392   } else {
   2393     assert(Dest->hasReg());
   2394     XmmRegister DestReg = Traits::getEncodedXmm(Dest->getRegNum());
   2395     auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
   2396     Asm->movd(Mem->getType(), DestReg, Mem->toAsmAddress(Asm, Target));
   2397   }
   2398 }
   2399 
   2400 template <typename TraitsType>
   2401 void InstImpl<TraitsType>::InstX86Movp::emit(const Cfg *Func) const {
   2402   if (!BuildDefs::dump())
   2403     return;
   2404   // TODO(wala,stichnot): movups works with all vector operands, but there
   2405   // exist other instructions (movaps, movdqa, movdqu) that may perform better,
   2406   // depending on the data type and alignment of the operands.
   2407   Ostream &Str = Func->getContext()->getStrEmit();
   2408   assert(this->getSrcSize() == 1);
   2409   Str << "\t"
   2410          "movups\t";
   2411   this->getSrc(0)->emit(Func);
   2412   Str << ", ";
   2413   this->getDest()->emit(Func);
   2414 }
   2415 
   2416 template <typename TraitsType>
   2417 void InstImpl<TraitsType>::InstX86Movp::emitIAS(const Cfg *Func) const {
   2418   assert(this->getSrcSize() == 1);
   2419   assert(isVectorType(this->getDest()->getType()));
   2420   const Variable *Dest = this->getDest();
   2421   const Operand *Src = this->getSrc(0);
   2422   static const XmmEmitterMovOps Emitter = {
   2423       &Assembler::movups, &Assembler::movups, &Assembler::movups};
   2424   emitIASMovlikeXMM(Func, Dest, Src, Emitter);
   2425 }
   2426 
   2427 template <typename TraitsType>
   2428 void InstImpl<TraitsType>::InstX86Movq::emit(const Cfg *Func) const {
   2429   if (!BuildDefs::dump())
   2430     return;
   2431   Ostream &Str = Func->getContext()->getStrEmit();
   2432   assert(this->getSrcSize() == 1);
   2433   assert(this->getDest()->getType() == IceType_i64 ||
   2434          this->getDest()->getType() == IceType_f64);
   2435   Str << "\t"
   2436          "movq"
   2437          "\t";
   2438   this->getSrc(0)->emit(Func);
   2439   Str << ", ";
   2440   this->getDest()->emit(Func);
   2441 }
   2442 
   2443 template <typename TraitsType>
   2444 void InstImpl<TraitsType>::InstX86Movq::emitIAS(const Cfg *Func) const {
   2445   assert(this->getSrcSize() == 1);
   2446   assert(this->getDest()->getType() == IceType_i64 ||
   2447          this->getDest()->getType() == IceType_f64 ||
   2448          isVectorType(this->getDest()->getType()));
   2449   const Variable *Dest = this->getDest();
   2450   const Operand *Src = this->getSrc(0);
   2451   static const XmmEmitterMovOps Emitter = {&Assembler::movq, &Assembler::movq,
   2452                                            &Assembler::movq};
   2453   emitIASMovlikeXMM(Func, Dest, Src, Emitter);
   2454 }
   2455 
   2456 template <typename TraitsType>
   2457 void InstImpl<TraitsType>::InstX86MovssRegs::emitIAS(const Cfg *Func) const {
   2458   // This is Binop variant is only intended to be used for reg-reg moves where
   2459   // part of the Dest register is untouched.
   2460   assert(this->getSrcSize() == 2);
   2461   const Variable *Dest = this->getDest();
   2462   assert(Dest == this->getSrc(0));
   2463   const auto *SrcVar = llvm::cast<Variable>(this->getSrc(1));
   2464   assert(Dest->hasReg() && SrcVar->hasReg());
   2465   Assembler *Asm = Func->getAssembler<Assembler>();
   2466   Asm->movss(IceType_f32, Traits::getEncodedXmm(Dest->getRegNum()),
   2467              Traits::getEncodedXmm(SrcVar->getRegNum()));
   2468 }
   2469 
   2470 template <typename TraitsType>
   2471 void InstImpl<TraitsType>::InstX86Movsx::emitIAS(const Cfg *Func) const {
   2472   assert(this->getSrcSize() == 1);
   2473   const Variable *Dest = this->getDest();
   2474   const Operand *Src = this->getSrc(0);
   2475   // Dest must be a > 8-bit register, but Src can be 8-bit. In practice we just
   2476   // use the full register for Dest to avoid having an OperandSizeOverride
   2477   // prefix. It also allows us to only dispatch on SrcTy.
   2478   Type SrcTy = Src->getType();
   2479   assert(typeWidthInBytes(Dest->getType()) > 1);
   2480   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
   2481   constexpr bool NotLea = false;
   2482   emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter);
   2483 }
   2484 
   2485 template <typename TraitsType>
   2486 bool InstImpl<TraitsType>::InstX86Movzx::mayBeElided(
   2487     const Variable *Dest, const Operand *SrcOpnd) const {
   2488   assert(Traits::Is64Bit);
   2489   const auto *Src = llvm::dyn_cast<Variable>(SrcOpnd);
   2490 
   2491   // Src is not a Variable, so it does not have a register. Movzx can't be
   2492   // elided.
   2493   if (Src == nullptr)
   2494     return false;
   2495 
   2496   // Movzx to/from memory can't be elided.
   2497   if (!Src->hasReg() || !Dest->hasReg())
   2498     return false;
   2499 
   2500   // Reg/reg move with different source and dest can't be elided.
   2501   if (Traits::getEncodedGPR(Src->getRegNum()) !=
   2502       Traits::getEncodedGPR(Dest->getRegNum()))
   2503     return false;
   2504 
   2505   // A must-keep movzx 32- to 64-bit is sometimes needed in x86-64 sandboxing.
   2506   return !MustKeep;
   2507 }
   2508 
   2509 template <typename TraitsType>
   2510 void InstImpl<TraitsType>::InstX86Movzx::emit(const Cfg *Func) const {
   2511   if (!BuildDefs::dump())
   2512     return;
   2513   if (Traits::Is64Bit) {
   2514     // There's no movzx %eXX, %rXX. To zero extend 32- to 64-bits, we emit a
   2515     // mov %eXX, %eXX. The processor will still do a movzx[bw]q.
   2516     assert(this->getSrcSize() == 1);
   2517     const Operand *Src = this->getSrc(0);
   2518     const Variable *Dest = this->Dest;
   2519     if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64) {
   2520       Ostream &Str = Func->getContext()->getStrEmit();
   2521       if (mayBeElided(Dest, Src)) {
   2522         Str << "\t/* elided movzx */";
   2523       } else {
   2524         Str << "\t"
   2525                "mov"
   2526                "\t";
   2527         Src->emit(Func);
   2528         Str << ", ";
   2529         Dest->asType(Func, IceType_i32,
   2530                      Traits::getGprForType(IceType_i32, Dest->getRegNum()))
   2531             ->emit(Func);
   2532         Str << " /* movzx */";
   2533       }
   2534       return;
   2535     }
   2536   }
   2537   InstX86BaseUnaryopGPR<InstX86Base::Movzx>::emit(Func);
   2538 }
   2539 
   2540 template <typename TraitsType>
   2541 void InstImpl<TraitsType>::InstX86Movzx::emitIAS(const Cfg *Func) const {
   2542   assert(this->getSrcSize() == 1);
   2543   const Variable *Dest = this->getDest();
   2544   const Operand *Src = this->getSrc(0);
   2545   Type SrcTy = Src->getType();
   2546   assert(typeWidthInBytes(Dest->getType()) > 1);
   2547   assert(typeWidthInBytes(Dest->getType()) > typeWidthInBytes(SrcTy));
   2548   if (Traits::Is64Bit) {
   2549     if (Src->getType() == IceType_i32 && Dest->getType() == IceType_i64 &&
   2550         mayBeElided(Dest, Src)) {
   2551       return;
   2552     }
   2553   }
   2554   constexpr bool NotLea = false;
   2555   emitIASRegOpTyGPR<false, true>(Func, NotLea, SrcTy, Dest, Src, this->Emitter);
   2556 }
   2557 
   2558 template <typename TraitsType>
   2559 void InstImpl<TraitsType>::InstX86Nop::emit(const Cfg *Func) const {
   2560   if (!BuildDefs::dump())
   2561     return;
   2562   Ostream &Str = Func->getContext()->getStrEmit();
   2563   // TODO: Emit the right code for each variant.
   2564   Str << "\t"
   2565          "nop\t/* variant = " << Variant << " */";
   2566 }
   2567 
   2568 template <typename TraitsType>
   2569 void InstImpl<TraitsType>::InstX86Nop::emitIAS(const Cfg *Func) const {
   2570   Assembler *Asm = Func->getAssembler<Assembler>();
   2571   // TODO: Emit the right code for the variant.
   2572   Asm->nop();
   2573 }
   2574 
   2575 template <typename TraitsType>
   2576 void InstImpl<TraitsType>::InstX86Nop::dump(const Cfg *Func) const {
   2577   if (!BuildDefs::dump())
   2578     return;
   2579   Ostream &Str = Func->getContext()->getStrDump();
   2580   Str << "nop (variant = " << Variant << ")";
   2581 }
   2582 
   2583 template <typename TraitsType>
   2584 void InstImpl<TraitsType>::InstX86Fld::emit(const Cfg *Func) const {
   2585   if (!BuildDefs::dump())
   2586     return;
   2587   Ostream &Str = Func->getContext()->getStrEmit();
   2588   assert(this->getSrcSize() == 1);
   2589   Type Ty = this->getSrc(0)->getType();
   2590   const auto *Var = llvm::dyn_cast<Variable>(this->getSrc(0));
   2591   if (Var && Var->hasReg()) {
   2592     // This is a physical xmm register, so we need to spill it to a temporary
   2593     // stack slot.  Function prolog emission guarantees that there is sufficient
   2594     // space to do this.
   2595     Str << "\t"
   2596            "mov" << Traits::TypeAttributes[Ty].SdSsString << "\t";
   2597     Var->emit(Func);
   2598     Str << ", (%esp)\n"
   2599            "\t"
   2600            "fld" << this->getFldString(Ty) << "\t"
   2601                                               "(%esp)";
   2602     return;
   2603   }
   2604   Str << "\t"
   2605          "fld" << this->getFldString(Ty) << "\t";
   2606   this->getSrc(0)->emit(Func);
   2607 }
   2608 
   2609 template <typename TraitsType>
   2610 void InstImpl<TraitsType>::InstX86Fld::emitIAS(const Cfg *Func) const {
   2611   Assembler *Asm = Func->getAssembler<Assembler>();
   2612   assert(this->getSrcSize() == 1);
   2613   const Operand *Src = this->getSrc(0);
   2614   auto *Target = InstX86Base::getTarget(Func);
   2615   Type Ty = Src->getType();
   2616   if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
   2617     if (Var->hasReg()) {
   2618       // This is a physical xmm register, so we need to spill it to a temporary
   2619       // stack slot.  Function prolog emission guarantees that there is
   2620       // sufficient space to do this.
   2621       Address StackSlot =
   2622           Address(RegisterSet::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup);
   2623       Asm->movss(Ty, StackSlot, Traits::getEncodedXmm(Var->getRegNum()));
   2624       Asm->fld(Ty, StackSlot);
   2625     } else {
   2626       Address StackAddr(Target->stackVarToAsmOperand(Var));
   2627       Asm->fld(Ty, StackAddr);
   2628     }
   2629   } else if (const auto *Mem = llvm::dyn_cast<X86OperandMem>(Src)) {
   2630     assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   2631     Asm->fld(Ty, Mem->toAsmAddress(Asm, Target));
   2632   } else if (const auto *Imm = llvm::dyn_cast<Constant>(Src)) {
   2633     Asm->fld(Ty, Traits::Address::ofConstPool(Asm, Imm));
   2634   } else {
   2635     llvm_unreachable("Unexpected operand type");
   2636   }
   2637 }
   2638 
   2639 template <typename TraitsType>
   2640 void InstImpl<TraitsType>::InstX86Fld::dump(const Cfg *Func) const {
   2641   if (!BuildDefs::dump())
   2642     return;
   2643   Ostream &Str = Func->getContext()->getStrDump();
   2644   Str << "fld." << this->getSrc(0)->getType() << " ";
   2645   this->dumpSources(Func);
   2646 }
   2647 
   2648 template <typename TraitsType>
   2649 void InstImpl<TraitsType>::InstX86Fstp::emit(const Cfg *Func) const {
   2650   if (!BuildDefs::dump())
   2651     return;
   2652   Ostream &Str = Func->getContext()->getStrEmit();
   2653   assert(this->getSrcSize() == 0);
   2654   // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
   2655   // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
   2656   // the fstp should be kept for the SideEffects of popping the stack.
   2657   if (!this->getDest()) {
   2658     Str << "\t"
   2659            "fstp\t"
   2660            "st(0)";
   2661     return;
   2662   }
   2663   Type Ty = this->getDest()->getType();
   2664   if (!this->getDest()->hasReg()) {
   2665     Str << "\t"
   2666            "fstp" << this->getFldString(Ty) << "\t";
   2667     this->getDest()->emit(Func);
   2668     return;
   2669   }
   2670   // Dest is a physical (xmm) register, so st(0) needs to go through memory.
   2671   // Hack this by using caller-reserved memory at the top of stack, spilling
   2672   // st(0) there, and loading it into the xmm register.
   2673   Str << "\t"
   2674          "fstp" << this->getFldString(Ty) << "\t"
   2675                                              "(%esp)\n";
   2676   Str << "\t"
   2677          "mov" << Traits::TypeAttributes[Ty].SdSsString << "\t"
   2678                                                            "(%esp), ";
   2679   this->getDest()->emit(Func);
   2680 }
   2681 
   2682 template <typename TraitsType>
   2683 void InstImpl<TraitsType>::InstX86Fstp::emitIAS(const Cfg *Func) const {
   2684   Assembler *Asm = Func->getAssembler<Assembler>();
   2685   assert(this->getSrcSize() == 0);
   2686   const Variable *Dest = this->getDest();
   2687   // TODO(jvoung,stichnot): Utilize this by setting Dest to nullptr to
   2688   // "partially" delete the fstp if the Dest is unused. Even if Dest is unused,
   2689   // the fstp should be kept for the SideEffects of popping the stack.
   2690   if (!Dest) {
   2691     Asm->fstp(RegisterSet::getEncodedSTReg(0));
   2692     return;
   2693   }
   2694   auto *Target = InstX86Base::getTarget(Func);
   2695   Type Ty = Dest->getType();
   2696   if (!Dest->hasReg()) {
   2697     Address StackAddr(Target->stackVarToAsmOperand(Dest));
   2698     Asm->fstp(Ty, StackAddr);
   2699   } else {
   2700     // Dest is a physical (xmm) register, so st(0) needs to go through memory.
   2701     // Hack this by using caller-reserved memory at the top of stack, spilling
   2702     // st(0) there, and loading it into the xmm register.
   2703     Address StackSlot =
   2704         Address(RegisterSet::Encoded_Reg_esp, 0, AssemblerFixup::NoFixup);
   2705     Asm->fstp(Ty, StackSlot);
   2706     Asm->movss(Ty, Traits::getEncodedXmm(Dest->getRegNum()), StackSlot);
   2707   }
   2708 }
   2709 
   2710 template <typename TraitsType>
   2711 void InstImpl<TraitsType>::InstX86Fstp::dump(const Cfg *Func) const {
   2712   if (!BuildDefs::dump())
   2713     return;
   2714   Ostream &Str = Func->getContext()->getStrDump();
   2715   this->dumpDest(Func);
   2716   Str << " = fstp." << this->getDest()->getType() << ", st(0)";
   2717 }
   2718 
   2719 template <typename TraitsType>
   2720 void InstImpl<TraitsType>::InstX86Pextr::emit(const Cfg *Func) const {
   2721   if (!BuildDefs::dump())
   2722     return;
   2723   Ostream &Str = Func->getContext()->getStrEmit();
   2724   assert(this->getSrcSize() == 2);
   2725   // pextrb and pextrd are SSE4.1 instructions.
   2726   Str << "\t" << this->Opcode
   2727       << Traits::TypeAttributes[this->getSrc(0)->getType()].IntegralString
   2728       << "\t";
   2729   this->getSrc(1)->emit(Func);
   2730   Str << ", ";
   2731   this->getSrc(0)->emit(Func);
   2732   Str << ", ";
   2733   Variable *Dest = this->getDest();
   2734   // pextrw must take a register dest. There is an SSE4.1 version that takes a
   2735   // memory dest, but we aren't using it. For uniformity, just restrict them
   2736   // all to have a register dest for now.
   2737   assert(Dest->hasReg());
   2738   Dest->asType(Func, IceType_i32, Dest->getRegNum())->emit(Func);
   2739 }
   2740 
   2741 template <typename TraitsType>
   2742 void InstImpl<TraitsType>::InstX86Pextr::emitIAS(const Cfg *Func) const {
   2743   assert(this->getSrcSize() == 2);
   2744   // pextrb and pextrd are SSE4.1 instructions.
   2745   const Variable *Dest = this->getDest();
   2746   Type DispatchTy = Traits::getInVectorElementType(this->getSrc(0)->getType());
   2747   // pextrw must take a register dest. There is an SSE4.1 version that takes a
   2748   // memory dest, but we aren't using it. For uniformity, just restrict them
   2749   // all to have a register dest for now.
   2750   assert(Dest->hasReg());
   2751   // pextrw's Src(0) must be a register (both SSE4.1 and SSE2).
   2752   assert(llvm::cast<Variable>(this->getSrc(0))->hasReg());
   2753   static const ThreeOpImmEmitter<GPRRegister, XmmRegister> Emitter = {
   2754       &Assembler::pextr, nullptr};
   2755   emitIASThreeOpImmOps<GPRRegister, XmmRegister, Traits::getEncodedGPR,
   2756                        Traits::getEncodedXmm>(
   2757       Func, DispatchTy, Dest, this->getSrc(0), this->getSrc(1), Emitter);
   2758 }
   2759 
   2760 template <typename TraitsType>
   2761 void InstImpl<TraitsType>::InstX86Pinsr::emit(const Cfg *Func) const {
   2762   if (!BuildDefs::dump())
   2763     return;
   2764   Ostream &Str = Func->getContext()->getStrEmit();
   2765   assert(this->getSrcSize() == 3);
   2766   Str << "\t" << this->Opcode
   2767       << Traits::TypeAttributes[this->getDest()->getType()].IntegralString
   2768       << "\t";
   2769   this->getSrc(2)->emit(Func);
   2770   Str << ", ";
   2771   Operand *Src1 = this->getSrc(1);
   2772   if (const auto *Src1Var = llvm::dyn_cast<Variable>(Src1)) {
   2773     // If src1 is a register, it should always be r32.
   2774     if (Src1Var->hasReg()) {
   2775       const auto NewRegNum = Traits::getBaseReg(Src1Var->getRegNum());
   2776       const Variable *NewSrc = Src1Var->asType(Func, IceType_i32, NewRegNum);
   2777       NewSrc->emit(Func);
   2778     } else {
   2779       Src1Var->emit(Func);
   2780     }
   2781   } else {
   2782     Src1->emit(Func);
   2783   }
   2784   Str << ", ";
   2785   this->getDest()->emit(Func);
   2786 }
   2787 
   2788 template <typename TraitsType>
   2789 void InstImpl<TraitsType>::InstX86Pinsr::emitIAS(const Cfg *Func) const {
   2790   assert(this->getSrcSize() == 3);
   2791   assert(this->getDest() == this->getSrc(0));
   2792   // pinsrb and pinsrd are SSE4.1 instructions.
   2793   const Operand *Src0 = this->getSrc(1);
   2794   Type DispatchTy = Src0->getType();
   2795   // If src1 is a register, it should always be r32 (this should fall out from
   2796   // the encodings for ByteRegs overlapping the encodings for r32), but we have
   2797   // to make sure the register allocator didn't choose an 8-bit high register
   2798   // like "ah".
   2799   if (BuildDefs::asserts()) {
   2800     if (auto *Src0Var = llvm::dyn_cast<Variable>(Src0)) {
   2801       if (Src0Var->hasReg()) {
   2802         const auto RegNum = Src0Var->getRegNum();
   2803         const auto BaseRegNum = Traits::getBaseReg(RegNum);
   2804         (void)BaseRegNum;
   2805         assert(Traits::getEncodedGPR(RegNum) ==
   2806                Traits::getEncodedGPR(BaseRegNum));
   2807       }
   2808     }
   2809   }
   2810   static const ThreeOpImmEmitter<XmmRegister, GPRRegister> Emitter = {
   2811       &Assembler::pinsr, &Assembler::pinsr};
   2812   emitIASThreeOpImmOps<XmmRegister, GPRRegister, Traits::getEncodedXmm,
   2813                        Traits::getEncodedGPR>(Func, DispatchTy, this->getDest(),
   2814                                               Src0, this->getSrc(2), Emitter);
   2815 }
   2816 
   2817 template <typename TraitsType>
   2818 void InstImpl<TraitsType>::InstX86Pshufd::emitIAS(const Cfg *Func) const {
   2819   assert(this->getSrcSize() == 2);
   2820   const Variable *Dest = this->getDest();
   2821   Type Ty = Dest->getType();
   2822   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
   2823       &Assembler::pshufd, &Assembler::pshufd};
   2824   emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
   2825                        Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(0),
   2826                                               this->getSrc(1), Emitter);
   2827 }
   2828 
   2829 template <typename TraitsType>
   2830 void InstImpl<TraitsType>::InstX86Shufps::emitIAS(const Cfg *Func) const {
   2831   assert(this->getSrcSize() == 3);
   2832   const Variable *Dest = this->getDest();
   2833   assert(Dest == this->getSrc(0));
   2834   Type Ty = Dest->getType();
   2835   static const ThreeOpImmEmitter<XmmRegister, XmmRegister> Emitter = {
   2836       &Assembler::shufps, &Assembler::shufps};
   2837   emitIASThreeOpImmOps<XmmRegister, XmmRegister, Traits::getEncodedXmm,
   2838                        Traits::getEncodedXmm>(Func, Ty, Dest, this->getSrc(1),
   2839                                               this->getSrc(2), Emitter);
   2840 }
   2841 
   2842 template <typename TraitsType>
   2843 void InstImpl<TraitsType>::InstX86Pop::emit(const Cfg *Func) const {
   2844   if (!BuildDefs::dump())
   2845     return;
   2846   Ostream &Str = Func->getContext()->getStrEmit();
   2847   assert(this->getSrcSize() == 0);
   2848   Str << "\t"
   2849          "pop\t";
   2850   this->getDest()->emit(Func);
   2851 }
   2852 
   2853 template <typename TraitsType>
   2854 void InstImpl<TraitsType>::InstX86Pop::emitIAS(const Cfg *Func) const {
   2855   assert(this->getSrcSize() == 0);
   2856   Assembler *Asm = Func->getAssembler<Assembler>();
   2857   if (this->getDest()->hasReg()) {
   2858     Asm->popl(Traits::getEncodedGPR(this->getDest()->getRegNum()));
   2859   } else {
   2860     auto *Target = InstX86Base::getTarget(Func);
   2861     Asm->popl(Target->stackVarToAsmOperand(this->getDest()));
   2862   }
   2863 }
   2864 
   2865 template <typename TraitsType>
   2866 void InstImpl<TraitsType>::InstX86Pop::dump(const Cfg *Func) const {
   2867   if (!BuildDefs::dump())
   2868     return;
   2869   Ostream &Str = Func->getContext()->getStrDump();
   2870   this->dumpDest(Func);
   2871   Str << " = pop." << this->getDest()->getType() << " ";
   2872 }
   2873 
   2874 template <typename TraitsType>
   2875 void InstImpl<TraitsType>::InstX86Push::emit(const Cfg *Func) const {
   2876   if (!BuildDefs::dump())
   2877     return;
   2878   Ostream &Str = Func->getContext()->getStrEmit();
   2879   Str << "\t"
   2880          "push"
   2881          "\t";
   2882   assert(this->getSrcSize() == 1);
   2883   const Operand *Src = this->getSrc(0);
   2884   Src->emit(Func);
   2885 }
   2886 
   2887 template <typename TraitsType>
   2888 void InstImpl<TraitsType>::InstX86Push::emitIAS(const Cfg *Func) const {
   2889   Assembler *Asm = Func->getAssembler<Assembler>();
   2890 
   2891   assert(this->getSrcSize() == 1);
   2892   const Operand *Src = this->getSrc(0);
   2893 
   2894   if (const auto *Var = llvm::dyn_cast<Variable>(Src)) {
   2895     Asm->pushl(Traits::getEncodedGPR(Var->getRegNum()));
   2896   } else if (const auto *Const32 = llvm::dyn_cast<ConstantInteger32>(Src)) {
   2897     Asm->pushl(AssemblerImmediate(Const32->getValue()));
   2898   } else if (auto *CR = llvm::dyn_cast<ConstantRelocatable>(Src)) {
   2899     Asm->pushl(CR);
   2900   } else {
   2901     llvm_unreachable("Unexpected operand type");
   2902   }
   2903 }
   2904 
   2905 template <typename TraitsType>
   2906 void InstImpl<TraitsType>::InstX86Push::dump(const Cfg *Func) const {
   2907   if (!BuildDefs::dump())
   2908     return;
   2909   Ostream &Str = Func->getContext()->getStrDump();
   2910   Str << "push." << this->getSrc(0)->getType() << " ";
   2911   this->dumpSources(Func);
   2912 }
   2913 
   2914 template <typename TraitsType>
   2915 void InstImpl<TraitsType>::InstX86Ret::emit(const Cfg *Func) const {
   2916   if (!BuildDefs::dump())
   2917     return;
   2918   Ostream &Str = Func->getContext()->getStrEmit();
   2919   Str << "\t"
   2920          "ret";
   2921 }
   2922 
   2923 template <typename TraitsType>
   2924 void InstImpl<TraitsType>::InstX86Ret::emitIAS(const Cfg *Func) const {
   2925   Assembler *Asm = Func->getAssembler<Assembler>();
   2926   Asm->ret();
   2927 }
   2928 
   2929 template <typename TraitsType>
   2930 void InstImpl<TraitsType>::InstX86Ret::dump(const Cfg *Func) const {
   2931   if (!BuildDefs::dump())
   2932     return;
   2933   Ostream &Str = Func->getContext()->getStrDump();
   2934   Type Ty =
   2935       (this->getSrcSize() == 0 ? IceType_void : this->getSrc(0)->getType());
   2936   Str << "ret." << Ty << " ";
   2937   this->dumpSources(Func);
   2938 }
   2939 
   2940 template <typename TraitsType>
   2941 void InstImpl<TraitsType>::InstX86Setcc::emit(const Cfg *Func) const {
   2942   if (!BuildDefs::dump())
   2943     return;
   2944   Ostream &Str = Func->getContext()->getStrEmit();
   2945   Str << "\t"
   2946          "set" << Traits::InstBrAttributes[Condition].DisplayString << "\t";
   2947   this->Dest->emit(Func);
   2948 }
   2949 
   2950 template <typename TraitsType>
   2951 void InstImpl<TraitsType>::InstX86Setcc::emitIAS(const Cfg *Func) const {
   2952   assert(Condition != Cond::Br_None);
   2953   assert(this->getDest()->getType() == IceType_i1);
   2954   assert(this->getSrcSize() == 0);
   2955   Assembler *Asm = Func->getAssembler<Assembler>();
   2956   auto *Target = InstX86Base::getTarget(Func);
   2957   if (this->getDest()->hasReg())
   2958     Asm->setcc(Condition,
   2959                Traits::getEncodedByteReg(this->getDest()->getRegNum()));
   2960   else
   2961     Asm->setcc(Condition, Target->stackVarToAsmOperand(this->getDest()));
   2962   return;
   2963 }
   2964 
   2965 template <typename TraitsType>
   2966 void InstImpl<TraitsType>::InstX86Setcc::dump(const Cfg *Func) const {
   2967   if (!BuildDefs::dump())
   2968     return;
   2969   Ostream &Str = Func->getContext()->getStrDump();
   2970   Str << "setcc." << Traits::InstBrAttributes[Condition].DisplayString << " ";
   2971   this->dumpDest(Func);
   2972 }
   2973 
   2974 template <typename TraitsType>
   2975 void InstImpl<TraitsType>::InstX86Xadd::emit(const Cfg *Func) const {
   2976   if (!BuildDefs::dump())
   2977     return;
   2978   Ostream &Str = Func->getContext()->getStrEmit();
   2979   if (this->Locked) {
   2980     Str << "\t"
   2981            "lock";
   2982   }
   2983   Str << "\t"
   2984          "xadd" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
   2985   this->getSrc(1)->emit(Func);
   2986   Str << ", ";
   2987   this->getSrc(0)->emit(Func);
   2988 }
   2989 
   2990 template <typename TraitsType>
   2991 void InstImpl<TraitsType>::InstX86Xadd::emitIAS(const Cfg *Func) const {
   2992   assert(this->getSrcSize() == 2);
   2993   Assembler *Asm = Func->getAssembler<Assembler>();
   2994   Type Ty = this->getSrc(0)->getType();
   2995   const auto Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
   2996   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   2997   auto *Target = InstX86Base::getTarget(Func);
   2998   const Address Addr = Mem->toAsmAddress(Asm, Target);
   2999   const auto *VarReg = llvm::cast<Variable>(this->getSrc(1));
   3000   assert(VarReg->hasReg());
   3001   const GPRRegister Reg = Traits::getEncodedGPR(VarReg->getRegNum());
   3002   Asm->xadd(Ty, Addr, Reg, this->Locked);
   3003 }
   3004 
   3005 template <typename TraitsType>
   3006 void InstImpl<TraitsType>::InstX86Xadd::dump(const Cfg *Func) const {
   3007   if (!BuildDefs::dump())
   3008     return;
   3009   Ostream &Str = Func->getContext()->getStrDump();
   3010   if (this->Locked) {
   3011     Str << "lock ";
   3012   }
   3013   Type Ty = this->getSrc(0)->getType();
   3014   Str << "xadd." << Ty << " ";
   3015   this->dumpSources(Func);
   3016 }
   3017 
   3018 template <typename TraitsType>
   3019 void InstImpl<TraitsType>::InstX86Xchg::emit(const Cfg *Func) const {
   3020   if (!BuildDefs::dump())
   3021     return;
   3022   Ostream &Str = Func->getContext()->getStrEmit();
   3023   Str << "\t"
   3024          "xchg" << this->getWidthString(this->getSrc(0)->getType()) << "\t";
   3025   this->getSrc(1)->emit(Func);
   3026   Str << ", ";
   3027   this->getSrc(0)->emit(Func);
   3028 }
   3029 
   3030 template <typename TraitsType>
   3031 void InstImpl<TraitsType>::InstX86Xchg::emitIAS(const Cfg *Func) const {
   3032   assert(this->getSrcSize() == 2);
   3033   Assembler *Asm = Func->getAssembler<Assembler>();
   3034   Type Ty = this->getSrc(0)->getType();
   3035   const auto *VarReg1 = llvm::cast<Variable>(this->getSrc(1));
   3036   assert(VarReg1->hasReg());
   3037   const GPRRegister Reg1 = Traits::getEncodedGPR(VarReg1->getRegNum());
   3038 
   3039   if (const auto *VarReg0 = llvm::dyn_cast<Variable>(this->getSrc(0))) {
   3040     assert(VarReg0->hasReg());
   3041     const GPRRegister Reg0 = Traits::getEncodedGPR(VarReg0->getRegNum());
   3042     Asm->xchg(Ty, Reg0, Reg1);
   3043     return;
   3044   }
   3045 
   3046   const auto *Mem = llvm::cast<X86OperandMem>(this->getSrc(0));
   3047   assert(Mem->getSegmentRegister() == X86OperandMem::DefaultSegment);
   3048   auto *Target = InstX86Base::getTarget(Func);
   3049   const Address Addr = Mem->toAsmAddress(Asm, Target);
   3050   Asm->xchg(Ty, Addr, Reg1);
   3051 }
   3052 
   3053 template <typename TraitsType>
   3054 void InstImpl<TraitsType>::InstX86Xchg::dump(const Cfg *Func) const {
   3055   if (!BuildDefs::dump())
   3056     return;
   3057   Ostream &Str = Func->getContext()->getStrDump();
   3058   Type Ty = this->getSrc(0)->getType();
   3059   Str << "xchg." << Ty << " ";
   3060   this->dumpSources(Func);
   3061 }
   3062 
   3063 template <typename TraitsType>
   3064 void InstImpl<TraitsType>::InstX86IacaStart::emit(const Cfg *Func) const {
   3065   if (!BuildDefs::dump())
   3066     return;
   3067   Ostream &Str = Func->getContext()->getStrEmit();
   3068   Str << "\t# IACA_START\n"
   3069          "\t.byte 0x0F, 0x0B\n"
   3070          "\t"
   3071          "movl\t$111, %ebx\n"
   3072          "\t.byte 0x64, 0x67, 0x90";
   3073 }
   3074 
   3075 template <typename TraitsType>
   3076 void InstImpl<TraitsType>::InstX86IacaStart::emitIAS(const Cfg *Func) const {
   3077   Assembler *Asm = Func->getAssembler<Assembler>();
   3078   Asm->iaca_start();
   3079 }
   3080 
   3081 template <typename TraitsType>
   3082 void InstImpl<TraitsType>::InstX86IacaStart::dump(const Cfg *Func) const {
   3083   if (!BuildDefs::dump())
   3084     return;
   3085   Ostream &Str = Func->getContext()->getStrDump();
   3086   Str << "IACA_START";
   3087 }
   3088 
   3089 template <typename TraitsType>
   3090 void InstImpl<TraitsType>::InstX86IacaEnd::emit(const Cfg *Func) const {
   3091   if (!BuildDefs::dump())
   3092     return;
   3093   Ostream &Str = Func->getContext()->getStrEmit();
   3094   Str << "\t# IACA_END\n"
   3095          "\t"
   3096          "movl\t$222, %ebx\n"
   3097          "\t.byte 0x64, 0x67, 0x90\n"
   3098          "\t.byte 0x0F, 0x0B";
   3099 }
   3100 
   3101 template <typename TraitsType>
   3102 void InstImpl<TraitsType>::InstX86IacaEnd::emitIAS(const Cfg *Func) const {
   3103   Assembler *Asm = Func->getAssembler<Assembler>();
   3104   Asm->iaca_end();
   3105 }
   3106 
   3107 template <typename TraitsType>
   3108 void InstImpl<TraitsType>::InstX86IacaEnd::dump(const Cfg *Func) const {
   3109   if (!BuildDefs::dump())
   3110     return;
   3111   Ostream &Str = Func->getContext()->getStrDump();
   3112   Str << "IACA_END";
   3113 }
   3114 
   3115 } // end of namespace X86NAMESPACE
   3116 
   3117 } // end of namespace Ice
   3118 
   3119 #endif // SUBZERO_SRC_ICEINSTX86BASEIMPL_H
   3120