blob: fe3612c4bf450969972fb452206892bc4e593064 [file] [log] [blame]
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -07001//===- subzero/src/IceTargetLoweringX8632.h - x86-32 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 TargetLoweringX8632 class, which
11// implements the TargetLowering interface for the x86-32
12// architecture.
13//
14//===----------------------------------------------------------------------===//
15
16#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632_H
17#define SUBZERO_SRC_ICETARGETLOWERINGX8632_H
18
Jim Stichnotha59ae6f2015-05-17 10:11:41 -070019#include <unordered_map>
20
John Portoaff4ccf2015-06-10 16:35:06 -070021#include "IceAssemblerX8632.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070022#include "IceDefs.h"
Jim Stichnotha59ae6f2015-05-17 10:11:41 -070023#include "IceInst.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070024#include "IceInstX8632.h"
Jan Voungbd385e42014-09-18 18:18:10 -070025#include "IceRegistersX8632.h"
Jim Stichnotha18cc9c2014-09-30 19:10:22 -070026#include "IceTargetLowering.h"
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070027
28namespace Ice {
29
Jim Stichnotha59ae6f2015-05-17 10:11:41 -070030class BoolFoldingEntry {
31 BoolFoldingEntry(const BoolFoldingEntry &) = delete;
32
33public:
34 BoolFoldingEntry()
35 : Instr(nullptr), IsComplex(false), IsLiveOut(true), NumUses(0) {}
36 explicit BoolFoldingEntry(Inst *I);
37 BoolFoldingEntry &operator=(const BoolFoldingEntry &) = default;
38 // Instr is the instruction producing the i1-type variable of interest.
39 Inst *Instr;
40 // IsComplex is the cached result of BoolFolding::hasComplexLowering(Instr).
41 bool IsComplex;
42 // IsLiveOut is initialized conservatively to true, and is set to false when
43 // we encounter an instruction that ends Var's live range. We disable the
44 // folding optimization when Var is live beyond this basic block. Note that
45 // if liveness analysis is not performed (e.g. in Om1 mode), IsLiveOut will
46 // always be true and the folding optimization will never be performed.
47 bool IsLiveOut;
48 // NumUses counts the number of times Var is used as a source operand in the
49 // basic block. If IsComplex is true and there is more than one use of Var,
50 // then the folding optimization is disabled for Var.
51 uint32_t NumUses;
52};
53
54class BoolFolding {
55public:
56 enum BoolFoldingProducerKind {
57 PK_None,
58 PK_Icmp32,
59 PK_Icmp64,
60 PK_Fcmp,
61 PK_Trunc
62 };
63
64 // Currently the actual enum values are not used (other than CK_None), but we
65 // go
66 // ahead and produce them anyway for symmetry with the
67 // BoolFoldingProducerKind.
68 enum BoolFoldingConsumerKind { CK_None, CK_Br, CK_Select, CK_Sext, CK_Zext };
69
70private:
71 BoolFolding(const BoolFolding &) = delete;
72 BoolFolding &operator=(const BoolFolding &) = delete;
73
74public:
75 BoolFolding() {}
76 static BoolFoldingProducerKind getProducerKind(const Inst *Instr);
77 static BoolFoldingConsumerKind getConsumerKind(const Inst *Instr);
78 static bool hasComplexLowering(const Inst *Instr);
79 void init(CfgNode *Node);
80 const Inst *getProducerFor(const Operand *Opnd) const;
81 void dump(const Cfg *Func) const;
82
83private:
84 // Returns true if Producers contains a valid entry for the given VarNum.
85 bool containsValid(SizeT VarNum) const {
86 auto Element = Producers.find(VarNum);
87 return Element != Producers.end() && Element->second.Instr != nullptr;
88 }
89 void setInvalid(SizeT VarNum) { Producers[VarNum].Instr = nullptr; }
90 // Producers maps Variable::Number to a BoolFoldingEntry.
91 std::unordered_map<SizeT, BoolFoldingEntry> Producers;
92};
93
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070094class TargetX8632 : public TargetLowering {
Jim Stichnothc6ead202015-02-24 09:30:30 -080095 TargetX8632() = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -070096 TargetX8632(const TargetX8632 &) = delete;
97 TargetX8632 &operator=(const TargetX8632 &) = delete;
98
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -070099public:
100 static TargetX8632 *create(Cfg *Func) { return new TargetX8632(Func); }
101
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700102 void translateOm1() override;
103 void translateO2() override;
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700104 void doLoadOpt();
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700105 bool doBranchOpt(Inst *I, const CfgNode *NextNode) override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700106
Jim Stichnoth3d44fe82014-11-01 10:10:18 -0700107 SizeT getNumRegisters() const override { return RegX8632::Reg_NUM; }
Jim Stichnoth98712a32014-10-24 10:59:02 -0700108 Variable *getPhysicalRegister(SizeT RegNum, Type Ty = IceType_void) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700109 IceString getRegName(SizeT RegNum, Type Ty) const override;
110 llvm::SmallBitVector getRegisterSet(RegSetMask Include,
111 RegSetMask Exclude) const override;
112 const llvm::SmallBitVector &getRegisterSetForType(Type Ty) const override {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700113 return TypeToRegisterSet[Ty];
114 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700115 bool hasFramePointer() const override { return IsEbpBasedFrame; }
116 SizeT getFrameOrStackReg() const override {
Jan Voungbd385e42014-09-18 18:18:10 -0700117 return IsEbpBasedFrame ? RegX8632::Reg_ebp : RegX8632::Reg_esp;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700118 }
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700119 size_t typeWidthInBytesOnStack(Type Ty) const override {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700120 // Round up to the next multiple of 4 bytes. In particular, i1,
121 // i8, and i16 are rounded up to 4 bytes.
122 return (typeWidthInBytes(Ty) + 3) & ~3;
123 }
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700124
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700125 void emitVariable(const Variable *Var) const override;
Jan Voung76bb0be2015-05-14 09:26:19 -0700126
127 const char *getConstantPrefix() const final { return "$"; }
128 void emit(const ConstantUndef *C) const final;
129 void emit(const ConstantInteger32 *C) const final;
130 void emit(const ConstantInteger64 *C) const final;
131 void emit(const ConstantFloat *C) const final;
132 void emit(const ConstantDouble *C) const final;
133
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700134 void lowerArguments() override;
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700135 void initNodeForLowering(CfgNode *Node) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700136 void addProlog(CfgNode *Node) override;
137 void addEpilog(CfgNode *Node) override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700138 // Ensure that a 64-bit Variable has been split into 2 32-bit
139 // Variables, creating them if necessary. This is needed for all
140 // I64 operations, and it is needed for pushing F64 arguments for
141 // function calls using the 32-bit push instruction (though the
142 // latter could be done by directly writing to the stack).
143 void split64(Variable *Var);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700144 Operand *loOperand(Operand *Operand);
145 Operand *hiOperand(Operand *Operand);
Jan Voung0fa6c5a2015-06-01 11:04:04 -0700146 void finishArgumentLowering(Variable *Arg, Variable *FramePtr,
147 size_t BasicFrameOffset, size_t &InArgsSizeBytes);
Jan Voung90ccc3f2015-04-30 14:15:10 -0700148 X8632::Address stackVarToAsmOperand(const Variable *Var) const;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700149
Matt Wala0a450512014-07-30 12:44:39 -0700150 enum X86InstructionSet {
Jan Voung1f47ad02015-03-20 15:01:26 -0700151 Begin,
Matt Wala0a450512014-07-30 12:44:39 -0700152 // SSE2 is the PNaCl baseline instruction set.
Jan Voung1f47ad02015-03-20 15:01:26 -0700153 SSE2 = Begin,
154 SSE4_1,
155 End
Matt Wala0a450512014-07-30 12:44:39 -0700156 };
157
158 X86InstructionSet getInstructionSet() const { return InstructionSet; }
159
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700160protected:
Jim Stichnothc6ead202015-02-24 09:30:30 -0800161 explicit TargetX8632(Cfg *Func);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700162
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700163 void postLower() override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700164
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700165 void lowerAlloca(const InstAlloca *Inst) override;
166 void lowerArithmetic(const InstArithmetic *Inst) override;
167 void lowerAssign(const InstAssign *Inst) override;
168 void lowerBr(const InstBr *Inst) override;
169 void lowerCall(const InstCall *Inst) override;
170 void lowerCast(const InstCast *Inst) override;
171 void lowerExtractElement(const InstExtractElement *Inst) override;
172 void lowerFcmp(const InstFcmp *Inst) override;
173 void lowerIcmp(const InstIcmp *Inst) override;
174 void lowerIntrinsicCall(const InstIntrinsicCall *Inst) override;
175 void lowerInsertElement(const InstInsertElement *Inst) override;
176 void lowerLoad(const InstLoad *Inst) override;
177 void lowerPhi(const InstPhi *Inst) override;
178 void lowerRet(const InstRet *Inst) override;
179 void lowerSelect(const InstSelect *Inst) override;
180 void lowerStore(const InstStore *Inst) override;
181 void lowerSwitch(const InstSwitch *Inst) override;
182 void lowerUnreachable(const InstUnreachable *Inst) override;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700183 void prelowerPhis() override;
184 void lowerPhiAssignments(CfgNode *Node,
185 const AssignList &Assignments) override;
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700186 void doAddressOptLoad() override;
187 void doAddressOptStore() override;
188 void randomlyInsertNop(float Probability) override;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700189
Jan Voungc820ddf2014-07-29 14:38:51 -0700190 // Naive lowering of cmpxchg.
Jan Vounga3a01a22014-07-14 10:32:41 -0700191 void lowerAtomicCmpxchg(Variable *DestPrev, Operand *Ptr, Operand *Expected,
192 Operand *Desired);
Jan Voungc820ddf2014-07-29 14:38:51 -0700193 // Attempt a more optimized lowering of cmpxchg. Returns true if optimized.
194 bool tryOptimizedCmpxchgCmpBr(Variable *DestPrev, Operand *Ptr,
195 Operand *Expected, Operand *Desired);
Jan Voung5cd240d2014-06-25 10:36:46 -0700196 void lowerAtomicRMW(Variable *Dest, uint32_t Operation, Operand *Ptr,
197 Operand *Val);
Jan Vounge4da26f2014-07-15 17:52:39 -0700198 void lowerCountZeros(bool Cttz, Type Ty, Variable *Dest, Operand *FirstVal,
199 Operand *SecondVal);
Jan Voung5cd240d2014-06-25 10:36:46 -0700200
Jan Vounga3a01a22014-07-14 10:32:41 -0700201 typedef void (TargetX8632::*LowerBinOp)(Variable *, Operand *);
202 void expandAtomicRMWAsCmpxchg(LowerBinOp op_lo, LowerBinOp op_hi,
203 Variable *Dest, Operand *Ptr, Operand *Val);
204
Matt Walace0ca8f2014-07-24 12:34:20 -0700205 void eliminateNextVectorSextInstruction(Variable *SignExtendedResult);
206
Matt Walaafeaee42014-08-07 13:47:30 -0700207 void scalarizeArithmetic(InstArithmetic::OpKind K, Variable *Dest,
208 Operand *Src0, Operand *Src1);
209
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700210 // Operand legalization helpers. To deal with address mode
211 // constraints, the helpers will create a new Operand and emit
212 // instructions that guarantee that the Operand kind is one of those
213 // indicated by the LegalMask (a bitmask of allowed kinds). If the
214 // input Operand is known to already meet the constraints, it may be
215 // simply returned as the result, without creating any new
216 // instructions or operands.
217 enum OperandLegalization {
218 Legal_None = 0,
219 Legal_Reg = 1 << 0, // physical register, not stack location
220 Legal_Imm = 1 << 1,
221 Legal_Mem = 1 << 2, // includes [eax+4*ecx] as well as [esp+12]
222 Legal_All = ~Legal_None
223 };
224 typedef uint32_t LegalMask;
Jim Stichnothdd165072014-11-02 09:41:45 -0800225 Operand *legalize(Operand *From, LegalMask Allowed = Legal_All,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700226 int32_t RegNum = Variable::NoRegister);
Jim Stichnothad403532014-09-25 12:44:17 -0700227 Variable *legalizeToVar(Operand *From, int32_t RegNum = Variable::NoRegister);
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700228 // Legalize the first source operand for use in the cmp instruction.
229 Operand *legalizeSrc0ForCmp(Operand *Src0, Operand *Src1);
Jan Voung5cd240d2014-06-25 10:36:46 -0700230 // Turn a pointer operand into a memory operand that can be
231 // used by a real load/store operation. Legalizes the operand as well.
232 // This is a nop if the operand is already a legal memory operand.
Jim Stichnoth8e6bf6e2015-06-03 15:58:12 -0700233 OperandX8632Mem *formMemoryOperand(Operand *Ptr, Type Ty,
234 bool DoLegalize = true);
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700235
236 Variable *makeReg(Type Ty, int32_t RegNum = Variable::NoRegister);
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700237 static Type stackSlotType();
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700238
Matt Wala928f1292014-07-07 16:50:46 -0700239 Variable *copyToReg(Operand *Src, int32_t RegNum = Variable::NoRegister);
240
Matt Wala83b80362014-07-16 10:21:30 -0700241 // Returns a vector in a register with the given constant entries.
242 Variable *makeVectorOfZeros(Type Ty, int32_t RegNum = Variable::NoRegister);
243 Variable *makeVectorOfOnes(Type Ty, int32_t RegNum = Variable::NoRegister);
Matt Wala9a0168a2014-07-23 14:56:10 -0700244 Variable *makeVectorOfMinusOnes(Type Ty,
245 int32_t RegNum = Variable::NoRegister);
246 Variable *makeVectorOfHighOrderBits(Type Ty,
247 int32_t RegNum = Variable::NoRegister);
Jim Stichnoth8c980d02015-03-19 13:01:50 -0700248 Variable *makeVectorOfFabsMask(Type Ty,
249 int32_t RegNum = Variable::NoRegister);
Matt Wala83b80362014-07-16 10:21:30 -0700250
Matt Wala49889232014-07-18 12:45:09 -0700251 // Return a memory operand corresponding to a stack allocated Variable.
252 OperandX8632Mem *getMemoryOperandForStackSlot(Type Ty, Variable *Slot,
253 uint32_t Offset = 0);
254
Jim Stichnothe6d24782014-12-19 05:42:24 -0800255 void makeRandomRegisterPermutation(
256 llvm::SmallVectorImpl<int32_t> &Permutation,
Jan Voung3ce1a992015-02-03 08:27:44 -0800257 const llvm::SmallBitVector &ExcludeRegisters) const override;
Jim Stichnothe6d24782014-12-19 05:42:24 -0800258
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700259 // The following are helpers that insert lowered x86 instructions
260 // with minimal syntactic overhead, so that the lowering code can
261 // look as close to assembly as practical.
262 void _adc(Variable *Dest, Operand *Src0) {
263 Context.insert(InstX8632Adc::create(Func, Dest, Src0));
264 }
265 void _add(Variable *Dest, Operand *Src0) {
266 Context.insert(InstX8632Add::create(Func, Dest, Src0));
267 }
Matt Wala105b7042014-08-11 19:56:19 -0700268 void _adjust_stack(int32_t Amount) {
Jim Stichnoth144cdce2014-09-22 16:02:59 -0700269 Context.insert(InstX8632AdjustStack::create(
270 Func, Amount, getPhysicalRegister(RegX8632::Reg_esp)));
Matt Wala105b7042014-08-11 19:56:19 -0700271 }
Matt Wala8d1072e2014-07-11 15:43:51 -0700272 void _addps(Variable *Dest, Operand *Src0) {
273 Context.insert(InstX8632Addps::create(Func, Dest, Src0));
274 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700275 void _addss(Variable *Dest, Operand *Src0) {
276 Context.insert(InstX8632Addss::create(Func, Dest, Src0));
277 }
278 void _and(Variable *Dest, Operand *Src0) {
279 Context.insert(InstX8632And::create(Func, Dest, Src0));
280 }
Matt Wala0a450512014-07-30 12:44:39 -0700281 void _blendvps(Variable *Dest, Operand *Src0, Operand *Src1) {
282 Context.insert(InstX8632Blendvps::create(Func, Dest, Src0, Src1));
283 }
Jan Voungbd385e42014-09-18 18:18:10 -0700284 void _br(CondX86::BrCond Condition, CfgNode *TargetTrue,
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700285 CfgNode *TargetFalse) {
286 Context.insert(
287 InstX8632Br::create(Func, TargetTrue, TargetFalse, Condition));
288 }
289 void _br(CfgNode *Target) {
290 Context.insert(InstX8632Br::create(Func, Target));
291 }
Jan Voungbd385e42014-09-18 18:18:10 -0700292 void _br(CondX86::BrCond Condition, CfgNode *Target) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700293 Context.insert(InstX8632Br::create(Func, Target, Condition));
294 }
Jan Voungbd385e42014-09-18 18:18:10 -0700295 void _br(CondX86::BrCond Condition, InstX8632Label *Label) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700296 Context.insert(InstX8632Br::create(Func, Label, Condition));
297 }
Jan Vounge4da26f2014-07-15 17:52:39 -0700298 void _bsf(Variable *Dest, Operand *Src0) {
299 Context.insert(InstX8632Bsf::create(Func, Dest, Src0));
300 }
301 void _bsr(Variable *Dest, Operand *Src0) {
302 Context.insert(InstX8632Bsr::create(Func, Dest, Src0));
303 }
Jan Voung7fa813b2014-07-18 13:01:08 -0700304 void _bswap(Variable *SrcDest) {
305 Context.insert(InstX8632Bswap::create(Func, SrcDest));
306 }
Matt Walaafeaee42014-08-07 13:47:30 -0700307 void _cbwdq(Variable *Dest, Operand *Src0) {
308 Context.insert(InstX8632Cbwdq::create(Func, Dest, Src0));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700309 }
Jan Voungbd385e42014-09-18 18:18:10 -0700310 void _cmov(Variable *Dest, Operand *Src0, CondX86::BrCond Condition) {
Jan Vounge4da26f2014-07-15 17:52:39 -0700311 Context.insert(InstX8632Cmov::create(Func, Dest, Src0, Condition));
312 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700313 void _cmp(Operand *Src0, Operand *Src1) {
314 Context.insert(InstX8632Icmp::create(Func, Src0, Src1));
315 }
Jan Voungbd385e42014-09-18 18:18:10 -0700316 void _cmpps(Variable *Dest, Operand *Src0, CondX86::CmppsCond Condition) {
Matt Walace0ca8f2014-07-24 12:34:20 -0700317 Context.insert(InstX8632Cmpps::create(Func, Dest, Src0, Condition));
318 }
Jan Vounga3a01a22014-07-14 10:32:41 -0700319 void _cmpxchg(Operand *DestOrAddr, Variable *Eax, Variable *Desired,
320 bool Locked) {
321 Context.insert(
322 InstX8632Cmpxchg::create(Func, DestOrAddr, Eax, Desired, Locked));
323 // Mark eax as possibly modified by cmpxchg.
324 Context.insert(
325 InstFakeDef::create(Func, Eax, llvm::dyn_cast<Variable>(DestOrAddr)));
Jim Stichnoth47752552014-10-13 17:15:08 -0700326 _set_dest_nonkillable();
Jim Stichnoth0e432ac2015-03-24 15:39:16 -0700327 Context.insert(InstFakeUse::create(Func, Eax));
Jan Vounga3a01a22014-07-14 10:32:41 -0700328 }
Jan Voung03532e52014-09-23 13:32:18 -0700329 void _cmpxchg8b(OperandX8632Mem *Addr, Variable *Edx, Variable *Eax,
Jan Vounga3a01a22014-07-14 10:32:41 -0700330 Variable *Ecx, Variable *Ebx, bool Locked) {
331 Context.insert(
332 InstX8632Cmpxchg8b::create(Func, Addr, Edx, Eax, Ecx, Ebx, Locked));
333 // Mark edx, and eax as possibly modified by cmpxchg8b.
334 Context.insert(InstFakeDef::create(Func, Edx));
Jim Stichnoth47752552014-10-13 17:15:08 -0700335 _set_dest_nonkillable();
Jim Stichnoth0e432ac2015-03-24 15:39:16 -0700336 Context.insert(InstFakeUse::create(Func, Edx));
Jan Vounga3a01a22014-07-14 10:32:41 -0700337 Context.insert(InstFakeDef::create(Func, Eax));
Jim Stichnoth47752552014-10-13 17:15:08 -0700338 _set_dest_nonkillable();
Jim Stichnoth0e432ac2015-03-24 15:39:16 -0700339 Context.insert(InstFakeUse::create(Func, Eax));
Jan Vounga3a01a22014-07-14 10:32:41 -0700340 }
Jan Voung699bf022014-10-08 13:52:10 -0700341 void _cvt(Variable *Dest, Operand *Src0, InstX8632Cvt::CvtVariant Variant) {
342 Context.insert(InstX8632Cvt::create(Func, Dest, Src0, Variant));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700343 }
344 void _div(Variable *Dest, Operand *Src0, Operand *Src1) {
345 Context.insert(InstX8632Div::create(Func, Dest, Src0, Src1));
346 }
Matt Wala8d1072e2014-07-11 15:43:51 -0700347 void _divps(Variable *Dest, Operand *Src0) {
348 Context.insert(InstX8632Divps::create(Func, Dest, Src0));
349 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700350 void _divss(Variable *Dest, Operand *Src0) {
351 Context.insert(InstX8632Divss::create(Func, Dest, Src0));
352 }
353 void _fld(Operand *Src0) { Context.insert(InstX8632Fld::create(Func, Src0)); }
354 void _fstp(Variable *Dest) {
355 Context.insert(InstX8632Fstp::create(Func, Dest));
356 }
357 void _idiv(Variable *Dest, Operand *Src0, Operand *Src1) {
358 Context.insert(InstX8632Idiv::create(Func, Dest, Src0, Src1));
359 }
360 void _imul(Variable *Dest, Operand *Src0) {
361 Context.insert(InstX8632Imul::create(Func, Dest, Src0));
362 }
Matt Wala0a450512014-07-30 12:44:39 -0700363 void _insertps(Variable *Dest, Operand *Src0, Operand *Src1) {
364 Context.insert(InstX8632Insertps::create(Func, Dest, Src0, Src1));
365 }
Jim Stichnoth9f42d8c2015-02-20 09:20:14 -0800366 void _jmp(Operand *Target) {
367 Context.insert(InstX8632Jmp::create(Func, Target));
368 }
Matt Wala49889232014-07-18 12:45:09 -0700369 void _lea(Variable *Dest, Operand *Src0) {
370 Context.insert(InstX8632Lea::create(Func, Dest, Src0));
371 }
Jan Voung5cd240d2014-06-25 10:36:46 -0700372 void _mfence() { Context.insert(InstX8632Mfence::create(Func)); }
Jim Stichnothae953202014-12-20 06:17:49 -0800373 // If Dest=nullptr is passed in, then a new variable is created,
374 // marked as infinite register allocation weight, and returned
375 // through the in/out Dest argument.
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700376 void _mov(Variable *&Dest, Operand *Src0,
377 int32_t RegNum = Variable::NoRegister) {
Jim Stichnothae953202014-12-20 06:17:49 -0800378 if (Dest == nullptr)
Jim Stichnothad403532014-09-25 12:44:17 -0700379 Dest = makeReg(Src0->getType(), RegNum);
380 Context.insert(InstX8632Mov::create(Func, Dest, Src0));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700381 }
Jim Stichnoth47752552014-10-13 17:15:08 -0700382 void _mov_nonkillable(Variable *Dest, Operand *Src0) {
383 Inst *NewInst = InstX8632Mov::create(Func, Dest, Src0);
384 NewInst->setDestNonKillable();
385 Context.insert(NewInst);
386 }
Matt Wala49889232014-07-18 12:45:09 -0700387 void _movd(Variable *Dest, Operand *Src0) {
388 Context.insert(InstX8632Movd::create(Func, Dest, Src0));
389 }
Matt Wala928f1292014-07-07 16:50:46 -0700390 void _movp(Variable *Dest, Operand *Src0) {
391 Context.insert(InstX8632Movp::create(Func, Dest, Src0));
392 }
Jan Voung5cd240d2014-06-25 10:36:46 -0700393 void _movq(Variable *Dest, Operand *Src0) {
394 Context.insert(InstX8632Movq::create(Func, Dest, Src0));
395 }
Jan Vounge4dc61b2014-10-06 08:53:52 -0700396 void _movss(Variable *Dest, Variable *Src0) {
397 Context.insert(InstX8632MovssRegs::create(Func, Dest, Src0));
Matt Wala49889232014-07-18 12:45:09 -0700398 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700399 void _movsx(Variable *Dest, Operand *Src0) {
400 Context.insert(InstX8632Movsx::create(Func, Dest, Src0));
401 }
402 void _movzx(Variable *Dest, Operand *Src0) {
403 Context.insert(InstX8632Movzx::create(Func, Dest, Src0));
404 }
405 void _mul(Variable *Dest, Variable *Src0, Operand *Src1) {
406 Context.insert(InstX8632Mul::create(Func, Dest, Src0, Src1));
407 }
Matt Wala8d1072e2014-07-11 15:43:51 -0700408 void _mulps(Variable *Dest, Operand *Src0) {
409 Context.insert(InstX8632Mulps::create(Func, Dest, Src0));
410 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700411 void _mulss(Variable *Dest, Operand *Src0) {
412 Context.insert(InstX8632Mulss::create(Func, Dest, Src0));
413 }
Jan Vounga3a01a22014-07-14 10:32:41 -0700414 void _neg(Variable *SrcDest) {
415 Context.insert(InstX8632Neg::create(Func, SrcDest));
416 }
Matt Walac3302742014-08-15 16:21:56 -0700417 void _nop(SizeT Variant) {
418 Context.insert(InstX8632Nop::create(Func, Variant));
419 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700420 void _or(Variable *Dest, Operand *Src0) {
421 Context.insert(InstX8632Or::create(Func, Dest, Src0));
422 }
Matt Wala7fa22d82014-07-17 12:41:31 -0700423 void _padd(Variable *Dest, Operand *Src0) {
424 Context.insert(InstX8632Padd::create(Func, Dest, Src0));
425 }
Matt Wala83b80362014-07-16 10:21:30 -0700426 void _pand(Variable *Dest, Operand *Src0) {
427 Context.insert(InstX8632Pand::create(Func, Dest, Src0));
428 }
Matt Wala9cb61e22014-07-24 09:44:42 -0700429 void _pandn(Variable *Dest, Operand *Src0) {
430 Context.insert(InstX8632Pandn::create(Func, Dest, Src0));
431 }
Matt Wala0a450512014-07-30 12:44:39 -0700432 void _pblendvb(Variable *Dest, Operand *Src0, Operand *Src1) {
433 Context.insert(InstX8632Pblendvb::create(Func, Dest, Src0, Src1));
434 }
Matt Wala83b80362014-07-16 10:21:30 -0700435 void _pcmpeq(Variable *Dest, Operand *Src0) {
436 Context.insert(InstX8632Pcmpeq::create(Func, Dest, Src0));
437 }
438 void _pcmpgt(Variable *Dest, Operand *Src0) {
439 Context.insert(InstX8632Pcmpgt::create(Func, Dest, Src0));
440 }
Matt Wala0a450512014-07-30 12:44:39 -0700441 void _pextr(Variable *Dest, Operand *Src0, Operand *Src1) {
442 Context.insert(InstX8632Pextr::create(Func, Dest, Src0, Src1));
Matt Wala49889232014-07-18 12:45:09 -0700443 }
Matt Wala0a450512014-07-30 12:44:39 -0700444 void _pinsr(Variable *Dest, Operand *Src0, Operand *Src1) {
445 Context.insert(InstX8632Pinsr::create(Func, Dest, Src0, Src1));
Matt Wala49889232014-07-18 12:45:09 -0700446 }
Matt Wala0a450512014-07-30 12:44:39 -0700447 void _pmull(Variable *Dest, Operand *Src0) {
448 Context.insert(InstX8632Pmull::create(Func, Dest, Src0));
Matt Wala7fa22d82014-07-17 12:41:31 -0700449 }
450 void _pmuludq(Variable *Dest, Operand *Src0) {
451 Context.insert(InstX8632Pmuludq::create(Func, Dest, Src0));
452 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700453 void _pop(Variable *Dest) {
454 Context.insert(InstX8632Pop::create(Func, Dest));
455 }
Matt Wala7fa22d82014-07-17 12:41:31 -0700456 void _por(Variable *Dest, Operand *Src0) {
457 Context.insert(InstX8632Por::create(Func, Dest, Src0));
458 }
459 void _pshufd(Variable *Dest, Operand *Src0, Operand *Src1) {
460 Context.insert(InstX8632Pshufd::create(Func, Dest, Src0, Src1));
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700461 }
Matt Wala83b80362014-07-16 10:21:30 -0700462 void _psll(Variable *Dest, Operand *Src0) {
463 Context.insert(InstX8632Psll::create(Func, Dest, Src0));
464 }
465 void _psra(Variable *Dest, Operand *Src0) {
466 Context.insert(InstX8632Psra::create(Func, Dest, Src0));
467 }
Jim Stichnoth8c980d02015-03-19 13:01:50 -0700468 void _psrl(Variable *Dest, Operand *Src0) {
469 Context.insert(InstX8632Psrl::create(Func, Dest, Src0));
470 }
Matt Wala83b80362014-07-16 10:21:30 -0700471 void _psub(Variable *Dest, Operand *Src0) {
472 Context.insert(InstX8632Psub::create(Func, Dest, Src0));
473 }
Jan Voung0b9eee52014-10-07 11:20:10 -0700474 void _push(Variable *Src0) {
475 Context.insert(InstX8632Push::create(Func, Src0));
Matt Wala7fa22d82014-07-17 12:41:31 -0700476 }
Matt Wala8d1072e2014-07-11 15:43:51 -0700477 void _pxor(Variable *Dest, Operand *Src0) {
478 Context.insert(InstX8632Pxor::create(Func, Dest, Src0));
479 }
Jim Stichnothae953202014-12-20 06:17:49 -0800480 void _ret(Variable *Src0 = nullptr) {
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700481 Context.insert(InstX8632Ret::create(Func, Src0));
482 }
Jan Voung7fa813b2014-07-18 13:01:08 -0700483 void _rol(Variable *Dest, Operand *Src0) {
484 Context.insert(InstX8632Rol::create(Func, Dest, Src0));
485 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700486 void _sar(Variable *Dest, Operand *Src0) {
487 Context.insert(InstX8632Sar::create(Func, Dest, Src0));
488 }
489 void _sbb(Variable *Dest, Operand *Src0) {
490 Context.insert(InstX8632Sbb::create(Func, Dest, Src0));
491 }
Jim Stichnothf48b3202015-05-04 10:22:17 -0700492 void _setcc(Variable *Dest, CondX86::BrCond Condition) {
493 Context.insert(InstX8632Setcc::create(Func, Dest, Condition));
494 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700495 void _shl(Variable *Dest, Operand *Src0) {
496 Context.insert(InstX8632Shl::create(Func, Dest, Src0));
497 }
498 void _shld(Variable *Dest, Variable *Src0, Variable *Src1) {
499 Context.insert(InstX8632Shld::create(Func, Dest, Src0, Src1));
500 }
501 void _shr(Variable *Dest, Operand *Src0) {
502 Context.insert(InstX8632Shr::create(Func, Dest, Src0));
503 }
504 void _shrd(Variable *Dest, Variable *Src0, Variable *Src1) {
505 Context.insert(InstX8632Shrd::create(Func, Dest, Src0, Src1));
506 }
Matt Wala7fa22d82014-07-17 12:41:31 -0700507 void _shufps(Variable *Dest, Operand *Src0, Operand *Src1) {
508 Context.insert(InstX8632Shufps::create(Func, Dest, Src0, Src1));
509 }
Jan Voungf37fbbe2014-07-09 16:13:13 -0700510 void _sqrtss(Variable *Dest, Operand *Src0) {
511 Context.insert(InstX8632Sqrtss::create(Func, Dest, Src0));
512 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700513 void _store(Operand *Value, OperandX8632 *Mem) {
514 Context.insert(InstX8632Store::create(Func, Value, Mem));
515 }
Jan Vounge4dc61b2014-10-06 08:53:52 -0700516 void _storep(Variable *Value, OperandX8632Mem *Mem) {
Matt Wala105b7042014-08-11 19:56:19 -0700517 Context.insert(InstX8632StoreP::create(Func, Value, Mem));
518 }
Jan Vounge4dc61b2014-10-06 08:53:52 -0700519 void _storeq(Variable *Value, OperandX8632Mem *Mem) {
Jan Voung5cd240d2014-06-25 10:36:46 -0700520 Context.insert(InstX8632StoreQ::create(Func, Value, Mem));
521 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700522 void _sub(Variable *Dest, Operand *Src0) {
523 Context.insert(InstX8632Sub::create(Func, Dest, Src0));
524 }
Matt Wala8d1072e2014-07-11 15:43:51 -0700525 void _subps(Variable *Dest, Operand *Src0) {
526 Context.insert(InstX8632Subps::create(Func, Dest, Src0));
527 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700528 void _subss(Variable *Dest, Operand *Src0) {
529 Context.insert(InstX8632Subss::create(Func, Dest, Src0));
530 }
531 void _test(Operand *Src0, Operand *Src1) {
532 Context.insert(InstX8632Test::create(Func, Src0, Src1));
533 }
534 void _ucomiss(Operand *Src0, Operand *Src1) {
535 Context.insert(InstX8632Ucomiss::create(Func, Src0, Src1));
536 }
Jan Voung3bd9f1a2014-06-18 10:50:57 -0700537 void _ud2() { Context.insert(InstX8632UD2::create(Func)); }
Jan Voung5cd240d2014-06-25 10:36:46 -0700538 void _xadd(Operand *Dest, Variable *Src, bool Locked) {
539 Context.insert(InstX8632Xadd::create(Func, Dest, Src, Locked));
540 // The xadd exchanges Dest and Src (modifying Src).
Jim Stichnoth0e432ac2015-03-24 15:39:16 -0700541 // Model that update with a FakeDef followed by a FakeUse.
Jan Vounga3a01a22014-07-14 10:32:41 -0700542 Context.insert(
543 InstFakeDef::create(Func, Src, llvm::dyn_cast<Variable>(Dest)));
Jim Stichnoth47752552014-10-13 17:15:08 -0700544 _set_dest_nonkillable();
Jim Stichnoth0e432ac2015-03-24 15:39:16 -0700545 Context.insert(InstFakeUse::create(Func, Src));
Jan Vounga3a01a22014-07-14 10:32:41 -0700546 }
547 void _xchg(Operand *Dest, Variable *Src) {
548 Context.insert(InstX8632Xchg::create(Func, Dest, Src));
Jim Stichnoth0e432ac2015-03-24 15:39:16 -0700549 // The xchg modifies Dest and Src -- model that update with a
550 // FakeDef/FakeUse.
Jan Vounga3a01a22014-07-14 10:32:41 -0700551 Context.insert(
552 InstFakeDef::create(Func, Src, llvm::dyn_cast<Variable>(Dest)));
Jim Stichnoth47752552014-10-13 17:15:08 -0700553 _set_dest_nonkillable();
Jim Stichnoth0e432ac2015-03-24 15:39:16 -0700554 Context.insert(InstFakeUse::create(Func, Src));
Jan Voung5cd240d2014-06-25 10:36:46 -0700555 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700556 void _xor(Variable *Dest, Operand *Src0) {
557 Context.insert(InstX8632Xor::create(Func, Dest, Src0));
558 }
Jim Stichnoth47752552014-10-13 17:15:08 -0700559 void _set_dest_nonkillable() {
560 Context.getLastInserted()->setDestNonKillable();
561 }
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700562
Jim Stichnoth0933c0c2015-06-12 10:41:16 -0700563 bool optimizeScalarMul(Variable *Dest, Operand *Src0, int32_t Src1);
564
Matt Wala0a450512014-07-30 12:44:39 -0700565 const X86InstructionSet InstructionSet;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700566 bool IsEbpBasedFrame;
Matt Wala105b7042014-08-11 19:56:19 -0700567 bool NeedsStackAlignment;
Matt Walad4799f42014-08-14 14:24:12 -0700568 size_t SpillAreaSizeBytes;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700569 llvm::SmallBitVector TypeToRegisterSet[IceType_NUM];
570 llvm::SmallBitVector ScratchRegs;
571 llvm::SmallBitVector RegsUsed;
Jim Stichnoth336f6c42014-10-30 15:01:31 -0700572 VarList PhysicalRegisters[IceType_NUM];
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700573 static IceString RegNames[];
574
575private:
Jim Stichnothb56c8f42014-09-26 09:28:46 -0700576 ~TargetX8632() override {}
Jim Stichnotha59ae6f2015-05-17 10:11:41 -0700577 BoolFolding FoldingInfo;
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700578};
579
John Porto0f86d032015-06-15 07:44:27 -0700580class TargetDataX8632 final : public TargetDataLowering {
Jan Voung72984d82015-01-29 14:42:38 -0800581 TargetDataX8632() = delete;
582 TargetDataX8632(const TargetDataX8632 &) = delete;
583 TargetDataX8632 &operator=(const TargetDataX8632 &) = delete;
Jim Stichnoth7b451a92014-10-15 14:39:23 -0700584
Jim Stichnothde4ca712014-06-29 08:13:48 -0700585public:
Jan Voungfb792842015-06-11 15:27:50 -0700586 static std::unique_ptr<TargetDataLowering> create(GlobalContext *Ctx) {
587 return std::unique_ptr<TargetDataLowering>(new TargetDataX8632(Ctx));
Jim Stichnothde4ca712014-06-29 08:13:48 -0700588 }
Karl Schimpfe3f64d02014-10-07 10:38:22 -0700589
John Porto0f86d032015-06-15 07:44:27 -0700590 void lowerGlobals(std::unique_ptr<VariableDeclarationList> Vars) override;
591 void lowerConstants() override;
Jim Stichnothde4ca712014-06-29 08:13:48 -0700592
593protected:
Jim Stichnothc6ead202015-02-24 09:30:30 -0800594 explicit TargetDataX8632(GlobalContext *Ctx);
Jim Stichnothde4ca712014-06-29 08:13:48 -0700595
596private:
John Porto0f86d032015-06-15 07:44:27 -0700597 void lowerGlobal(const VariableDeclaration &Var);
Jan Voung72984d82015-01-29 14:42:38 -0800598 ~TargetDataX8632() override {}
Jim Stichnothfa4efea2015-01-27 05:06:03 -0800599 template <typename T> static void emitConstantPool(GlobalContext *Ctx);
Jim Stichnothde4ca712014-06-29 08:13:48 -0700600};
601
Jan Voungfb792842015-06-11 15:27:50 -0700602class TargetHeaderX8632 final : public TargetHeaderLowering {
603 TargetHeaderX8632() = delete;
604 TargetHeaderX8632(const TargetHeaderX8632 &) = delete;
605 TargetHeaderX8632 &operator=(const TargetHeaderX8632 &) = delete;
606
607public:
608 static std::unique_ptr<TargetHeaderLowering> create(GlobalContext *Ctx) {
609 return std::unique_ptr<TargetHeaderLowering>(new TargetHeaderX8632(Ctx));
610 }
611
612protected:
613 explicit TargetHeaderX8632(GlobalContext *Ctx);
614
615private:
616 ~TargetHeaderX8632() = default;
617};
618
Jim Stichnoth5bc2b1d2014-05-22 13:38:48 -0700619} // end of namespace Ice
620
621#endif // SUBZERO_SRC_ICETARGETLOWERINGX8632_H