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