John Porto | 7e93c62 | 2015-06-23 10:58:57 -0700 | [diff] [blame] | 1 | //===- subzero/src/IceTargetLoweringX86Base.h - x86 lowering ----*- C++ -*-===// |
| 2 | // |
| 3 | // The Subzero Code Generator |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file declares the TargetLoweringX86 template class, which |
| 11 | // implements the TargetLowering base interface for the x86 |
| 12 | // architecture. |
| 13 | // |
| 14 | //===----------------------------------------------------------------------===// |
| 15 | |
| 16 | #ifndef SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H |
| 17 | #define SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H |
| 18 | |
| 19 | #include <unordered_map> |
| 20 | |
| 21 | #include "IceDefs.h" |
| 22 | #include "IceInst.h" |
| 23 | #include "IceTargetLowering.h" |
| 24 | |
| 25 | namespace Ice { |
| 26 | namespace X86Internal { |
| 27 | |
| 28 | template <class MachineTraits> class BoolFolding; |
| 29 | |
| 30 | template <class Machine> struct MachineTraits {}; |
| 31 | |
| 32 | template <class Machine> class TargetX86Base : public Machine { |
| 33 | TargetX86Base() = delete; |
| 34 | TargetX86Base(const TargetX86Base &) = delete; |
| 35 | TargetX86Base &operator=(const TargetX86Base &) = delete; |
| 36 | |
| 37 | protected: |
| 38 | using TargetLowering::H_bitcast_16xi1_i16; |
| 39 | using TargetLowering::H_bitcast_8xi1_i8; |
| 40 | using TargetLowering::H_bitcast_i16_16xi1; |
| 41 | using TargetLowering::H_bitcast_i8_8xi1; |
| 42 | using TargetLowering::H_call_ctpop_i32; |
| 43 | using TargetLowering::H_call_ctpop_i64; |
| 44 | using TargetLowering::H_call_longjmp; |
| 45 | using TargetLowering::H_call_memcpy; |
| 46 | using TargetLowering::H_call_memmove; |
| 47 | using TargetLowering::H_call_memset; |
| 48 | using TargetLowering::H_call_read_tp; |
| 49 | using TargetLowering::H_call_setjmp; |
| 50 | using TargetLowering::H_fptosi_f32_i64; |
| 51 | using TargetLowering::H_fptosi_f64_i64; |
| 52 | using TargetLowering::H_fptoui_4xi32_f32; |
| 53 | using TargetLowering::H_fptoui_f32_i32; |
| 54 | using TargetLowering::H_fptoui_f32_i64; |
| 55 | using TargetLowering::H_fptoui_f64_i32; |
| 56 | using TargetLowering::H_fptoui_f64_i64; |
| 57 | using TargetLowering::H_frem_f32; |
| 58 | using TargetLowering::H_frem_f64; |
| 59 | using TargetLowering::H_sdiv_i64; |
| 60 | using TargetLowering::H_sitofp_i64_f32; |
| 61 | using TargetLowering::H_sitofp_i64_f64; |
| 62 | using TargetLowering::H_srem_i64; |
| 63 | using TargetLowering::H_udiv_i64; |
| 64 | using TargetLowering::H_uitofp_4xi32_4xf32; |
| 65 | using TargetLowering::H_uitofp_i32_f32; |
| 66 | using TargetLowering::H_uitofp_i32_f64; |
| 67 | using TargetLowering::H_uitofp_i64_f32; |
| 68 | using TargetLowering::H_uitofp_i64_f64; |
| 69 | using TargetLowering::H_urem_i64; |
| 70 | |
| 71 | using TargetLowering::alignStackSpillAreas; |
| 72 | using TargetLowering::assignVarStackSlots; |
| 73 | using TargetLowering::inferTwoAddress; |
| 74 | using TargetLowering::makeHelperCall; |
| 75 | using TargetLowering::getVarStackSlotParams; |
| 76 | |
| 77 | public: |
| 78 | using Traits = MachineTraits<Machine>; |
| 79 | using BoolFolding = ::Ice::X86Internal::BoolFolding<Traits>; |
| 80 | |
| 81 | using TargetLowering::RegSet_All; |
| 82 | using TargetLowering::RegSet_CalleeSave; |
| 83 | using TargetLowering::RegSet_CallerSave; |
| 84 | using TargetLowering::RegSet_FramePointer; |
| 85 | using TargetLowering::RegSet_None; |
| 86 | using TargetLowering::RegSet_StackPointer; |
| 87 | using TargetLowering::Context; |
| 88 | using TargetLowering::Ctx; |
| 89 | using TargetLowering::Func; |
| 90 | using TargetLowering::RegSetMask; |
| 91 | |
| 92 | using TargetLowering::_bundle_lock; |
| 93 | using TargetLowering::_bundle_unlock; |
| 94 | using TargetLowering::getContext; |
| 95 | using TargetLowering::getStackAdjustment; |
| 96 | using TargetLowering::regAlloc; |
| 97 | using TargetLowering::resetStackAdjustment; |
| 98 | |
| 99 | static TargetX86Base *create(Cfg *Func) { return new TargetX86Base(Func); } |
| 100 | |
| 101 | void translateOm1() override; |
| 102 | void translateO2() override; |
| 103 | void doLoadOpt(); |
| 104 | bool doBranchOpt(Inst *I, const CfgNode *NextNode) override; |
| 105 | |
| 106 | SizeT getNumRegisters() const override { return RegX8632::Reg_NUM; } |
| 107 | Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override; |
| 108 | IceString getRegName(SizeT RegNum, Type Ty) const override; |
| 109 | llvm::SmallBitVector getRegisterSet(RegSetMask Include, |
| 110 | RegSetMask Exclude) const override; |
| 111 | const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override { |
| 112 | return TypeToRegisterSet[Ty]; |
| 113 | } |
| 114 | bool hasFramePointer() const override { return IsEbpBasedFrame; } |
| 115 | SizeT getFrameOrStackReg() const override { |
| 116 | return IsEbpBasedFrame ? RegX8632::Reg_ebp : RegX8632::Reg_esp; |
| 117 | } |
| 118 | size_t typeWidthInBytesOnStack(Type Ty) const override { |
| 119 | // Round up to the next multiple of 4 bytes. In particular, i1, |
| 120 | // i8, and i16 are rounded up to 4 bytes. |
| 121 | return (typeWidthInBytes(Ty) + 3) & ~3; |
| 122 | } |
| 123 | |
| 124 | void emitVariable(const Variable *Var) const override; |
| 125 | |
| 126 | const char *getConstantPrefix() const final { return "$"; } |
| 127 | void emit(const ConstantUndef *C) const final; |
| 128 | void emit(const ConstantInteger32 *C) const final; |
| 129 | void emit(const ConstantInteger64 *C) const final; |
| 130 | void emit(const ConstantFloat *C) const final; |
| 131 | void emit(const ConstantDouble *C) const final; |
| 132 | |
| 133 | void lowerArguments() override; |
| 134 | void initNodeForLowering(CfgNode *Node) override; |
| 135 | void addProlog(CfgNode *Node) override; |
| 136 | void addEpilog(CfgNode *Node) override; |
| 137 | // Ensure that a 64-bit Variable has been split into 2 32-bit |
| 138 | // Variables, creating them if necessary. This is needed for all |
| 139 | // I64 operations, and it is needed for pushing F64 arguments for |
| 140 | // function calls using the 32-bit push instruction (though the |
| 141 | // latter could be done by directly writing to the stack). |
| 142 | void split64(Variable *Var); |
| 143 | Operand *loOperand(Operand *Operand); |
| 144 | Operand *hiOperand(Operand *Operand); |
| 145 | void finishArgumentLowering(Variable *Arg, Variable *FramePtr, |
| 146 | size_t BasicFrameOffset, size_t &InArgsSizeBytes); |
| 147 | X8632::Address stackVarToAsmOperand(const Variable *Var) const final; |
| 148 | |
| 149 | typename Traits::InstructionSet getInstructionSet() const final { |
| 150 | return InstructionSet; |
| 151 | } |
| 152 | |
| 153 | protected: |
| 154 | explicit TargetX86Base(Cfg *Func); |
| 155 | |
| 156 | void postLower() override; |
| 157 | |
| 158 | void lowerAlloca(const InstAlloca *Inst) override; |
| 159 | void lowerArithmetic(const InstArithmetic *Inst) override; |
| 160 | void lowerAssign(const InstAssign *Inst) override; |
| 161 | void lowerBr(const InstBr *Inst) override; |
| 162 | void lowerCall(const InstCall *Inst) override; |
| 163 | void lowerCast(const InstCast *Inst) override; |
| 164 | void lowerExtractElement(const InstExtractElement *Inst) override; |
| 165 | void lowerFcmp(const InstFcmp *Inst) override; |
| 166 | void lowerIcmp(const InstIcmp *Inst) override; |
| 167 | void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override; |
| 168 | void lowerInsertElement(const InstInsertElement *Inst) override; |
| 169 | void lowerLoad(const InstLoad *Inst) override; |
| 170 | void lowerPhi(const InstPhi *Inst) override; |
| 171 | void lowerRet(const InstRet *Inst) override; |
| 172 | void lowerSelect(const InstSelect *Inst) override; |
| 173 | void lowerStore(const InstStore *Inst) override; |
| 174 | void lowerSwitch(const InstSwitch *Inst) override; |
| 175 | void lowerUnreachable(const InstUnreachable *Inst) override; |
| 176 | void lowerOther(const Inst *Instr) override; |
| 177 | void lowerRMW(const InstX8632FakeRMW *RMW); |
| 178 | void prelowerPhis() override; |
| 179 | void lowerPhiAssignments(CfgNode *Node, |
| 180 | const AssignList &Assignments) override; |
| 181 | void doAddressOptLoad() override; |
| 182 | void doAddressOptStore() override; |
| 183 | void randomlyInsertNop(float Probability) override; |
| 184 | |
| 185 | // Naive lowering of cmpxchg. |
| 186 | void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected, |
| 187 | Operand *Desired); |
| 188 | // Attempt a more optimized lowering of cmpxchg. Returns true if optimized. |
| 189 | bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr, |
| 190 | Operand *Expected, Operand *Desired); |
| 191 | void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, |
| 192 | Operand *Val); |
| 193 | void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal, |
| 194 | Operand *SecondVal); |
| 195 | |
| 196 | typedef void (TargetX86Base::*LowerBinOp)(Variable *, Operand *); |
| 197 | void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi, |
| 198 | Variable *Dest, Operand *Ptr, Operand *Val); |
| 199 | |
| 200 | void eliminateNextVectorSextInstruction(Variable *SignExtendedResult); |
| 201 | |
| 202 | void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest, |
| 203 | Operand *Src0, Operand *Src1); |
| 204 | |
| 205 | // Operand legalization helpers. To deal with address mode |
| 206 | // constraints, the helpers will create a new Operand and emit |
| 207 | // instructions that guarantee that the Operand kind is one of those |
| 208 | // indicated by the LegalMask (a bitmask of allowed kinds). If the |
| 209 | // input Operand is known to already meet the constraints, it may be |
| 210 | // simply returned as the result, without creating any new |
| 211 | // instructions or operands. |
| 212 | enum OperandLegalization { |
| 213 | Legal_None = 0, |
| 214 | Legal_Reg = 1 << 0, // physical register, not stack location |
| 215 | Legal_Imm = 1 << 1, |
| 216 | Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12] |
| 217 | Legal_All = ~Legal_None |
| 218 | }; |
| 219 | typedef uint32_t LegalMask; |
| 220 | Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, |
| 221 | int32_t RegNum = Variable::NoRegister); |
| 222 | Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister); |
| 223 | // Legalize the first source operand for use in the cmp instruction. |
| 224 | Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1); |
| 225 | // Turn a pointer operand into a memory operand that can be |
| 226 | // used by a real load/store operation. Legalizes the operand as well. |
| 227 | // This is a nop if the operand is already a legal memory operand. |
| 228 | OperandX8632Mem *formMemoryOperand(Operand *Ptr, Type Ty, |
| 229 | bool DoLegalize = true); |
| 230 | |
| 231 | Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); |
| 232 | static Type stackSlotType(); |
| 233 | |
| 234 | Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); |
| 235 | |
| 236 | // Returns a vector in a register with the given constant entries. |
| 237 | Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); |
| 238 | Variable *makeVectorOfOnes(Type Ty, int32_t RegNum = Variable::NoRegister); |
| 239 | Variable *makeVectorOfMinusOnes(Type Ty, |
| 240 | int32_t RegNum = Variable::NoRegister); |
| 241 | Variable *makeVectorOfHighOrderBits(Type Ty, |
| 242 | int32_t RegNum = Variable::NoRegister); |
| 243 | Variable *makeVectorOfFabsMask(Type Ty, |
| 244 | int32_t RegNum = Variable::NoRegister); |
| 245 | |
| 246 | // Return a memory operand corresponding to a stack allocated Variable. |
| 247 | OperandX8632Mem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot, |
| 248 | uint32_t Offset = 0); |
| 249 | |
| 250 | void makeRandomRegisterPermutation( |
| 251 | llvm::SmallVectorImpl<int32_t> &Permutation, |
| 252 | const llvm::SmallBitVector &ExcludeRegisters) const override; |
| 253 | |
| 254 | // The following are helpers that insert lowered x86 instructions |
| 255 | // with minimal syntactic overhead, so that the lowering code can |
| 256 | // look as close to assembly as practical. |
| 257 | void _adc(Variable *Dest, Operand *Src0) { |
| 258 | Context.insert(InstX8632Adc::create(Func, Dest, Src0)); |
| 259 | } |
| 260 | void _adc_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { |
| 261 | Context.insert(InstX8632AdcRMW::create(Func, DestSrc0, Src1)); |
| 262 | } |
| 263 | void _add(Variable *Dest, Operand *Src0) { |
| 264 | Context.insert(InstX8632Add::create(Func, Dest, Src0)); |
| 265 | } |
| 266 | void _add_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { |
| 267 | Context.insert(InstX8632AddRMW::create(Func, DestSrc0, Src1)); |
| 268 | } |
| 269 | void _adjust_stack(int32_t Amount) { |
| 270 | Context.insert(InstX8632AdjustStack::create( |
| 271 | Func, Amount, getPhysicalRegister(RegX8632::Reg_esp))); |
| 272 | } |
| 273 | void _addps(Variable *Dest, Operand *Src0) { |
| 274 | Context.insert(InstX8632Addps::create(Func, Dest, Src0)); |
| 275 | } |
| 276 | void _addss(Variable *Dest, Operand *Src0) { |
| 277 | Context.insert(InstX8632Addss::create(Func, Dest, Src0)); |
| 278 | } |
| 279 | void _and(Variable *Dest, Operand *Src0) { |
| 280 | Context.insert(InstX8632And::create(Func, Dest, Src0)); |
| 281 | } |
| 282 | void _and_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { |
| 283 | Context.insert(InstX8632AndRMW::create(Func, DestSrc0, Src1)); |
| 284 | } |
| 285 | void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 286 | Context.insert(InstX8632Blendvps::create(Func, Dest, Src0, Src1)); |
| 287 | } |
| 288 | void _br(CondX86::BrCond Condition, CfgNode *TargetTrue, |
| 289 | CfgNode *TargetFalse) { |
| 290 | Context.insert( |
| 291 | InstX8632Br::create(Func, TargetTrue, TargetFalse, Condition)); |
| 292 | } |
| 293 | void _br(CfgNode *Target) { |
| 294 | Context.insert(InstX8632Br::create(Func, Target)); |
| 295 | } |
| 296 | void _br(CondX86::BrCond Condition, CfgNode *Target) { |
| 297 | Context.insert(InstX8632Br::create(Func, Target, Condition)); |
| 298 | } |
| 299 | void _br(CondX86::BrCond Condition, InstX8632Label *Label) { |
| 300 | Context.insert(InstX8632Br::create(Func, Label, Condition)); |
| 301 | } |
| 302 | void _bsf(Variable *Dest, Operand *Src0) { |
| 303 | Context.insert(InstX8632Bsf::create(Func, Dest, Src0)); |
| 304 | } |
| 305 | void _bsr(Variable *Dest, Operand *Src0) { |
| 306 | Context.insert(InstX8632Bsr::create(Func, Dest, Src0)); |
| 307 | } |
| 308 | void _bswap(Variable *SrcDest) { |
| 309 | Context.insert(InstX8632Bswap::create(Func, SrcDest)); |
| 310 | } |
| 311 | void _cbwdq(Variable *Dest, Operand *Src0) { |
| 312 | Context.insert(InstX8632Cbwdq::create(Func, Dest, Src0)); |
| 313 | } |
| 314 | void _cmov(Variable *Dest, Operand *Src0, CondX86::BrCond Condition) { |
| 315 | Context.insert(InstX8632Cmov::create(Func, Dest, Src0, Condition)); |
| 316 | } |
| 317 | void _cmp(Operand *Src0, Operand *Src1) { |
| 318 | Context.insert(InstX8632Icmp::create(Func, Src0, Src1)); |
| 319 | } |
| 320 | void _cmpps(Variable *Dest, Operand *Src0, CondX86::CmppsCond Condition) { |
| 321 | Context.insert(InstX8632Cmpps::create(Func, Dest, Src0, Condition)); |
| 322 | } |
| 323 | void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired, |
| 324 | bool Locked) { |
| 325 | Context.insert( |
| 326 | InstX8632Cmpxchg::create(Func, DestOrAddr, Eax, Desired, Locked)); |
| 327 | // Mark eax as possibly modified by cmpxchg. |
| 328 | Context.insert( |
| 329 | InstFakeDef::create(Func, Eax, llvm::dyn_cast<Variable>(DestOrAddr))); |
| 330 | _set_dest_nonkillable(); |
| 331 | Context.insert(InstFakeUse::create(Func, Eax)); |
| 332 | } |
| 333 | void _cmpxchg8b(OperandX8632Mem *Addr, Variable *Edx, Variable *Eax, |
| 334 | Variable *Ecx, Variable *Ebx, bool Locked) { |
| 335 | Context.insert( |
| 336 | InstX8632Cmpxchg8b::create(Func, Addr, Edx, Eax, Ecx, Ebx, Locked)); |
| 337 | // Mark edx, and eax as possibly modified by cmpxchg8b. |
| 338 | Context.insert(InstFakeDef::create(Func, Edx)); |
| 339 | _set_dest_nonkillable(); |
| 340 | Context.insert(InstFakeUse::create(Func, Edx)); |
| 341 | Context.insert(InstFakeDef::create(Func, Eax)); |
| 342 | _set_dest_nonkillable(); |
| 343 | Context.insert(InstFakeUse::create(Func, Eax)); |
| 344 | } |
| 345 | void _cvt(Variable *Dest, Operand *Src0, InstX8632Cvt::CvtVariant Variant) { |
| 346 | Context.insert(InstX8632Cvt::create(Func, Dest, Src0, Variant)); |
| 347 | } |
| 348 | void _div(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 349 | Context.insert(InstX8632Div::create(Func, Dest, Src0, Src1)); |
| 350 | } |
| 351 | void _divps(Variable *Dest, Operand *Src0) { |
| 352 | Context.insert(InstX8632Divps::create(Func, Dest, Src0)); |
| 353 | } |
| 354 | void _divss(Variable *Dest, Operand *Src0) { |
| 355 | Context.insert(InstX8632Divss::create(Func, Dest, Src0)); |
| 356 | } |
| 357 | void _fld(Operand *Src0) { Context.insert(InstX8632Fld::create(Func, Src0)); } |
| 358 | void _fstp(Variable *Dest) { |
| 359 | Context.insert(InstX8632Fstp::create(Func, Dest)); |
| 360 | } |
| 361 | void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 362 | Context.insert(InstX8632Idiv::create(Func, Dest, Src0, Src1)); |
| 363 | } |
| 364 | void _imul(Variable *Dest, Operand *Src0) { |
| 365 | Context.insert(InstX8632Imul::create(Func, Dest, Src0)); |
| 366 | } |
| 367 | void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 368 | Context.insert(InstX8632Insertps::create(Func, Dest, Src0, Src1)); |
| 369 | } |
| 370 | void _jmp(Operand *Target) { |
| 371 | Context.insert(InstX8632Jmp::create(Func, Target)); |
| 372 | } |
| 373 | void _lea(Variable *Dest, Operand *Src0) { |
| 374 | Context.insert(InstX8632Lea::create(Func, Dest, Src0)); |
| 375 | } |
| 376 | void _mfence() { Context.insert(InstX8632Mfence::create(Func)); } |
| 377 | // If Dest=nullptr is passed in, then a new variable is created, |
| 378 | // marked as infinite register allocation weight, and returned |
| 379 | // through the in/out Dest argument. |
| 380 | void _mov(Variable *&Dest, Operand *Src0, |
| 381 | int32_t RegNum = Variable::NoRegister) { |
| 382 | if (Dest == nullptr) |
| 383 | Dest = makeReg(Src0->getType(), RegNum); |
| 384 | Context.insert(InstX8632Mov::create(Func, Dest, Src0)); |
| 385 | } |
| 386 | void _mov_nonkillable(Variable *Dest, Operand *Src0) { |
| 387 | Inst *NewInst = InstX8632Mov::create(Func, Dest, Src0); |
| 388 | NewInst->setDestNonKillable(); |
| 389 | Context.insert(NewInst); |
| 390 | } |
| 391 | void _movd(Variable *Dest, Operand *Src0) { |
| 392 | Context.insert(InstX8632Movd::create(Func, Dest, Src0)); |
| 393 | } |
| 394 | void _movp(Variable *Dest, Operand *Src0) { |
| 395 | Context.insert(InstX8632Movp::create(Func, Dest, Src0)); |
| 396 | } |
| 397 | void _movq(Variable *Dest, Operand *Src0) { |
| 398 | Context.insert(InstX8632Movq::create(Func, Dest, Src0)); |
| 399 | } |
| 400 | void _movss(Variable *Dest, Variable *Src0) { |
| 401 | Context.insert(InstX8632MovssRegs::create(Func, Dest, Src0)); |
| 402 | } |
| 403 | void _movsx(Variable *Dest, Operand *Src0) { |
| 404 | Context.insert(InstX8632Movsx::create(Func, Dest, Src0)); |
| 405 | } |
| 406 | void _movzx(Variable *Dest, Operand *Src0) { |
| 407 | Context.insert(InstX8632Movzx::create(Func, Dest, Src0)); |
| 408 | } |
| 409 | void _mul(Variable *Dest, Variable *Src0, Operand *Src1) { |
| 410 | Context.insert(InstX8632Mul::create(Func, Dest, Src0, Src1)); |
| 411 | } |
| 412 | void _mulps(Variable *Dest, Operand *Src0) { |
| 413 | Context.insert(InstX8632Mulps::create(Func, Dest, Src0)); |
| 414 | } |
| 415 | void _mulss(Variable *Dest, Operand *Src0) { |
| 416 | Context.insert(InstX8632Mulss::create(Func, Dest, Src0)); |
| 417 | } |
| 418 | void _neg(Variable *SrcDest) { |
| 419 | Context.insert(InstX8632Neg::create(Func, SrcDest)); |
| 420 | } |
| 421 | void _nop(SizeT Variant) { |
| 422 | Context.insert(InstX8632Nop::create(Func, Variant)); |
| 423 | } |
| 424 | void _or(Variable *Dest, Operand *Src0) { |
| 425 | Context.insert(InstX8632Or::create(Func, Dest, Src0)); |
| 426 | } |
| 427 | void _or_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { |
| 428 | Context.insert(InstX8632OrRMW::create(Func, DestSrc0, Src1)); |
| 429 | } |
| 430 | void _padd(Variable *Dest, Operand *Src0) { |
| 431 | Context.insert(InstX8632Padd::create(Func, Dest, Src0)); |
| 432 | } |
| 433 | void _pand(Variable *Dest, Operand *Src0) { |
| 434 | Context.insert(InstX8632Pand::create(Func, Dest, Src0)); |
| 435 | } |
| 436 | void _pandn(Variable *Dest, Operand *Src0) { |
| 437 | Context.insert(InstX8632Pandn::create(Func, Dest, Src0)); |
| 438 | } |
| 439 | void _pblendvb(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 440 | Context.insert(InstX8632Pblendvb::create(Func, Dest, Src0, Src1)); |
| 441 | } |
| 442 | void _pcmpeq(Variable *Dest, Operand *Src0) { |
| 443 | Context.insert(InstX8632Pcmpeq::create(Func, Dest, Src0)); |
| 444 | } |
| 445 | void _pcmpgt(Variable *Dest, Operand *Src0) { |
| 446 | Context.insert(InstX8632Pcmpgt::create(Func, Dest, Src0)); |
| 447 | } |
| 448 | void _pextr(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 449 | Context.insert(InstX8632Pextr::create(Func, Dest, Src0, Src1)); |
| 450 | } |
| 451 | void _pinsr(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 452 | Context.insert(InstX8632Pinsr::create(Func, Dest, Src0, Src1)); |
| 453 | } |
| 454 | void _pmull(Variable *Dest, Operand *Src0) { |
| 455 | Context.insert(InstX8632Pmull::create(Func, Dest, Src0)); |
| 456 | } |
| 457 | void _pmuludq(Variable *Dest, Operand *Src0) { |
| 458 | Context.insert(InstX8632Pmuludq::create(Func, Dest, Src0)); |
| 459 | } |
| 460 | void _pop(Variable *Dest) { |
| 461 | Context.insert(InstX8632Pop::create(Func, Dest)); |
| 462 | } |
| 463 | void _por(Variable *Dest, Operand *Src0) { |
| 464 | Context.insert(InstX8632Por::create(Func, Dest, Src0)); |
| 465 | } |
| 466 | void _pshufd(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 467 | Context.insert(InstX8632Pshufd::create(Func, Dest, Src0, Src1)); |
| 468 | } |
| 469 | void _psll(Variable *Dest, Operand *Src0) { |
| 470 | Context.insert(InstX8632Psll::create(Func, Dest, Src0)); |
| 471 | } |
| 472 | void _psra(Variable *Dest, Operand *Src0) { |
| 473 | Context.insert(InstX8632Psra::create(Func, Dest, Src0)); |
| 474 | } |
| 475 | void _psrl(Variable *Dest, Operand *Src0) { |
| 476 | Context.insert(InstX8632Psrl::create(Func, Dest, Src0)); |
| 477 | } |
| 478 | void _psub(Variable *Dest, Operand *Src0) { |
| 479 | Context.insert(InstX8632Psub::create(Func, Dest, Src0)); |
| 480 | } |
| 481 | void _push(Variable *Src0) { |
| 482 | Context.insert(InstX8632Push::create(Func, Src0)); |
| 483 | } |
| 484 | void _pxor(Variable *Dest, Operand *Src0) { |
| 485 | Context.insert(InstX8632Pxor::create(Func, Dest, Src0)); |
| 486 | } |
| 487 | void _ret(Variable *Src0 = nullptr) { |
| 488 | Context.insert(InstX8632Ret::create(Func, Src0)); |
| 489 | } |
| 490 | void _rol(Variable *Dest, Operand *Src0) { |
| 491 | Context.insert(InstX8632Rol::create(Func, Dest, Src0)); |
| 492 | } |
| 493 | void _sar(Variable *Dest, Operand *Src0) { |
| 494 | Context.insert(InstX8632Sar::create(Func, Dest, Src0)); |
| 495 | } |
| 496 | void _sbb(Variable *Dest, Operand *Src0) { |
| 497 | Context.insert(InstX8632Sbb::create(Func, Dest, Src0)); |
| 498 | } |
| 499 | void _sbb_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { |
| 500 | Context.insert(InstX8632SbbRMW::create(Func, DestSrc0, Src1)); |
| 501 | } |
| 502 | void _setcc(Variable *Dest, CondX86::BrCond Condition) { |
| 503 | Context.insert(InstX8632Setcc::create(Func, Dest, Condition)); |
| 504 | } |
| 505 | void _shl(Variable *Dest, Operand *Src0) { |
| 506 | Context.insert(InstX8632Shl::create(Func, Dest, Src0)); |
| 507 | } |
| 508 | void _shld(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 509 | Context.insert(InstX8632Shld::create(Func, Dest, Src0, Src1)); |
| 510 | } |
| 511 | void _shr(Variable *Dest, Operand *Src0) { |
| 512 | Context.insert(InstX8632Shr::create(Func, Dest, Src0)); |
| 513 | } |
| 514 | void _shrd(Variable *Dest, Variable *Src0, Variable *Src1) { |
| 515 | Context.insert(InstX8632Shrd::create(Func, Dest, Src0, Src1)); |
| 516 | } |
| 517 | void _shufps(Variable *Dest, Operand *Src0, Operand *Src1) { |
| 518 | Context.insert(InstX8632Shufps::create(Func, Dest, Src0, Src1)); |
| 519 | } |
| 520 | void _sqrtss(Variable *Dest, Operand *Src0) { |
| 521 | Context.insert(InstX8632Sqrtss::create(Func, Dest, Src0)); |
| 522 | } |
| 523 | void _store(Operand *Value, OperandX8632 *Mem) { |
| 524 | Context.insert(InstX8632Store::create(Func, Value, Mem)); |
| 525 | } |
| 526 | void _storep(Variable *Value, OperandX8632Mem *Mem) { |
| 527 | Context.insert(InstX8632StoreP::create(Func, Value, Mem)); |
| 528 | } |
| 529 | void _storeq(Variable *Value, OperandX8632Mem *Mem) { |
| 530 | Context.insert(InstX8632StoreQ::create(Func, Value, Mem)); |
| 531 | } |
| 532 | void _sub(Variable *Dest, Operand *Src0) { |
| 533 | Context.insert(InstX8632Sub::create(Func, Dest, Src0)); |
| 534 | } |
| 535 | void _sub_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { |
| 536 | Context.insert(InstX8632SubRMW::create(Func, DestSrc0, Src1)); |
| 537 | } |
| 538 | void _subps(Variable *Dest, Operand *Src0) { |
| 539 | Context.insert(InstX8632Subps::create(Func, Dest, Src0)); |
| 540 | } |
| 541 | void _subss(Variable *Dest, Operand *Src0) { |
| 542 | Context.insert(InstX8632Subss::create(Func, Dest, Src0)); |
| 543 | } |
| 544 | void _test(Operand *Src0, Operand *Src1) { |
| 545 | Context.insert(InstX8632Test::create(Func, Src0, Src1)); |
| 546 | } |
| 547 | void _ucomiss(Operand *Src0, Operand *Src1) { |
| 548 | Context.insert(InstX8632Ucomiss::create(Func, Src0, Src1)); |
| 549 | } |
| 550 | void _ud2() { Context.insert(InstX8632UD2::create(Func)); } |
| 551 | void _xadd(Operand *Dest, Variable *Src, bool Locked) { |
| 552 | Context.insert(InstX8632Xadd::create(Func, Dest, Src, Locked)); |
| 553 | // The xadd exchanges Dest and Src (modifying Src). |
| 554 | // Model that update with a FakeDef followed by a FakeUse. |
| 555 | Context.insert( |
| 556 | InstFakeDef::create(Func, Src, llvm::dyn_cast<Variable>(Dest))); |
| 557 | _set_dest_nonkillable(); |
| 558 | Context.insert(InstFakeUse::create(Func, Src)); |
| 559 | } |
| 560 | void _xchg(Operand *Dest, Variable *Src) { |
| 561 | Context.insert(InstX8632Xchg::create(Func, Dest, Src)); |
| 562 | // The xchg modifies Dest and Src -- model that update with a |
| 563 | // FakeDef/FakeUse. |
| 564 | Context.insert( |
| 565 | InstFakeDef::create(Func, Src, llvm::dyn_cast<Variable>(Dest))); |
| 566 | _set_dest_nonkillable(); |
| 567 | Context.insert(InstFakeUse::create(Func, Src)); |
| 568 | } |
| 569 | void _xor(Variable *Dest, Operand *Src0) { |
| 570 | Context.insert(InstX8632Xor::create(Func, Dest, Src0)); |
| 571 | } |
| 572 | void _xor_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { |
| 573 | Context.insert(InstX8632XorRMW::create(Func, DestSrc0, Src1)); |
| 574 | } |
| 575 | void _set_dest_nonkillable() { |
| 576 | Context.getLastInserted()->setDestNonKillable(); |
| 577 | } |
| 578 | |
| 579 | bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1); |
| 580 | void findRMW(); |
| 581 | |
| 582 | typename Traits::InstructionSet InstructionSet = |
| 583 | Traits::InstructionSet::Begin; |
| 584 | bool IsEbpBasedFrame = false; |
| 585 | bool NeedsStackAlignment = false; |
| 586 | size_t SpillAreaSizeBytes = 0; |
| 587 | llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; |
| 588 | llvm::SmallBitVector ScratchRegs; |
| 589 | llvm::SmallBitVector RegsUsed; |
| 590 | VarList PhysicalRegisters[IceType_NUM]; |
| 591 | static IceString RegNames[]; |
| 592 | |
| 593 | // Randomize a given immediate operand |
| 594 | Operand *randomizeOrPoolImmediate(Constant *Immediate, |
| 595 | int32_t RegNum = Variable::NoRegister); |
| 596 | OperandX8632Mem * |
| 597 | randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, |
| 598 | int32_t RegNum = Variable::NoRegister); |
| 599 | bool RandomizationPoolingPaused = false; |
| 600 | |
| 601 | private: |
| 602 | ~TargetX86Base() override {} |
| 603 | BoolFolding FoldingInfo; |
| 604 | }; |
| 605 | } // end of namespace X86Internal |
| 606 | } // end of namespace Ice |
| 607 | |
| 608 | #include "IceTargetLoweringX86BaseImpl.h" |
| 609 | |
| 610 | #endif // SUBZERO_SRC_ICETARGETLOWERINGX86BASE_H |