1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceTargetLoweringX8664.h - lowering for x86-64 -*- C++ -*-=// 2*03ce13f7SAndroid Build Coastguard Worker // 3*03ce13f7SAndroid Build Coastguard Worker // The Subzero Code Generator 4*03ce13f7SAndroid Build Coastguard Worker // 5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*03ce13f7SAndroid Build Coastguard Worker // 8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*03ce13f7SAndroid Build Coastguard Worker /// 10*03ce13f7SAndroid Build Coastguard Worker /// \file 11*03ce13f7SAndroid Build Coastguard Worker /// \brief Declares the TargetLoweringX8664 class, which implements the 12*03ce13f7SAndroid Build Coastguard Worker /// TargetLowering interface for the X86 64-bit architecture. 13*03ce13f7SAndroid Build Coastguard Worker /// 14*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 15*03ce13f7SAndroid Build Coastguard Worker 16*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8664_H 17*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICETARGETLOWERINGX8664_H 18*03ce13f7SAndroid Build Coastguard Worker 19*03ce13f7SAndroid Build Coastguard Worker #include "IceAssemblerX8664.h" 20*03ce13f7SAndroid Build Coastguard Worker #include "IceCfg.h" 21*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h" 22*03ce13f7SAndroid Build Coastguard Worker #include "IceGlobalContext.h" 23*03ce13f7SAndroid Build Coastguard Worker #include "IceInst.h" 24*03ce13f7SAndroid Build Coastguard Worker #include "IceInstX8664.h" 25*03ce13f7SAndroid Build Coastguard Worker #include "IceSwitchLowering.h" 26*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLoweringX86.h" 27*03ce13f7SAndroid Build Coastguard Worker #include "IceTargetLoweringX86RegClass.h" 28*03ce13f7SAndroid Build Coastguard Worker #include "IceUtils.h" 29*03ce13f7SAndroid Build Coastguard Worker 30*03ce13f7SAndroid Build Coastguard Worker #include <array> 31*03ce13f7SAndroid Build Coastguard Worker #include <type_traits> 32*03ce13f7SAndroid Build Coastguard Worker #include <utility> 33*03ce13f7SAndroid Build Coastguard Worker 34*03ce13f7SAndroid Build Coastguard Worker namespace Ice { 35*03ce13f7SAndroid Build Coastguard Worker namespace X8664 { 36*03ce13f7SAndroid Build Coastguard Worker 37*03ce13f7SAndroid Build Coastguard Worker using namespace ::Ice::X86; 38*03ce13f7SAndroid Build Coastguard Worker 39*03ce13f7SAndroid Build Coastguard Worker constexpr Type WordType = IceType_i64; 40*03ce13f7SAndroid Build Coastguard Worker 41*03ce13f7SAndroid Build Coastguard Worker class BoolFoldingEntry { 42*03ce13f7SAndroid Build Coastguard Worker BoolFoldingEntry(const BoolFoldingEntry &) = delete; 43*03ce13f7SAndroid Build Coastguard Worker 44*03ce13f7SAndroid Build Coastguard Worker public: 45*03ce13f7SAndroid Build Coastguard Worker BoolFoldingEntry() = default; 46*03ce13f7SAndroid Build Coastguard Worker explicit BoolFoldingEntry(Inst *I); 47*03ce13f7SAndroid Build Coastguard Worker BoolFoldingEntry &operator=(const BoolFoldingEntry &) = default; 48*03ce13f7SAndroid Build Coastguard Worker /// Instr is the instruction producing the i1-type variable of interest. 49*03ce13f7SAndroid Build Coastguard Worker Inst *Instr = nullptr; 50*03ce13f7SAndroid Build Coastguard Worker /// IsComplex is the cached result of BoolFolding::hasComplexLowering(Instr). 51*03ce13f7SAndroid Build Coastguard Worker bool IsComplex = false; 52*03ce13f7SAndroid Build Coastguard Worker /// IsLiveOut is initialized conservatively to true, and is set to false when 53*03ce13f7SAndroid Build Coastguard Worker /// we encounter an instruction that ends Var's live range. We disable the 54*03ce13f7SAndroid Build Coastguard Worker /// folding optimization when Var is live beyond this basic block. Note that 55*03ce13f7SAndroid Build Coastguard Worker /// if liveness analysis is not performed (e.g. in Om1 mode), IsLiveOut will 56*03ce13f7SAndroid Build Coastguard Worker /// always be true and the folding optimization will never be performed. 57*03ce13f7SAndroid Build Coastguard Worker bool IsLiveOut = true; 58*03ce13f7SAndroid Build Coastguard Worker // NumUses counts the number of times Var is used as a source operand in the 59*03ce13f7SAndroid Build Coastguard Worker // basic block. If IsComplex is true and there is more than one use of Var, 60*03ce13f7SAndroid Build Coastguard Worker // then the folding optimization is disabled for Var. 61*03ce13f7SAndroid Build Coastguard Worker uint32_t NumUses = 0; 62*03ce13f7SAndroid Build Coastguard Worker }; 63*03ce13f7SAndroid Build Coastguard Worker 64*03ce13f7SAndroid Build Coastguard Worker class BoolFolding { 65*03ce13f7SAndroid Build Coastguard Worker public: 66*03ce13f7SAndroid Build Coastguard Worker enum BoolFoldingProducerKind { 67*03ce13f7SAndroid Build Coastguard Worker PK_None, 68*03ce13f7SAndroid Build Coastguard Worker // TODO(jpp): PK_Icmp32 is no longer meaningful. Rename to PK_IcmpNative. 69*03ce13f7SAndroid Build Coastguard Worker PK_Icmp32, 70*03ce13f7SAndroid Build Coastguard Worker PK_Icmp64, 71*03ce13f7SAndroid Build Coastguard Worker PK_Fcmp, 72*03ce13f7SAndroid Build Coastguard Worker PK_Trunc, 73*03ce13f7SAndroid Build Coastguard Worker PK_Arith // A flag-setting arithmetic instruction. 74*03ce13f7SAndroid Build Coastguard Worker }; 75*03ce13f7SAndroid Build Coastguard Worker 76*03ce13f7SAndroid Build Coastguard Worker /// Currently the actual enum values are not used (other than CK_None), but we 77*03ce13f7SAndroid Build Coastguard Worker /// go ahead and produce them anyway for symmetry with the 78*03ce13f7SAndroid Build Coastguard Worker /// BoolFoldingProducerKind. 79*03ce13f7SAndroid Build Coastguard Worker enum BoolFoldingConsumerKind { CK_None, CK_Br, CK_Select, CK_Sext, CK_Zext }; 80*03ce13f7SAndroid Build Coastguard Worker 81*03ce13f7SAndroid Build Coastguard Worker private: 82*03ce13f7SAndroid Build Coastguard Worker BoolFolding(const BoolFolding &) = delete; 83*03ce13f7SAndroid Build Coastguard Worker BoolFolding &operator=(const BoolFolding &) = delete; 84*03ce13f7SAndroid Build Coastguard Worker 85*03ce13f7SAndroid Build Coastguard Worker public: 86*03ce13f7SAndroid Build Coastguard Worker BoolFolding() = default; 87*03ce13f7SAndroid Build Coastguard Worker static BoolFoldingProducerKind getProducerKind(const Inst *Instr); 88*03ce13f7SAndroid Build Coastguard Worker static BoolFoldingConsumerKind getConsumerKind(const Inst *Instr); 89*03ce13f7SAndroid Build Coastguard Worker static bool hasComplexLowering(const Inst *Instr); 90*03ce13f7SAndroid Build Coastguard Worker static bool isValidFolding(BoolFoldingProducerKind ProducerKind, 91*03ce13f7SAndroid Build Coastguard Worker BoolFoldingConsumerKind ConsumerKind); 92*03ce13f7SAndroid Build Coastguard Worker void init(CfgNode *Node); 93*03ce13f7SAndroid Build Coastguard Worker const Inst *getProducerFor(const Operand *Opnd) const; 94*03ce13f7SAndroid Build Coastguard Worker void dump(const Cfg *Func) const; 95*03ce13f7SAndroid Build Coastguard Worker 96*03ce13f7SAndroid Build Coastguard Worker private: 97*03ce13f7SAndroid Build Coastguard Worker /// Returns true if Producers contains a valid entry for the given VarNum. containsValid(SizeT VarNum)98*03ce13f7SAndroid Build Coastguard Worker bool containsValid(SizeT VarNum) const { 99*03ce13f7SAndroid Build Coastguard Worker auto Element = Producers.find(VarNum); 100*03ce13f7SAndroid Build Coastguard Worker return Element != Producers.end() && Element->second.Instr != nullptr; 101*03ce13f7SAndroid Build Coastguard Worker } setInvalid(SizeT VarNum)102*03ce13f7SAndroid Build Coastguard Worker void setInvalid(SizeT VarNum) { Producers[VarNum].Instr = nullptr; } 103*03ce13f7SAndroid Build Coastguard Worker void invalidateProducersOnStore(const Inst *Instr); 104*03ce13f7SAndroid Build Coastguard Worker /// Producers maps Variable::Number to a BoolFoldingEntry. 105*03ce13f7SAndroid Build Coastguard Worker CfgUnorderedMap<SizeT, BoolFoldingEntry> Producers; 106*03ce13f7SAndroid Build Coastguard Worker }; 107*03ce13f7SAndroid Build Coastguard Worker 108*03ce13f7SAndroid Build Coastguard Worker class TargetX8664 : public TargetX86 { 109*03ce13f7SAndroid Build Coastguard Worker TargetX8664() = delete; 110*03ce13f7SAndroid Build Coastguard Worker TargetX8664(const TargetX8664 &) = delete; 111*03ce13f7SAndroid Build Coastguard Worker TargetX8664 &operator=(const TargetX8664 &) = delete; 112*03ce13f7SAndroid Build Coastguard Worker 113*03ce13f7SAndroid Build Coastguard Worker friend class BoolFolding; 114*03ce13f7SAndroid Build Coastguard Worker 115*03ce13f7SAndroid Build Coastguard Worker public: 116*03ce13f7SAndroid Build Coastguard Worker using BrCond = CondX86::BrCond; 117*03ce13f7SAndroid Build Coastguard Worker using CmppsCond = CondX86::CmppsCond; 118*03ce13f7SAndroid Build Coastguard Worker 119*03ce13f7SAndroid Build Coastguard Worker using SegmentRegisters = X86OperandMem::SegmentRegisters; 120*03ce13f7SAndroid Build Coastguard Worker 121*03ce13f7SAndroid Build Coastguard Worker using InstX86Br = Insts::Br; 122*03ce13f7SAndroid Build Coastguard Worker using InstX86FakeRMW = Insts::FakeRMW; 123*03ce13f7SAndroid Build Coastguard Worker using InstX86Label = Insts::Label; 124*03ce13f7SAndroid Build Coastguard Worker 125*03ce13f7SAndroid Build Coastguard Worker ~TargetX8664() override = default; 126*03ce13f7SAndroid Build Coastguard Worker 127*03ce13f7SAndroid Build Coastguard Worker static void staticInit(GlobalContext *Ctx); 128*03ce13f7SAndroid Build Coastguard Worker static bool shouldBePooled(const Constant *C); 129*03ce13f7SAndroid Build Coastguard Worker static ::Ice::Type getPointerType(); 130*03ce13f7SAndroid Build Coastguard Worker 131*03ce13f7SAndroid Build Coastguard Worker void translateOm1() override; 132*03ce13f7SAndroid Build Coastguard Worker void translateO2() override; 133*03ce13f7SAndroid Build Coastguard Worker void doLoadOpt(); 134*03ce13f7SAndroid Build Coastguard Worker bool doBranchOpt(Inst *I, const CfgNode *NextNode) override; 135*03ce13f7SAndroid Build Coastguard Worker getNumRegisters()136*03ce13f7SAndroid Build Coastguard Worker SizeT getNumRegisters() const override { return RegisterSet::Reg_NUM; } 137*03ce13f7SAndroid Build Coastguard Worker createLoweredMove(Variable * Dest,Variable * SrcVar)138*03ce13f7SAndroid Build Coastguard Worker Inst *createLoweredMove(Variable *Dest, Variable *SrcVar) override { 139*03ce13f7SAndroid Build Coastguard Worker if (isVectorType(Dest->getType())) { 140*03ce13f7SAndroid Build Coastguard Worker return Insts::Movp::create(Func, Dest, SrcVar); 141*03ce13f7SAndroid Build Coastguard Worker } 142*03ce13f7SAndroid Build Coastguard Worker return Insts::Mov::create(Func, Dest, SrcVar); 143*03ce13f7SAndroid Build Coastguard Worker (void)Dest; 144*03ce13f7SAndroid Build Coastguard Worker (void)SrcVar; 145*03ce13f7SAndroid Build Coastguard Worker return nullptr; 146*03ce13f7SAndroid Build Coastguard Worker } 147*03ce13f7SAndroid Build Coastguard Worker 148*03ce13f7SAndroid Build Coastguard Worker Variable *getPhysicalRegister(RegNumT RegNum, 149*03ce13f7SAndroid Build Coastguard Worker Type Ty = IceType_void) override; 150*03ce13f7SAndroid Build Coastguard Worker const char *getRegName(RegNumT RegNum, Type Ty) const override; getRegClassName(RegClass C)151*03ce13f7SAndroid Build Coastguard Worker static const char *getRegClassName(RegClass C) { 152*03ce13f7SAndroid Build Coastguard Worker auto ClassNum = static_cast<RegClassX86>(C); 153*03ce13f7SAndroid Build Coastguard Worker assert(ClassNum < RCX86_NUM); 154*03ce13f7SAndroid Build Coastguard Worker switch (ClassNum) { 155*03ce13f7SAndroid Build Coastguard Worker default: 156*03ce13f7SAndroid Build Coastguard Worker assert(C < RC_Target); 157*03ce13f7SAndroid Build Coastguard Worker return regClassString(C); 158*03ce13f7SAndroid Build Coastguard Worker case RCX86_Is64To8: 159*03ce13f7SAndroid Build Coastguard Worker return "i64to8"; // 64-bit GPR truncable to i8 160*03ce13f7SAndroid Build Coastguard Worker case RCX86_Is32To8: 161*03ce13f7SAndroid Build Coastguard Worker return "i32to8"; // 32-bit GPR truncable to i8 162*03ce13f7SAndroid Build Coastguard Worker case RCX86_Is16To8: 163*03ce13f7SAndroid Build Coastguard Worker return "i16to8"; // 16-bit GPR truncable to i8 164*03ce13f7SAndroid Build Coastguard Worker case RCX86_IsTrunc8Rcvr: 165*03ce13f7SAndroid Build Coastguard Worker return "i8from"; // 8-bit GPR truncable from wider GPRs 166*03ce13f7SAndroid Build Coastguard Worker case RCX86_IsAhRcvr: 167*03ce13f7SAndroid Build Coastguard Worker return "i8fromah"; // 8-bit GPR that ah can be assigned to 168*03ce13f7SAndroid Build Coastguard Worker } 169*03ce13f7SAndroid Build Coastguard Worker } 170*03ce13f7SAndroid Build Coastguard Worker SmallBitVector getRegisterSet(RegSetMask Include, 171*03ce13f7SAndroid Build Coastguard Worker RegSetMask Exclude) const override; 172*03ce13f7SAndroid Build Coastguard Worker const SmallBitVector & getRegistersForVariable(const Variable * Var)173*03ce13f7SAndroid Build Coastguard Worker getRegistersForVariable(const Variable *Var) const override { 174*03ce13f7SAndroid Build Coastguard Worker RegClass RC = Var->getRegClass(); 175*03ce13f7SAndroid Build Coastguard Worker assert(static_cast<RegClassX86>(RC) < RCX86_NUM); 176*03ce13f7SAndroid Build Coastguard Worker return TypeToRegisterSet[RC]; 177*03ce13f7SAndroid Build Coastguard Worker } 178*03ce13f7SAndroid Build Coastguard Worker 179*03ce13f7SAndroid Build Coastguard Worker const SmallBitVector & getAllRegistersForVariable(const Variable * Var)180*03ce13f7SAndroid Build Coastguard Worker getAllRegistersForVariable(const Variable *Var) const override { 181*03ce13f7SAndroid Build Coastguard Worker RegClass RC = Var->getRegClass(); 182*03ce13f7SAndroid Build Coastguard Worker assert(static_cast<RegClassX86>(RC) < RCX86_NUM); 183*03ce13f7SAndroid Build Coastguard Worker return TypeToRegisterSetUnfiltered[RC]; 184*03ce13f7SAndroid Build Coastguard Worker } 185*03ce13f7SAndroid Build Coastguard Worker getAliasesForRegister(RegNumT Reg)186*03ce13f7SAndroid Build Coastguard Worker const SmallBitVector &getAliasesForRegister(RegNumT Reg) const override { 187*03ce13f7SAndroid Build Coastguard Worker Reg.assertIsValid(); 188*03ce13f7SAndroid Build Coastguard Worker return RegisterAliases[Reg]; 189*03ce13f7SAndroid Build Coastguard Worker } 190*03ce13f7SAndroid Build Coastguard Worker hasFramePointer()191*03ce13f7SAndroid Build Coastguard Worker bool hasFramePointer() const override { return IsEbpBasedFrame; } setHasFramePointer()192*03ce13f7SAndroid Build Coastguard Worker void setHasFramePointer() override { IsEbpBasedFrame = true; } getStackReg()193*03ce13f7SAndroid Build Coastguard Worker RegNumT getStackReg() const override { return RegX8664::Reg_rsp; } getFrameReg()194*03ce13f7SAndroid Build Coastguard Worker RegNumT getFrameReg() const override { return RegX8664::Reg_rbp; } getFrameOrStackReg()195*03ce13f7SAndroid Build Coastguard Worker RegNumT getFrameOrStackReg() const override { 196*03ce13f7SAndroid Build Coastguard Worker // If the stack pointer needs to be aligned, then the frame pointer is 197*03ce13f7SAndroid Build Coastguard Worker // unaligned, so always use the stack pointer. 198*03ce13f7SAndroid Build Coastguard Worker if (needsStackPointerAlignment()) 199*03ce13f7SAndroid Build Coastguard Worker return getStackReg(); 200*03ce13f7SAndroid Build Coastguard Worker return IsEbpBasedFrame ? getFrameReg() : getStackReg(); 201*03ce13f7SAndroid Build Coastguard Worker } typeWidthInBytesOnStack(Type Ty)202*03ce13f7SAndroid Build Coastguard Worker size_t typeWidthInBytesOnStack(Type Ty) const override { 203*03ce13f7SAndroid Build Coastguard Worker // Round up to the next multiple of WordType bytes. 204*03ce13f7SAndroid Build Coastguard Worker const uint32_t WordSizeInBytes = typeWidthInBytes(WordType); 205*03ce13f7SAndroid Build Coastguard Worker return Utils::applyAlignment(typeWidthInBytes(Ty), WordSizeInBytes); 206*03ce13f7SAndroid Build Coastguard Worker } getStackAlignment()207*03ce13f7SAndroid Build Coastguard Worker uint32_t getStackAlignment() const override { 208*03ce13f7SAndroid Build Coastguard Worker return X86_STACK_ALIGNMENT_BYTES; 209*03ce13f7SAndroid Build Coastguard Worker } needsStackPointerAlignment()210*03ce13f7SAndroid Build Coastguard Worker bool needsStackPointerAlignment() const override { 211*03ce13f7SAndroid Build Coastguard Worker // If the ABI's stack alignment is smaller than the vector size, 212*03ce13f7SAndroid Build Coastguard Worker // use the (realigned) stack pointer for addressing any stack variables. 213*03ce13f7SAndroid Build Coastguard Worker return X86_STACK_ALIGNMENT_BYTES < RequiredStackAlignment; 214*03ce13f7SAndroid Build Coastguard Worker } reserveFixedAllocaArea(size_t Size,size_t Align)215*03ce13f7SAndroid Build Coastguard Worker void reserveFixedAllocaArea(size_t Size, size_t Align) override { 216*03ce13f7SAndroid Build Coastguard Worker FixedAllocaSizeBytes = Size; 217*03ce13f7SAndroid Build Coastguard Worker assert(llvm::isPowerOf2_32(Align)); 218*03ce13f7SAndroid Build Coastguard Worker FixedAllocaAlignBytes = Align; 219*03ce13f7SAndroid Build Coastguard Worker PrologEmitsFixedAllocas = true; 220*03ce13f7SAndroid Build Coastguard Worker } 221*03ce13f7SAndroid Build Coastguard Worker /// Returns the (negative) offset from ebp/rbp where the fixed Allocas start. getFrameFixedAllocaOffset()222*03ce13f7SAndroid Build Coastguard Worker int32_t getFrameFixedAllocaOffset() const override { 223*03ce13f7SAndroid Build Coastguard Worker return FixedAllocaSizeBytes - (SpillAreaSizeBytes - maxOutArgsSizeBytes()); 224*03ce13f7SAndroid Build Coastguard Worker } maxOutArgsSizeBytes()225*03ce13f7SAndroid Build Coastguard Worker virtual uint32_t maxOutArgsSizeBytes() const override { 226*03ce13f7SAndroid Build Coastguard Worker return MaxOutArgsSizeBytes; 227*03ce13f7SAndroid Build Coastguard Worker } updateMaxOutArgsSizeBytes(uint32_t Size)228*03ce13f7SAndroid Build Coastguard Worker virtual void updateMaxOutArgsSizeBytes(uint32_t Size) { 229*03ce13f7SAndroid Build Coastguard Worker MaxOutArgsSizeBytes = std::max(MaxOutArgsSizeBytes, Size); 230*03ce13f7SAndroid Build Coastguard Worker } 231*03ce13f7SAndroid Build Coastguard Worker shouldSplitToVariable64On32(Type Ty)232*03ce13f7SAndroid Build Coastguard Worker bool shouldSplitToVariable64On32(Type Ty) const override { return false; } 233*03ce13f7SAndroid Build Coastguard Worker getMinJumpTableSize()234*03ce13f7SAndroid Build Coastguard Worker SizeT getMinJumpTableSize() const override { return 4; } 235*03ce13f7SAndroid Build Coastguard Worker 236*03ce13f7SAndroid Build Coastguard Worker void emitVariable(const Variable *Var) const override; 237*03ce13f7SAndroid Build Coastguard Worker 238*03ce13f7SAndroid Build Coastguard Worker void emit(const ConstantInteger32 *C) const final; 239*03ce13f7SAndroid Build Coastguard Worker void emit(const ConstantInteger64 *C) const final; 240*03ce13f7SAndroid Build Coastguard Worker void emit(const ConstantFloat *C) const final; 241*03ce13f7SAndroid Build Coastguard Worker void emit(const ConstantDouble *C) const final; 242*03ce13f7SAndroid Build Coastguard Worker void emit(const ConstantUndef *C) const final; 243*03ce13f7SAndroid Build Coastguard Worker void emit(const ConstantRelocatable *C) const final; 244*03ce13f7SAndroid Build Coastguard Worker 245*03ce13f7SAndroid Build Coastguard Worker void initNodeForLowering(CfgNode *Node) override; 246*03ce13f7SAndroid Build Coastguard Worker 247*03ce13f7SAndroid Build Coastguard Worker void addProlog(CfgNode *Node) override; 248*03ce13f7SAndroid Build Coastguard Worker void finishArgumentLowering(Variable *Arg, Variable *FramePtr, 249*03ce13f7SAndroid Build Coastguard Worker size_t BasicFrameOffset, size_t StackAdjBytes, 250*03ce13f7SAndroid Build Coastguard Worker size_t &InArgsSizeBytes); 251*03ce13f7SAndroid Build Coastguard Worker void addEpilog(CfgNode *Node) override; 252*03ce13f7SAndroid Build Coastguard Worker 253*03ce13f7SAndroid Build Coastguard Worker Operand *legalizeUndef(Operand *From, RegNumT RegNum = RegNumT()); 254*03ce13f7SAndroid Build Coastguard Worker 255*03ce13f7SAndroid Build Coastguard Worker protected: 256*03ce13f7SAndroid Build Coastguard Worker void postLower() override; 257*03ce13f7SAndroid Build Coastguard Worker 258*03ce13f7SAndroid Build Coastguard Worker void lowerAlloca(const InstAlloca *Instr) override; 259*03ce13f7SAndroid Build Coastguard Worker void lowerArguments() override; 260*03ce13f7SAndroid Build Coastguard Worker void lowerArithmetic(const InstArithmetic *Instr) override; 261*03ce13f7SAndroid Build Coastguard Worker void lowerAssign(const InstAssign *Instr) override; 262*03ce13f7SAndroid Build Coastguard Worker void lowerBr(const InstBr *Instr) override; 263*03ce13f7SAndroid Build Coastguard Worker void lowerBreakpoint(const InstBreakpoint *Instr) override; 264*03ce13f7SAndroid Build Coastguard Worker void lowerCall(const InstCall *Instr) override; 265*03ce13f7SAndroid Build Coastguard Worker void lowerCast(const InstCast *Instr) override; 266*03ce13f7SAndroid Build Coastguard Worker void lowerExtractElement(const InstExtractElement *Instr) override; 267*03ce13f7SAndroid Build Coastguard Worker void lowerFcmp(const InstFcmp *Instr) override; 268*03ce13f7SAndroid Build Coastguard Worker void lowerIcmp(const InstIcmp *Instr) override; 269*03ce13f7SAndroid Build Coastguard Worker 270*03ce13f7SAndroid Build Coastguard Worker void lowerIntrinsic(const InstIntrinsic *Instr) override; 271*03ce13f7SAndroid Build Coastguard Worker void lowerInsertElement(const InstInsertElement *Instr) override; 272*03ce13f7SAndroid Build Coastguard Worker void lowerLoad(const InstLoad *Instr) override; 273*03ce13f7SAndroid Build Coastguard Worker void lowerPhi(const InstPhi *Instr) override; 274*03ce13f7SAndroid Build Coastguard Worker void lowerRet(const InstRet *Instr) override; 275*03ce13f7SAndroid Build Coastguard Worker void lowerSelect(const InstSelect *Instr) override; 276*03ce13f7SAndroid Build Coastguard Worker void lowerShuffleVector(const InstShuffleVector *Instr) override; 277*03ce13f7SAndroid Build Coastguard Worker void lowerStore(const InstStore *Instr) override; 278*03ce13f7SAndroid Build Coastguard Worker void lowerSwitch(const InstSwitch *Instr) override; 279*03ce13f7SAndroid Build Coastguard Worker void lowerUnreachable(const InstUnreachable *Instr) override; 280*03ce13f7SAndroid Build Coastguard Worker void lowerOther(const Inst *Instr) override; 281*03ce13f7SAndroid Build Coastguard Worker void lowerRMW(const InstX86FakeRMW *RMW); 282*03ce13f7SAndroid Build Coastguard Worker void prelowerPhis() override; 283*03ce13f7SAndroid Build Coastguard Worker uint32_t getCallStackArgumentsSizeBytes(const CfgVector<Type> &ArgTypes, 284*03ce13f7SAndroid Build Coastguard Worker Type ReturnType); 285*03ce13f7SAndroid Build Coastguard Worker uint32_t getCallStackArgumentsSizeBytes(const InstCall *Instr) override; 286*03ce13f7SAndroid Build Coastguard Worker void genTargetHelperCallFor(Inst *Instr) override; 287*03ce13f7SAndroid Build Coastguard Worker 288*03ce13f7SAndroid Build Coastguard Worker /// OptAddr wraps all the possible operands that an x86 address might have. 289*03ce13f7SAndroid Build Coastguard Worker struct OptAddr { 290*03ce13f7SAndroid Build Coastguard Worker Variable *Base = nullptr; 291*03ce13f7SAndroid Build Coastguard Worker Variable *Index = nullptr; 292*03ce13f7SAndroid Build Coastguard Worker uint16_t Shift = 0; 293*03ce13f7SAndroid Build Coastguard Worker int32_t Offset = 0; 294*03ce13f7SAndroid Build Coastguard Worker ConstantRelocatable *Relocatable = nullptr; 295*03ce13f7SAndroid Build Coastguard Worker }; 296*03ce13f7SAndroid Build Coastguard Worker 297*03ce13f7SAndroid Build Coastguard Worker // Builds information for a canonical address expresion: 298*03ce13f7SAndroid Build Coastguard Worker // <Relocatable + Offset>(Base, Index, Shift) 299*03ce13f7SAndroid Build Coastguard Worker X86OperandMem *computeAddressOpt(const Inst *Instr, Type MemType, 300*03ce13f7SAndroid Build Coastguard Worker Operand *Addr); 301*03ce13f7SAndroid Build Coastguard Worker void doAddressOptOther() override; 302*03ce13f7SAndroid Build Coastguard Worker void doAddressOptLoad() override; 303*03ce13f7SAndroid Build Coastguard Worker void doAddressOptStore() override; 304*03ce13f7SAndroid Build Coastguard Worker void doAddressOptLoadSubVector() override; 305*03ce13f7SAndroid Build Coastguard Worker void doAddressOptStoreSubVector() override; 306*03ce13f7SAndroid Build Coastguard Worker void doMockBoundsCheck(Operand *Opnd) override; 307*03ce13f7SAndroid Build Coastguard Worker 308*03ce13f7SAndroid Build Coastguard Worker /// Naive lowering of cmpxchg. 309*03ce13f7SAndroid Build Coastguard Worker void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected, 310*03ce13f7SAndroid Build Coastguard Worker Operand *Desired); 311*03ce13f7SAndroid Build Coastguard Worker /// Attempt a more optimized lowering of cmpxchg. Returns true if optimized. 312*03ce13f7SAndroid Build Coastguard Worker bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr, 313*03ce13f7SAndroid Build Coastguard Worker Operand *Expected, Operand *Desired); 314*03ce13f7SAndroid Build Coastguard Worker void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, 315*03ce13f7SAndroid Build Coastguard Worker Operand *Val); 316*03ce13f7SAndroid Build Coastguard Worker void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal, 317*03ce13f7SAndroid Build Coastguard Worker Operand *SecondVal); 318*03ce13f7SAndroid Build Coastguard Worker /// Load from memory for a given type. 319*03ce13f7SAndroid Build Coastguard Worker void typedLoad(Type Ty, Variable *Dest, Variable *Base, Constant *Offset); 320*03ce13f7SAndroid Build Coastguard Worker /// Store to memory for a given type. 321*03ce13f7SAndroid Build Coastguard Worker void typedStore(Type Ty, Variable *Value, Variable *Base, Constant *Offset); 322*03ce13f7SAndroid Build Coastguard Worker /// Copy memory of given type from Src to Dest using OffsetAmt on both. 323*03ce13f7SAndroid Build Coastguard Worker void copyMemory(Type Ty, Variable *Dest, Variable *Src, int32_t OffsetAmt); 324*03ce13f7SAndroid Build Coastguard Worker /// Replace some calls to memcpy with inline instructions. 325*03ce13f7SAndroid Build Coastguard Worker void lowerMemcpy(Operand *Dest, Operand *Src, Operand *Count); 326*03ce13f7SAndroid Build Coastguard Worker /// Replace some calls to memmove with inline instructions. 327*03ce13f7SAndroid Build Coastguard Worker void lowerMemmove(Operand *Dest, Operand *Src, Operand *Count); 328*03ce13f7SAndroid Build Coastguard Worker /// Replace some calls to memset with inline instructions. 329*03ce13f7SAndroid Build Coastguard Worker void lowerMemset(Operand *Dest, Operand *Val, Operand *Count); 330*03ce13f7SAndroid Build Coastguard Worker 331*03ce13f7SAndroid Build Coastguard Worker /// Lower an indirect jump . 332*03ce13f7SAndroid Build Coastguard Worker void lowerIndirectJump(Variable *JumpTarget); 333*03ce13f7SAndroid Build Coastguard Worker 334*03ce13f7SAndroid Build Coastguard Worker /// Check the comparison is in [Min,Max]. The flags register will be modified 335*03ce13f7SAndroid Build Coastguard Worker /// with: 336*03ce13f7SAndroid Build Coastguard Worker /// - below equal, if in range 337*03ce13f7SAndroid Build Coastguard Worker /// - above, set if not in range 338*03ce13f7SAndroid Build Coastguard Worker /// The index into the range is returned. 339*03ce13f7SAndroid Build Coastguard Worker Operand *lowerCmpRange(Operand *Comparison, uint64_t Min, uint64_t Max); 340*03ce13f7SAndroid Build Coastguard Worker /// Lowering of a cluster of switch cases. If the case is not matched control 341*03ce13f7SAndroid Build Coastguard Worker /// will pass to the default label provided. If the default label is nullptr 342*03ce13f7SAndroid Build Coastguard Worker /// then control will fall through to the next instruction. DoneCmp should be 343*03ce13f7SAndroid Build Coastguard Worker /// true if the flags contain the result of a comparison with the Comparison. 344*03ce13f7SAndroid Build Coastguard Worker void lowerCaseCluster(const CaseCluster &Case, Operand *Src0, bool DoneCmp, 345*03ce13f7SAndroid Build Coastguard Worker CfgNode *DefaultLabel = nullptr); 346*03ce13f7SAndroid Build Coastguard Worker 347*03ce13f7SAndroid Build Coastguard Worker using LowerBinOp = void (TargetX8664::*)(Variable *, Operand *); 348*03ce13f7SAndroid Build Coastguard Worker void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi, 349*03ce13f7SAndroid Build Coastguard Worker Variable *Dest, Operand *Ptr, Operand *Val); 350*03ce13f7SAndroid Build Coastguard Worker 351*03ce13f7SAndroid Build Coastguard Worker void eliminateNextVectorSextInstruction(Variable *SignExtendedResult); 352*03ce13f7SAndroid Build Coastguard Worker 353*03ce13f7SAndroid Build Coastguard Worker void emitStackProbe(size_t StackSizeBytes); 354*03ce13f7SAndroid Build Coastguard Worker 355*03ce13f7SAndroid Build Coastguard Worker /// Emit just the call instruction (without argument or return variable 356*03ce13f7SAndroid Build Coastguard Worker /// processing). 357*03ce13f7SAndroid Build Coastguard Worker Inst *emitCallToTarget(Operand *CallTarget, Variable *ReturnReg, 358*03ce13f7SAndroid Build Coastguard Worker size_t NumVariadicFpArgs = 0); 359*03ce13f7SAndroid Build Coastguard Worker /// Materialize the moves needed to return a value of the specified type. 360*03ce13f7SAndroid Build Coastguard Worker Variable *moveReturnValueToRegister(Operand *Value, Type ReturnType); 361*03ce13f7SAndroid Build Coastguard Worker 362*03ce13f7SAndroid Build Coastguard Worker /// Emit a jump table to the constant pool. 363*03ce13f7SAndroid Build Coastguard Worker void emitJumpTable(const Cfg *Func, 364*03ce13f7SAndroid Build Coastguard Worker const InstJumpTable *JumpTable) const override; 365*03ce13f7SAndroid Build Coastguard Worker 366*03ce13f7SAndroid Build Coastguard Worker /// Emit a fake use of esp to make sure esp stays alive for the entire 367*03ce13f7SAndroid Build Coastguard Worker /// function. Otherwise some esp adjustments get dead-code eliminated. keepEspLiveAtExit()368*03ce13f7SAndroid Build Coastguard Worker void keepEspLiveAtExit() { 369*03ce13f7SAndroid Build Coastguard Worker Variable *esp = 370*03ce13f7SAndroid Build Coastguard Worker Func->getTarget()->getPhysicalRegister(getStackReg(), WordType); 371*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(esp); 372*03ce13f7SAndroid Build Coastguard Worker } 373*03ce13f7SAndroid Build Coastguard Worker 374*03ce13f7SAndroid Build Coastguard Worker /// Operand legalization helpers. To deal with address mode constraints, the 375*03ce13f7SAndroid Build Coastguard Worker /// helpers will create a new Operand and emit instructions that guarantee 376*03ce13f7SAndroid Build Coastguard Worker /// that the Operand kind is one of those indicated by the LegalMask (a 377*03ce13f7SAndroid Build Coastguard Worker /// bitmask of allowed kinds). If the input Operand is known to already meet 378*03ce13f7SAndroid Build Coastguard Worker /// the constraints, it may be simply returned as the result, without creating 379*03ce13f7SAndroid Build Coastguard Worker /// any new instructions or operands. 380*03ce13f7SAndroid Build Coastguard Worker enum OperandLegalization { 381*03ce13f7SAndroid Build Coastguard Worker Legal_None = 0, 382*03ce13f7SAndroid Build Coastguard Worker Legal_Reg = 1 << 0, // physical register, not stack location 383*03ce13f7SAndroid Build Coastguard Worker Legal_Imm = 1 << 1, 384*03ce13f7SAndroid Build Coastguard Worker Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12] 385*03ce13f7SAndroid Build Coastguard Worker Legal_Rematerializable = 1 << 3, 386*03ce13f7SAndroid Build Coastguard Worker Legal_AddrAbs = 1 << 4, // ConstantRelocatable doesn't have to add RebasePtr 387*03ce13f7SAndroid Build Coastguard Worker Legal_Default = ~(Legal_Rematerializable | Legal_AddrAbs) 388*03ce13f7SAndroid Build Coastguard Worker // TODO(stichnot): Figure out whether this default works for x86-64. 389*03ce13f7SAndroid Build Coastguard Worker }; 390*03ce13f7SAndroid Build Coastguard Worker using LegalMask = uint32_t; 391*03ce13f7SAndroid Build Coastguard Worker Operand *legalize(Operand *From, LegalMask Allowed = Legal_Default, 392*03ce13f7SAndroid Build Coastguard Worker RegNumT RegNum = RegNumT()); 393*03ce13f7SAndroid Build Coastguard Worker Variable *legalizeToReg(Operand *From, RegNumT RegNum = RegNumT()); 394*03ce13f7SAndroid Build Coastguard Worker /// Legalize the first source operand for use in the cmp instruction. 395*03ce13f7SAndroid Build Coastguard Worker Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1); 396*03ce13f7SAndroid Build Coastguard Worker /// Turn a pointer operand into a memory operand that can be used by a real 397*03ce13f7SAndroid Build Coastguard Worker /// load/store operation. Legalizes the operand as well. This is a nop if the 398*03ce13f7SAndroid Build Coastguard Worker /// operand is already a legal memory operand. 399*03ce13f7SAndroid Build Coastguard Worker X86OperandMem *formMemoryOperand(Operand *Ptr, Type Ty, 400*03ce13f7SAndroid Build Coastguard Worker bool DoLegalize = true); 401*03ce13f7SAndroid Build Coastguard Worker 402*03ce13f7SAndroid Build Coastguard Worker Variable *makeReg(Type Ty, RegNumT RegNum = RegNumT()); 403*03ce13f7SAndroid Build Coastguard Worker static Type stackSlotType(); 404*03ce13f7SAndroid Build Coastguard Worker 405*03ce13f7SAndroid Build Coastguard Worker static constexpr uint32_t NoSizeLimit = 0; 406*03ce13f7SAndroid Build Coastguard Worker /// Returns the largest type which is equal to or larger than Size bytes. The 407*03ce13f7SAndroid Build Coastguard Worker /// type is suitable for copying memory i.e. a load and store will be a single 408*03ce13f7SAndroid Build Coastguard Worker /// instruction (for example x86 will get f64 not i64). 409*03ce13f7SAndroid Build Coastguard Worker static Type largestTypeInSize(uint32_t Size, uint32_t MaxSize = NoSizeLimit); 410*03ce13f7SAndroid Build Coastguard Worker /// Returns the smallest type which is equal to or larger than Size bytes. If 411*03ce13f7SAndroid Build Coastguard Worker /// one doesn't exist then the largest type smaller than Size bytes is 412*03ce13f7SAndroid Build Coastguard Worker /// returned. The type is suitable for memory copies as described at 413*03ce13f7SAndroid Build Coastguard Worker /// largestTypeInSize. 414*03ce13f7SAndroid Build Coastguard Worker static Type firstTypeThatFitsSize(uint32_t Size, 415*03ce13f7SAndroid Build Coastguard Worker uint32_t MaxSize = NoSizeLimit); 416*03ce13f7SAndroid Build Coastguard Worker 417*03ce13f7SAndroid Build Coastguard Worker Variable *copyToReg8(Operand *Src, RegNumT RegNum = RegNumT()); 418*03ce13f7SAndroid Build Coastguard Worker Variable *copyToReg(Operand *Src, RegNumT RegNum = RegNumT()); 419*03ce13f7SAndroid Build Coastguard Worker 420*03ce13f7SAndroid Build Coastguard Worker /// Returns a register containing all zeros, without affecting the FLAGS 421*03ce13f7SAndroid Build Coastguard Worker /// register, using the best instruction for the type. 422*03ce13f7SAndroid Build Coastguard Worker Variable *makeZeroedRegister(Type Ty, RegNumT RegNum = RegNumT()); 423*03ce13f7SAndroid Build Coastguard Worker 424*03ce13f7SAndroid Build Coastguard Worker /// \name Returns a vector in a register with the given constant entries. 425*03ce13f7SAndroid Build Coastguard Worker /// @{ 426*03ce13f7SAndroid Build Coastguard Worker Variable *makeVectorOfZeros(Type Ty, RegNumT RegNum = RegNumT()); 427*03ce13f7SAndroid Build Coastguard Worker Variable *makeVectorOfOnes(Type Ty, RegNumT RegNum = RegNumT()); 428*03ce13f7SAndroid Build Coastguard Worker Variable *makeVectorOfMinusOnes(Type Ty, RegNumT RegNum = RegNumT()); 429*03ce13f7SAndroid Build Coastguard Worker Variable *makeVectorOfHighOrderBits(Type Ty, RegNumT RegNum = RegNumT()); 430*03ce13f7SAndroid Build Coastguard Worker Variable *makeVectorOfFabsMask(Type Ty, RegNumT RegNum = RegNumT()); 431*03ce13f7SAndroid Build Coastguard Worker /// @} 432*03ce13f7SAndroid Build Coastguard Worker 433*03ce13f7SAndroid Build Coastguard Worker /// Return a memory operand corresponding to a stack allocated Variable. 434*03ce13f7SAndroid Build Coastguard Worker X86OperandMem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot, 435*03ce13f7SAndroid Build Coastguard Worker uint32_t Offset = 0); 436*03ce13f7SAndroid Build Coastguard Worker 437*03ce13f7SAndroid Build Coastguard Worker /// The following are helpers that insert lowered x86 instructions with 438*03ce13f7SAndroid Build Coastguard Worker /// minimal syntactic overhead, so that the lowering code can look as close to 439*03ce13f7SAndroid Build Coastguard Worker /// assembly as practical. _adc(Variable * Dest,Operand * Src0)440*03ce13f7SAndroid Build Coastguard Worker void _adc(Variable *Dest, Operand *Src0) { 441*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Adc>(Dest, Src0); 442*03ce13f7SAndroid Build Coastguard Worker } _adc_rmw(X86OperandMem * DestSrc0,Operand * Src1)443*03ce13f7SAndroid Build Coastguard Worker void _adc_rmw(X86OperandMem *DestSrc0, Operand *Src1) { 444*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::AdcRMW>(DestSrc0, Src1); 445*03ce13f7SAndroid Build Coastguard Worker } _add(Variable * Dest,Operand * Src0)446*03ce13f7SAndroid Build Coastguard Worker void _add(Variable *Dest, Operand *Src0) { 447*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Add>(Dest, Src0); 448*03ce13f7SAndroid Build Coastguard Worker } _add_rmw(X86OperandMem * DestSrc0,Operand * Src1)449*03ce13f7SAndroid Build Coastguard Worker void _add_rmw(X86OperandMem *DestSrc0, Operand *Src1) { 450*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::AddRMW>(DestSrc0, Src1); 451*03ce13f7SAndroid Build Coastguard Worker } _addps(Variable * Dest,Operand * Src0)452*03ce13f7SAndroid Build Coastguard Worker void _addps(Variable *Dest, Operand *Src0) { 453*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Addps>(Dest, Src0); 454*03ce13f7SAndroid Build Coastguard Worker } _addss(Variable * Dest,Operand * Src0)455*03ce13f7SAndroid Build Coastguard Worker void _addss(Variable *Dest, Operand *Src0) { 456*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Addss>(Dest, Src0); 457*03ce13f7SAndroid Build Coastguard Worker } 458*03ce13f7SAndroid Build Coastguard Worker void _add_sp(Operand *Adjustment); _and(Variable * Dest,Operand * Src0)459*03ce13f7SAndroid Build Coastguard Worker void _and(Variable *Dest, Operand *Src0) { 460*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::And>(Dest, Src0); 461*03ce13f7SAndroid Build Coastguard Worker } _andnps(Variable * Dest,Operand * Src0)462*03ce13f7SAndroid Build Coastguard Worker void _andnps(Variable *Dest, Operand *Src0) { 463*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Andnps>(Dest, Src0); 464*03ce13f7SAndroid Build Coastguard Worker } _andps(Variable * Dest,Operand * Src0)465*03ce13f7SAndroid Build Coastguard Worker void _andps(Variable *Dest, Operand *Src0) { 466*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Andps>(Dest, Src0); 467*03ce13f7SAndroid Build Coastguard Worker } _and_rmw(X86OperandMem * DestSrc0,Operand * Src1)468*03ce13f7SAndroid Build Coastguard Worker void _and_rmw(X86OperandMem *DestSrc0, Operand *Src1) { 469*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::AndRMW>(DestSrc0, Src1); 470*03ce13f7SAndroid Build Coastguard Worker } _blendvps(Variable * Dest,Operand * Src0,Operand * Src1)471*03ce13f7SAndroid Build Coastguard Worker void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) { 472*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Blendvps>(Dest, Src0, Src1); 473*03ce13f7SAndroid Build Coastguard Worker } _br(BrCond Condition,CfgNode * TargetTrue,CfgNode * TargetFalse)474*03ce13f7SAndroid Build Coastguard Worker void _br(BrCond Condition, CfgNode *TargetTrue, CfgNode *TargetFalse) { 475*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstX86Br>(TargetTrue, TargetFalse, Condition, 476*03ce13f7SAndroid Build Coastguard Worker InstX86Br::Far); 477*03ce13f7SAndroid Build Coastguard Worker } _br(CfgNode * Target)478*03ce13f7SAndroid Build Coastguard Worker void _br(CfgNode *Target) { 479*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstX86Br>(Target, InstX86Br::Far); 480*03ce13f7SAndroid Build Coastguard Worker } _br(BrCond Condition,CfgNode * Target)481*03ce13f7SAndroid Build Coastguard Worker void _br(BrCond Condition, CfgNode *Target) { 482*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstX86Br>(Target, Condition, InstX86Br::Far); 483*03ce13f7SAndroid Build Coastguard Worker } 484*03ce13f7SAndroid Build Coastguard Worker void _br(BrCond Condition, InstX86Label *Label, 485*03ce13f7SAndroid Build Coastguard Worker InstX86Br::Mode Kind = InstX86Br::Near) { 486*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstX86Br>(Label, Condition, Kind); 487*03ce13f7SAndroid Build Coastguard Worker } _bsf(Variable * Dest,Operand * Src0)488*03ce13f7SAndroid Build Coastguard Worker void _bsf(Variable *Dest, Operand *Src0) { 489*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Bsf>(Dest, Src0); 490*03ce13f7SAndroid Build Coastguard Worker } _bsr(Variable * Dest,Operand * Src0)491*03ce13f7SAndroid Build Coastguard Worker void _bsr(Variable *Dest, Operand *Src0) { 492*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Bsr>(Dest, Src0); 493*03ce13f7SAndroid Build Coastguard Worker } _bswap(Variable * SrcDest)494*03ce13f7SAndroid Build Coastguard Worker void _bswap(Variable *SrcDest) { Context.insert<Insts::Bswap>(SrcDest); } _cbwdq(Variable * Dest,Operand * Src0)495*03ce13f7SAndroid Build Coastguard Worker void _cbwdq(Variable *Dest, Operand *Src0) { 496*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Cbwdq>(Dest, Src0); 497*03ce13f7SAndroid Build Coastguard Worker } _cmov(Variable * Dest,Operand * Src0,BrCond Condition)498*03ce13f7SAndroid Build Coastguard Worker void _cmov(Variable *Dest, Operand *Src0, BrCond Condition) { 499*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Cmov>(Dest, Src0, Condition); 500*03ce13f7SAndroid Build Coastguard Worker } _cmp(Operand * Src0,Operand * Src1)501*03ce13f7SAndroid Build Coastguard Worker void _cmp(Operand *Src0, Operand *Src1) { 502*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Icmp>(Src0, Src1); 503*03ce13f7SAndroid Build Coastguard Worker } _cmpps(Variable * Dest,Operand * Src0,CmppsCond Condition)504*03ce13f7SAndroid Build Coastguard Worker void _cmpps(Variable *Dest, Operand *Src0, CmppsCond Condition) { 505*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Cmpps>(Dest, Src0, Condition); 506*03ce13f7SAndroid Build Coastguard Worker } _cmpxchg(Operand * DestOrAddr,Variable * Eax,Variable * Desired,bool Locked)507*03ce13f7SAndroid Build Coastguard Worker void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired, 508*03ce13f7SAndroid Build Coastguard Worker bool Locked) { 509*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Cmpxchg>(DestOrAddr, Eax, Desired, Locked); 510*03ce13f7SAndroid Build Coastguard Worker // Mark eax as possibly modified by cmpxchg. 511*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(Eax, llvm::dyn_cast<Variable>(DestOrAddr)); 512*03ce13f7SAndroid Build Coastguard Worker _set_dest_redefined(); 513*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(Eax); 514*03ce13f7SAndroid Build Coastguard Worker } _cmpxchg8b(X86OperandMem * Addr,Variable * Edx,Variable * Eax,Variable * Ecx,Variable * Ebx,bool Locked)515*03ce13f7SAndroid Build Coastguard Worker void _cmpxchg8b(X86OperandMem *Addr, Variable *Edx, Variable *Eax, 516*03ce13f7SAndroid Build Coastguard Worker Variable *Ecx, Variable *Ebx, bool Locked) { 517*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Cmpxchg8b>(Addr, Edx, Eax, Ecx, Ebx, Locked); 518*03ce13f7SAndroid Build Coastguard Worker // Mark edx, and eax as possibly modified by cmpxchg8b. 519*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(Edx); 520*03ce13f7SAndroid Build Coastguard Worker _set_dest_redefined(); 521*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(Edx); 522*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(Eax); 523*03ce13f7SAndroid Build Coastguard Worker _set_dest_redefined(); 524*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(Eax); 525*03ce13f7SAndroid Build Coastguard Worker } _cvt(Variable * Dest,Operand * Src0,Insts::Cvt::CvtVariant Variant)526*03ce13f7SAndroid Build Coastguard Worker void _cvt(Variable *Dest, Operand *Src0, Insts::Cvt::CvtVariant Variant) { 527*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Cvt>(Dest, Src0, Variant); 528*03ce13f7SAndroid Build Coastguard Worker } _round(Variable * Dest,Operand * Src0,Operand * Imm)529*03ce13f7SAndroid Build Coastguard Worker void _round(Variable *Dest, Operand *Src0, Operand *Imm) { 530*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Round>(Dest, Src0, Imm); 531*03ce13f7SAndroid Build Coastguard Worker } _div(Variable * Dest,Operand * Src0,Operand * Src1)532*03ce13f7SAndroid Build Coastguard Worker void _div(Variable *Dest, Operand *Src0, Operand *Src1) { 533*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Div>(Dest, Src0, Src1); 534*03ce13f7SAndroid Build Coastguard Worker } _divps(Variable * Dest,Operand * Src0)535*03ce13f7SAndroid Build Coastguard Worker void _divps(Variable *Dest, Operand *Src0) { 536*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Divps>(Dest, Src0); 537*03ce13f7SAndroid Build Coastguard Worker } _divss(Variable * Dest,Operand * Src0)538*03ce13f7SAndroid Build Coastguard Worker void _divss(Variable *Dest, Operand *Src0) { 539*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Divss>(Dest, Src0); 540*03ce13f7SAndroid Build Coastguard Worker } _idiv(Variable * Dest,Operand * Src0,Operand * Src1)541*03ce13f7SAndroid Build Coastguard Worker void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) { 542*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Idiv>(Dest, Src0, Src1); 543*03ce13f7SAndroid Build Coastguard Worker } _imul(Variable * Dest,Operand * Src0)544*03ce13f7SAndroid Build Coastguard Worker void _imul(Variable *Dest, Operand *Src0) { 545*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Imul>(Dest, Src0); 546*03ce13f7SAndroid Build Coastguard Worker } _imul_imm(Variable * Dest,Operand * Src0,Constant * Imm)547*03ce13f7SAndroid Build Coastguard Worker void _imul_imm(Variable *Dest, Operand *Src0, Constant *Imm) { 548*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::ImulImm>(Dest, Src0, Imm); 549*03ce13f7SAndroid Build Coastguard Worker } _insertps(Variable * Dest,Operand * Src0,Operand * Src1)550*03ce13f7SAndroid Build Coastguard Worker void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) { 551*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Insertps>(Dest, Src0, Src1); 552*03ce13f7SAndroid Build Coastguard Worker } _int3()553*03ce13f7SAndroid Build Coastguard Worker void _int3() { Context.insert<Insts::Int3>(); } _jmp(Operand * Target)554*03ce13f7SAndroid Build Coastguard Worker void _jmp(Operand *Target) { Context.insert<Insts::Jmp>(Target); } _lea(Variable * Dest,Operand * Src0)555*03ce13f7SAndroid Build Coastguard Worker void _lea(Variable *Dest, Operand *Src0) { 556*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Lea>(Dest, Src0); 557*03ce13f7SAndroid Build Coastguard Worker } 558*03ce13f7SAndroid Build Coastguard Worker void _link_bp(); 559*03ce13f7SAndroid Build Coastguard Worker void _push_reg(RegNumT RegNum); 560*03ce13f7SAndroid Build Coastguard Worker void _pop_reg(RegNumT RegNum); _mfence()561*03ce13f7SAndroid Build Coastguard Worker void _mfence() { Context.insert<Insts::Mfence>(); } 562*03ce13f7SAndroid Build Coastguard Worker /// Moves can be used to redefine registers, creating "partial kills" for 563*03ce13f7SAndroid Build Coastguard Worker /// liveness. Mark where moves are used in this way. 564*03ce13f7SAndroid Build Coastguard Worker void _redefined(Inst *MovInst, bool IsRedefinition = true) { 565*03ce13f7SAndroid Build Coastguard Worker if (IsRedefinition) 566*03ce13f7SAndroid Build Coastguard Worker MovInst->setDestRedefined(); 567*03ce13f7SAndroid Build Coastguard Worker } 568*03ce13f7SAndroid Build Coastguard Worker /// If Dest=nullptr is passed in, then a new variable is created, marked as 569*03ce13f7SAndroid Build Coastguard Worker /// infinite register allocation weight, and returned through the in/out Dest 570*03ce13f7SAndroid Build Coastguard Worker /// argument. 571*03ce13f7SAndroid Build Coastguard Worker Insts::Mov *_mov(Variable *&Dest, Operand *Src0, RegNumT RegNum = RegNumT()) { 572*03ce13f7SAndroid Build Coastguard Worker if (Dest == nullptr) 573*03ce13f7SAndroid Build Coastguard Worker Dest = makeReg(Src0->getType(), RegNum); 574*03ce13f7SAndroid Build Coastguard Worker return Context.insert<Insts::Mov>(Dest, Src0); 575*03ce13f7SAndroid Build Coastguard Worker } 576*03ce13f7SAndroid Build Coastguard Worker void _mov_sp(Operand *NewValue); _movp(Variable * Dest,Operand * Src0)577*03ce13f7SAndroid Build Coastguard Worker Insts::Movp *_movp(Variable *Dest, Operand *Src0) { 578*03ce13f7SAndroid Build Coastguard Worker return Context.insert<Insts::Movp>(Dest, Src0); 579*03ce13f7SAndroid Build Coastguard Worker } _movd(Variable * Dest,Operand * Src0)580*03ce13f7SAndroid Build Coastguard Worker void _movd(Variable *Dest, Operand *Src0) { 581*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Movd>(Dest, Src0); 582*03ce13f7SAndroid Build Coastguard Worker } _movq(Variable * Dest,Operand * Src0)583*03ce13f7SAndroid Build Coastguard Worker void _movq(Variable *Dest, Operand *Src0) { 584*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Movq>(Dest, Src0); 585*03ce13f7SAndroid Build Coastguard Worker } _movss(Variable * Dest,Variable * Src0)586*03ce13f7SAndroid Build Coastguard Worker void _movss(Variable *Dest, Variable *Src0) { 587*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::MovssRegs>(Dest, Src0); 588*03ce13f7SAndroid Build Coastguard Worker } _movsx(Variable * Dest,Operand * Src0)589*03ce13f7SAndroid Build Coastguard Worker void _movsx(Variable *Dest, Operand *Src0) { 590*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Movsx>(Dest, Src0); 591*03ce13f7SAndroid Build Coastguard Worker } _movzx(Variable * Dest,Operand * Src0)592*03ce13f7SAndroid Build Coastguard Worker Insts::Movzx *_movzx(Variable *Dest, Operand *Src0) { 593*03ce13f7SAndroid Build Coastguard Worker return Context.insert<Insts::Movzx>(Dest, Src0); 594*03ce13f7SAndroid Build Coastguard Worker } _maxss(Variable * Dest,Operand * Src0)595*03ce13f7SAndroid Build Coastguard Worker void _maxss(Variable *Dest, Operand *Src0) { 596*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Maxss>(Dest, Src0); 597*03ce13f7SAndroid Build Coastguard Worker } _minss(Variable * Dest,Operand * Src0)598*03ce13f7SAndroid Build Coastguard Worker void _minss(Variable *Dest, Operand *Src0) { 599*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Minss>(Dest, Src0); 600*03ce13f7SAndroid Build Coastguard Worker } _maxps(Variable * Dest,Operand * Src0)601*03ce13f7SAndroid Build Coastguard Worker void _maxps(Variable *Dest, Operand *Src0) { 602*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Maxps>(Dest, Src0); 603*03ce13f7SAndroid Build Coastguard Worker } _minps(Variable * Dest,Operand * Src0)604*03ce13f7SAndroid Build Coastguard Worker void _minps(Variable *Dest, Operand *Src0) { 605*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Minps>(Dest, Src0); 606*03ce13f7SAndroid Build Coastguard Worker } _mul(Variable * Dest,Variable * Src0,Operand * Src1)607*03ce13f7SAndroid Build Coastguard Worker void _mul(Variable *Dest, Variable *Src0, Operand *Src1) { 608*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Mul>(Dest, Src0, Src1); 609*03ce13f7SAndroid Build Coastguard Worker } _mulps(Variable * Dest,Operand * Src0)610*03ce13f7SAndroid Build Coastguard Worker void _mulps(Variable *Dest, Operand *Src0) { 611*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Mulps>(Dest, Src0); 612*03ce13f7SAndroid Build Coastguard Worker } _mulss(Variable * Dest,Operand * Src0)613*03ce13f7SAndroid Build Coastguard Worker void _mulss(Variable *Dest, Operand *Src0) { 614*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Mulss>(Dest, Src0); 615*03ce13f7SAndroid Build Coastguard Worker } _neg(Variable * SrcDest)616*03ce13f7SAndroid Build Coastguard Worker void _neg(Variable *SrcDest) { Context.insert<Insts::Neg>(SrcDest); } _nop(SizeT Variant)617*03ce13f7SAndroid Build Coastguard Worker void _nop(SizeT Variant) { Context.insert<Insts::Nop>(Variant); } _or(Variable * Dest,Operand * Src0)618*03ce13f7SAndroid Build Coastguard Worker void _or(Variable *Dest, Operand *Src0) { 619*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Or>(Dest, Src0); 620*03ce13f7SAndroid Build Coastguard Worker } _orps(Variable * Dest,Operand * Src0)621*03ce13f7SAndroid Build Coastguard Worker void _orps(Variable *Dest, Operand *Src0) { 622*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Orps>(Dest, Src0); 623*03ce13f7SAndroid Build Coastguard Worker } _or_rmw(X86OperandMem * DestSrc0,Operand * Src1)624*03ce13f7SAndroid Build Coastguard Worker void _or_rmw(X86OperandMem *DestSrc0, Operand *Src1) { 625*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::OrRMW>(DestSrc0, Src1); 626*03ce13f7SAndroid Build Coastguard Worker } _padd(Variable * Dest,Operand * Src0)627*03ce13f7SAndroid Build Coastguard Worker void _padd(Variable *Dest, Operand *Src0) { 628*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Padd>(Dest, Src0); 629*03ce13f7SAndroid Build Coastguard Worker } _padds(Variable * Dest,Operand * Src0)630*03ce13f7SAndroid Build Coastguard Worker void _padds(Variable *Dest, Operand *Src0) { 631*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Padds>(Dest, Src0); 632*03ce13f7SAndroid Build Coastguard Worker } _paddus(Variable * Dest,Operand * Src0)633*03ce13f7SAndroid Build Coastguard Worker void _paddus(Variable *Dest, Operand *Src0) { 634*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Paddus>(Dest, Src0); 635*03ce13f7SAndroid Build Coastguard Worker } _pand(Variable * Dest,Operand * Src0)636*03ce13f7SAndroid Build Coastguard Worker void _pand(Variable *Dest, Operand *Src0) { 637*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pand>(Dest, Src0); 638*03ce13f7SAndroid Build Coastguard Worker } _pandn(Variable * Dest,Operand * Src0)639*03ce13f7SAndroid Build Coastguard Worker void _pandn(Variable *Dest, Operand *Src0) { 640*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pandn>(Dest, Src0); 641*03ce13f7SAndroid Build Coastguard Worker } _pblendvb(Variable * Dest,Operand * Src0,Operand * Src1)642*03ce13f7SAndroid Build Coastguard Worker void _pblendvb(Variable *Dest, Operand *Src0, Operand *Src1) { 643*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pblendvb>(Dest, Src0, Src1); 644*03ce13f7SAndroid Build Coastguard Worker } 645*03ce13f7SAndroid Build Coastguard Worker void _pcmpeq(Variable *Dest, Operand *Src0, 646*03ce13f7SAndroid Build Coastguard Worker Type ArithmeticTypeOverride = IceType_void) { 647*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pcmpeq>(Dest, Src0, ArithmeticTypeOverride); 648*03ce13f7SAndroid Build Coastguard Worker } _pcmpgt(Variable * Dest,Operand * Src0)649*03ce13f7SAndroid Build Coastguard Worker void _pcmpgt(Variable *Dest, Operand *Src0) { 650*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pcmpgt>(Dest, Src0); 651*03ce13f7SAndroid Build Coastguard Worker } _pextr(Variable * Dest,Operand * Src0,Operand * Src1)652*03ce13f7SAndroid Build Coastguard Worker void _pextr(Variable *Dest, Operand *Src0, Operand *Src1) { 653*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pextr>(Dest, Src0, Src1); 654*03ce13f7SAndroid Build Coastguard Worker } _pinsr(Variable * Dest,Operand * Src0,Operand * Src1)655*03ce13f7SAndroid Build Coastguard Worker void _pinsr(Variable *Dest, Operand *Src0, Operand *Src1) { 656*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pinsr>(Dest, Src0, Src1); 657*03ce13f7SAndroid Build Coastguard Worker } _pmull(Variable * Dest,Operand * Src0)658*03ce13f7SAndroid Build Coastguard Worker void _pmull(Variable *Dest, Operand *Src0) { 659*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pmull>(Dest, Src0); 660*03ce13f7SAndroid Build Coastguard Worker } _pmulhw(Variable * Dest,Operand * Src0)661*03ce13f7SAndroid Build Coastguard Worker void _pmulhw(Variable *Dest, Operand *Src0) { 662*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pmulhw>(Dest, Src0); 663*03ce13f7SAndroid Build Coastguard Worker } _pmulhuw(Variable * Dest,Operand * Src0)664*03ce13f7SAndroid Build Coastguard Worker void _pmulhuw(Variable *Dest, Operand *Src0) { 665*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pmulhuw>(Dest, Src0); 666*03ce13f7SAndroid Build Coastguard Worker } _pmaddwd(Variable * Dest,Operand * Src0)667*03ce13f7SAndroid Build Coastguard Worker void _pmaddwd(Variable *Dest, Operand *Src0) { 668*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pmaddwd>(Dest, Src0); 669*03ce13f7SAndroid Build Coastguard Worker } _pmuludq(Variable * Dest,Operand * Src0)670*03ce13f7SAndroid Build Coastguard Worker void _pmuludq(Variable *Dest, Operand *Src0) { 671*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pmuludq>(Dest, Src0); 672*03ce13f7SAndroid Build Coastguard Worker } _pop(Variable * Dest)673*03ce13f7SAndroid Build Coastguard Worker void _pop(Variable *Dest) { Context.insert<Insts::Pop>(Dest); } _por(Variable * Dest,Operand * Src0)674*03ce13f7SAndroid Build Coastguard Worker void _por(Variable *Dest, Operand *Src0) { 675*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Por>(Dest, Src0); 676*03ce13f7SAndroid Build Coastguard Worker } _punpckl(Variable * Dest,Operand * Src0)677*03ce13f7SAndroid Build Coastguard Worker void _punpckl(Variable *Dest, Operand *Src0) { 678*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Punpckl>(Dest, Src0); 679*03ce13f7SAndroid Build Coastguard Worker } _punpckh(Variable * Dest,Operand * Src0)680*03ce13f7SAndroid Build Coastguard Worker void _punpckh(Variable *Dest, Operand *Src0) { 681*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Punpckh>(Dest, Src0); 682*03ce13f7SAndroid Build Coastguard Worker } _packss(Variable * Dest,Operand * Src0)683*03ce13f7SAndroid Build Coastguard Worker void _packss(Variable *Dest, Operand *Src0) { 684*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Packss>(Dest, Src0); 685*03ce13f7SAndroid Build Coastguard Worker } _packus(Variable * Dest,Operand * Src0)686*03ce13f7SAndroid Build Coastguard Worker void _packus(Variable *Dest, Operand *Src0) { 687*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Packus>(Dest, Src0); 688*03ce13f7SAndroid Build Coastguard Worker } _pshufb(Variable * Dest,Operand * Src0)689*03ce13f7SAndroid Build Coastguard Worker void _pshufb(Variable *Dest, Operand *Src0) { 690*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pshufb>(Dest, Src0); 691*03ce13f7SAndroid Build Coastguard Worker } _pshufd(Variable * Dest,Operand * Src0,Operand * Src1)692*03ce13f7SAndroid Build Coastguard Worker void _pshufd(Variable *Dest, Operand *Src0, Operand *Src1) { 693*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pshufd>(Dest, Src0, Src1); 694*03ce13f7SAndroid Build Coastguard Worker } _psll(Variable * Dest,Operand * Src0)695*03ce13f7SAndroid Build Coastguard Worker void _psll(Variable *Dest, Operand *Src0) { 696*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Psll>(Dest, Src0); 697*03ce13f7SAndroid Build Coastguard Worker } _psra(Variable * Dest,Operand * Src0)698*03ce13f7SAndroid Build Coastguard Worker void _psra(Variable *Dest, Operand *Src0) { 699*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Psra>(Dest, Src0); 700*03ce13f7SAndroid Build Coastguard Worker } _psrl(Variable * Dest,Operand * Src0)701*03ce13f7SAndroid Build Coastguard Worker void _psrl(Variable *Dest, Operand *Src0) { 702*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Psrl>(Dest, Src0); 703*03ce13f7SAndroid Build Coastguard Worker } _psub(Variable * Dest,Operand * Src0)704*03ce13f7SAndroid Build Coastguard Worker void _psub(Variable *Dest, Operand *Src0) { 705*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Psub>(Dest, Src0); 706*03ce13f7SAndroid Build Coastguard Worker } _psubs(Variable * Dest,Operand * Src0)707*03ce13f7SAndroid Build Coastguard Worker void _psubs(Variable *Dest, Operand *Src0) { 708*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Psubs>(Dest, Src0); 709*03ce13f7SAndroid Build Coastguard Worker } _psubus(Variable * Dest,Operand * Src0)710*03ce13f7SAndroid Build Coastguard Worker void _psubus(Variable *Dest, Operand *Src0) { 711*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Psubus>(Dest, Src0); 712*03ce13f7SAndroid Build Coastguard Worker } _push(Operand * Src0)713*03ce13f7SAndroid Build Coastguard Worker void _push(Operand *Src0) { Context.insert<Insts::Push>(Src0); } _pxor(Variable * Dest,Operand * Src0)714*03ce13f7SAndroid Build Coastguard Worker void _pxor(Variable *Dest, Operand *Src0) { 715*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Pxor>(Dest, Src0); 716*03ce13f7SAndroid Build Coastguard Worker } 717*03ce13f7SAndroid Build Coastguard Worker void _ret(Variable *Src0 = nullptr) { Context.insert<Insts::Ret>(Src0); } _rol(Variable * Dest,Operand * Src0)718*03ce13f7SAndroid Build Coastguard Worker void _rol(Variable *Dest, Operand *Src0) { 719*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Rol>(Dest, Src0); 720*03ce13f7SAndroid Build Coastguard Worker } _round(Variable * Dest,Operand * Src,Constant * Imm)721*03ce13f7SAndroid Build Coastguard Worker void _round(Variable *Dest, Operand *Src, Constant *Imm) { 722*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Round>(Dest, Src, Imm); 723*03ce13f7SAndroid Build Coastguard Worker } _sar(Variable * Dest,Operand * Src0)724*03ce13f7SAndroid Build Coastguard Worker void _sar(Variable *Dest, Operand *Src0) { 725*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Sar>(Dest, Src0); 726*03ce13f7SAndroid Build Coastguard Worker } _sbb(Variable * Dest,Operand * Src0)727*03ce13f7SAndroid Build Coastguard Worker void _sbb(Variable *Dest, Operand *Src0) { 728*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Sbb>(Dest, Src0); 729*03ce13f7SAndroid Build Coastguard Worker } _sbb_rmw(X86OperandMem * DestSrc0,Operand * Src1)730*03ce13f7SAndroid Build Coastguard Worker void _sbb_rmw(X86OperandMem *DestSrc0, Operand *Src1) { 731*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::SbbRMW>(DestSrc0, Src1); 732*03ce13f7SAndroid Build Coastguard Worker } _setcc(Variable * Dest,BrCond Condition)733*03ce13f7SAndroid Build Coastguard Worker void _setcc(Variable *Dest, BrCond Condition) { 734*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Setcc>(Dest, Condition); 735*03ce13f7SAndroid Build Coastguard Worker } _shl(Variable * Dest,Operand * Src0)736*03ce13f7SAndroid Build Coastguard Worker void _shl(Variable *Dest, Operand *Src0) { 737*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Shl>(Dest, Src0); 738*03ce13f7SAndroid Build Coastguard Worker } _shld(Variable * Dest,Variable * Src0,Operand * Src1)739*03ce13f7SAndroid Build Coastguard Worker void _shld(Variable *Dest, Variable *Src0, Operand *Src1) { 740*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Shld>(Dest, Src0, Src1); 741*03ce13f7SAndroid Build Coastguard Worker } _shr(Variable * Dest,Operand * Src0)742*03ce13f7SAndroid Build Coastguard Worker void _shr(Variable *Dest, Operand *Src0) { 743*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Shr>(Dest, Src0); 744*03ce13f7SAndroid Build Coastguard Worker } _shrd(Variable * Dest,Variable * Src0,Operand * Src1)745*03ce13f7SAndroid Build Coastguard Worker void _shrd(Variable *Dest, Variable *Src0, Operand *Src1) { 746*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Shrd>(Dest, Src0, Src1); 747*03ce13f7SAndroid Build Coastguard Worker } _shufps(Variable * Dest,Operand * Src0,Operand * Src1)748*03ce13f7SAndroid Build Coastguard Worker void _shufps(Variable *Dest, Operand *Src0, Operand *Src1) { 749*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Shufps>(Dest, Src0, Src1); 750*03ce13f7SAndroid Build Coastguard Worker } _movmsk(Variable * Dest,Operand * Src0)751*03ce13f7SAndroid Build Coastguard Worker void _movmsk(Variable *Dest, Operand *Src0) { 752*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Movmsk>(Dest, Src0); 753*03ce13f7SAndroid Build Coastguard Worker } _sqrt(Variable * Dest,Operand * Src0)754*03ce13f7SAndroid Build Coastguard Worker void _sqrt(Variable *Dest, Operand *Src0) { 755*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Sqrt>(Dest, Src0); 756*03ce13f7SAndroid Build Coastguard Worker } _store(Operand * Value,X86Operand * Mem)757*03ce13f7SAndroid Build Coastguard Worker void _store(Operand *Value, X86Operand *Mem) { 758*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Store>(Value, Mem); 759*03ce13f7SAndroid Build Coastguard Worker } _storep(Variable * Value,X86OperandMem * Mem)760*03ce13f7SAndroid Build Coastguard Worker void _storep(Variable *Value, X86OperandMem *Mem) { 761*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::StoreP>(Value, Mem); 762*03ce13f7SAndroid Build Coastguard Worker } _storeq(Operand * Value,X86OperandMem * Mem)763*03ce13f7SAndroid Build Coastguard Worker void _storeq(Operand *Value, X86OperandMem *Mem) { 764*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::StoreQ>(Value, Mem); 765*03ce13f7SAndroid Build Coastguard Worker } _stored(Operand * Value,X86OperandMem * Mem)766*03ce13f7SAndroid Build Coastguard Worker void _stored(Operand *Value, X86OperandMem *Mem) { 767*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::StoreD>(Value, Mem); 768*03ce13f7SAndroid Build Coastguard Worker } _sub(Variable * Dest,Operand * Src0)769*03ce13f7SAndroid Build Coastguard Worker void _sub(Variable *Dest, Operand *Src0) { 770*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Sub>(Dest, Src0); 771*03ce13f7SAndroid Build Coastguard Worker } _sub_rmw(X86OperandMem * DestSrc0,Operand * Src1)772*03ce13f7SAndroid Build Coastguard Worker void _sub_rmw(X86OperandMem *DestSrc0, Operand *Src1) { 773*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::SubRMW>(DestSrc0, Src1); 774*03ce13f7SAndroid Build Coastguard Worker } 775*03ce13f7SAndroid Build Coastguard Worker void _sub_sp(Operand *Adjustment); _subps(Variable * Dest,Operand * Src0)776*03ce13f7SAndroid Build Coastguard Worker void _subps(Variable *Dest, Operand *Src0) { 777*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Subps>(Dest, Src0); 778*03ce13f7SAndroid Build Coastguard Worker } _subss(Variable * Dest,Operand * Src0)779*03ce13f7SAndroid Build Coastguard Worker void _subss(Variable *Dest, Operand *Src0) { 780*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Subss>(Dest, Src0); 781*03ce13f7SAndroid Build Coastguard Worker } _test(Operand * Src0,Operand * Src1)782*03ce13f7SAndroid Build Coastguard Worker void _test(Operand *Src0, Operand *Src1) { 783*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Test>(Src0, Src1); 784*03ce13f7SAndroid Build Coastguard Worker } _ucomiss(Operand * Src0,Operand * Src1)785*03ce13f7SAndroid Build Coastguard Worker void _ucomiss(Operand *Src0, Operand *Src1) { 786*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Ucomiss>(Src0, Src1); 787*03ce13f7SAndroid Build Coastguard Worker } _ud2()788*03ce13f7SAndroid Build Coastguard Worker void _ud2() { Context.insert<Insts::UD2>(); } 789*03ce13f7SAndroid Build Coastguard Worker void _unlink_bp(); _xadd(Operand * Dest,Variable * Src,bool Locked)790*03ce13f7SAndroid Build Coastguard Worker void _xadd(Operand *Dest, Variable *Src, bool Locked) { 791*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Xadd>(Dest, Src, Locked); 792*03ce13f7SAndroid Build Coastguard Worker // The xadd exchanges Dest and Src (modifying Src). Model that update with 793*03ce13f7SAndroid Build Coastguard Worker // a FakeDef followed by a FakeUse. 794*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest)); 795*03ce13f7SAndroid Build Coastguard Worker _set_dest_redefined(); 796*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(Src); 797*03ce13f7SAndroid Build Coastguard Worker } _xchg(Operand * Dest,Variable * Src)798*03ce13f7SAndroid Build Coastguard Worker void _xchg(Operand *Dest, Variable *Src) { 799*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Xchg>(Dest, Src); 800*03ce13f7SAndroid Build Coastguard Worker // The xchg modifies Dest and Src -- model that update with a 801*03ce13f7SAndroid Build Coastguard Worker // FakeDef/FakeUse. 802*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeDef>(Src, llvm::dyn_cast<Variable>(Dest)); 803*03ce13f7SAndroid Build Coastguard Worker _set_dest_redefined(); 804*03ce13f7SAndroid Build Coastguard Worker Context.insert<InstFakeUse>(Src); 805*03ce13f7SAndroid Build Coastguard Worker } _xor(Variable * Dest,Operand * Src0)806*03ce13f7SAndroid Build Coastguard Worker void _xor(Variable *Dest, Operand *Src0) { 807*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Xor>(Dest, Src0); 808*03ce13f7SAndroid Build Coastguard Worker } _xorps(Variable * Dest,Operand * Src0)809*03ce13f7SAndroid Build Coastguard Worker void _xorps(Variable *Dest, Operand *Src0) { 810*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::Xorps>(Dest, Src0); 811*03ce13f7SAndroid Build Coastguard Worker } _xor_rmw(X86OperandMem * DestSrc0,Operand * Src1)812*03ce13f7SAndroid Build Coastguard Worker void _xor_rmw(X86OperandMem *DestSrc0, Operand *Src1) { 813*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::XorRMW>(DestSrc0, Src1); 814*03ce13f7SAndroid Build Coastguard Worker } 815*03ce13f7SAndroid Build Coastguard Worker _iaca_start()816*03ce13f7SAndroid Build Coastguard Worker void _iaca_start() { 817*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::minimal()) 818*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::IacaStart>(); 819*03ce13f7SAndroid Build Coastguard Worker } _iaca_end()820*03ce13f7SAndroid Build Coastguard Worker void _iaca_end() { 821*03ce13f7SAndroid Build Coastguard Worker if (!BuildDefs::minimal()) 822*03ce13f7SAndroid Build Coastguard Worker Context.insert<Insts::IacaEnd>(); 823*03ce13f7SAndroid Build Coastguard Worker } 824*03ce13f7SAndroid Build Coastguard Worker 825*03ce13f7SAndroid Build Coastguard Worker /// This class helps wrap IACA markers around the code generated by the 826*03ce13f7SAndroid Build Coastguard Worker /// current scope. It means you don't need to put an end before each return. 827*03ce13f7SAndroid Build Coastguard Worker class ScopedIacaMark { 828*03ce13f7SAndroid Build Coastguard Worker ScopedIacaMark(const ScopedIacaMark &) = delete; 829*03ce13f7SAndroid Build Coastguard Worker ScopedIacaMark &operator=(const ScopedIacaMark &) = delete; 830*03ce13f7SAndroid Build Coastguard Worker 831*03ce13f7SAndroid Build Coastguard Worker public: ScopedIacaMark(TargetX8664 * Lowering)832*03ce13f7SAndroid Build Coastguard Worker ScopedIacaMark(TargetX8664 *Lowering) : Lowering(Lowering) { 833*03ce13f7SAndroid Build Coastguard Worker Lowering->_iaca_start(); 834*03ce13f7SAndroid Build Coastguard Worker } ~ScopedIacaMark()835*03ce13f7SAndroid Build Coastguard Worker ~ScopedIacaMark() { end(); } end()836*03ce13f7SAndroid Build Coastguard Worker void end() { 837*03ce13f7SAndroid Build Coastguard Worker if (!Lowering) 838*03ce13f7SAndroid Build Coastguard Worker return; 839*03ce13f7SAndroid Build Coastguard Worker Lowering->_iaca_end(); 840*03ce13f7SAndroid Build Coastguard Worker Lowering = nullptr; 841*03ce13f7SAndroid Build Coastguard Worker } 842*03ce13f7SAndroid Build Coastguard Worker 843*03ce13f7SAndroid Build Coastguard Worker private: 844*03ce13f7SAndroid Build Coastguard Worker TargetX8664 *Lowering; 845*03ce13f7SAndroid Build Coastguard Worker }; 846*03ce13f7SAndroid Build Coastguard Worker 847*03ce13f7SAndroid Build Coastguard Worker bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1); 848*03ce13f7SAndroid Build Coastguard Worker void findRMW(); 849*03ce13f7SAndroid Build Coastguard Worker 850*03ce13f7SAndroid Build Coastguard Worker static uint32_t applyStackAlignment(uint32_t Value); 851*03ce13f7SAndroid Build Coastguard Worker 852*03ce13f7SAndroid Build Coastguard Worker bool IsEbpBasedFrame = false; 853*03ce13f7SAndroid Build Coastguard Worker 854*03ce13f7SAndroid Build Coastguard Worker /// Stack alignment guaranteed by the ABI. 855*03ce13f7SAndroid Build Coastguard Worker static constexpr uint32_t X86_STACK_ALIGNMENT_BYTES = 16; 856*03ce13f7SAndroid Build Coastguard Worker /// Stack alignment required by the currently lowered function. 857*03ce13f7SAndroid Build Coastguard Worker const uint32_t RequiredStackAlignment = X86_STACK_ALIGNMENT_BYTES; 858*03ce13f7SAndroid Build Coastguard Worker size_t SpillAreaSizeBytes = 0; 859*03ce13f7SAndroid Build Coastguard Worker size_t FixedAllocaSizeBytes = 0; 860*03ce13f7SAndroid Build Coastguard Worker size_t FixedAllocaAlignBytes = 0; 861*03ce13f7SAndroid Build Coastguard Worker bool PrologEmitsFixedAllocas = false; 862*03ce13f7SAndroid Build Coastguard Worker uint32_t MaxOutArgsSizeBytes = 0; 863*03ce13f7SAndroid Build Coastguard Worker static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSet; 864*03ce13f7SAndroid Build Coastguard Worker static std::array<SmallBitVector, RCX86_NUM> TypeToRegisterSetUnfiltered; 865*03ce13f7SAndroid Build Coastguard Worker static std::array<SmallBitVector, RegisterSet::Reg_NUM> RegisterAliases; 866*03ce13f7SAndroid Build Coastguard Worker SmallBitVector RegsUsed; 867*03ce13f7SAndroid Build Coastguard Worker std::array<VarList, IceType_NUM> PhysicalRegisters; 868*03ce13f7SAndroid Build Coastguard Worker 869*03ce13f7SAndroid Build Coastguard Worker private: 870*03ce13f7SAndroid Build Coastguard Worker void lowerShift64(InstArithmetic::OpKind Op, Operand *Src0Lo, Operand *Src0Hi, 871*03ce13f7SAndroid Build Coastguard Worker Operand *Src1Lo, Variable *DestLo, Variable *DestHi); 872*03ce13f7SAndroid Build Coastguard Worker 873*03ce13f7SAndroid Build Coastguard Worker /// Emit the code for a combined operation and consumer instruction, or set 874*03ce13f7SAndroid Build Coastguard Worker /// the destination variable of the operation if Consumer == nullptr. 875*03ce13f7SAndroid Build Coastguard Worker void lowerIcmpAndConsumer(const InstIcmp *Icmp, const Inst *Consumer); 876*03ce13f7SAndroid Build Coastguard Worker void lowerFcmpAndConsumer(const InstFcmp *Fcmp, const Inst *Consumer); 877*03ce13f7SAndroid Build Coastguard Worker void lowerArithAndConsumer(const InstArithmetic *Arith, const Inst *Consumer); 878*03ce13f7SAndroid Build Coastguard Worker 879*03ce13f7SAndroid Build Coastguard Worker /// Emit a setcc instruction if Consumer == nullptr; otherwise emit a 880*03ce13f7SAndroid Build Coastguard Worker /// specialized version of Consumer. 881*03ce13f7SAndroid Build Coastguard Worker void setccOrConsumer(BrCond Condition, Variable *Dest, const Inst *Consumer); 882*03ce13f7SAndroid Build Coastguard Worker 883*03ce13f7SAndroid Build Coastguard Worker /// Emit a mov [1|0] instruction if Consumer == nullptr; otherwise emit a 884*03ce13f7SAndroid Build Coastguard Worker /// specialized version of Consumer. 885*03ce13f7SAndroid Build Coastguard Worker void movOrConsumer(bool IcmpResult, Variable *Dest, const Inst *Consumer); 886*03ce13f7SAndroid Build Coastguard Worker 887*03ce13f7SAndroid Build Coastguard Worker /// Emit the code for instructions with a vector type. 888*03ce13f7SAndroid Build Coastguard Worker void lowerIcmpVector(const InstIcmp *Icmp); 889*03ce13f7SAndroid Build Coastguard Worker void lowerFcmpVector(const InstFcmp *Icmp); 890*03ce13f7SAndroid Build Coastguard Worker void lowerSelectVector(const InstSelect *Instr); 891*03ce13f7SAndroid Build Coastguard Worker 892*03ce13f7SAndroid Build Coastguard Worker /// Helpers for select lowering. 893*03ce13f7SAndroid Build Coastguard Worker void lowerSelectMove(Variable *Dest, BrCond Cond, Operand *SrcT, 894*03ce13f7SAndroid Build Coastguard Worker Operand *SrcF); 895*03ce13f7SAndroid Build Coastguard Worker void lowerSelectIntMove(Variable *Dest, BrCond Cond, Operand *SrcT, 896*03ce13f7SAndroid Build Coastguard Worker Operand *SrcF); 897*03ce13f7SAndroid Build Coastguard Worker /// Generic helper to move an arbitrary type from Src to Dest. 898*03ce13f7SAndroid Build Coastguard Worker void lowerMove(Variable *Dest, Operand *Src, bool IsRedefinition); 899*03ce13f7SAndroid Build Coastguard Worker 900*03ce13f7SAndroid Build Coastguard Worker /// Optimizations for idiom recognition. 901*03ce13f7SAndroid Build Coastguard Worker bool lowerOptimizeFcmpSelect(const InstFcmp *Fcmp, const InstSelect *Select); 902*03ce13f7SAndroid Build Coastguard Worker 903*03ce13f7SAndroid Build Coastguard Worker BoolFolding FoldingInfo; 904*03ce13f7SAndroid Build Coastguard Worker 905*03ce13f7SAndroid Build Coastguard Worker /// Helpers for lowering ShuffleVector 906*03ce13f7SAndroid Build Coastguard Worker /// @{ 907*03ce13f7SAndroid Build Coastguard Worker Variable *lowerShuffleVector_AllFromSameSrc(Operand *Src, SizeT Index0, 908*03ce13f7SAndroid Build Coastguard Worker SizeT Index1, SizeT Index2, 909*03ce13f7SAndroid Build Coastguard Worker SizeT Index3); 910*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT IGNORE_INDEX = 0x80000000u; 911*03ce13f7SAndroid Build Coastguard Worker Variable *lowerShuffleVector_TwoFromSameSrc(Operand *Src0, SizeT Index0, 912*03ce13f7SAndroid Build Coastguard Worker SizeT Index1, Operand *Src1, 913*03ce13f7SAndroid Build Coastguard Worker SizeT Index2, SizeT Index3); 914*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT UNIFIED_INDEX_0 = 0; 915*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT UNIFIED_INDEX_1 = 2; 916*03ce13f7SAndroid Build Coastguard Worker Variable *lowerShuffleVector_UnifyFromDifferentSrcs(Operand *Src0, 917*03ce13f7SAndroid Build Coastguard Worker SizeT Index0, 918*03ce13f7SAndroid Build Coastguard Worker Operand *Src1, 919*03ce13f7SAndroid Build Coastguard Worker SizeT Index1); 920*03ce13f7SAndroid Build Coastguard Worker static constexpr SizeT CLEAR_ALL_BITS = 0x80; 921*03ce13f7SAndroid Build Coastguard Worker SizeT PshufbMaskCount = 0; 922*03ce13f7SAndroid Build Coastguard Worker GlobalString lowerShuffleVector_NewMaskName(); 923*03ce13f7SAndroid Build Coastguard Worker ConstantRelocatable *lowerShuffleVector_CreatePshufbMask( 924*03ce13f7SAndroid Build Coastguard Worker int8_t Idx0, int8_t Idx1, int8_t Idx2, int8_t Idx3, int8_t Idx4, 925*03ce13f7SAndroid Build Coastguard Worker int8_t Idx5, int8_t Idx6, int8_t Idx7, int8_t Idx8, int8_t Idx9, 926*03ce13f7SAndroid Build Coastguard Worker int8_t Idx10, int8_t Idx11, int8_t Idx12, int8_t Idx13, int8_t Idx14, 927*03ce13f7SAndroid Build Coastguard Worker int8_t Idx15); 928*03ce13f7SAndroid Build Coastguard Worker void lowerShuffleVector_UsingPshufb(Variable *Dest, Operand *Src0, 929*03ce13f7SAndroid Build Coastguard Worker Operand *Src1, int8_t Idx0, int8_t Idx1, 930*03ce13f7SAndroid Build Coastguard Worker int8_t Idx2, int8_t Idx3, int8_t Idx4, 931*03ce13f7SAndroid Build Coastguard Worker int8_t Idx5, int8_t Idx6, int8_t Idx7, 932*03ce13f7SAndroid Build Coastguard Worker int8_t Idx8, int8_t Idx9, int8_t Idx10, 933*03ce13f7SAndroid Build Coastguard Worker int8_t Idx11, int8_t Idx12, int8_t Idx13, 934*03ce13f7SAndroid Build Coastguard Worker int8_t Idx14, int8_t Idx15); 935*03ce13f7SAndroid Build Coastguard Worker /// @} 936*03ce13f7SAndroid Build Coastguard Worker 937*03ce13f7SAndroid Build Coastguard Worker /// The following table summarizes the logic for lowering the fcmp 938*03ce13f7SAndroid Build Coastguard Worker /// instruction. There is one table entry for each of the 16 conditions. 939*03ce13f7SAndroid Build Coastguard Worker /// 940*03ce13f7SAndroid Build Coastguard Worker /// The first four columns describe the case when the operands are floating 941*03ce13f7SAndroid Build Coastguard Worker /// point scalar values. A comment in lowerFcmp() describes the lowering 942*03ce13f7SAndroid Build Coastguard Worker /// template. In the most general case, there is a compare followed by two 943*03ce13f7SAndroid Build Coastguard Worker /// conditional branches, because some fcmp conditions don't map to a single 944*03ce13f7SAndroid Build Coastguard Worker /// x86 conditional branch. However, in many cases it is possible to swap the 945*03ce13f7SAndroid Build Coastguard Worker /// operands in the comparison and have a single conditional branch. Since 946*03ce13f7SAndroid Build Coastguard Worker /// it's quite tedious to validate the table by hand, good execution tests are 947*03ce13f7SAndroid Build Coastguard Worker /// helpful. 948*03ce13f7SAndroid Build Coastguard Worker /// 949*03ce13f7SAndroid Build Coastguard Worker /// The last two columns describe the case when the operands are vectors of 950*03ce13f7SAndroid Build Coastguard Worker /// floating point values. For most fcmp conditions, there is a clear mapping 951*03ce13f7SAndroid Build Coastguard Worker /// to a single x86 cmpps instruction variant. Some fcmp conditions require 952*03ce13f7SAndroid Build Coastguard Worker /// special code to handle and these are marked in the table with a 953*03ce13f7SAndroid Build Coastguard Worker /// Cmpps_Invalid predicate. 954*03ce13f7SAndroid Build Coastguard Worker /// {@ 955*03ce13f7SAndroid Build Coastguard Worker static const struct TableFcmpType { 956*03ce13f7SAndroid Build Coastguard Worker uint32_t Default; 957*03ce13f7SAndroid Build Coastguard Worker bool SwapScalarOperands; 958*03ce13f7SAndroid Build Coastguard Worker CondX86::BrCond C1, C2; 959*03ce13f7SAndroid Build Coastguard Worker bool SwapVectorOperands; 960*03ce13f7SAndroid Build Coastguard Worker CondX86::CmppsCond Predicate; 961*03ce13f7SAndroid Build Coastguard Worker } TableFcmp[]; 962*03ce13f7SAndroid Build Coastguard Worker static const size_t TableFcmpSize; 963*03ce13f7SAndroid Build Coastguard Worker /// @} 964*03ce13f7SAndroid Build Coastguard Worker 965*03ce13f7SAndroid Build Coastguard Worker /// The following table summarizes the logic for lowering the icmp instruction 966*03ce13f7SAndroid Build Coastguard Worker /// for i32 and narrower types. Each icmp condition has a clear mapping to an 967*03ce13f7SAndroid Build Coastguard Worker /// x86 conditional branch instruction. 968*03ce13f7SAndroid Build Coastguard Worker /// {@ 969*03ce13f7SAndroid Build Coastguard Worker static const struct TableIcmp32Type { 970*03ce13f7SAndroid Build Coastguard Worker CondX86::BrCond Mapping; 971*03ce13f7SAndroid Build Coastguard Worker } TableIcmp32[]; 972*03ce13f7SAndroid Build Coastguard Worker static const size_t TableIcmp32Size; 973*03ce13f7SAndroid Build Coastguard Worker /// @} 974*03ce13f7SAndroid Build Coastguard Worker 975*03ce13f7SAndroid Build Coastguard Worker /// The following table summarizes the logic for lowering the icmp instruction 976*03ce13f7SAndroid Build Coastguard Worker /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and 977*03ce13f7SAndroid Build Coastguard Worker /// conditional branches are needed. For the other conditions, three separate 978*03ce13f7SAndroid Build Coastguard Worker /// conditional branches are needed. 979*03ce13f7SAndroid Build Coastguard Worker /// {@ 980*03ce13f7SAndroid Build Coastguard Worker static const struct TableIcmp64Type { 981*03ce13f7SAndroid Build Coastguard Worker CondX86::BrCond C1, C2, C3; 982*03ce13f7SAndroid Build Coastguard Worker } TableIcmp64[]; 983*03ce13f7SAndroid Build Coastguard Worker static const size_t TableIcmp64Size; 984*03ce13f7SAndroid Build Coastguard Worker /// @} 985*03ce13f7SAndroid Build Coastguard Worker getIcmp32Mapping(InstIcmp::ICond Cond)986*03ce13f7SAndroid Build Coastguard Worker static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { 987*03ce13f7SAndroid Build Coastguard Worker assert(Cond < TableIcmp32Size); 988*03ce13f7SAndroid Build Coastguard Worker return TableIcmp32[Cond].Mapping; 989*03ce13f7SAndroid Build Coastguard Worker } 990*03ce13f7SAndroid Build Coastguard Worker 991*03ce13f7SAndroid Build Coastguard Worker public: create(Cfg * Func)992*03ce13f7SAndroid Build Coastguard Worker static std::unique_ptr<::Ice::TargetLowering> create(Cfg *Func) { 993*03ce13f7SAndroid Build Coastguard Worker return makeUnique<TargetX8664>(Func); 994*03ce13f7SAndroid Build Coastguard Worker } 995*03ce13f7SAndroid Build Coastguard Worker createAssembler()996*03ce13f7SAndroid Build Coastguard Worker std::unique_ptr<::Ice::Assembler> createAssembler() const override { 997*03ce13f7SAndroid Build Coastguard Worker return makeUnique<X8664::AssemblerX8664>(); 998*03ce13f7SAndroid Build Coastguard Worker } 999*03ce13f7SAndroid Build Coastguard Worker 1000*03ce13f7SAndroid Build Coastguard Worker private: 1001*03ce13f7SAndroid Build Coastguard Worker ENABLE_MAKE_UNIQUE; 1002*03ce13f7SAndroid Build Coastguard Worker 1003*03ce13f7SAndroid Build Coastguard Worker explicit TargetX8664(Cfg *Func); 1004*03ce13f7SAndroid Build Coastguard Worker }; 1005*03ce13f7SAndroid Build Coastguard Worker 1006*03ce13f7SAndroid Build Coastguard Worker class TargetDataX8664 final : public TargetDataLowering { 1007*03ce13f7SAndroid Build Coastguard Worker TargetDataX8664() = delete; 1008*03ce13f7SAndroid Build Coastguard Worker TargetDataX8664(const TargetDataX8664 &) = delete; 1009*03ce13f7SAndroid Build Coastguard Worker TargetDataX8664 &operator=(const TargetDataX8664 &) = delete; 1010*03ce13f7SAndroid Build Coastguard Worker 1011*03ce13f7SAndroid Build Coastguard Worker public: 1012*03ce13f7SAndroid Build Coastguard Worker ~TargetDataX8664() override = default; 1013*03ce13f7SAndroid Build Coastguard Worker create(GlobalContext * Ctx)1014*03ce13f7SAndroid Build Coastguard Worker static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { 1015*03ce13f7SAndroid Build Coastguard Worker return makeUnique<TargetDataX8664>(Ctx); 1016*03ce13f7SAndroid Build Coastguard Worker } 1017*03ce13f7SAndroid Build Coastguard Worker 1018*03ce13f7SAndroid Build Coastguard Worker void lowerGlobals(const VariableDeclarationList &Vars, 1019*03ce13f7SAndroid Build Coastguard Worker const std::string &SectionSuffix) override; 1020*03ce13f7SAndroid Build Coastguard Worker void lowerConstants() override; 1021*03ce13f7SAndroid Build Coastguard Worker void lowerJumpTables() override; 1022*03ce13f7SAndroid Build Coastguard Worker 1023*03ce13f7SAndroid Build Coastguard Worker private: 1024*03ce13f7SAndroid Build Coastguard Worker ENABLE_MAKE_UNIQUE; 1025*03ce13f7SAndroid Build Coastguard Worker TargetDataX8664(GlobalContext * Ctx)1026*03ce13f7SAndroid Build Coastguard Worker explicit TargetDataX8664(GlobalContext *Ctx) : TargetDataLowering(Ctx) {} 1027*03ce13f7SAndroid Build Coastguard Worker template <typename T> static void emitConstantPool(GlobalContext *Ctx); 1028*03ce13f7SAndroid Build Coastguard Worker }; 1029*03ce13f7SAndroid Build Coastguard Worker 1030*03ce13f7SAndroid Build Coastguard Worker class TargetHeaderX86 : public TargetHeaderLowering { 1031*03ce13f7SAndroid Build Coastguard Worker TargetHeaderX86() = delete; 1032*03ce13f7SAndroid Build Coastguard Worker TargetHeaderX86(const TargetHeaderX86 &) = delete; 1033*03ce13f7SAndroid Build Coastguard Worker TargetHeaderX86 &operator=(const TargetHeaderX86 &) = delete; 1034*03ce13f7SAndroid Build Coastguard Worker 1035*03ce13f7SAndroid Build Coastguard Worker public: 1036*03ce13f7SAndroid Build Coastguard Worker ~TargetHeaderX86() = default; 1037*03ce13f7SAndroid Build Coastguard Worker create(GlobalContext * Ctx)1038*03ce13f7SAndroid Build Coastguard Worker static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) { 1039*03ce13f7SAndroid Build Coastguard Worker return makeUnique<TargetHeaderX86>(Ctx); 1040*03ce13f7SAndroid Build Coastguard Worker } 1041*03ce13f7SAndroid Build Coastguard Worker 1042*03ce13f7SAndroid Build Coastguard Worker private: 1043*03ce13f7SAndroid Build Coastguard Worker ENABLE_MAKE_UNIQUE; 1044*03ce13f7SAndroid Build Coastguard Worker TargetHeaderX86(GlobalContext * Ctx)1045*03ce13f7SAndroid Build Coastguard Worker explicit TargetHeaderX86(GlobalContext *Ctx) : TargetHeaderLowering(Ctx) {} 1046*03ce13f7SAndroid Build Coastguard Worker }; 1047*03ce13f7SAndroid Build Coastguard Worker 1048*03ce13f7SAndroid Build Coastguard Worker } // end of namespace X8664 1049*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice 1050*03ce13f7SAndroid Build Coastguard Worker 1051*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICETARGETLOWERINGX8664_H 1052