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