Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 //===- subzero/src/IceTargetLoweringX8632.h - x86-32 lowering ---*- C++ -*-===// | 1 //===- subzero/src/IceTargetLoweringX8632.h - x86-32 lowering ---*- C++ -*-===// |
| 2 // | 2 // |
| 3 // The Subzero Code Generator | 3 // The Subzero Code Generator |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // This file declares the TargetLoweringX8632 class, which | 10 // This file declares the TargetLoweringX8632 class, which |
| 11 // implements the TargetLowering interface for the x86-32 | 11 // implements the TargetLowering interface for the x86-32 |
| 12 // architecture. | 12 // architecture. |
| 13 // | 13 // |
| 14 //===----------------------------------------------------------------------===// | 14 //===----------------------------------------------------------------------===// |
| 15 | 15 |
| 16 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632_H | 16 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632_H |
| 17 #define SUBZERO_SRC_ICETARGETLOWERINGX8632_H | 17 #define SUBZERO_SRC_ICETARGETLOWERINGX8632_H |
| 18 | 18 |
| 19 #include <unordered_map> | |
| 20 | |
| 21 #include "IceAssemblerX8632.h" | 19 #include "IceAssemblerX8632.h" |
| 22 #include "IceDefs.h" | 20 #include "IceDefs.h" |
| 23 #include "IceInst.h" | |
| 24 #include "IceInstX8632.h" | 21 #include "IceInstX8632.h" |
| 25 #include "IceRegistersX8632.h" | 22 #include "IceRegistersX8632.h" |
| 26 #include "IceTargetLowering.h" | 23 #include "IceTargetLowering.h" |
| 27 | 24 |
| 28 namespace Ice { | 25 namespace Ice { |
| 29 | 26 |
| 30 class BoolFoldingEntry { | 27 class Cfg; |
|
Jim Stichnoth
2015/06/23 17:24:33
These are already forward-declared in IceDefs.h.
John
2015/06/23 17:52:50
IceDefs..... :(
Done.
| |
| 31 BoolFoldingEntry(const BoolFoldingEntry &) = delete; | 28 class GlobalContext; |
| 32 | |
| 33 public: | |
| 34 BoolFoldingEntry() = default; | |
| 35 explicit BoolFoldingEntry(Inst *I); | |
| 36 BoolFoldingEntry &operator=(const BoolFoldingEntry &) = default; | |
| 37 // Instr is the instruction producing the i1-type variable of interest. | |
| 38 Inst *Instr = nullptr; | |
| 39 // IsComplex is the cached result of BoolFolding::hasComplexLowering(Instr). | |
| 40 bool IsComplex = false; | |
| 41 // IsLiveOut is initialized conservatively to true, and is set to false when | |
| 42 // we encounter an instruction that ends Var's live range. We disable the | |
| 43 // folding optimization when Var is live beyond this basic block. Note that | |
| 44 // if liveness analysis is not performed (e.g. in Om1 mode), IsLiveOut will | |
| 45 // always be true and the folding optimization will never be performed. | |
| 46 bool IsLiveOut = true; | |
| 47 // NumUses counts the number of times Var is used as a source operand in the | |
| 48 // basic block. If IsComplex is true and there is more than one use of Var, | |
| 49 // then the folding optimization is disabled for Var. | |
| 50 uint32_t NumUses = 0; | |
| 51 }; | |
| 52 | |
| 53 class BoolFolding { | |
| 54 public: | |
| 55 enum BoolFoldingProducerKind { | |
| 56 PK_None, | |
| 57 PK_Icmp32, | |
| 58 PK_Icmp64, | |
| 59 PK_Fcmp, | |
| 60 PK_Trunc | |
| 61 }; | |
| 62 | |
| 63 // Currently the actual enum values are not used (other than CK_None), but we | |
| 64 // go | |
| 65 // ahead and produce them anyway for symmetry with the | |
| 66 // BoolFoldingProducerKind. | |
| 67 enum BoolFoldingConsumerKind { CK_None, CK_Br, CK_Select, CK_Sext, CK_Zext }; | |
| 68 | |
| 69 private: | |
| 70 BoolFolding(const BoolFolding &) = delete; | |
| 71 BoolFolding &operator=(const BoolFolding &) = delete; | |
| 72 | |
| 73 public: | |
| 74 BoolFolding() = default; | |
| 75 static BoolFoldingProducerKind getProducerKind(const Inst *Instr); | |
| 76 static BoolFoldingConsumerKind getConsumerKind(const Inst *Instr); | |
| 77 static bool hasComplexLowering(const Inst *Instr); | |
| 78 void init(CfgNode *Node); | |
| 79 const Inst *getProducerFor(const Operand *Opnd) const; | |
| 80 void dump(const Cfg *Func) const; | |
| 81 | |
| 82 private: | |
| 83 // Returns true if Producers contains a valid entry for the given VarNum. | |
| 84 bool containsValid(SizeT VarNum) const { | |
| 85 auto Element = Producers.find(VarNum); | |
| 86 return Element != Producers.end() && Element->second.Instr != nullptr; | |
| 87 } | |
| 88 void setInvalid(SizeT VarNum) { Producers[VarNum].Instr = nullptr; } | |
| 89 // Producers maps Variable::Number to a BoolFoldingEntry. | |
| 90 std::unordered_map<SizeT, BoolFoldingEntry> Producers; | |
| 91 }; | |
| 92 | 29 |
| 93 class TargetX8632 : public TargetLowering { | 30 class TargetX8632 : public TargetLowering { |
| 94 TargetX8632() = delete; | 31 TargetX8632() = delete; |
| 95 TargetX8632(const TargetX8632 &) = delete; | 32 TargetX8632(const TargetX8632 &) = delete; |
| 96 TargetX8632 &operator=(const TargetX8632 &) = delete; | 33 TargetX8632 &operator=(const TargetX8632 &) = delete; |
| 97 | 34 |
| 98 public: | 35 public: |
| 99 static TargetX8632 *create(Cfg *Func) { return new TargetX8632(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; | |
| 148 | |
| 149 enum X86InstructionSet { | 36 enum X86InstructionSet { |
| 150 Begin, | 37 Begin, |
| 151 // SSE2 is the PNaCl baseline instruction set. | 38 // SSE2 is the PNaCl baseline instruction set. |
| 152 SSE2 = Begin, | 39 SSE2 = Begin, |
| 153 SSE4_1, | 40 SSE4_1, |
| 154 End | 41 End |
| 155 }; | 42 }; |
| 156 | 43 |
| 157 X86InstructionSet getInstructionSet() const { return InstructionSet; } | 44 static TargetX8632 *create(Cfg *Func); |
| 45 virtual X8632::Address stackVarToAsmOperand(const Variable *Var) const = 0; | |
| 46 virtual X86InstructionSet getInstructionSet() const = 0; | |
| 158 | 47 |
| 159 protected: | 48 protected: |
| 160 explicit TargetX8632(Cfg *Func); | 49 explicit TargetX8632(Cfg *Func) : TargetLowering(Func) {} |
| 161 | |
| 162 void postLower() override; | |
| 163 | |
| 164 void lowerAlloca(const InstAlloca *Inst) override; | |
| 165 void lowerArithmetic(const InstArithmetic *Inst) override; | |
| 166 void lowerAssign(const InstAssign *Inst) override; | |
| 167 void lowerBr(const InstBr *Inst) override; | |
| 168 void lowerCall(const InstCall *Inst) override; | |
| 169 void lowerCast(const InstCast *Inst) override; | |
| 170 void lowerExtractElement(const InstExtractElement *Inst) override; | |
| 171 void lowerFcmp(const InstFcmp *Inst) override; | |
| 172 void lowerIcmp(const InstIcmp *Inst) override; | |
| 173 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override; | |
| 174 void lowerInsertElement(const InstInsertElement *Inst) override; | |
| 175 void lowerLoad(const InstLoad *Inst) override; | |
| 176 void lowerPhi(const InstPhi *Inst) override; | |
| 177 void lowerRet(const InstRet *Inst) override; | |
| 178 void lowerSelect(const InstSelect *Inst) override; | |
| 179 void lowerStore(const InstStore *Inst) override; | |
| 180 void lowerSwitch(const InstSwitch *Inst) override; | |
| 181 void lowerUnreachable(const InstUnreachable *Inst) override; | |
| 182 void lowerOther(const Inst *Instr) override; | |
| 183 void lowerRMW(const InstX8632FakeRMW *RMW); | |
| 184 void prelowerPhis() override; | |
| 185 void lowerPhiAssignments(CfgNode *Node, | |
| 186 const AssignList &Assignments) override; | |
| 187 void doAddressOptLoad() override; | |
| 188 void doAddressOptStore() override; | |
| 189 void randomlyInsertNop(float Probability) override; | |
| 190 | |
| 191 // Naive lowering of cmpxchg. | |
| 192 void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected, | |
| 193 Operand *Desired); | |
| 194 // Attempt a more optimized lowering of cmpxchg. Returns true if optimized. | |
| 195 bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr, | |
| 196 Operand *Expected, Operand *Desired); | |
| 197 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr, | |
| 198 Operand *Val); | |
| 199 void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal, | |
| 200 Operand *SecondVal); | |
| 201 | |
| 202 typedef void (TargetX8632::*LowerBinOp)(Variable *, Operand *); | |
| 203 void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi, | |
| 204 Variable *Dest, Operand *Ptr, Operand *Val); | |
| 205 | |
| 206 void eliminateNextVectorSextInstruction(Variable *SignExtendedResult); | |
| 207 | |
| 208 void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest, | |
| 209 Operand *Src0, Operand *Src1); | |
| 210 | |
| 211 // Operand legalization helpers. To deal with address mode | |
| 212 // constraints, the helpers will create a new Operand and emit | |
| 213 // instructions that guarantee that the Operand kind is one of those | |
| 214 // indicated by the LegalMask (a bitmask of allowed kinds). If the | |
| 215 // input Operand is known to already meet the constraints, it may be | |
| 216 // simply returned as the result, without creating any new | |
| 217 // instructions or operands. | |
| 218 enum OperandLegalization { | |
| 219 Legal_None = 0, | |
| 220 Legal_Reg = 1 << 0, // physical register, not stack location | |
| 221 Legal_Imm = 1 << 1, | |
| 222 Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12] | |
| 223 Legal_All = ~Legal_None | |
| 224 }; | |
| 225 typedef uint32_t LegalMask; | |
| 226 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All, | |
| 227 int32_t RegNum = Variable::NoRegister); | |
| 228 Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister); | |
| 229 // Legalize the first source operand for use in the cmp instruction. | |
| 230 Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1); | |
| 231 // Turn a pointer operand into a memory operand that can be | |
| 232 // used by a real load/store operation. Legalizes the operand as well. | |
| 233 // This is a nop if the operand is already a legal memory operand. | |
| 234 OperandX8632Mem *formMemoryOperand(Operand *Ptr, Type Ty, | |
| 235 bool DoLegalize = true); | |
| 236 | |
| 237 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister); | |
| 238 static Type stackSlotType(); | |
| 239 | |
| 240 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister); | |
| 241 | |
| 242 // Returns a vector in a register with the given constant entries. | |
| 243 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister); | |
| 244 Variable *makeVectorOfOnes(Type Ty, int32_t RegNum = Variable::NoRegister); | |
| 245 Variable *makeVectorOfMinusOnes(Type Ty, | |
| 246 int32_t RegNum = Variable::NoRegister); | |
| 247 Variable *makeVectorOfHighOrderBits(Type Ty, | |
| 248 int32_t RegNum = Variable::NoRegister); | |
| 249 Variable *makeVectorOfFabsMask(Type Ty, | |
| 250 int32_t RegNum = Variable::NoRegister); | |
| 251 | |
| 252 // Return a memory operand corresponding to a stack allocated Variable. | |
| 253 OperandX8632Mem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot, | |
| 254 uint32_t Offset = 0); | |
| 255 | |
| 256 void makeRandomRegisterPermutation( | |
| 257 llvm::SmallVectorImpl<int32_t> &Permutation, | |
| 258 const llvm::SmallBitVector &ExcludeRegisters) const override; | |
| 259 | |
| 260 // The following are helpers that insert lowered x86 instructions | |
| 261 // with minimal syntactic overhead, so that the lowering code can | |
| 262 // look as close to assembly as practical. | |
| 263 void _adc(Variable *Dest, Operand *Src0) { | |
| 264 Context.insert(InstX8632Adc::create(Func, Dest, Src0)); | |
| 265 } | |
| 266 void _adc_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { | |
| 267 Context.insert(InstX8632AdcRMW::create(Func, DestSrc0, Src1)); | |
| 268 } | |
| 269 void _add(Variable *Dest, Operand *Src0) { | |
| 270 Context.insert(InstX8632Add::create(Func, Dest, Src0)); | |
| 271 } | |
| 272 void _add_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { | |
| 273 Context.insert(InstX8632AddRMW::create(Func, DestSrc0, Src1)); | |
| 274 } | |
| 275 void _adjust_stack(int32_t Amount) { | |
| 276 Context.insert(InstX8632AdjustStack::create( | |
| 277 Func, Amount, getPhysicalRegister(RegX8632::Reg_esp))); | |
| 278 } | |
| 279 void _addps(Variable *Dest, Operand *Src0) { | |
| 280 Context.insert(InstX8632Addps::create(Func, Dest, Src0)); | |
| 281 } | |
| 282 void _addss(Variable *Dest, Operand *Src0) { | |
| 283 Context.insert(InstX8632Addss::create(Func, Dest, Src0)); | |
| 284 } | |
| 285 void _and(Variable *Dest, Operand *Src0) { | |
| 286 Context.insert(InstX8632And::create(Func, Dest, Src0)); | |
| 287 } | |
| 288 void _and_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { | |
| 289 Context.insert(InstX8632AndRMW::create(Func, DestSrc0, Src1)); | |
| 290 } | |
| 291 void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) { | |
| 292 Context.insert(InstX8632Blendvps::create(Func, Dest, Src0, Src1)); | |
| 293 } | |
| 294 void _br(CondX86::BrCond Condition, CfgNode *TargetTrue, | |
| 295 CfgNode *TargetFalse) { | |
| 296 Context.insert( | |
| 297 InstX8632Br::create(Func, TargetTrue, TargetFalse, Condition)); | |
| 298 } | |
| 299 void _br(CfgNode *Target) { | |
| 300 Context.insert(InstX8632Br::create(Func, Target)); | |
| 301 } | |
| 302 void _br(CondX86::BrCond Condition, CfgNode *Target) { | |
| 303 Context.insert(InstX8632Br::create(Func, Target, Condition)); | |
| 304 } | |
| 305 void _br(CondX86::BrCond Condition, InstX8632Label *Label) { | |
| 306 Context.insert(InstX8632Br::create(Func, Label, Condition)); | |
| 307 } | |
| 308 void _bsf(Variable *Dest, Operand *Src0) { | |
| 309 Context.insert(InstX8632Bsf::create(Func, Dest, Src0)); | |
| 310 } | |
| 311 void _bsr(Variable *Dest, Operand *Src0) { | |
| 312 Context.insert(InstX8632Bsr::create(Func, Dest, Src0)); | |
| 313 } | |
| 314 void _bswap(Variable *SrcDest) { | |
| 315 Context.insert(InstX8632Bswap::create(Func, SrcDest)); | |
| 316 } | |
| 317 void _cbwdq(Variable *Dest, Operand *Src0) { | |
| 318 Context.insert(InstX8632Cbwdq::create(Func, Dest, Src0)); | |
| 319 } | |
| 320 void _cmov(Variable *Dest, Operand *Src0, CondX86::BrCond Condition) { | |
| 321 Context.insert(InstX8632Cmov::create(Func, Dest, Src0, Condition)); | |
| 322 } | |
| 323 void _cmp(Operand *Src0, Operand *Src1) { | |
| 324 Context.insert(InstX8632Icmp::create(Func, Src0, Src1)); | |
| 325 } | |
| 326 void _cmpps(Variable *Dest, Operand *Src0, CondX86::CmppsCond Condition) { | |
| 327 Context.insert(InstX8632Cmpps::create(Func, Dest, Src0, Condition)); | |
| 328 } | |
| 329 void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired, | |
| 330 bool Locked) { | |
| 331 Context.insert( | |
| 332 InstX8632Cmpxchg::create(Func, DestOrAddr, Eax, Desired, Locked)); | |
| 333 // Mark eax as possibly modified by cmpxchg. | |
| 334 Context.insert( | |
| 335 InstFakeDef::create(Func, Eax, llvm::dyn_cast<Variable>(DestOrAddr))); | |
| 336 _set_dest_nonkillable(); | |
| 337 Context.insert(InstFakeUse::create(Func, Eax)); | |
| 338 } | |
| 339 void _cmpxchg8b(OperandX8632Mem *Addr, Variable *Edx, Variable *Eax, | |
| 340 Variable *Ecx, Variable *Ebx, bool Locked) { | |
| 341 Context.insert( | |
| 342 InstX8632Cmpxchg8b::create(Func, Addr, Edx, Eax, Ecx, Ebx, Locked)); | |
| 343 // Mark edx, and eax as possibly modified by cmpxchg8b. | |
| 344 Context.insert(InstFakeDef::create(Func, Edx)); | |
| 345 _set_dest_nonkillable(); | |
| 346 Context.insert(InstFakeUse::create(Func, Edx)); | |
| 347 Context.insert(InstFakeDef::create(Func, Eax)); | |
| 348 _set_dest_nonkillable(); | |
| 349 Context.insert(InstFakeUse::create(Func, Eax)); | |
| 350 } | |
| 351 void _cvt(Variable *Dest, Operand *Src0, InstX8632Cvt::CvtVariant Variant) { | |
| 352 Context.insert(InstX8632Cvt::create(Func, Dest, Src0, Variant)); | |
| 353 } | |
| 354 void _div(Variable *Dest, Operand *Src0, Operand *Src1) { | |
| 355 Context.insert(InstX8632Div::create(Func, Dest, Src0, Src1)); | |
| 356 } | |
| 357 void _divps(Variable *Dest, Operand *Src0) { | |
| 358 Context.insert(InstX8632Divps::create(Func, Dest, Src0)); | |
| 359 } | |
| 360 void _divss(Variable *Dest, Operand *Src0) { | |
| 361 Context.insert(InstX8632Divss::create(Func, Dest, Src0)); | |
| 362 } | |
| 363 void _fld(Operand *Src0) { Context.insert(InstX8632Fld::create(Func, Src0)); } | |
| 364 void _fstp(Variable *Dest) { | |
| 365 Context.insert(InstX8632Fstp::create(Func, Dest)); | |
| 366 } | |
| 367 void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) { | |
| 368 Context.insert(InstX8632Idiv::create(Func, Dest, Src0, Src1)); | |
| 369 } | |
| 370 void _imul(Variable *Dest, Operand *Src0) { | |
| 371 Context.insert(InstX8632Imul::create(Func, Dest, Src0)); | |
| 372 } | |
| 373 void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) { | |
| 374 Context.insert(InstX8632Insertps::create(Func, Dest, Src0, Src1)); | |
| 375 } | |
| 376 void _jmp(Operand *Target) { | |
| 377 Context.insert(InstX8632Jmp::create(Func, Target)); | |
| 378 } | |
| 379 void _lea(Variable *Dest, Operand *Src0) { | |
| 380 Context.insert(InstX8632Lea::create(Func, Dest, Src0)); | |
| 381 } | |
| 382 void _mfence() { Context.insert(InstX8632Mfence::create(Func)); } | |
| 383 // If Dest=nullptr is passed in, then a new variable is created, | |
| 384 // marked as infinite register allocation weight, and returned | |
| 385 // through the in/out Dest argument. | |
| 386 void _mov(Variable *&Dest, Operand *Src0, | |
| 387 int32_t RegNum = Variable::NoRegister) { | |
| 388 if (Dest == nullptr) | |
| 389 Dest = makeReg(Src0->getType(), RegNum); | |
| 390 Context.insert(InstX8632Mov::create(Func, Dest, Src0)); | |
| 391 } | |
| 392 void _mov_nonkillable(Variable *Dest, Operand *Src0) { | |
| 393 Inst *NewInst = InstX8632Mov::create(Func, Dest, Src0); | |
| 394 NewInst->setDestNonKillable(); | |
| 395 Context.insert(NewInst); | |
| 396 } | |
| 397 void _movd(Variable *Dest, Operand *Src0) { | |
| 398 Context.insert(InstX8632Movd::create(Func, Dest, Src0)); | |
| 399 } | |
| 400 void _movp(Variable *Dest, Operand *Src0) { | |
| 401 Context.insert(InstX8632Movp::create(Func, Dest, Src0)); | |
| 402 } | |
| 403 void _movq(Variable *Dest, Operand *Src0) { | |
| 404 Context.insert(InstX8632Movq::create(Func, Dest, Src0)); | |
| 405 } | |
| 406 void _movss(Variable *Dest, Variable *Src0) { | |
| 407 Context.insert(InstX8632MovssRegs::create(Func, Dest, Src0)); | |
| 408 } | |
| 409 void _movsx(Variable *Dest, Operand *Src0) { | |
| 410 Context.insert(InstX8632Movsx::create(Func, Dest, Src0)); | |
| 411 } | |
| 412 void _movzx(Variable *Dest, Operand *Src0) { | |
| 413 Context.insert(InstX8632Movzx::create(Func, Dest, Src0)); | |
| 414 } | |
| 415 void _mul(Variable *Dest, Variable *Src0, Operand *Src1) { | |
| 416 Context.insert(InstX8632Mul::create(Func, Dest, Src0, Src1)); | |
| 417 } | |
| 418 void _mulps(Variable *Dest, Operand *Src0) { | |
| 419 Context.insert(InstX8632Mulps::create(Func, Dest, Src0)); | |
| 420 } | |
| 421 void _mulss(Variable *Dest, Operand *Src0) { | |
| 422 Context.insert(InstX8632Mulss::create(Func, Dest, Src0)); | |
| 423 } | |
| 424 void _neg(Variable *SrcDest) { | |
| 425 Context.insert(InstX8632Neg::create(Func, SrcDest)); | |
| 426 } | |
| 427 void _nop(SizeT Variant) { | |
| 428 Context.insert(InstX8632Nop::create(Func, Variant)); | |
| 429 } | |
| 430 void _or(Variable *Dest, Operand *Src0) { | |
| 431 Context.insert(InstX8632Or::create(Func, Dest, Src0)); | |
| 432 } | |
| 433 void _or_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { | |
| 434 Context.insert(InstX8632OrRMW::create(Func, DestSrc0, Src1)); | |
| 435 } | |
| 436 void _padd(Variable *Dest, Operand *Src0) { | |
| 437 Context.insert(InstX8632Padd::create(Func, Dest, Src0)); | |
| 438 } | |
| 439 void _pand(Variable *Dest, Operand *Src0) { | |
| 440 Context.insert(InstX8632Pand::create(Func, Dest, Src0)); | |
| 441 } | |
| 442 void _pandn(Variable *Dest, Operand *Src0) { | |
| 443 Context.insert(InstX8632Pandn::create(Func, Dest, Src0)); | |
| 444 } | |
| 445 void _pblendvb(Variable *Dest, Operand *Src0, Operand *Src1) { | |
| 446 Context.insert(InstX8632Pblendvb::create(Func, Dest, Src0, Src1)); | |
| 447 } | |
| 448 void _pcmpeq(Variable *Dest, Operand *Src0) { | |
| 449 Context.insert(InstX8632Pcmpeq::create(Func, Dest, Src0)); | |
| 450 } | |
| 451 void _pcmpgt(Variable *Dest, Operand *Src0) { | |
| 452 Context.insert(InstX8632Pcmpgt::create(Func, Dest, Src0)); | |
| 453 } | |
| 454 void _pextr(Variable *Dest, Operand *Src0, Operand *Src1) { | |
| 455 Context.insert(InstX8632Pextr::create(Func, Dest, Src0, Src1)); | |
| 456 } | |
| 457 void _pinsr(Variable *Dest, Operand *Src0, Operand *Src1) { | |
| 458 Context.insert(InstX8632Pinsr::create(Func, Dest, Src0, Src1)); | |
| 459 } | |
| 460 void _pmull(Variable *Dest, Operand *Src0) { | |
| 461 Context.insert(InstX8632Pmull::create(Func, Dest, Src0)); | |
| 462 } | |
| 463 void _pmuludq(Variable *Dest, Operand *Src0) { | |
| 464 Context.insert(InstX8632Pmuludq::create(Func, Dest, Src0)); | |
| 465 } | |
| 466 void _pop(Variable *Dest) { | |
| 467 Context.insert(InstX8632Pop::create(Func, Dest)); | |
| 468 } | |
| 469 void _por(Variable *Dest, Operand *Src0) { | |
| 470 Context.insert(InstX8632Por::create(Func, Dest, Src0)); | |
| 471 } | |
| 472 void _pshufd(Variable *Dest, Operand *Src0, Operand *Src1) { | |
| 473 Context.insert(InstX8632Pshufd::create(Func, Dest, Src0, Src1)); | |
| 474 } | |
| 475 void _psll(Variable *Dest, Operand *Src0) { | |
| 476 Context.insert(InstX8632Psll::create(Func, Dest, Src0)); | |
| 477 } | |
| 478 void _psra(Variable *Dest, Operand *Src0) { | |
| 479 Context.insert(InstX8632Psra::create(Func, Dest, Src0)); | |
| 480 } | |
| 481 void _psrl(Variable *Dest, Operand *Src0) { | |
| 482 Context.insert(InstX8632Psrl::create(Func, Dest, Src0)); | |
| 483 } | |
| 484 void _psub(Variable *Dest, Operand *Src0) { | |
| 485 Context.insert(InstX8632Psub::create(Func, Dest, Src0)); | |
| 486 } | |
| 487 void _push(Variable *Src0) { | |
| 488 Context.insert(InstX8632Push::create(Func, Src0)); | |
| 489 } | |
| 490 void _pxor(Variable *Dest, Operand *Src0) { | |
| 491 Context.insert(InstX8632Pxor::create(Func, Dest, Src0)); | |
| 492 } | |
| 493 void _ret(Variable *Src0 = nullptr) { | |
| 494 Context.insert(InstX8632Ret::create(Func, Src0)); | |
| 495 } | |
| 496 void _rol(Variable *Dest, Operand *Src0) { | |
| 497 Context.insert(InstX8632Rol::create(Func, Dest, Src0)); | |
| 498 } | |
| 499 void _sar(Variable *Dest, Operand *Src0) { | |
| 500 Context.insert(InstX8632Sar::create(Func, Dest, Src0)); | |
| 501 } | |
| 502 void _sbb(Variable *Dest, Operand *Src0) { | |
| 503 Context.insert(InstX8632Sbb::create(Func, Dest, Src0)); | |
| 504 } | |
| 505 void _sbb_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { | |
| 506 Context.insert(InstX8632SbbRMW::create(Func, DestSrc0, Src1)); | |
| 507 } | |
| 508 void _setcc(Variable *Dest, CondX86::BrCond Condition) { | |
| 509 Context.insert(InstX8632Setcc::create(Func, Dest, Condition)); | |
| 510 } | |
| 511 void _shl(Variable *Dest, Operand *Src0) { | |
| 512 Context.insert(InstX8632Shl::create(Func, Dest, Src0)); | |
| 513 } | |
| 514 void _shld(Variable *Dest, Variable *Src0, Variable *Src1) { | |
| 515 Context.insert(InstX8632Shld::create(Func, Dest, Src0, Src1)); | |
| 516 } | |
| 517 void _shr(Variable *Dest, Operand *Src0) { | |
| 518 Context.insert(InstX8632Shr::create(Func, Dest, Src0)); | |
| 519 } | |
| 520 void _shrd(Variable *Dest, Variable *Src0, Variable *Src1) { | |
| 521 Context.insert(InstX8632Shrd::create(Func, Dest, Src0, Src1)); | |
| 522 } | |
| 523 void _shufps(Variable *Dest, Operand *Src0, Operand *Src1) { | |
| 524 Context.insert(InstX8632Shufps::create(Func, Dest, Src0, Src1)); | |
| 525 } | |
| 526 void _sqrtss(Variable *Dest, Operand *Src0) { | |
| 527 Context.insert(InstX8632Sqrtss::create(Func, Dest, Src0)); | |
| 528 } | |
| 529 void _store(Operand *Value, OperandX8632 *Mem) { | |
| 530 Context.insert(InstX8632Store::create(Func, Value, Mem)); | |
| 531 } | |
| 532 void _storep(Variable *Value, OperandX8632Mem *Mem) { | |
| 533 Context.insert(InstX8632StoreP::create(Func, Value, Mem)); | |
| 534 } | |
| 535 void _storeq(Variable *Value, OperandX8632Mem *Mem) { | |
| 536 Context.insert(InstX8632StoreQ::create(Func, Value, Mem)); | |
| 537 } | |
| 538 void _sub(Variable *Dest, Operand *Src0) { | |
| 539 Context.insert(InstX8632Sub::create(Func, Dest, Src0)); | |
| 540 } | |
| 541 void _sub_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { | |
| 542 Context.insert(InstX8632SubRMW::create(Func, DestSrc0, Src1)); | |
| 543 } | |
| 544 void _subps(Variable *Dest, Operand *Src0) { | |
| 545 Context.insert(InstX8632Subps::create(Func, Dest, Src0)); | |
| 546 } | |
| 547 void _subss(Variable *Dest, Operand *Src0) { | |
| 548 Context.insert(InstX8632Subss::create(Func, Dest, Src0)); | |
| 549 } | |
| 550 void _test(Operand *Src0, Operand *Src1) { | |
| 551 Context.insert(InstX8632Test::create(Func, Src0, Src1)); | |
| 552 } | |
| 553 void _ucomiss(Operand *Src0, Operand *Src1) { | |
| 554 Context.insert(InstX8632Ucomiss::create(Func, Src0, Src1)); | |
| 555 } | |
| 556 void _ud2() { Context.insert(InstX8632UD2::create(Func)); } | |
| 557 void _xadd(Operand *Dest, Variable *Src, bool Locked) { | |
| 558 Context.insert(InstX8632Xadd::create(Func, Dest, Src, Locked)); | |
| 559 // The xadd exchanges Dest and Src (modifying Src). | |
| 560 // Model that update with a FakeDef followed by a FakeUse. | |
| 561 Context.insert( | |
| 562 InstFakeDef::create(Func, Src, llvm::dyn_cast<Variable>(Dest))); | |
| 563 _set_dest_nonkillable(); | |
| 564 Context.insert(InstFakeUse::create(Func, Src)); | |
| 565 } | |
| 566 void _xchg(Operand *Dest, Variable *Src) { | |
| 567 Context.insert(InstX8632Xchg::create(Func, Dest, Src)); | |
| 568 // The xchg modifies Dest and Src -- model that update with a | |
| 569 // FakeDef/FakeUse. | |
| 570 Context.insert( | |
| 571 InstFakeDef::create(Func, Src, llvm::dyn_cast<Variable>(Dest))); | |
| 572 _set_dest_nonkillable(); | |
| 573 Context.insert(InstFakeUse::create(Func, Src)); | |
| 574 } | |
| 575 void _xor(Variable *Dest, Operand *Src0) { | |
| 576 Context.insert(InstX8632Xor::create(Func, Dest, Src0)); | |
| 577 } | |
| 578 void _xor_rmw(OperandX8632Mem *DestSrc0, Operand *Src1) { | |
| 579 Context.insert(InstX8632XorRMW::create(Func, DestSrc0, Src1)); | |
| 580 } | |
| 581 void _set_dest_nonkillable() { | |
| 582 Context.getLastInserted()->setDestNonKillable(); | |
| 583 } | |
| 584 | |
| 585 bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1); | |
| 586 void findRMW(); | |
| 587 | |
| 588 X86InstructionSet InstructionSet = X86InstructionSet::Begin; | |
| 589 bool IsEbpBasedFrame = false; | |
| 590 bool NeedsStackAlignment = false; | |
| 591 size_t SpillAreaSizeBytes = 0; | |
| 592 llvm::SmallBitVector TypeToRegisterSet[IceType_NUM]; | |
| 593 llvm::SmallBitVector ScratchRegs; | |
| 594 llvm::SmallBitVector RegsUsed; | |
| 595 VarList PhysicalRegisters[IceType_NUM]; | |
| 596 static IceString RegNames[]; | |
| 597 | |
| 598 // Randomize a given immediate operand | |
| 599 Operand *randomizeOrPoolImmediate(Constant *Immediate, | |
| 600 int32_t RegNum = Variable::NoRegister); | |
| 601 OperandX8632Mem * | |
| 602 randomizeOrPoolImmediate(OperandX8632Mem *MemOperand, | |
| 603 int32_t RegNum = Variable::NoRegister); | |
| 604 bool RandomizationPoolingPaused = false; | |
| 605 | |
| 606 private: | |
| 607 ~TargetX8632() override {} | |
| 608 BoolFolding FoldingInfo; | |
| 609 }; | 50 }; |
| 610 | 51 |
| 611 class TargetDataX8632 final : public TargetDataLowering { | 52 class TargetDataX8632 final : public TargetDataLowering { |
| 612 TargetDataX8632() = delete; | 53 TargetDataX8632() = delete; |
| 613 TargetDataX8632(const TargetDataX8632 &) = delete; | 54 TargetDataX8632(const TargetDataX8632 &) = delete; |
| 614 TargetDataX8632 &operator=(const TargetDataX8632 &) = delete; | 55 TargetDataX8632 &operator=(const TargetDataX8632 &) = delete; |
| 615 | 56 |
| 616 public: | 57 public: |
| 617 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { | 58 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) { |
| 618 return std::unique_ptr<TargetDataLowering>(new TargetDataX8632(Ctx)); | 59 return std::unique_ptr<TargetDataLowering>(new TargetDataX8632(Ctx)); |
| 619 } | 60 } |
| 620 | 61 |
| 621 void lowerGlobals(const VariableDeclarationList &Vars, | 62 void lowerGlobals(const VariableDeclarationList &Vars, |
| 622 const IceString &SectionSuffix) override; | 63 const IceString &SectionSuffix) override; |
| 623 void lowerConstants() override; | 64 void lowerConstants() override; |
| 624 | 65 |
| 625 protected: | 66 protected: |
| 626 explicit TargetDataX8632(GlobalContext *Ctx); | 67 explicit TargetDataX8632(GlobalContext *Ctx); |
| 627 | 68 |
| 628 private: | 69 private: |
| 629 ~TargetDataX8632() override {} | 70 ~TargetDataX8632() override = default; |
| 630 template <typename T> static void emitConstantPool(GlobalContext *Ctx); | 71 template <typename T> static void emitConstantPool(GlobalContext *Ctx); |
| 631 }; | 72 }; |
| 632 | 73 |
| 633 class TargetHeaderX8632 final : public TargetHeaderLowering { | 74 class TargetHeaderX8632 final : public TargetHeaderLowering { |
| 634 TargetHeaderX8632() = delete; | 75 TargetHeaderX8632() = delete; |
| 635 TargetHeaderX8632(const TargetHeaderX8632 &) = delete; | 76 TargetHeaderX8632(const TargetHeaderX8632 &) = delete; |
| 636 TargetHeaderX8632 &operator=(const TargetHeaderX8632 &) = delete; | 77 TargetHeaderX8632 &operator=(const TargetHeaderX8632 &) = delete; |
| 637 | 78 |
| 638 public: | 79 public: |
| 639 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) { | 80 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) { |
| 640 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderX8632(Ctx)); | 81 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderX8632(Ctx)); |
| 641 } | 82 } |
| 642 | 83 |
| 643 protected: | 84 protected: |
| 644 explicit TargetHeaderX8632(GlobalContext *Ctx); | 85 explicit TargetHeaderX8632(GlobalContext *Ctx); |
| 645 | 86 |
| 646 private: | 87 private: |
| 647 ~TargetHeaderX8632() = default; | 88 ~TargetHeaderX8632() = default; |
| 648 }; | 89 }; |
| 649 | 90 |
| 650 } // end of namespace Ice | 91 } // end of namespace Ice |
| 651 | 92 |
| 652 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632_H | 93 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632_H |
| OLD | NEW |