1 //===- subzero/src/IceTargetLoweringX8664Traits.h - x86-64 traits -*- C++ -*-=//
3 // The Subzero Code Generator
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief Declares the X8664 Target Lowering Traits.
13 //===----------------------------------------------------------------------===//
15 #ifndef SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H
16 #define SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H
18 #include "IceAssembler.h"
19 #include "IceConditionCodesX8664.h"
22 #include "IceInstX8664.def"
23 #include "IceOperand.h"
24 #include "IceRegistersX8664.h"
25 #include "IceTargetLowering.h"
26 #include "IceTargetLoweringX8664.def"
27 #include "IceTargetLoweringX86RegClass.h"
30 #include <initializer_list>
35 using namespace ::Ice::X86;
37 template <class TraitsType> class AssemblerX86Base;
38 template <class TraitsType> struct Insts;
39 template <class TraitsType> class TargetX86Base;
43 struct TargetX8664Traits {
44 //----------------------------------------------------------------------------
45 // ______ ______ __ __
46 // /\ __ \/\ ___\/\ "-./ \
47 // \ \ __ \ \___ \ \ \-./\ \
48 // \ \_\ \_\/\_____\ \_\ \ \_\
49 // \/_/\/_/\/_____/\/_/ \/_/
51 //----------------------------------------------------------------------------
52 static constexpr ::Ice::Assembler::AssemblerKind AsmKind =
53 ::Ice::Assembler::Asm_X8632;
55 static constexpr bool Is64Bit = true;
56 static constexpr bool HasPopa = false;
57 static constexpr bool HasPusha = false;
58 static constexpr bool UsesX87 = false;
59 static constexpr ::Ice::RegX8664::GPRRegister Last8BitGPR =
60 ::Ice::RegX8664::GPRRegister::Encoded_Reg_r15d;
62 enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
64 using GPRRegister = ::Ice::RegX8664::GPRRegister;
65 using ByteRegister = ::Ice::RegX8664::ByteRegister;
66 using XmmRegister = ::Ice::RegX8664::XmmRegister;
68 using Cond = ::Ice::CondX8664;
70 using RegisterSet = ::Ice::RegX8664;
71 static constexpr RegisterSet::AllRegisters StackPtr = RegX8664::Reg_rsp;
72 static constexpr RegisterSet::AllRegisters FramePtr = RegX8664::Reg_rbp;
73 static constexpr GPRRegister Encoded_Reg_Accumulator =
74 RegX8664::Encoded_Reg_eax;
75 static constexpr GPRRegister Encoded_Reg_Counter = RegX8664::Encoded_Reg_ecx;
76 static constexpr FixupKind FK_PcRel = llvm::ELF::R_X86_64_PC32;
77 static constexpr FixupKind FK_Abs = llvm::ELF::R_X86_64_32S;
78 static constexpr FixupKind FK_Gotoff = llvm::ELF::R_X86_64_GOTOFF64;
79 static constexpr FixupKind FK_GotPC = llvm::ELF::R_X86_64_GOTPC32;
86 RexW = RexBase | (1 << 3),
87 RexR = RexBase | (1 << 2),
88 RexX = RexBase | (1 << 1),
89 RexB = RexBase | (1 << 0),
93 // Needed by subclass Address.
97 Operand(const Operand &) = default;
98 Operand(Operand &&) = default;
99 Operand &operator=(const Operand &) = default;
100 Operand &operator=(Operand &&) = default;
102 uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
104 uint8_t rexX() const { return (rex_ & RexX) != RexX ? RexNone : RexX; }
105 uint8_t rexB() const { return (rex_ & RexB) != RexB ? RexNone : RexB; }
107 GPRRegister rm() const {
108 return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) |
109 (encoding_at(0) & 7));
112 ScaleFactor scale() const {
113 return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
116 GPRRegister index() const {
117 return static_cast<GPRRegister>((rexX() != 0 ? 0x08 : 0) |
118 ((encoding_at(1) >> 3) & 7));
121 GPRRegister base() const {
122 return static_cast<GPRRegister>((rexB() != 0 ? 0x08 : 0) |
123 (encoding_at(1) & 7));
126 int8_t disp8() const {
127 assert(length_ >= 2);
128 return static_cast<int8_t>(encoding_[length_ - 1]);
131 AssemblerFixup *fixup() const { return fixup_; }
134 void SetModRM(int mod, GPRRegister rm) {
135 assert((mod & ~3) == 0);
136 encoding_[0] = (mod << 6) | (rm & 0x07);
137 rex_ = (rm & 0x08) ? RexB : RexNone;
141 void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
142 assert(length_ == 1);
143 assert((scale & ~3) == 0);
144 encoding_[1] = (scale << 6) | ((index & 0x07) << 3) | (base & 0x07);
146 ((base & 0x08) ? RexB : RexNone) | ((index & 0x08) ? RexX : RexNone);
150 void SetDisp8(int8_t disp) {
151 assert(length_ == 1 || length_ == 2);
152 encoding_[length_++] = static_cast<uint8_t>(disp);
155 void SetDisp32(int32_t disp) {
156 assert(length_ == 1 || length_ == 2);
157 intptr_t disp_size = sizeof(disp);
158 memmove(&encoding_[length_], &disp, disp_size);
159 length_ += disp_size;
162 void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
165 AssemblerFixup *fixup_ = nullptr;
167 uint8_t encoding_[6];
170 explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
172 /// Get the operand encoding byte at the given index.
173 uint8_t encoding_at(intptr_t index) const {
174 assert(index >= 0 && index < length_);
175 return encoding_[index];
178 /// Returns whether or not this operand is really the given register in
179 /// disguise. Used from the assembler to generate better encodings.
180 bool IsRegister(GPRRegister reg) const {
181 return ((encoding_[0] & 0xF8) ==
182 0xC0) // Addressing mode is register only.
184 (rm() == reg); // Register codes match.
187 friend class AssemblerX86Base<TargetX8664Traits>;
190 class Address : public Operand {
194 Address(const Address &) = default;
195 Address(Address &&) = default;
196 Address &operator=(const Address &) = default;
197 Address &operator=(Address &&) = default;
199 Address(GPRRegister Base, int32_t Disp, AssemblerFixup *Fixup) {
200 if (Fixup == nullptr && Disp == 0 &&
201 (Base & 7) != RegX8664::Encoded_Reg_rbp) {
203 if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
204 SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
205 } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
207 if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
208 SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
212 if ((Base & 7) == RegX8664::Encoded_Reg_rsp)
213 SetSIB(TIMES_1, RegX8664::Encoded_Reg_rsp, Base);
220 Address(GPRRegister Index, ScaleFactor Scale, int32_t Disp,
221 AssemblerFixup *Fixup) {
222 assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
223 SetModRM(0, RegX8664::Encoded_Reg_rsp);
224 SetSIB(Scale, Index, RegX8664::Encoded_Reg_rbp);
230 Address(GPRRegister Base, GPRRegister Index, ScaleFactor Scale,
231 int32_t Disp, AssemblerFixup *Fixup) {
232 assert(Index != RegX8664::Encoded_Reg_rsp); // Illegal addressing mode.
233 if (Fixup == nullptr && Disp == 0 &&
234 (Base & 7) != RegX8664::Encoded_Reg_rbp) {
235 SetModRM(0, RegX8664::Encoded_Reg_rsp);
236 SetSIB(Scale, Index, Base);
237 } else if (Fixup == nullptr && Utils::IsInt(8, Disp)) {
238 SetModRM(1, RegX8664::Encoded_Reg_rsp);
239 SetSIB(Scale, Index, Base);
242 SetModRM(2, RegX8664::Encoded_Reg_rsp);
243 SetSIB(Scale, Index, Base);
250 /// Generate a RIP-relative address expression on x86-64.
251 static Address RipRelative(RelocOffsetT Offset, AssemblerFixup *Fixup) {
252 assert(Fixup != nullptr);
253 assert(Fixup->kind() == FK_PcRel);
255 NewAddress.SetModRM(0x0, RegX8664::Encoded_Reg_rbp);
257 // Use the Offset in the displacement for now. If we decide to process
258 // fixups later, we'll need to patch up the emitted displacement.
259 NewAddress.SetDisp32(Offset);
261 NewAddress.SetFixup(Fixup);
266 /// Generate an absolute address.
267 static Address Absolute(RelocOffsetT Addr) {
269 NewAddress.SetModRM(0x0, RegX8664::Encoded_Reg_rsp);
270 static constexpr ScaleFactor NoScale = TIMES_1;
271 NewAddress.SetSIB(NoScale, RegX8664::Encoded_Reg_rsp,
272 RegX8664::Encoded_Reg_rbp);
273 NewAddress.SetDisp32(Addr);
277 static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
279 AssemblerFixup *Fixup = Asm->createFixup(FK_Abs, Imm);
280 const RelocOffsetT Offset = 4;
281 return Address::RipRelative(Offset, Fixup);
285 //----------------------------------------------------------------------------
286 // __ ______ __ __ ______ ______ __ __ __ ______
287 // /\ \ /\ __ \/\ \ _ \ \/\ ___\/\ == \/\ \/\ "-.\ \/\ ___\
288 // \ \ \___\ \ \/\ \ \ \/ ".\ \ \ __\\ \ __<\ \ \ \ \-. \ \ \__ \
289 // \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
290 // \/_____/\/_____/\/_/ \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
292 //----------------------------------------------------------------------------
293 enum InstructionSet {
295 // SSE2 is the PNaCl baseline instruction set.
301 static const char *TargetName;
302 static constexpr Type WordType = IceType_i64;
304 static const char *getRegName(RegNumT RegNum) {
305 static const char *const RegNames[RegisterSet::Reg_NUM] = {
306 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
307 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
308 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
313 RegNum.assertIsValid();
314 return RegNames[RegNum];
317 static GPRRegister getEncodedGPR(RegNumT RegNum) {
318 static const GPRRegister GPRRegs[RegisterSet::Reg_NUM] = {
319 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
320 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
321 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
322 GPRRegister(isGPR ? encode : GPRRegister::Encoded_Not_GPR),
326 RegNum.assertIsValid();
327 assert(GPRRegs[RegNum] != GPRRegister::Encoded_Not_GPR);
328 return GPRRegs[RegNum];
331 static ByteRegister getEncodedByteReg(RegNumT RegNum) {
332 static const ByteRegister ByteRegs[RegisterSet::Reg_NUM] = {
333 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
334 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
335 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
336 ByteRegister(is8 ? encode : ByteRegister::Encoded_Not_ByteReg),
340 RegNum.assertIsValid();
341 assert(ByteRegs[RegNum] != ByteRegister::Encoded_Not_ByteReg);
342 return ByteRegs[RegNum];
345 static XmmRegister getEncodedXmm(RegNumT RegNum) {
346 static const XmmRegister XmmRegs[RegisterSet::Reg_NUM] = {
347 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
348 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
349 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
350 XmmRegister(isXmm ? encode : XmmRegister::Encoded_Not_Xmm),
354 RegNum.assertIsValid();
355 assert(XmmRegs[RegNum] != XmmRegister::Encoded_Not_Xmm);
356 return XmmRegs[RegNum];
359 static uint32_t getEncoding(RegNumT RegNum) {
360 static const uint32_t Encoding[RegisterSet::Reg_NUM] = {
361 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
362 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
363 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
368 RegNum.assertIsValid();
369 return Encoding[RegNum];
372 static inline RegNumT getBaseReg(RegNumT RegNum) {
373 static const RegNumT BaseRegs[RegisterSet::Reg_NUM] = {
374 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
375 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
376 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
381 RegNum.assertIsValid();
382 return BaseRegs[RegNum];
386 static RegNumT getFirstGprForType(Type Ty) {
389 llvm_unreachable("Invalid type for GPR.");
392 return RegisterSet::Reg_al;
394 return RegisterSet::Reg_ax;
396 return RegisterSet::Reg_eax;
398 return RegisterSet::Reg_rax;
403 static RegNumT getGprForType(Type Ty, RegNumT RegNum) {
404 assert(RegNum.hasValue());
406 if (!isScalarIntegerType(Ty)) {
410 assert(Ty == IceType_i1 || Ty == IceType_i8 || Ty == IceType_i16 ||
411 Ty == IceType_i32 || Ty == IceType_i64);
413 if (RegNum == RegisterSet::Reg_ah) {
414 assert(Ty == IceType_i8);
418 assert(RegNum != RegisterSet::Reg_bh);
419 assert(RegNum != RegisterSet::Reg_ch);
420 assert(RegNum != RegisterSet::Reg_dh);
422 const RegNumT FirstGprForType = getFirstGprForType(Ty);
426 llvm::report_fatal_error("Unknown register.");
427 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
428 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
429 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
430 case RegisterSet::val: { \
432 return RegisterSet::val; \
433 assert((is64) || (is32) || (is16) || (is8) || \
434 getBaseReg(RegisterSet::val) == RegisterSet::Reg_rsp); \
435 constexpr RegisterSet::AllRegisters FirstGprWithRegNumSize = \
436 ((is64) || RegisterSet::val == RegisterSet::Reg_rsp) \
437 ? RegisterSet::Reg_rax \
438 : (((is32) || RegisterSet::val == RegisterSet::Reg_esp) \
439 ? RegisterSet::Reg_eax \
440 : (((is16) || RegisterSet::val == RegisterSet::Reg_sp) \
441 ? RegisterSet::Reg_ax \
442 : RegisterSet::Reg_al)); \
443 const auto NewRegNum = \
444 RegNumT::fixme(RegNum - FirstGprWithRegNumSize + FirstGprForType); \
445 assert(getBaseReg(RegNum) == getBaseReg(NewRegNum) && \
446 "Error involving " #val); \
455 /// SizeOf is used to obtain the size of an initializer list as a constexpr
456 /// expression. This is only needed until our C++ library is updated to
457 /// C++ 14 -- which defines constexpr members to std::initializer_list.
459 SizeOf(const SizeOf &) = delete;
460 SizeOf &operator=(const SizeOf &) = delete;
463 constexpr SizeOf() : Size(0) {}
464 template <typename... T>
465 explicit constexpr SizeOf(T...)
466 : Size(length<T...>::value) {}
467 constexpr SizeT size() const { return Size; }
470 template <typename T, typename... U> struct length {
471 static constexpr std::size_t value = 1 + length<U...>::value;
474 template <typename T> struct length<T> {
475 static constexpr std::size_t value = 1;
478 const std::size_t Size;
482 static void initRegisterSet(
483 const ::Ice::ClFlags &Flags,
484 std::array<SmallBitVector, RCX86_NUM> *TypeToRegisterSet,
485 std::array<SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases) {
486 SmallBitVector IntegerRegistersI64(RegisterSet::Reg_NUM);
487 SmallBitVector IntegerRegistersI32(RegisterSet::Reg_NUM);
488 SmallBitVector IntegerRegistersI16(RegisterSet::Reg_NUM);
489 SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
490 SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
491 SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
492 SmallBitVector Trunc64To8Registers(RegisterSet::Reg_NUM);
493 SmallBitVector Trunc32To8Registers(RegisterSet::Reg_NUM);
494 SmallBitVector Trunc16To8Registers(RegisterSet::Reg_NUM);
495 SmallBitVector Trunc8RcvrRegisters(RegisterSet::Reg_NUM);
496 SmallBitVector AhRcvrRegisters(RegisterSet::Reg_NUM);
497 SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
499 static constexpr struct {
501 unsigned IsReservedWhenSandboxing : 1;
507 unsigned Is64To8 : 1;
508 unsigned Is32To8 : 1;
509 unsigned Is16To8 : 1;
510 unsigned IsTrunc8Rcvr : 1;
511 unsigned IsAhRcvr : 1;
512 #define NUM_ALIASES_BITS 2
513 SizeT NumAliases : (NUM_ALIASES_BITS + 1);
514 uint16_t Aliases[1 << NUM_ALIASES_BITS];
515 #undef NUM_ALIASES_BITS
516 } X8664RegTable[RegisterSet::Reg_NUM] = {
517 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
518 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
519 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
521 RegisterSet::val, sboxres, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
522 is16To8, isTrunc8Rcvr, isAhRcvr, (SizeOf aliases).size(), aliases, \
529 const bool NeedSandboxing = Flags.getUseSandboxing();
530 for (SizeT ii = 0; ii < llvm::array_lengthof(X8664RegTable); ++ii) {
531 const auto &Entry = X8664RegTable[ii];
532 // Even though the register is disabled for register allocation, it might
533 // still be used by the Target Lowering (e.g., base pointer), so the
534 // register alias table still needs to be defined.
535 (*RegisterAliases)[Entry.Val].resize(RegisterSet::Reg_NUM);
536 for (int J = 0; J < Entry.NumAliases; ++J) {
537 SizeT Alias = Entry.Aliases[J];
538 assert(!(*RegisterAliases)[Entry.Val][Alias] && "Duplicate alias");
539 (*RegisterAliases)[Entry.Val].set(Alias);
542 (*RegisterAliases)[Entry.Val].set(Entry.Val);
543 const bool DisabledRegister =
544 NeedSandboxing && Entry.IsReservedWhenSandboxing;
545 if (DisabledRegister) {
548 (IntegerRegistersI64)[Entry.Val] = Entry.Is64;
549 (IntegerRegistersI32)[Entry.Val] = Entry.Is32;
550 (IntegerRegistersI16)[Entry.Val] = Entry.Is16;
551 (IntegerRegistersI8)[Entry.Val] = Entry.Is8;
552 (FloatRegisters)[Entry.Val] = Entry.IsXmm;
553 (VectorRegisters)[Entry.Val] = Entry.IsXmm;
554 (Trunc64To8Registers)[Entry.Val] = Entry.Is64To8;
555 (Trunc32To8Registers)[Entry.Val] = Entry.Is32To8;
556 (Trunc16To8Registers)[Entry.Val] = Entry.Is16To8;
557 (Trunc8RcvrRegisters)[Entry.Val] = Entry.IsTrunc8Rcvr;
558 (AhRcvrRegisters)[Entry.Val] = Entry.IsAhRcvr;
561 (*TypeToRegisterSet)[RC_void] = InvalidRegisters;
562 (*TypeToRegisterSet)[RC_i1] = IntegerRegistersI8;
563 (*TypeToRegisterSet)[RC_i8] = IntegerRegistersI8;
564 (*TypeToRegisterSet)[RC_i16] = IntegerRegistersI16;
565 (*TypeToRegisterSet)[RC_i32] = IntegerRegistersI32;
566 (*TypeToRegisterSet)[RC_i64] = IntegerRegistersI64;
567 (*TypeToRegisterSet)[RC_f32] = FloatRegisters;
568 (*TypeToRegisterSet)[RC_f64] = FloatRegisters;
569 (*TypeToRegisterSet)[RC_v4i1] = VectorRegisters;
570 (*TypeToRegisterSet)[RC_v8i1] = VectorRegisters;
571 (*TypeToRegisterSet)[RC_v16i1] = VectorRegisters;
572 (*TypeToRegisterSet)[RC_v16i8] = VectorRegisters;
573 (*TypeToRegisterSet)[RC_v8i16] = VectorRegisters;
574 (*TypeToRegisterSet)[RC_v4i32] = VectorRegisters;
575 (*TypeToRegisterSet)[RC_v4f32] = VectorRegisters;
576 (*TypeToRegisterSet)[RCX86_Is64To8] = Trunc64To8Registers;
577 (*TypeToRegisterSet)[RCX86_Is32To8] = Trunc32To8Registers;
578 (*TypeToRegisterSet)[RCX86_Is16To8] = Trunc16To8Registers;
579 (*TypeToRegisterSet)[RCX86_IsTrunc8Rcvr] = Trunc8RcvrRegisters;
580 (*TypeToRegisterSet)[RCX86_IsAhRcvr] = AhRcvrRegisters;
583 static SmallBitVector getRegisterSet(const ::Ice::ClFlags &Flags,
584 TargetLowering::RegSetMask Include,
585 TargetLowering::RegSetMask Exclude) {
586 SmallBitVector Registers(RegisterSet::Reg_NUM);
588 const bool NeedSandboxing = Flags.getUseSandboxing();
589 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
590 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
591 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
592 if (!NeedSandboxing || !(sboxres)) { \
593 if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave)) \
594 Registers[RegisterSet::val] = true; \
595 if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave)) \
596 Registers[RegisterSet::val] = true; \
597 if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer)) \
598 Registers[RegisterSet::val] = true; \
599 if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer)) \
600 Registers[RegisterSet::val] = true; \
601 if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave)) \
602 Registers[RegisterSet::val] = false; \
603 if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave)) \
604 Registers[RegisterSet::val] = false; \
605 if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer)) \
606 Registers[RegisterSet::val] = false; \
607 if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer)) \
608 Registers[RegisterSet::val] = false; \
618 static void makeRandomRegisterPermutation(
619 Cfg *Func, llvm::SmallVectorImpl<RegNumT> &Permutation,
620 const SmallBitVector &ExcludeRegisters, uint64_t Salt) {
621 // TODO(stichnot): Declaring Permutation this way loses type/size
622 // information. Fix this in conjunction with the caller-side TODO.
623 assert(Permutation.size() >= RegisterSet::Reg_NUM);
624 // Expected upper bound on the number of registers in a single equivalence
625 // class. For x86-64, this would comprise the 16 XMM registers. This is
626 // for performance, not correctness.
627 static const unsigned MaxEquivalenceClassSize = 8;
628 using RegisterList = llvm::SmallVector<RegNumT, MaxEquivalenceClassSize>;
629 using EquivalenceClassMap = std::map<uint32_t, RegisterList>;
630 EquivalenceClassMap EquivalenceClasses;
631 SizeT NumShuffled = 0, NumPreserved = 0;
633 // Build up the equivalence classes of registers by looking at the register
634 // properties as well as whether the registers should be explicitly excluded
636 #define X(val, encode, name, base, scratch, preserved, stackptr, frameptr, \
637 sboxres, isGPR, is64, is32, is16, is8, isXmm, is64To8, is32To8, \
638 is16To8, isTrunc8Rcvr, isAhRcvr, aliases) \
639 if (ExcludeRegisters[RegisterSet::val]) { \
640 /* val stays the same in the resulting permutation. */ \
641 Permutation[RegisterSet::val] = RegisterSet::val; \
644 uint32_t AttrKey = 0; \
645 uint32_t Index = 0; \
646 /* Combine relevant attributes into an equivalence class key. */ \
647 Index |= (scratch << (AttrKey++)); \
648 Index |= (preserved << (AttrKey++)); \
649 Index |= (is8 << (AttrKey++)); \
650 Index |= (is16 << (AttrKey++)); \
651 Index |= (is32 << (AttrKey++)); \
652 Index |= (is64 << (AttrKey++)); \
653 Index |= (isXmm << (AttrKey++)); \
654 Index |= (is16To8 << (AttrKey++)); \
655 Index |= (is32To8 << (AttrKey++)); \
656 Index |= (is64To8 << (AttrKey++)); \
657 Index |= (isTrunc8Rcvr << (AttrKey++)); \
658 /* val is assigned to an equivalence class based on its properties. */ \
659 EquivalenceClasses[Index].push_back(RegisterSet::val); \
664 // Create a random number generator for regalloc randomization.
665 RandomNumberGenerator RNG(getFlags().getRandomSeed(),
666 RPE_RegAllocRandomization, Salt);
667 RandomNumberGeneratorWrapper RNGW(RNG);
669 // Shuffle the resulting equivalence classes.
670 for (auto I : EquivalenceClasses) {
671 const RegisterList &List = I.second;
672 RegisterList Shuffled(List);
673 RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW);
674 for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
675 Permutation[List[SI]] = Shuffled[SI];
680 assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM);
682 if (Func->isVerbose(IceV_Random)) {
683 OstreamLocker L(Func->getContext());
684 Ostream &Str = Func->getContext()->getStrDump();
685 Str << "Register equivalence classes:\n";
686 for (auto I : EquivalenceClasses) {
688 const RegisterList &List = I.second;
690 for (RegNumT Register : List) {
694 Str << getRegName(Register);
701 static RegNumT getRaxOrDie() { return RegisterSet::Reg_rax; }
703 static RegNumT getRdxOrDie() { return RegisterSet::Reg_rdx; }
705 // x86-64 calling convention:
707 // * The first eight arguments of vector/fp type, regardless of their
708 // position relative to the other arguments in the argument list, are placed
709 // in registers %xmm0 - %xmm7.
711 // * The first six arguments of integer types, regardless of their position
712 // relative to the other arguments in the argument list, are placed in
713 // registers %rdi, %rsi, %rdx, %rcx, %r8, and %r9.
715 // This intends to match the section "Function Calling Sequence" of the
716 // document "System V Application Binary Interface."
718 /// The maximum number of arguments to pass in XMM registers
719 static constexpr uint32_t X86_MAX_XMM_ARGS = 8;
720 /// The maximum number of arguments to pass in GPR registers
721 static constexpr uint32_t X86_MAX_GPR_ARGS = 6;
722 /// Whether scalar floating point arguments are passed in XMM registers
723 static constexpr bool X86_PASS_SCALAR_FP_IN_XMM = true;
724 /// Get the register for a given argument slot in the XMM registers.
725 static RegNumT getRegisterForXmmArgNum(uint32_t ArgNum) {
726 // TODO(sehr): Change to use the CCArg technique used in ARM32.
727 static_assert(RegisterSet::Reg_xmm0 + 1 == RegisterSet::Reg_xmm1,
728 "Inconsistency between XMM register numbers and ordinals");
729 if (ArgNum >= X86_MAX_XMM_ARGS) {
732 return RegNumT::fixme(RegisterSet::Reg_xmm0 + ArgNum);
734 /// Get the register for a given argument slot in the GPRs.
735 static RegNumT getRegisterForGprArgNum(Type Ty, uint32_t ArgNum) {
736 if (ArgNum >= X86_MAX_GPR_ARGS) {
739 static const RegisterSet::AllRegisters GprForArgNum[] = {
740 RegisterSet::Reg_rdi, RegisterSet::Reg_rsi, RegisterSet::Reg_rdx,
741 RegisterSet::Reg_rcx, RegisterSet::Reg_r8, RegisterSet::Reg_r9,
743 static_assert(llvm::array_lengthof(GprForArgNum) == X86_MAX_GPR_ARGS,
744 "Mismatch between MAX_GPR_ARGS and GprForArgNum.");
745 assert(Ty == IceType_i64 || Ty == IceType_i32);
746 return getGprForType(Ty, GprForArgNum[ArgNum]);
749 /// The number of bits in a byte
750 static constexpr uint32_t X86_CHAR_BIT = 8;
751 /// Stack alignment. This is defined in IceTargetLoweringX8664.cpp because it
752 /// is used as an argument to std::max(), and the default std::less<T> has an
753 /// operator(T const&, T const&) which requires this member to have an
755 static const uint32_t X86_STACK_ALIGNMENT_BYTES;
756 /// Size of the return address on the stack
757 static constexpr uint32_t X86_RET_IP_SIZE_BYTES = 8;
758 /// The number of different NOP instructions
759 static constexpr uint32_t X86_NUM_NOP_VARIANTS = 5;
761 /// \name Limits for unrolling memory intrinsics.
763 static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
764 static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
765 static constexpr uint32_t MEMSET_UNROLL_LIMIT = 16;
768 /// Value is in bytes. Return Value adjusted to the next highest multiple of
769 /// the stack alignment.
770 static uint32_t applyStackAlignment(uint32_t Value) {
771 return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
774 /// Return the type which the elements of the vector have in the X86
775 /// representation of the vector.
776 static Type getInVectorElementType(Type Ty) {
777 assert(isVectorType(Ty));
778 assert(Ty < TableTypeX8664AttributesSize);
779 return TableTypeX8664Attributes[Ty].InVectorElementType;
782 // Note: The following data structures are defined in
783 // IceTargetLoweringX8664.cpp.
785 /// The following table summarizes the logic for lowering the fcmp
786 /// instruction. There is one table entry for each of the 16 conditions.
788 /// The first four columns describe the case when the operands are floating
789 /// point scalar values. A comment in lowerFcmp() describes the lowering
790 /// template. In the most general case, there is a compare followed by two
791 /// conditional branches, because some fcmp conditions don't map to a single
792 /// x86 conditional branch. However, in many cases it is possible to swap the
793 /// operands in the comparison and have a single conditional branch. Since
794 /// it's quite tedious to validate the table by hand, good execution tests are
797 /// The last two columns describe the case when the operands are vectors of
798 /// floating point values. For most fcmp conditions, there is a clear mapping
799 /// to a single x86 cmpps instruction variant. Some fcmp conditions require
800 /// special code to handle and these are marked in the table with a
801 /// Cmpps_Invalid predicate.
803 static const struct TableFcmpType {
805 bool SwapScalarOperands;
807 bool SwapVectorOperands;
808 Cond::CmppsCond Predicate;
810 static const size_t TableFcmpSize;
813 /// The following table summarizes the logic for lowering the icmp instruction
814 /// for i32 and narrower types. Each icmp condition has a clear mapping to an
815 /// x86 conditional branch instruction.
817 static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[];
818 static const size_t TableIcmp32Size;
821 /// The following table summarizes the logic for lowering the icmp instruction
822 /// for the i64 type. For Eq and Ne, two separate 32-bit comparisons and
823 /// conditional branches are needed. For the other conditions, three separate
824 /// conditional branches are needed.
826 static const struct TableIcmp64Type {
827 Cond::BrCond C1, C2, C3;
829 static const size_t TableIcmp64Size;
832 static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
833 assert(Cond < TableIcmp32Size);
834 return TableIcmp32[Cond].Mapping;
837 static const struct TableTypeX8664AttributesType {
838 Type InVectorElementType;
839 } TableTypeX8664Attributes[];
840 static const size_t TableTypeX8664AttributesSize;
842 //----------------------------------------------------------------------------
843 // __ __ __ ______ ______
844 // /\ \/\ "-.\ \/\ ___\/\__ _\
845 // \ \ \ \ \-. \ \___ \/_/\ \/
846 // \ \_\ \_\\"\_\/\_____\ \ \_\
847 // \/_/\/_/ \/_/\/_____/ \/_/
849 //----------------------------------------------------------------------------
850 using Traits = TargetX8664Traits;
851 using Insts = ::Ice::X8664::Insts<Traits>;
853 using TargetLowering = ::Ice::X8664::TargetX86Base<Traits>;
854 using ConcreteTarget = ::Ice::X8664::TargetX8664;
855 using Assembler = ::Ice::X8664::AssemblerX86Base<Traits>;
857 /// X86Operand extends the Operand hierarchy. Its subclasses are X86OperandMem
858 /// and VariableSplit.
859 class X86Operand : public ::Ice::Operand {
860 X86Operand() = delete;
861 X86Operand(const X86Operand &) = delete;
862 X86Operand &operator=(const X86Operand &) = delete;
865 enum OperandKindX8664 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit };
866 using ::Ice::Operand::dump;
868 void dump(const Cfg *, Ostream &Str) const override;
871 X86Operand(OperandKindX8664 Kind, Type Ty)
872 : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {}
875 /// X86OperandMem represents the m64 addressing mode, with optional base and
876 /// index registers, a constant offset, and a fixed shift value for the index
878 class X86OperandMem : public X86Operand {
879 X86OperandMem() = delete;
880 X86OperandMem(const X86OperandMem &) = delete;
881 X86OperandMem &operator=(const X86OperandMem &) = delete;
884 enum SegmentRegisters { DefaultSegment = -1, SegReg_NUM };
885 static X86OperandMem *
886 create(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
887 Variable *Index = nullptr, uint16_t Shift = 0,
888 SegmentRegisters SegmentRegister = DefaultSegment,
889 bool IsRebased = false) {
890 assert(SegmentRegister == DefaultSegment);
891 (void)SegmentRegister;
892 return new (Func->allocate<X86OperandMem>())
893 X86OperandMem(Func, Ty, Base, Offset, Index, Shift, IsRebased);
895 static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
896 Constant *Offset, bool IsRebased) {
897 constexpr Variable *NoIndex = nullptr;
898 constexpr uint16_t NoShift = 0;
899 return new (Func->allocate<X86OperandMem>())
900 X86OperandMem(Func, Ty, Base, Offset, NoIndex, NoShift, IsRebased);
902 Variable *getBase() const { return Base; }
903 Constant *getOffset() const { return Offset; }
904 Variable *getIndex() const { return Index; }
905 uint16_t getShift() const { return Shift; }
906 SegmentRegisters getSegmentRegister() const { return DefaultSegment; }
907 void emitSegmentOverride(Assembler *) const {}
908 bool getIsRebased() const { return IsRebased; }
909 Address toAsmAddress(Assembler *Asm, const Ice::TargetLowering *Target,
910 bool IsLeaAddr = false) const;
912 void emit(const Cfg *Func) const override;
913 using X86Operand::dump;
914 void dump(const Cfg *Func, Ostream &Str) const override;
916 static bool classof(const Operand *Operand) {
917 return Operand->getKind() == static_cast<OperandKind>(kMem);
920 void setRandomized(bool R) { Randomized = R; }
922 bool getRandomized() const { return Randomized; }
925 X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
926 Variable *Index, uint16_t Shift, bool IsRebased);
928 Variable *const Base;
929 Constant *const Offset;
930 Variable *const Index;
931 const uint16_t Shift;
932 const bool IsRebased;
933 /// A flag to show if this memory operand is a randomized one. Randomized
934 /// memory operands are generated in
935 /// TargetX86Base::randomizeOrPoolImmediate()
936 bool Randomized = false;
939 /// VariableSplit is a way to treat an f64 memory location as a pair of i32
940 /// locations (Low and High). This is needed for some cases of the Bitcast
941 /// instruction. Since it's not possible for integer registers to access the
942 /// XMM registers and vice versa, the lowering forces the f64 to be spilled to
943 /// the stack and then accesses through the VariableSplit.
944 // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit
945 // targets can natively handle these.
946 class VariableSplit : public X86Operand {
947 VariableSplit() = delete;
948 VariableSplit(const VariableSplit &) = delete;
949 VariableSplit &operator=(const VariableSplit &) = delete;
952 enum Portion { Low, High };
953 static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
954 return new (Func->allocate<VariableSplit>())
955 VariableSplit(Func, Var, Part);
957 int32_t getOffset() const { return Part == High ? 4 : 0; }
959 Address toAsmAddress(const Cfg *Func) const;
960 void emit(const Cfg *Func) const override;
961 using X86Operand::dump;
962 void dump(const Cfg *Func, Ostream &Str) const override;
964 static bool classof(const Operand *Operand) {
965 return Operand->getKind() == static_cast<OperandKind>(kSplit);
969 VariableSplit(Cfg *Func, Variable *Var, Portion Part)
970 : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) {
971 assert(Var->getType() == IceType_f64);
972 Vars = Func->allocateArrayOf<Variable *>(1);
981 /// SpillVariable decorates a Variable by linking it to another Variable. When
982 /// stack frame offsets are computed, the SpillVariable is given a distinct
983 /// stack slot only if its linked Variable has a register. If the linked
984 /// Variable has a stack slot, then the Variable and SpillVariable share that
986 class SpillVariable : public Variable {
987 SpillVariable() = delete;
988 SpillVariable(const SpillVariable &) = delete;
989 SpillVariable &operator=(const SpillVariable &) = delete;
992 static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) {
993 return new (Func->allocate<SpillVariable>())
994 SpillVariable(Func, Ty, Index);
996 constexpr static auto SpillVariableKind =
997 static_cast<OperandKind>(kVariable_Target);
998 static bool classof(const Operand *Operand) {
999 return Operand->getKind() == SpillVariableKind;
1001 void setLinkedTo(Variable *Var) { LinkedTo = Var; }
1002 Variable *getLinkedTo() const { return LinkedTo; }
1003 // Inherit dump() and emit() from Variable.
1006 SpillVariable(const Cfg *Func, Type Ty, SizeT Index)
1007 : Variable(Func, SpillVariableKind, Ty, Index), LinkedTo(nullptr) {}
1011 // Note: The following data structures are defined in IceInstX8664.cpp.
1013 static const struct InstBrAttributesType {
1014 Cond::BrCond Opposite;
1015 const char *DisplayString;
1016 const char *EmitString;
1017 } InstBrAttributes[];
1019 static const struct InstCmppsAttributesType {
1020 const char *EmitString;
1021 } InstCmppsAttributes[];
1023 static const struct TypeAttributesType {
1024 const char *CvtString; // i (integer), s (single FP), d (double FP)
1025 const char *SdSsString; // ss, sd, or <blank>
1026 const char *PdPsString; // ps, pd, or <blank>
1027 const char *SpSdString; // ss, sd, ps, pd, or <blank>
1028 const char *PackString; // b, w, d, or <blank>
1029 const char *UnpackString; // bw, wd, dq, or <blank>
1030 const char *WidthString; // b, w, l, q, or <blank>
1031 const char *FldString; // s, l, or <blank>
1035 using Traits = ::Ice::X8664::TargetX8664Traits;
1036 } // end of namespace X8664
1038 } // end of namespace Ice
1040 #endif // SUBZERO_SRC_ICETARGETLOWERINGX8664TRAITS_H