Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(587)

Side by Side Diff: src/IceTargetLoweringX8632Traits.h

Issue 1216933015: X8632 Templatization completed. (Closed) Base URL: https://chromium.googlesource.com/native_client/pnacl-subzero.git@master
Patch Set: Addresses comments. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/IceTargetLoweringX8632.cpp ('k') | src/IceTargetLoweringX86Base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 //===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- C++ -*-=// 1 //===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- 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 defines the X8632 Target Lowering Traits. 10 /// \file
11 // 11 /// This file declares the X8632 Target Lowering Traits.
12 ///
12 //===----------------------------------------------------------------------===// 13 //===----------------------------------------------------------------------===//
13 14
14 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 15 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
15 #define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 16 #define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
16 17
17 #include "IceAssembler.h" 18 #include "IceAssembler.h"
18 #include "IceConditionCodesX8632.h" 19 #include "IceConditionCodesX8632.h"
19 #include "IceDefs.h" 20 #include "IceDefs.h"
20 #include "IceInst.h" 21 #include "IceInst.h"
21 #include "IceInstX8632.def" 22 #include "IceInstX8632.def"
23 #include "IceOperand.h"
22 #include "IceRegistersX8632.h" 24 #include "IceRegistersX8632.h"
23 #include "IceTargetLoweringX8632.def" 25 #include "IceTargetLoweringX8632.def"
26 #include "IceTargetLowering.h"
24 27
25 namespace Ice { 28 namespace Ice {
26 29
27 class TargetX8632; 30 class TargetX8632;
28 31
32 namespace X8632 {
33 class AssemblerX8632;
34 } // end of namespace X8632
35
29 namespace X86Internal { 36 namespace X86Internal {
30 37
38 template <class Machine> struct Insts;
31 template <class Machine> struct MachineTraits; 39 template <class Machine> struct MachineTraits;
32 40
33 template <> struct MachineTraits<TargetX8632> { 41 template <> struct MachineTraits<TargetX8632> {
34 //---------------------------------------------------------------------------- 42 //----------------------------------------------------------------------------
35 // ______ ______ __ __ 43 // ______ ______ __ __
36 // /\ __ \/\ ___\/\ "-./ \ 44 // /\ __ \/\ ___\/\ "-./ \
37 // \ \ __ \ \___ \ \ \-./\ \ 45 // \ \ __ \ \___ \ \ \-./\ \
38 // \ \_\ \_\/\_____\ \_\ \ \_\ 46 // \ \_\ \_\/\_____\ \_\ \ \_\
39 // \/_/\/_/\/_____/\/_/ \/_/ 47 // \/_/\/_/\/_____/\/_/ \/_/
40 // 48 //
41 //---------------------------------------------------------------------------- 49 //----------------------------------------------------------------------------
42 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; 50 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
43 51
44 using GPRRegister = ::Ice::RegX8632::GPRRegister; 52 using GPRRegister = ::Ice::RegX8632::GPRRegister;
45 using XmmRegister = ::Ice::RegX8632::XmmRegister; 53 using XmmRegister = ::Ice::RegX8632::XmmRegister;
46 using ByteRegister = ::Ice::RegX8632::ByteRegister; 54 using ByteRegister = ::Ice::RegX8632::ByteRegister;
47 using X87STRegister = ::Ice::RegX8632::X87STRegister; 55 using X87STRegister = ::Ice::RegX8632::X87STRegister;
48 56
49 using Cond = ::Ice::CondX86; 57 using Cond = ::Ice::CondX86;
50 58
51 using RegisterSet = ::Ice::RegX8632; 59 using RegisterSet = ::Ice::RegX8632;
52 static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax; 60 static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax;
53 static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx; 61 static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
54 static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32; 62 static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32;
55 63
56 class Operand { 64 class Operand {
57 public: 65 public:
58 Operand(const Operand &other) 66 Operand(const Operand &other)
59 : length_(other.length_), fixup_(other.fixup_) { 67 : fixup_(other.fixup_), length_(other.length_) {
60 memmove(&encoding_[0], &other.encoding_[0], other.length_); 68 memmove(&encoding_[0], &other.encoding_[0], other.length_);
61 } 69 }
62 70
63 Operand &operator=(const Operand &other) { 71 Operand &operator=(const Operand &other) {
64 length_ = other.length_; 72 length_ = other.length_;
65 fixup_ = other.fixup_; 73 fixup_ = other.fixup_;
66 memmove(&encoding_[0], &other.encoding_[0], other.length_); 74 memmove(&encoding_[0], &other.encoding_[0], other.length_);
67 return *this; 75 return *this;
68 } 76 }
69 77
(...skipping 21 matching lines...) Expand all
91 } 99 }
92 100
93 int32_t disp32() const { 101 int32_t disp32() const {
94 assert(length_ >= 5); 102 assert(length_ >= 5);
95 return bit_copy<int32_t>(encoding_[length_ - 4]); 103 return bit_copy<int32_t>(encoding_[length_ - 4]);
96 } 104 }
97 105
98 AssemblerFixup *fixup() const { return fixup_; } 106 AssemblerFixup *fixup() const { return fixup_; }
99 107
100 protected: 108 protected:
101 Operand() : length_(0), fixup_(nullptr) {} // Needed by subclass Address. 109 Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address.
102 110
103 void SetModRM(int mod, GPRRegister rm) { 111 void SetModRM(int mod, GPRRegister rm) {
104 assert((mod & ~3) == 0); 112 assert((mod & ~3) == 0);
105 encoding_[0] = (mod << 6) | rm; 113 encoding_[0] = (mod << 6) | rm;
106 length_ = 1; 114 length_ = 1;
107 } 115 }
108 116
109 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { 117 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
110 assert(length_ == 1); 118 assert(length_ == 1);
111 assert((scale & ~3) == 0); 119 assert((scale & ~3) == 0);
112 encoding_[1] = (scale << 6) | (index << 3) | base; 120 encoding_[1] = (scale << 6) | (index << 3) | base;
113 length_ = 2; 121 length_ = 2;
114 } 122 }
115 123
116 void SetDisp8(int8_t disp) { 124 void SetDisp8(int8_t disp) {
117 assert(length_ == 1 || length_ == 2); 125 assert(length_ == 1 || length_ == 2);
118 encoding_[length_++] = static_cast<uint8_t>(disp); 126 encoding_[length_++] = static_cast<uint8_t>(disp);
119 } 127 }
120 128
121 void SetDisp32(int32_t disp) { 129 void SetDisp32(int32_t disp) {
122 assert(length_ == 1 || length_ == 2); 130 assert(length_ == 1 || length_ == 2);
123 intptr_t disp_size = sizeof(disp); 131 intptr_t disp_size = sizeof(disp);
124 memmove(&encoding_[length_], &disp, disp_size); 132 memmove(&encoding_[length_], &disp, disp_size);
125 length_ += disp_size; 133 length_ += disp_size;
126 } 134 }
127 135
128 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } 136 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
129 137
130 private: 138 private:
139 AssemblerFixup *fixup_;
140 uint8_t encoding_[6];
131 uint8_t length_; 141 uint8_t length_;
132 uint8_t encoding_[6];
133 AssemblerFixup *fixup_;
134 142
135 explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); } 143 explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
136 144
137 // Get the operand encoding byte at the given index. 145 /// Get the operand encoding byte at the given index.
138 uint8_t encoding_at(intptr_t index) const { 146 uint8_t encoding_at(intptr_t index) const {
139 assert(index >= 0 && index < length_); 147 assert(index >= 0 && index < length_);
140 return encoding_[index]; 148 return encoding_[index];
141 } 149 }
142 150
143 // Returns whether or not this operand is really the given register in 151 /// Returns whether or not this operand is really the given register in
144 // disguise. Used from the assembler to generate better encodings. 152 /// disguise. Used from the assembler to generate better encodings.
145 bool IsRegister(GPRRegister reg) const { 153 bool IsRegister(GPRRegister reg) const {
146 return ((encoding_[0] & 0xF8) == 154 return ((encoding_[0] & 0xF8) ==
147 0xC0) // Addressing mode is register only. 155 0xC0) // Addressing mode is register only.
148 && 156 &&
149 ((encoding_[0] & 0x07) == reg); // Register codes match. 157 ((encoding_[0] & 0x07) == reg); // Register codes match.
150 } 158 }
151 159
152 template <class> friend class AssemblerX86Base; 160 template <class> friend class AssemblerX86Base;
153 }; 161 };
154 162
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 SetModRM(1, RegX8632::Encoded_Reg_esp); 206 SetModRM(1, RegX8632::Encoded_Reg_esp);
199 SetSIB(scale, index, base); 207 SetSIB(scale, index, base);
200 SetDisp8(disp); 208 SetDisp8(disp);
201 } else { 209 } else {
202 SetModRM(2, RegX8632::Encoded_Reg_esp); 210 SetModRM(2, RegX8632::Encoded_Reg_esp);
203 SetSIB(scale, index, base); 211 SetSIB(scale, index, base);
204 SetDisp32(disp); 212 SetDisp32(disp);
205 } 213 }
206 } 214 }
207 215
208 // AbsoluteTag is a special tag used by clients to create an absolute 216 /// AbsoluteTag is a special tag used by clients to create an absolute
209 // Address. 217 /// Address.
210 enum AbsoluteTag { ABSOLUTE }; 218 enum AbsoluteTag { ABSOLUTE };
211 219
212 Address(AbsoluteTag, const uintptr_t Addr) { 220 Address(AbsoluteTag, const uintptr_t Addr) {
213 SetModRM(0, RegX8632::Encoded_Reg_ebp); 221 SetModRM(0, RegX8632::Encoded_Reg_ebp);
214 SetDisp32(Addr); 222 SetDisp32(Addr);
215 } 223 }
216 224
217 // TODO(jpp): remove this. 225 // TODO(jpp): remove this.
218 static Address Absolute(const uintptr_t Addr) { 226 static Address Absolute(const uintptr_t Addr) {
219 return Address(ABSOLUTE, Addr); 227 return Address(ABSOLUTE, Addr);
(...skipping 28 matching lines...) Expand all
248 // 256 //
249 //---------------------------------------------------------------------------- 257 //----------------------------------------------------------------------------
250 enum InstructionSet { 258 enum InstructionSet {
251 Begin, 259 Begin,
252 // SSE2 is the PNaCl baseline instruction set. 260 // SSE2 is the PNaCl baseline instruction set.
253 SSE2 = Begin, 261 SSE2 = Begin,
254 SSE4_1, 262 SSE4_1,
255 End 263 End
256 }; 264 };
257 265
258 // The maximum number of arguments to pass in XMM registers 266 static const char *TargetName;
267
268 static IceString getRegName(SizeT RegNum, Type Ty) {
269 assert(RegNum < RegisterSet::Reg_NUM);
270 static const char *RegNames8[] = {
271 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
272 frameptr, isI8, isInt, isFP) \
273 name8,
274 REGX8632_TABLE
275 #undef X
276 };
277
278 static const char *RegNames16[] = {
279 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
280 frameptr, isI8, isInt, isFP) \
281 name16,
282 REGX8632_TABLE
283 #undef X
284 };
285
286 static const char *RegNames[] = {
287 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
288 frameptr, isI8, isInt, isFP) \
289 name,
290 REGX8632_TABLE
291 #undef X
292 };
293
294 switch (Ty) {
295 case IceType_i1:
296 case IceType_i8:
297 return RegNames8[RegNum];
298 case IceType_i16:
299 return RegNames16[RegNum];
300 default:
301 return RegNames[RegNum];
302 }
303 }
304
305 static void initRegisterSet(llvm::SmallBitVector *IntegerRegisters,
306 llvm::SmallBitVector *IntegerRegistersI8,
307 llvm::SmallBitVector *FloatRegisters,
308 llvm::SmallBitVector *VectorRegisters,
309 llvm::SmallBitVector *ScratchRegs) {
310 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
311 frameptr, isI8, isInt, isFP) \
312 (*IntegerRegisters)[RegisterSet::val] = isInt; \
313 (*IntegerRegistersI8)[RegisterSet::val] = isI8; \
314 (*FloatRegisters)[RegisterSet::val] = isFP; \
315 (*VectorRegisters)[RegisterSet::val] = isFP; \
316 (*ScratchRegs)[RegisterSet::val] = scratch;
317 REGX8632_TABLE;
318 #undef X
319 }
320
321 static llvm::SmallBitVector
322 getRegisterSet(TargetLowering::RegSetMask Include,
323 TargetLowering::RegSetMask Exclude) {
324 llvm::SmallBitVector Registers(RegisterSet::Reg_NUM);
325
326 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
327 frameptr, isI8, isInt, isFP) \
328 if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \
329 Registers[RegisterSet::val] = true; \
330 if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \
331 Registers[RegisterSet::val] = true; \
332 if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \
333 Registers[RegisterSet::val] = true; \
334 if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \
335 Registers[RegisterSet::val] = true; \
336 if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \
337 Registers[RegisterSet::val] = false; \
338 if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \
339 Registers[RegisterSet::val] = false; \
340 if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \
341 Registers[RegisterSet::val] = false; \
342 if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \
343 Registers[RegisterSet::val] = false;
344
345 REGX8632_TABLE
346
347 #undef X
348
349 return Registers;
350 }
351
352 static void
353 makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func,
354 llvm::SmallVectorImpl<int32_t> &Permutation,
355 const llvm::SmallBitVector &ExcludeRegisters) {
356 // TODO(stichnot): Declaring Permutation this way loses type/size
357 // information. Fix this in conjunction with the caller-side TODO.
358 assert(Permutation.size() >= RegisterSet::Reg_NUM);
359 // Expected upper bound on the number of registers in a single equivalence
360 // class. For x86-32, this would comprise the 8 XMM registers. This is for
361 // performance, not correctness.
362 static const unsigned MaxEquivalenceClassSize = 8;
363 typedef llvm::SmallVector<int32_t, MaxEquivalenceClassSize> RegisterList;
364 typedef std::map<uint32_t, RegisterList> EquivalenceClassMap;
365 EquivalenceClassMap EquivalenceClasses;
366 SizeT NumShuffled = 0, NumPreserved = 0;
367
368 // Build up the equivalence classes of registers by looking at the register
369 // properties as well as whether the registers should be explicitly excluded
370 // from shuffling.
371 #define X(val, encode, name, name16, name8, scratch, preserved, stackptr, \
372 frameptr, isI8, isInt, isFP) \
373 if (ExcludeRegisters[RegisterSet::val]) { \
374 /* val stays the same in the resulting permutation. */ \
375 Permutation[RegisterSet::val] = RegisterSet::val; \
376 ++NumPreserved; \
377 } else { \
378 const uint32_t Index = (scratch << 0) | (preserved << 1) | (isI8 << 2) | \
379 (isInt << 3) | (isFP << 4); \
380 /* val is assigned to an equivalence class based on its properties. */ \
381 EquivalenceClasses[Index].push_back(RegisterSet::val); \
382 }
383 REGX8632_TABLE
384 #undef X
385
386 RandomNumberGeneratorWrapper RNG(Ctx->getRNG());
387
388 // Shuffle the resulting equivalence classes.
389 for (auto I : EquivalenceClasses) {
390 const RegisterList &List = I.second;
391 RegisterList Shuffled(List);
392 RandomShuffle(Shuffled.begin(), Shuffled.end(), RNG);
393 for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
394 Permutation[List[SI]] = Shuffled[SI];
395 ++NumShuffled;
396 }
397 }
398
399 assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM);
400
401 if (Func->isVerbose(IceV_Random)) {
402 OstreamLocker L(Func->getContext());
403 Ostream &Str = Func->getContext()->getStrDump();
404 Str << "Register equivalence classes:\n";
405 for (auto I : EquivalenceClasses) {
406 Str << "{";
407 const RegisterList &List = I.second;
408 bool First = true;
409 for (int32_t Register : List) {
410 if (!First)
411 Str << " ";
412 First = false;
413 Str << getRegName(Register, IceType_i32);
414 }
415 Str << "}\n";
416 }
417 }
418 }
419
420 /// The maximum number of arguments to pass in XMM registers
259 static const uint32_t X86_MAX_XMM_ARGS = 4; 421 static const uint32_t X86_MAX_XMM_ARGS = 4;
260 // The number of bits in a byte 422 /// The number of bits in a byte
261 static const uint32_t X86_CHAR_BIT = 8; 423 static const uint32_t X86_CHAR_BIT = 8;
262 // Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it 424 /// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it
263 // is used as an argument to std::max(), and the default std::less<T> has an 425 /// is used as an argument to std::max(), and the default std::less<T> has an
264 // operator(T const&, T const&) which requires this member to have an address. 426 /// operator(T const&, T const&) which requires this member to have an
427 /// address.
265 static const uint32_t X86_STACK_ALIGNMENT_BYTES; 428 static const uint32_t X86_STACK_ALIGNMENT_BYTES;
266 // Size of the return address on the stack 429 /// Size of the return address on the stack
267 static const uint32_t X86_RET_IP_SIZE_BYTES = 4; 430 static const uint32_t X86_RET_IP_SIZE_BYTES = 4;
268 // The number of different NOP instructions 431 /// The number of different NOP instructions
269 static const uint32_t X86_NUM_NOP_VARIANTS = 5; 432 static const uint32_t X86_NUM_NOP_VARIANTS = 5;
270 433
271 // Value is in bytes. Return Value adjusted to the next highest multiple 434 /// Value is in bytes. Return Value adjusted to the next highest multiple
272 // of the stack alignment. 435 /// of the stack alignment.
273 static uint32_t applyStackAlignment(uint32_t Value) { 436 static uint32_t applyStackAlignment(uint32_t Value) {
274 return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); 437 return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
275 } 438 }
276 439
277 // Return the type which the elements of the vector have in the X86 440 /// Return the type which the elements of the vector have in the X86
278 // representation of the vector. 441 /// representation of the vector.
279 static Type getInVectorElementType(Type Ty) { 442 static Type getInVectorElementType(Type Ty) {
280 assert(isVectorType(Ty)); 443 assert(isVectorType(Ty));
281 size_t Index = static_cast<size_t>(Ty); 444 size_t Index = static_cast<size_t>(Ty);
282 (void)Index; 445 (void)Index;
283 assert(Index < TableTypeX8632AttributesSize); 446 assert(Index < TableTypeX8632AttributesSize);
284 return TableTypeX8632Attributes[Ty].InVectorElementType; 447 return TableTypeX8632Attributes[Ty].InVectorElementType;
285 } 448 }
286 449
287 // Note: The following data structures are defined in 450 // Note: The following data structures are defined in
288 // IceTargetLoweringX8632.cpp. 451 // IceTargetLoweringX8632.cpp.
289 452
290 // The following table summarizes the logic for lowering the fcmp 453 /// The following table summarizes the logic for lowering the fcmp
291 // instruction. There is one table entry for each of the 16 conditions. 454 /// instruction. There is one table entry for each of the 16 conditions.
292 // 455 ///
293 // The first four columns describe the case when the operands are 456 /// The first four columns describe the case when the operands are floating
294 // floating point scalar values. A comment in lowerFcmp() describes the 457 /// point scalar values. A comment in lowerFcmp() describes the lowering
295 // lowering template. In the most general case, there is a compare 458 /// template. In the most general case, there is a compare followed by two
296 // followed by two conditional branches, because some fcmp conditions 459 /// conditional branches, because some fcmp conditions don't map to a single
297 // don't map to a single x86 conditional branch. However, in many cases 460 /// x86 conditional branch. However, in many cases it is possible to swap the
298 // it is possible to swap the operands in the comparison and have a 461 /// operands in the comparison and have a single conditional branch. Since
299 // single conditional branch. Since it's quite tedious to validate the 462 /// it's quite tedious to validate the table by hand, good execution tests are
300 // table by hand, good execution tests are helpful. 463 /// helpful.
301 // 464 ///
302 // The last two columns describe the case when the operands are vectors 465 /// The last two columns describe the case when the operands are vectors of
303 // of floating point values. For most fcmp conditions, there is a clear 466 /// floating point values. For most fcmp conditions, there is a clear mapping
304 // mapping to a single x86 cmpps instruction variant. Some fcmp 467 /// to a single x86 cmpps instruction variant. Some fcmp conditions require
305 // conditions require special code to handle and these are marked in the 468 /// special code to handle and these are marked in the table with a
306 // table with a Cmpps_Invalid predicate. 469 /// Cmpps_Invalid predicate.
470 /// {@
307 static const struct TableFcmpType { 471 static const struct TableFcmpType {
308 uint32_t Default; 472 uint32_t Default;
309 bool SwapScalarOperands; 473 bool SwapScalarOperands;
310 CondX86::BrCond C1, C2; 474 Cond::BrCond C1, C2;
311 bool SwapVectorOperands; 475 bool SwapVectorOperands;
312 CondX86::CmppsCond Predicate; 476 Cond::CmppsCond Predicate;
313 } TableFcmp[]; 477 } TableFcmp[];
314 static const size_t TableFcmpSize; 478 static const size_t TableFcmpSize;
479 /// @}
315 480
316 // The following table summarizes the logic for lowering the icmp instruction 481 /// The following table summarizes the logic for lowering the icmp instruction
317 // for i32 and narrower types. Each icmp condition has a clear mapping to an 482 /// for i32 and narrower types. Each icmp condition has a clear mapping to an
318 // x86 conditional branch instruction. 483 /// x86 conditional branch instruction.
484 /// {@
485 static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[];
486 static const size_t TableIcmp32Size;
487 /// @}
319 488
320 static const struct TableIcmp32Type { 489 /// The following table summarizes the logic for lowering the icmp instruction
321 CondX86::BrCond Mapping; 490 /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
322 } TableIcmp32[]; 491 /// conditional branches are needed. For the other conditions, three separate
323 static const size_t TableIcmp32Size; 492 /// conditional branches are needed.
324 493 /// {@
325 // The following table summarizes the logic for lowering the icmp instruction
326 // for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
327 // conditional branches are needed. For the other conditions, three separate
328 // conditional branches are needed.
329 static const struct TableIcmp64Type { 494 static const struct TableIcmp64Type {
330 CondX86::BrCond C1, C2, C3; 495 Cond::BrCond C1, C2, C3;
331 } TableIcmp64[]; 496 } TableIcmp64[];
332 static const size_t TableIcmp64Size; 497 static const size_t TableIcmp64Size;
498 /// @}
333 499
334 static CondX86::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { 500 static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
335 size_t Index = static_cast<size_t>(Cond); 501 size_t Index = static_cast<size_t>(Cond);
336 assert(Index < TableIcmp32Size); 502 assert(Index < TableIcmp32Size);
337 return TableIcmp32[Index].Mapping; 503 return TableIcmp32[Index].Mapping;
338 } 504 }
339 505
340 static const struct TableTypeX8632AttributesType { 506 static const struct TableTypeX8632AttributesType {
341 Type InVectorElementType; 507 Type InVectorElementType;
342 } TableTypeX8632Attributes[]; 508 } TableTypeX8632Attributes[];
343 static const size_t TableTypeX8632AttributesSize; 509 static const size_t TableTypeX8632AttributesSize;
510
511 //----------------------------------------------------------------------------
512 // __ __ __ ______ ______
513 // /\ \/\ "-.\ \/\ ___\/\__ _\
514 // \ \ \ \ \-. \ \___ \/_/\ \/
515 // \ \_\ \_\\"\_\/\_____\ \ \_\
516 // \/_/\/_/ \/_/\/_____/ \/_/
517 //
518 //----------------------------------------------------------------------------
519 using Insts = ::Ice::X86Internal::Insts<TargetX8632>;
520
521 using TargetLowering = TargetX8632;
522 using Assembler = X8632::AssemblerX8632;
523
524 /// X86Operand extends the Operand hierarchy. Its subclasses are
525 /// X86OperandMem and VariableSplit.
526 class X86Operand : public ::Ice::Operand {
527 X86Operand() = delete;
528 X86Operand(const X86Operand &) = delete;
529 X86Operand &operator=(const X86Operand &) = delete;
530
531 public:
532 enum OperandKindX8632 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit };
533 using ::Ice::Operand::dump;
534
535 void dump(const Cfg *, Ostream &Str) const override;
536
537 protected:
538 X86Operand(OperandKindX8632 Kind, Type Ty)
539 : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {}
540 };
541
542 /// X86OperandMem represents the m32 addressing mode, with optional base and
543 /// index registers, a constant offset, and a fixed shift value for the index
544 /// register.
545 class X86OperandMem : public X86Operand {
546 X86OperandMem() = delete;
547 X86OperandMem(const X86OperandMem &) = delete;
548 X86OperandMem &operator=(const X86OperandMem &) = delete;
549
550 public:
551 enum SegmentRegisters {
552 DefaultSegment = -1,
553 #define X(val, name, prefix) val,
554 SEG_REGX8632_TABLE
555 #undef X
556 SegReg_NUM
557 };
558 static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
559 Constant *Offset, Variable *Index = nullptr,
560 uint16_t Shift = 0,
561 SegmentRegisters SegmentReg = DefaultSegment) {
562 return new (Func->allocate<X86OperandMem>())
563 X86OperandMem(Func, Ty, Base, Offset, Index, Shift, SegmentReg);
564 }
565 Variable *getBase() const { return Base; }
566 Constant *getOffset() const { return Offset; }
567 Variable *getIndex() const { return Index; }
568 uint16_t getShift() const { return Shift; }
569 SegmentRegisters getSegmentRegister() const { return SegmentReg; }
570 void emitSegmentOverride(Assembler *Asm) const;
571 Address toAsmAddress(Assembler *Asm) const;
572
573 void emit(const Cfg *Func) const override;
574 using X86Operand::dump;
575 void dump(const Cfg *Func, Ostream &Str) const override;
576
577 static bool classof(const Operand *Operand) {
578 return Operand->getKind() == static_cast<OperandKind>(kMem);
579 }
580
581 void setRandomized(bool R) { Randomized = R; }
582
583 bool getRandomized() const { return Randomized; }
584
585 private:
586 X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
587 Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg);
588
589 Variable *Base;
590 Constant *Offset;
591 Variable *Index;
592 uint16_t Shift;
593 SegmentRegisters SegmentReg : 16;
594 /// A flag to show if this memory operand is a randomized one. Randomized
595 /// memory operands are generated in
596 /// TargetX86Base::randomizeOrPoolImmediate()
597 bool Randomized;
598 };
599
600 /// VariableSplit is a way to treat an f64 memory location as a pair of i32
601 /// locations (Low and High). This is needed for some cases of the Bitcast
602 /// instruction. Since it's not possible for integer registers to access the
603 /// XMM registers and vice versa, the lowering forces the f64 to be spilled to
604 /// the stack and then accesses through the VariableSplit.
605 // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit
606 // targets can natively handle these.
607 class VariableSplit : public X86Operand {
608 VariableSplit() = delete;
609 VariableSplit(const VariableSplit &) = delete;
610 VariableSplit &operator=(const VariableSplit &) = delete;
611
612 public:
613 enum Portion { Low, High };
614 static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
615 return new (Func->allocate<VariableSplit>())
616 VariableSplit(Func, Var, Part);
617 }
618 int32_t getOffset() const { return Part == High ? 4 : 0; }
619
620 Address toAsmAddress(const Cfg *Func) const;
621 void emit(const Cfg *Func) const override;
622 using X86Operand::dump;
623 void dump(const Cfg *Func, Ostream &Str) const override;
624
625 static bool classof(const Operand *Operand) {
626 return Operand->getKind() == static_cast<OperandKind>(kSplit);
627 }
628
629 private:
630 VariableSplit(Cfg *Func, Variable *Var, Portion Part)
631 : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) {
632 assert(Var->getType() == IceType_f64);
633 Vars = Func->allocateArrayOf<Variable *>(1);
634 Vars[0] = Var;
635 NumVars = 1;
636 }
637
638 Variable *Var;
639 Portion Part;
640 };
641
642 /// SpillVariable decorates a Variable by linking it to another Variable.
643 /// When stack frame offsets are computed, the SpillVariable is given a
644 /// distinct stack slot only if its linked Variable has a register. If the
645 /// linked Variable has a stack slot, then the Variable and SpillVariable
646 /// share that slot.
647 class SpillVariable : public Variable {
648 SpillVariable() = delete;
649 SpillVariable(const SpillVariable &) = delete;
650 SpillVariable &operator=(const SpillVariable &) = delete;
651
652 public:
653 static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) {
654 return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index);
655 }
656 const static OperandKind SpillVariableKind =
657 static_cast<OperandKind>(kVariable_Target);
658 static bool classof(const Operand *Operand) {
659 return Operand->getKind() == SpillVariableKind;
660 }
661 void setLinkedTo(Variable *Var) { LinkedTo = Var; }
662 Variable *getLinkedTo() const { return LinkedTo; }
663 // Inherit dump() and emit() from Variable.
664
665 private:
666 SpillVariable(Type Ty, SizeT Index)
667 : Variable(SpillVariableKind, Ty, Index), LinkedTo(nullptr) {}
668 Variable *LinkedTo;
669 };
670
671 // Note: The following data structures are defined in IceInstX8632.cpp.
672
673 static const struct InstBrAttributesType {
674 Cond::BrCond Opposite;
675 const char *DisplayString;
676 const char *EmitString;
677 } InstBrAttributes[];
678
679 static const struct InstCmppsAttributesType {
680 const char *EmitString;
681 } InstCmppsAttributes[];
682
683 static const struct TypeAttributesType {
684 const char *CvtString; // i (integer), s (single FP), d (double FP)
685 const char *SdSsString; // ss, sd, or <blank>
686 const char *PackString; // b, w, d, or <blank>
687 const char *WidthString; // b, w, l, q, or <blank>
688 const char *FldString; // s, l, or <blank>
689 } TypeAttributes[];
690
691 static const char *InstSegmentRegNames[];
692
693 static uint8_t InstSegmentPrefixes[];
344 }; 694 };
345 695
346 } // end of namespace X86Internal 696 } // end of namespace X86Internal
347 697
348 namespace X8632 { 698 namespace X8632 {
349 using Traits = ::Ice::X86Internal::MachineTraits<TargetX8632>; 699 using Traits = ::Ice::X86Internal::MachineTraits<TargetX8632>;
350 } // end of namespace X8632 700 } // end of namespace X8632
351 701
352 } // end of namespace Ice 702 } // end of namespace Ice
353 703
354 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 704 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
OLDNEW
« no previous file with comments | « src/IceTargetLoweringX8632.cpp ('k') | src/IceTargetLoweringX86Base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698