1 //===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- 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 /// \file 11 /// \brief Declares the X8632 Target Lowering Traits. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 16 #define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 17 18 #include "IceAssembler.h" 19 #include "IceConditionCodesX8632.h" 20 #include "IceDefs.h" 21 #include "IceInst.h" 22 #include "IceInstX8632.def" 23 #include "IceOperand.h" 24 #include "IceRegistersX8632.h" 25 #include "IceTargetLowering.h" 26 #include "IceTargetLoweringX8632.def" 27 #include "IceTargetLoweringX86RegClass.h" 28 29 #include <array> 30 31 namespace Ice { 32 33 namespace X8632 { 34 using namespace ::Ice::X86; 35 36 template <class Machine> struct Insts; 37 template <class Machine> class TargetX86Base; 38 template <class Machine> class AssemblerX86Base; 39 40 class TargetX8632; 41 42 struct TargetX8632Traits { 43 //---------------------------------------------------------------------------- 44 // ______ ______ __ __ 45 // /\ __ \/\ ___\/\ "-./ \ 46 // \ \ __ \ \___ \ \ \-./\ \ 47 // \ \_\ \_\/\_____\ \_\ \ \_\ 48 // \/_/\/_/\/_____/\/_/ \/_/ 49 // 50 //---------------------------------------------------------------------------- 51 static constexpr ::Ice::Assembler::AssemblerKind AsmKind = 52 ::Ice::Assembler::Asm_X8632; 53 54 static constexpr bool Is64Bit = false; 55 static constexpr bool HasPopa = true; 56 static constexpr bool HasPusha = true; 57 static constexpr bool UsesX87 = true; 58 static constexpr ::Ice::RegX8632::GPRRegister Last8BitGPR = 59 ::Ice::RegX8632::GPRRegister::Encoded_Reg_ebx; 60 61 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 }; 62 63 using GPRRegister = ::Ice::RegX8632::GPRRegister; 64 using ByteRegister = ::Ice::RegX8632::ByteRegister; 65 using XmmRegister = ::Ice::RegX8632::XmmRegister; 66 using X87STRegister = ::Ice::RegX8632::X87STRegister; 67 68 using Cond = ::Ice::CondX86; 69 70 using RegisterSet = ::Ice::RegX8632; 71 static constexpr RegisterSet::AllRegisters StackPtr = RegX8632::Reg_esp; 72 static constexpr RegisterSet::AllRegisters FramePtr = RegX8632::Reg_ebp; 73 static constexpr GPRRegister Encoded_Reg_Accumulator = 74 RegX8632::Encoded_Reg_eax; 75 static constexpr GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx; 76 static constexpr FixupKind FK_PcRel = llvm::ELF::R_386_PC32; 77 static constexpr FixupKind FK_Abs = llvm::ELF::R_386_32; 78 static constexpr FixupKind FK_Gotoff = llvm::ELF::R_386_GOTOFF; 79 static constexpr FixupKind FK_GotPC = llvm::ELF::R_386_GOTPC; 80 81 class Operand { 82 public: OperandTargetX8632Traits83 Operand(const Operand &other) 84 : fixup_(other.fixup_), length_(other.length_) { 85 memmove(&encoding_[0], &other.encoding_[0], other.length_); 86 } 87 88 Operand &operator=(const Operand &other) { 89 length_ = other.length_; 90 fixup_ = other.fixup_; 91 memmove(&encoding_[0], &other.encoding_[0], other.length_); 92 return *this; 93 } 94 modTargetX8632Traits95 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; } 96 rmTargetX8632Traits97 GPRRegister rm() const { 98 return static_cast<GPRRegister>(encoding_at(0) & 7); 99 } 100 scaleTargetX8632Traits101 ScaleFactor scale() const { 102 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3); 103 } 104 indexTargetX8632Traits105 GPRRegister index() const { 106 return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7); 107 } 108 baseTargetX8632Traits109 GPRRegister base() const { 110 return static_cast<GPRRegister>(encoding_at(1) & 7); 111 } 112 disp8TargetX8632Traits113 int8_t disp8() const { 114 assert(length_ >= 2); 115 return static_cast<int8_t>(encoding_[length_ - 1]); 116 } 117 disp32TargetX8632Traits118 int32_t disp32() const { 119 assert(length_ >= 5); 120 // TODO(stichnot): This method is not currently used. Delete it along 121 // with other unused methods, or use a safe version of bitCopy(). 122 llvm::report_fatal_error("Unexpected call to disp32()"); 123 // return Utils::bitCopy<int32_t>(encoding_[length_ - 4]); 124 } 125 fixupTargetX8632Traits126 AssemblerFixup *fixup() const { return fixup_; } 127 128 protected: OperandTargetX8632Traits129 Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address. 130 SetModRMTargetX8632Traits131 void SetModRM(int mod, GPRRegister rm) { 132 assert((mod & ~3) == 0); 133 encoding_[0] = (mod << 6) | rm; 134 length_ = 1; 135 } 136 SetSIBTargetX8632Traits137 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) { 138 assert(length_ == 1); 139 assert((scale & ~3) == 0); 140 encoding_[1] = (scale << 6) | (index << 3) | base; 141 length_ = 2; 142 } 143 SetDisp8TargetX8632Traits144 void SetDisp8(int8_t disp) { 145 assert(length_ == 1 || length_ == 2); 146 encoding_[length_++] = static_cast<uint8_t>(disp); 147 } 148 SetDisp32TargetX8632Traits149 void SetDisp32(int32_t disp) { 150 assert(length_ == 1 || length_ == 2); 151 intptr_t disp_size = sizeof(disp); 152 memmove(&encoding_[length_], &disp, disp_size); 153 length_ += disp_size; 154 } 155 SetFixupTargetX8632Traits156 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; } 157 158 private: 159 AssemblerFixup *fixup_; 160 uint8_t encoding_[6]; 161 uint8_t length_; 162 OperandTargetX8632Traits163 explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); } 164 165 /// Get the operand encoding byte at the given index. encoding_atTargetX8632Traits166 uint8_t encoding_at(intptr_t index) const { 167 assert(index >= 0 && index < length_); 168 return encoding_[index]; 169 } 170 171 /// Returns whether or not this operand is really the given register in 172 /// disguise. Used from the assembler to generate better encodings. IsRegisterTargetX8632Traits173 bool IsRegister(GPRRegister reg) const { 174 return ((encoding_[0] & 0xF8) == 175 0xC0) // Addressing mode is register only. 176 && 177 ((encoding_[0] & 0x07) == reg); // Register codes match. 178 } 179 180 friend class AssemblerX86Base<TargetX8632Traits>; 181 }; 182 183 class Address : public Operand { 184 Address() = delete; 185 186 public: AddressTargetX8632Traits187 Address(const Address &other) : Operand(other) {} 188 189 Address &operator=(const Address &other) { 190 Operand::operator=(other); 191 return *this; 192 } 193 AddressTargetX8632Traits194 Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) { 195 if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) { 196 SetModRM(0, Base); 197 if (Base == RegX8632::Encoded_Reg_esp) 198 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base); 199 } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) { 200 SetModRM(1, Base); 201 if (Base == RegX8632::Encoded_Reg_esp) 202 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base); 203 SetDisp8(Disp); 204 } else { 205 SetModRM(2, Base); 206 if (Base == RegX8632::Encoded_Reg_esp) 207 SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, Base); 208 SetDisp32(Disp); 209 if (Fixup) 210 SetFixup(Fixup); 211 } 212 } 213 AddressTargetX8632Traits214 Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp, 215 AssemblerFixup *Fixup) { 216 assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. 217 SetModRM(0, RegX8632::Encoded_Reg_esp); 218 SetSIB(Scale, Index, RegX8632::Encoded_Reg_ebp); 219 SetDisp32(Disp); 220 if (Fixup) 221 SetFixup(Fixup); 222 } 223 AddressTargetX8632Traits224 Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale, 225 int32_t Disp, AssemblerFixup *Fixup) { 226 assert(Index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode. 227 if (Fixup == nullptr && Disp == 0 && Base != RegX8632::Encoded_Reg_ebp) { 228 SetModRM(0, RegX8632::Encoded_Reg_esp); 229 SetSIB(Scale, Index, Base); 230 } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) { 231 SetModRM(1, RegX8632::Encoded_Reg_esp); 232 SetSIB(Scale, Index, Base); 233 SetDisp8(Disp); 234 } else { 235 SetModRM(2, RegX8632::Encoded_Reg_esp); 236 SetSIB(Scale, Index, Base); 237 SetDisp32(Disp); 238 if (Fixup) 239 SetFixup(Fixup); 240 } 241 } 242 243 /// Generate an absolute address expression on x86-32. AddressTargetX8632Traits244 Address(RelocOffsetT Offset, AssemblerFixup *Fixup) { 245 SetModRM(0, RegX8632::Encoded_Reg_ebp); 246 // Use the Offset in the displacement for now. If we decide to process 247 // fixups later, we'll need to patch up the emitted displacement. 248 SetDisp32(Offset); 249 if (Fixup) 250 SetFixup(Fixup); 251 } 252 ofConstPoolTargetX8632Traits253 static Address ofConstPool(Assembler *Asm, const Constant *Imm) { 254 AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm); 255 const RelocOffsetT Offset = 0; 256 return Address(Offset, Fixup); 257 } 258 }; 259 260 //---------------------------------------------------------------------------- 261 // __ ______ __ __ ______ ______ __ __ __ ______ 262 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\ 263 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \ 264 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\ 265 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/ 266 // 267 //---------------------------------------------------------------------------- 268 enum InstructionSet { 269 Begin, 270 // SSE2 is the PNaCl baseline instruction set. 271 SSE2 = Begin, 272 SSE4_1, 273 End 274 }; 275 276 static const char *TargetName; 277 static constexpr Type WordType = IceType_i32; 278 getRegNameTargetX8632Traits279 static const char *getRegName(RegNumT RegNum) { 280 static const char *const RegNames[RegisterSet::Reg_NUM] = { 281 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 282 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 283 isTrunc8Rcvr, isAhRcvr, aliases) \ 284 name, 285 REGX8632_TABLE 286 #undef X 287 }; 288 RegNum.assertIsValid(); 289 return RegNames[RegNum]; 290 } 291 getEncodedGPRTargetX8632Traits292 static GPRRegister getEncodedGPR(RegNumT RegNum) { 293 static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = { 294 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 295 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 296 isTrunc8Rcvr, isAhRcvr, aliases) \ 297 GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR), 298 REGX8632_TABLE 299 #undef X 300 }; 301 RegNum.assertIsValid(); 302 assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR); 303 return GPRRegs[RegNum]; 304 } 305 getEncodedByteRegTargetX8632Traits306 static ByteRegister getEncodedByteReg(RegNumT RegNum) { 307 static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = { 308 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 309 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 310 isTrunc8Rcvr, isAhRcvr, aliases) \ 311 ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg), 312 REGX8632_TABLE 313 #undef X 314 }; 315 RegNum.assertIsValid(); 316 assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg); 317 return ByteRegs[RegNum]; 318 } 319 getEncodedXmmTargetX8632Traits320 static XmmRegister getEncodedXmm(RegNumT RegNum) { 321 static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = { 322 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 323 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 324 isTrunc8Rcvr, isAhRcvr, aliases) \ 325 XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm), 326 REGX8632_TABLE 327 #undef X 328 }; 329 RegNum.assertIsValid(); 330 assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm); 331 return XmmRegs[RegNum]; 332 } 333 getEncodingTargetX8632Traits334 static uint32_t getEncoding(RegNumT RegNum) { 335 static const uint32_t Encoding[RegisterSet::Reg_NUM] = { 336 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 337 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 338 isTrunc8Rcvr, isAhRcvr, aliases) \ 339 encode, 340 REGX8632_TABLE 341 #undef X 342 }; 343 RegNum.assertIsValid(); 344 return Encoding[RegNum]; 345 } 346 getBaseRegTargetX8632Traits347 static RegNumT getBaseReg(RegNumT RegNum) { 348 static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = { 349 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 350 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 351 isTrunc8Rcvr, isAhRcvr, aliases) \ 352 RegisterSet::base, 353 REGX8632_TABLE 354 #undef X 355 }; 356 RegNum.assertIsValid(); 357 return BaseRegs[RegNum]; 358 } 359 360 private: getFirstGprForTypeTargetX8632Traits361 static RegisterSet::AllRegisters getFirstGprForType(Type Ty) { 362 switch (Ty) { 363 default: 364 llvm_unreachable("Invalid type for GPR."); 365 case IceType_i1: 366 case IceType_i8: 367 return RegisterSet::Reg_al; 368 case IceType_i16: 369 return RegisterSet::Reg_ax; 370 case IceType_i32: 371 return RegisterSet::Reg_eax; 372 } 373 } 374 375 public: 376 // Return a register in RegNum's alias set that is suitable for Ty. getGprForTypeTargetX8632Traits377 static RegNumT getGprForType(Type Ty, RegNumT RegNum) { 378 assert(RegNum.hasValue()); 379 380 if (!isScalarIntegerType(Ty)) { 381 return RegNum; 382 } 383 384 // [abcd]h registers are not convertible to their ?l, ?x, and e?x versions. 385 switch (RegNum) { 386 default: 387 break; 388 case RegisterSet::Reg_ah: 389 case RegisterSet::Reg_bh: 390 case RegisterSet::Reg_ch: 391 case RegisterSet::Reg_dh: 392 assert(isByteSizedType(Ty)); 393 return RegNum; 394 } 395 396 const RegisterSet::AllRegisters FirstGprForType = getFirstGprForType(Ty); 397 398 switch (RegNum) { 399 default: 400 llvm::report_fatal_error("Unknown register."); 401 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 402 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 403 isTrunc8Rcvr, isAhRcvr, aliases) \ 404 case RegisterSet::val: { \ 405 if (!isGPR) \ 406 return RegisterSet::val; \ 407 assert((is32) || (is16) || (is8) || \ 408 getBaseReg(RegisterSet::val) == RegisterSet::Reg_esp); \ 409 constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize = \ 410 (((is32) || RegisterSet::val == RegisterSet::Reg_esp) \ 411 ? RegisterSet::Reg_eax \ 412 : (((is16) || RegisterSet::val == RegisterSet::Reg_sp) \ 413 ? RegisterSet::Reg_ax \ 414 : RegisterSet::Reg_al)); \ 415 const RegNumT NewRegNum = \ 416 RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType); \ 417 assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) && \ 418 "Error involving " #val); \ 419 return NewRegNum; \ 420 } 421 REGX8632_TABLE 422 #undef X 423 } 424 } 425 426 private: 427 /// SizeOf is used to obtain the size of an initializer list as a constexpr 428 /// expression. This is only needed until our C++ library is updated to 429 /// C++ 14 -- which defines constexpr members to std::initializer_list. 430 class SizeOf { 431 SizeOf(const SizeOf &) = delete; 432 SizeOf &operator=(const SizeOf &) = delete; 433 434 public: SizeOfTargetX8632Traits435 constexpr SizeOf() : Size(0) {} 436 template <typename... T> SizeOfTargetX8632Traits437 explicit constexpr SizeOf(T...) 438 : Size(__length<T...>::value) {} sizeTargetX8632Traits439 constexpr SizeT size() const { return Size; } 440 441 private: 442 template <typename T, typename... U> struct __length { 443 static constexpr std::size_t value = 1 + __length<U...>::value; 444 }; 445 446 template <typename T> struct __length<T> { 447 static constexpr std::size_t value = 1; 448 }; 449 450 const std::size_t Size; 451 }; 452 453 public: 454 static void initRegisterSet( 455 const ::Ice::ClFlags & /*Flags*/, 456 std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet, 457 std::array<SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) { 458 SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM); 459 SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM); 460 SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM); 461 SmallBitVector FloatRegisters(RegisterSet::Reg_NUM); 462 SmallBitVector VectorRegisters(RegisterSet::Reg_NUM); 463 SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM); 464 SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM); 465 SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM); 466 SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM); 467 SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM); 468 SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM); 469 470 static constexpr struct { 471 uint16_t Val; 472 unsigned Is64 : 1; 473 unsigned Is32 : 1; 474 unsigned Is16 : 1; 475 unsigned Is8 : 1; 476 unsigned IsXmm : 1; 477 unsigned Is64To8 : 1; 478 unsigned Is32To8 : 1; 479 unsigned Is16To8 : 1; 480 unsigned IsTrunc8Rcvr : 1; 481 unsigned IsAhRcvr : 1; 482 #define NUM_ALIASES_BITS 2 483 SizeT NumAliases : (NUM_ALIASES_BITS + 1); 484 uint16_t Aliases[1 << NUM_ALIASES_BITS]; 485 #undef NUM_ALIASES_BITS 486 } X8632RegTable[RegisterSet::Reg_NUM] = { 487 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 488 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 489 isTrunc8Rcvr, isAhRcvr, aliases) \ 490 { \ 491 RegisterSet::val, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 492 isTrunc8Rcvr, isAhRcvr, (SizeOf aliases).size(), aliases, \ 493 } \ 494 , 495 REGX8632_TABLE 496 #undef X 497 }; 498 499 for (SizeT ii = 0; ii < llvm::array_lengthof(X8632RegTable); ++ii) { 500 const auto &Entry = X8632RegTable[ii]; 501 (IntegerRegistersI32)[Entry.Val] = Entry.Is32; 502 (IntegerRegistersI16)[Entry.Val] = Entry.Is16; 503 (IntegerRegistersI8)[Entry.Val] = Entry.Is8; 504 (FloatRegisters)[Entry.Val] = Entry.IsXmm; 505 (VectorRegisters)[Entry.Val] = Entry.IsXmm; 506 (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8; 507 (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8; 508 (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8; 509 (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr; 510 (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr; 511 (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM); 512 for (int J = 0; J < Entry.NumAliases; J++) { 513 SizeT Alias = Entry.Aliases[J]; 514 assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias"); 515 (*RegisterAliases)[Entry.Val].set(Alias); 516 } 517 (*RegisterAliases)[Entry.Val].set(Entry.Val); 518 } 519 520 (*TypeToRegisterSet)[RC_void] = InvalidRegisters; 521 (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8; 522 (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8; 523 (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16; 524 (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32; 525 (*TypeToRegisterSet)[RC_i64] = InvalidRegisters; 526 (*TypeToRegisterSet)[RC_f32] = FloatRegisters; 527 (*TypeToRegisterSet)[RC_f64] = FloatRegisters; 528 (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters; 529 (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters; 530 (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters; 531 (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters; 532 (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters; 533 (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters; 534 (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters; 535 (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers; 536 (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers; 537 (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers; 538 (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters; 539 (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters; 540 } 541 542 static SmallBitVector getRegisterSet(const ::Ice::ClFlags & /*Flags*/, 543 TargetLowering::RegSetMask Include, 544 TargetLowering::RegSetMask Exclude) { 545 SmallBitVector Registers(RegisterSet::Reg_NUM); 546 547 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 548 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 549 isTrunc8Rcvr, isAhRcvr, aliases) \ 550 if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \ 551 Registers[RegisterSet::val] = true; \ 552 if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \ 553 Registers[RegisterSet::val] = true; \ 554 if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \ 555 Registers[RegisterSet::val] = true; \ 556 if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \ 557 Registers[RegisterSet::val] = true; \ 558 if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \ 559 Registers[RegisterSet::val] = false; \ 560 if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \ 561 Registers[RegisterSet::val] = false; \ 562 if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \ 563 Registers[RegisterSet::val] = false; \ 564 if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \ 565 Registers[RegisterSet::val] = false; 566 567 REGX8632_TABLE 568 569 #undef X 570 571 return Registers; 572 } 573 574 static void makeRandomRegisterPermutation( 575 Cfg *Func, llvm::SmallVectorImpl<RegNumT> &Permutation, 576 const SmallBitVector &ExcludeRegisters, uint64_t Salt) { 577 // TODO(stichnot): Declaring Permutation this way loses type/size 578 // information. Fix this in conjunction with the caller-side TODO. 579 assert(Permutation.size() >= RegisterSet::Reg_NUM); 580 // Expected upper bound on the number of registers in a single equivalence 581 // class. For x86-32, this would comprise the 8 XMM registers. This is for 582 // performance, not correctness. 583 static const unsigned MaxEquivalenceClassSize = 8; 584 using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>; 585 using EquivalenceClassMap = std::map<uint32_t, RegisterList>; 586 EquivalenceClassMap EquivalenceClasses; 587 SizeT NumShuffled = 0, NumPreserved = 0; 588 589 // Build up the equivalence classes of registers by looking at the register 590 // properties as well as whether the registers should be explicitly excluded 591 // from shuffling. 592 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \ 593 isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, is16To8, \ 594 isTrunc8Rcvr, isAhRcvr, aliases) \ 595 if (ExcludeRegisters[RegisterSet::val]) { \ 596 /* val stays the same in the resulting permutation. */ \ 597 Permutation[RegisterSet::val] = RegisterSet::val; \ 598 ++NumPreserved; \ 599 } else { \ 600 uint32_t AttrKey = 0; \ 601 uint32_t Index = 0; \ 602 /* Combine relevant attributes into an equivalence class key. */ \ 603 Index |= (scratch << (AttrKey++)); \ 604 Index |= (preserved << (AttrKey++)); \ 605 Index |= (is8 << (AttrKey++)); \ 606 Index |= (is16 << (AttrKey++)); \ 607 Index |= (is32 << (AttrKey++)); \ 608 Index |= (is64 << (AttrKey++)); \ 609 Index |= (isXmm << (AttrKey++)); \ 610 Index |= (is16To8 << (AttrKey++)); \ 611 Index |= (is32To8 << (AttrKey++)); \ 612 Index |= (is64To8 << (AttrKey++)); \ 613 Index |= (isTrunc8Rcvr << (AttrKey++)); \ 614 /* val is assigned to an equivalence class based on its properties. */ \ 615 EquivalenceClasses[Index].push_back(RegisterSet::val); \ 616 } 617 REGX8632_TABLE 618 #undef X 619 620 // Create a random number generator for regalloc randomization. 621 RandomNumberGenerator RNG(getFlags().getRandomSeed(), 622 RPE_RegAllocRandomization, Salt); 623 RandomNumberGeneratorWrapper RNGW(RNG); 624 625 // Shuffle the resulting equivalence classes. 626 for (auto I : EquivalenceClasses) { 627 const RegisterList &List = I.second; 628 RegisterList Shuffled(List); 629 RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW); 630 for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) { 631 Permutation[List[SI]] = Shuffled[SI]; 632 ++NumShuffled; 633 } 634 } 635 636 assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM); 637 638 if (Func->isVerbose(IceV_Random)) { 639 OstreamLocker L(Func->getContext()); 640 Ostream &Str = Func->getContext()->getStrDump(); 641 Str << "Register equivalence classes:\n"; 642 for (auto I : EquivalenceClasses) { 643 Str << "{"; 644 const RegisterList &List = I.second; 645 bool First = true; 646 for (RegNumT Register : List) { 647 if (!First) 648 Str << " "; 649 First = false; 650 Str << getRegName(Register); 651 } 652 Str << "}\n"; 653 } 654 } 655 } 656 657 static RegNumT getRaxOrDie() { 658 llvm::report_fatal_error("no rax in non-64-bit mode."); 659 } 660 661 static RegNumT getRdxOrDie() { 662 llvm::report_fatal_error("no rdx in non-64-bit mode."); 663 } 664 665 // x86-32 calling convention: 666 // 667 // * The first four arguments of vector type, regardless of their position 668 // relative to the other arguments in the argument list, are placed in 669 // registers xmm0 - xmm3. 670 // 671 // This intends to match the section "IA-32 Function Calling Convention" of 672 // the document "OS X ABI Function Call Guide" by Apple. 673 674 /// The maximum number of arguments to pass in XMM registers 675 static constexpr uint32_t X86_MAX_XMM_ARGS = 4; 676 /// The maximum number of arguments to pass in GPR registers 677 static constexpr uint32_t X86_MAX_GPR_ARGS = 0; 678 /// Whether scalar floating point arguments are passed in XMM registers 679 static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = false; 680 /// Get the register for a given argument slot in the XMM registers. 681 static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) { 682 // TODO(sehr): Change to use the CCArg technique used in ARM32. 683 static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1, 684 "Inconsistency between XMM register numbers and ordinals"); 685 if (ArgNum >= X86_MAX_XMM_ARGS) { 686 return RegNumT(); 687 } 688 return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum); 689 } 690 /// Get the register for a given argument slot in the GPRs. 691 static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) { 692 assert(Ty == IceType_i64 || Ty == IceType_i32); 693 (void)Ty; 694 (void)ArgNum; 695 return RegNumT(); 696 } 697 698 /// The number of bits in a byte 699 static constexpr uint32_t X86_CHAR_BIT = 8; 700 /// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it 701 /// is used as an argument to std::max(), and the default std::less<T> has an 702 /// operator(T const&, T const&) which requires this member to have an 703 /// address. 704 static const uint32_t X86_STACK_ALIGNMENT_BYTES; 705 /// Size of the return address on the stack 706 static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 4; 707 /// The number of different NOP instructions 708 static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5; 709 710 /// \name Limits for unrolling memory intrinsics. 711 /// @{ 712 static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8; 713 static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8; 714 static constexpr uint32_t MEMSET_UNROLL_LIMIT = 8; 715 /// @} 716 717 /// Value is in bytes. Return Value adjusted to the next highest multiple of 718 /// the stack alignment. 719 static uint32_t applyStackAlignment(uint32_t Value) { 720 return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES); 721 } 722 723 /// Return the type which the elements of the vector have in the X86 724 /// representation of the vector. 725 static Type getInVectorElementType(Type Ty) { 726 assert(isVectorType(Ty)); 727 assert(Ty < TableTypeX8632AttributesSize); 728 return TableTypeX8632Attributes[Ty].InVectorElementType; 729 } 730 731 // Note: The following data structures are defined in 732 // IceTargetLoweringX8632.cpp. 733 734 /// The following table summarizes the logic for lowering the fcmp 735 /// instruction. There is one table entry for each of the 16 conditions. 736 /// 737 /// The first four columns describe the case when the operands are floating 738 /// point scalar values. A comment in lowerFcmp() describes the lowering 739 /// template. In the most general case, there is a compare followed by two 740 /// conditional branches, because some fcmp conditions don't map to a single 741 /// x86 conditional branch. However, in many cases it is possible to swap the 742 /// operands in the comparison and have a single conditional branch. Since 743 /// it's quite tedious to validate the table by hand, good execution tests are 744 /// helpful. 745 /// 746 /// The last two columns describe the case when the operands are vectors of 747 /// floating point values. For most fcmp conditions, there is a clear mapping 748 /// to a single x86 cmpps instruction variant. Some fcmp conditions require 749 /// special code to handle and these are marked in the table with a 750 /// Cmpps_Invalid predicate. 751 /// {@ 752 static const struct TableFcmpType { 753 uint32_t Default; 754 bool SwapScalarOperands; 755 Cond::BrCond C1, C2; 756 bool SwapVectorOperands; 757 Cond::CmppsCond Predicate; 758 } TableFcmp[]; 759 static const size_t TableFcmpSize; 760 /// @} 761 762 /// The following table summarizes the logic for lowering the icmp instruction 763 /// for i32 and narrower types. Each icmp condition has a clear mapping to an 764 /// x86 conditional branch instruction. 765 /// {@ 766 static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[]; 767 static const size_t TableIcmp32Size; 768 /// @} 769 770 /// The following table summarizes the logic for lowering the icmp instruction 771 /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and 772 /// conditional branches are needed. For the other conditions, three separate 773 /// conditional branches are needed. 774 /// {@ 775 static const struct TableIcmp64Type { 776 Cond::BrCond C1, C2, C3; 777 } TableIcmp64[]; 778 static const size_t TableIcmp64Size; 779 /// @} 780 781 static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) { 782 assert(Cond < TableIcmp32Size); 783 return TableIcmp32[Cond].Mapping; 784 } 785 786 static const struct TableTypeX8632AttributesType { 787 Type InVectorElementType; 788 } TableTypeX8632Attributes[]; 789 static const size_t TableTypeX8632AttributesSize; 790 791 //---------------------------------------------------------------------------- 792 // __ __ __ ______ ______ 793 // /\ \/\ "-.\ \/\ ___\/\__ _\ 794 // \ \ \ \ \-. \ \___ \/_/\ \/ 795 // \ \_\ \_\\"\_\/\_____\ \ \_\ 796 // \/_/\/_/ \/_/\/_____/ \/_/ 797 // 798 //---------------------------------------------------------------------------- 799 using Traits = TargetX8632Traits; 800 using Insts = ::Ice::X8632::Insts<Traits>; 801 802 using TargetLowering = ::Ice::X8632::TargetX86Base<Traits>; 803 using ConcreteTarget = ::Ice::X8632::TargetX8632; 804 using Assembler = ::Ice::X8632::AssemblerX86Base<Traits>; 805 806 /// X86Operand extends the Operand hierarchy. Its subclasses are X86OperandMem 807 /// and VariableSplit. 808 class X86Operand : public ::Ice::Operand { 809 X86Operand() = delete; 810 X86Operand(const X86Operand &) = delete; 811 X86Operand &operator=(const X86Operand &) = delete; 812 813 public: 814 enum OperandKindX8632 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit }; 815 using ::Ice::Operand::dump; 816 817 void dump(const Cfg *, Ostream &Str) const override; 818 819 protected: 820 X86Operand(OperandKindX8632 Kind, Type Ty) 821 : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {} 822 }; 823 824 /// X86OperandMem represents the m32 addressing mode, with optional base and 825 /// index registers, a constant offset, and a fixed shift value for the index 826 /// register. 827 class X86OperandMem : public X86Operand { 828 X86OperandMem() = delete; 829 X86OperandMem(const X86OperandMem &) = delete; 830 X86OperandMem &operator=(const X86OperandMem &) = delete; 831 832 public: 833 enum SegmentRegisters { 834 DefaultSegment = -1, 835 #define X(val, name, prefix) val, 836 SEG_REGX8632_TABLE 837 #undef X 838 SegReg_NUM 839 }; 840 static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base, 841 Constant *Offset, Variable *Index = nullptr, 842 uint16_t Shift = 0, 843 SegmentRegisters SegmentReg = DefaultSegment, 844 bool IsRebased = false) { 845 return new (Func->allocate<X86OperandMem>()) X86OperandMem( 846 Func, Ty, Base, Offset, Index, Shift, SegmentReg, IsRebased); 847 } 848 static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base, 849 Constant *Offset, bool IsRebased) { 850 constexpr Variable *NoIndex = nullptr; 851 constexpr uint16_t NoShift = 0; 852 return new (Func->allocate<X86OperandMem>()) X86OperandMem( 853 Func, Ty, Base, Offset, NoIndex, NoShift, DefaultSegment, IsRebased); 854 } 855 Variable *getBase() const { return Base; } 856 Constant *getOffset() const { return Offset; } 857 Variable *getIndex() const { return Index; } 858 uint16_t getShift() const { return Shift; } 859 SegmentRegisters getSegmentRegister() const { return SegmentReg; } 860 void emitSegmentOverride(Assembler *Asm) const; 861 bool getIsRebased() const { return IsRebased; } 862 Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target, 863 bool LeaAddr = false) const; 864 865 void emit(const Cfg *Func) const override; 866 using X86Operand::dump; 867 void dump(const Cfg *Func, Ostream &Str) const override; 868 869 static bool classof(const Operand *Operand) { 870 return Operand->getKind() == static_cast<OperandKind>(kMem); 871 } 872 873 void setRandomized(bool R) { Randomized = R; } 874 875 bool getRandomized() const { return Randomized; } 876 877 private: 878 X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset, 879 Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg, 880 bool IsRebased); 881 882 Variable *const Base; 883 Constant *const Offset; 884 Variable *const Index; 885 const uint16_t Shift; 886 const SegmentRegisters SegmentReg : 16; 887 const bool IsRebased; 888 /// A flag to show if this memory operand is a randomized one. Randomized 889 /// memory operands are generated in 890 /// TargetX86Base::randomizeOrPoolImmediate() 891 bool Randomized = false; 892 }; 893 894 /// VariableSplit is a way to treat an f64 memory location as a pair of i32 895 /// locations (Low and High). This is needed for some cases of the Bitcast 896 /// instruction. Since it's not possible for integer registers to access the 897 /// XMM registers and vice versa, the lowering forces the f64 to be spilled to 898 /// the stack and then accesses through the VariableSplit. 899 // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit 900 // targets can natively handle these. 901 class VariableSplit : public X86Operand { 902 VariableSplit() = delete; 903 VariableSplit(const VariableSplit &) = delete; 904 VariableSplit &operator=(const VariableSplit &) = delete; 905 906 public: 907 enum Portion { Low, High }; 908 static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) { 909 return new (Func->allocate<VariableSplit>()) 910 VariableSplit(Func, Var, Part); 911 } 912 int32_t getOffset() const { return Part == High ? 4 : 0; } 913 914 Address toAsmAddress(const Cfg *Func) const; 915 void emit(const Cfg *Func) const override; 916 using X86Operand::dump; 917 void dump(const Cfg *Func, Ostream &Str) const override; 918 919 static bool classof(const Operand *Operand) { 920 return Operand->getKind() == static_cast<OperandKind>(kSplit); 921 } 922 923 private: 924 VariableSplit(Cfg *Func, Variable *Var, Portion Part) 925 : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) { 926 assert(Var->getType() == IceType_f64); 927 Vars = Func->allocateArrayOf<Variable *>(1); 928 Vars[0] = Var; 929 NumVars = 1; 930 } 931 932 Variable *Var; 933 Portion Part; 934 }; 935 936 // Note: The following data structures are defined in IceInstX8632.cpp. 937 938 static const struct InstBrAttributesType { 939 Cond::BrCond Opposite; 940 const char *DisplayString; 941 const char *EmitString; 942 } InstBrAttributes[]; 943 944 static const struct InstCmppsAttributesType { 945 const char *EmitString; 946 } InstCmppsAttributes[]; 947 948 static const struct TypeAttributesType { 949 const char *CvtString; // i (integer), s (single FP), d (double FP) 950 const char *SdSsString; // ss, sd, or <blank> 951 const char *PdPsString; // ps, pd, or <blank> 952 const char *SpSdString; // ss, sd, ps, pd, or <blank> 953 const char *IntegralString; // b, w, d, or <blank> 954 const char *UnpackString; // bw, wd, dq, or <blank> 955 const char *PackString; // wb, dw, or <blank> 956 const char *WidthString; // b, w, l, q, or <blank> 957 const char *FldString; // s, l, or <blank> 958 } TypeAttributes[]; 959 960 static const char *InstSegmentRegNames[]; 961 962 static uint8_t InstSegmentPrefixes[]; 963 }; 964 965 using Traits = ::Ice::X8632::TargetX8632Traits; 966 } // end of namespace X8632 967 968 } // end of namespace Ice 969 970 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H 971