IceTargetLoweringX8632Traits.h revision bb0a5fe31a71fdc5b3292d62169f428d531437a4
15d0acff3a2fa421923392aadb4df2742064b6248John Porto//===- subzero/src/IceTargetLoweringX8632Traits.h - x86-32 traits -*- C++ -*-=//
25d0acff3a2fa421923392aadb4df2742064b6248John Porto//
35d0acff3a2fa421923392aadb4df2742064b6248John Porto//                        The Subzero Code Generator
45d0acff3a2fa421923392aadb4df2742064b6248John Porto//
55d0acff3a2fa421923392aadb4df2742064b6248John Porto// This file is distributed under the University of Illinois Open Source
65d0acff3a2fa421923392aadb4df2742064b6248John Porto// License. See LICENSE.TXT for details.
75d0acff3a2fa421923392aadb4df2742064b6248John Porto//
85d0acff3a2fa421923392aadb4df2742064b6248John Porto//===----------------------------------------------------------------------===//
9921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto///
10921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto/// \file
11921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto/// This file declares the X8632 Target Lowering Traits.
12921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto///
135d0acff3a2fa421923392aadb4df2742064b6248John Porto//===----------------------------------------------------------------------===//
145d0acff3a2fa421923392aadb4df2742064b6248John Porto
155d0acff3a2fa421923392aadb4df2742064b6248John Porto#ifndef SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
165d0acff3a2fa421923392aadb4df2742064b6248John Porto#define SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
175d0acff3a2fa421923392aadb4df2742064b6248John Porto
185d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceAssembler.h"
195d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceConditionCodesX8632.h"
205d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceDefs.h"
215d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceInst.h"
225d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceInstX8632.def"
23921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#include "IceOperand.h"
245d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceRegistersX8632.h"
255d0acff3a2fa421923392aadb4df2742064b6248John Porto#include "IceTargetLoweringX8632.def"
26921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#include "IceTargetLowering.h"
275d0acff3a2fa421923392aadb4df2742064b6248John Porto
28bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto#include <array>
29bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto
305d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace Ice {
315d0acff3a2fa421923392aadb4df2742064b6248John Porto
325d0acff3a2fa421923392aadb4df2742064b6248John Portoclass TargetX8632;
335d0acff3a2fa421923392aadb4df2742064b6248John Porto
34921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Portonamespace X8632 {
35921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Portoclass AssemblerX8632;
36921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto} // end of namespace X8632
37921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
385d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace X86Internal {
395d0acff3a2fa421923392aadb4df2742064b6248John Porto
40921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Portotemplate <class Machine> struct Insts;
415d0acff3a2fa421923392aadb4df2742064b6248John Portotemplate <class Machine> struct MachineTraits;
425aeed955e17bac8cc44cc6d2b6ff7513cc714c2fJohn Portotemplate <class Machine> class TargetX86Base;
435d0acff3a2fa421923392aadb4df2742064b6248John Porto
445d0acff3a2fa421923392aadb4df2742064b6248John Portotemplate <> struct MachineTraits<TargetX8632> {
455d0acff3a2fa421923392aadb4df2742064b6248John Porto  //----------------------------------------------------------------------------
465d0acff3a2fa421923392aadb4df2742064b6248John Porto  //     ______  ______  __    __
475d0acff3a2fa421923392aadb4df2742064b6248John Porto  //    /\  __ \/\  ___\/\ "-./  \
485d0acff3a2fa421923392aadb4df2742064b6248John Porto  //    \ \  __ \ \___  \ \ \-./\ \
495d0acff3a2fa421923392aadb4df2742064b6248John Porto  //     \ \_\ \_\/\_____\ \_\ \ \_\
505d0acff3a2fa421923392aadb4df2742064b6248John Porto  //      \/_/\/_/\/_____/\/_/  \/_/
515d0acff3a2fa421923392aadb4df2742064b6248John Porto  //
525d0acff3a2fa421923392aadb4df2742064b6248John Porto  //----------------------------------------------------------------------------
532fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool Is64Bit = false;
542fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool HasPopa = true;
552fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool HasPusha = true;
562fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr bool UsesX87 = true;
572fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto  static constexpr ::Ice::RegX8632::GPRRegister Last8BitGPR =
582fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto      ::Ice::RegX8632::GPRRegister::Encoded_Reg_ebx;
592fea26cae5a6b140c67e18aec3dcf645a16694d5John Porto
605d0acff3a2fa421923392aadb4df2742064b6248John Porto  enum ScaleFactor { TIMES_1 = 0, TIMES_2 = 1, TIMES_4 = 2, TIMES_8 = 3 };
615d0acff3a2fa421923392aadb4df2742064b6248John Porto
625d0acff3a2fa421923392aadb4df2742064b6248John Porto  using GPRRegister = ::Ice::RegX8632::GPRRegister;
635d0acff3a2fa421923392aadb4df2742064b6248John Porto  using XmmRegister = ::Ice::RegX8632::XmmRegister;
645d0acff3a2fa421923392aadb4df2742064b6248John Porto  using ByteRegister = ::Ice::RegX8632::ByteRegister;
655d0acff3a2fa421923392aadb4df2742064b6248John Porto  using X87STRegister = ::Ice::RegX8632::X87STRegister;
665d0acff3a2fa421923392aadb4df2742064b6248John Porto
675d0acff3a2fa421923392aadb4df2742064b6248John Porto  using Cond = ::Ice::CondX86;
685d0acff3a2fa421923392aadb4df2742064b6248John Porto
695d0acff3a2fa421923392aadb4df2742064b6248John Porto  using RegisterSet = ::Ice::RegX8632;
705d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const GPRRegister Encoded_Reg_Accumulator = RegX8632::Encoded_Reg_eax;
715d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const GPRRegister Encoded_Reg_Counter = RegX8632::Encoded_Reg_ecx;
725d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const FixupKind PcRelFixup = llvm::ELF::R_386_PC32;
731d235425dab1f3dd059973fc53f1b1d5879469e3John Porto  static const FixupKind RelFixup = llvm::ELF::R_386_32;
745d0acff3a2fa421923392aadb4df2742064b6248John Porto
755d0acff3a2fa421923392aadb4df2742064b6248John Porto  class Operand {
765d0acff3a2fa421923392aadb4df2742064b6248John Porto  public:
775d0acff3a2fa421923392aadb4df2742064b6248John Porto    Operand(const Operand &other)
78921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        : fixup_(other.fixup_), length_(other.length_) {
795d0acff3a2fa421923392aadb4df2742064b6248John Porto      memmove(&encoding_[0], &other.encoding_[0], other.length_);
805d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
815d0acff3a2fa421923392aadb4df2742064b6248John Porto
825d0acff3a2fa421923392aadb4df2742064b6248John Porto    Operand &operator=(const Operand &other) {
835d0acff3a2fa421923392aadb4df2742064b6248John Porto      length_ = other.length_;
845d0acff3a2fa421923392aadb4df2742064b6248John Porto      fixup_ = other.fixup_;
855d0acff3a2fa421923392aadb4df2742064b6248John Porto      memmove(&encoding_[0], &other.encoding_[0], other.length_);
865d0acff3a2fa421923392aadb4df2742064b6248John Porto      return *this;
875d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
885d0acff3a2fa421923392aadb4df2742064b6248John Porto
895d0acff3a2fa421923392aadb4df2742064b6248John Porto    uint8_t mod() const { return (encoding_at(0) >> 6) & 3; }
905d0acff3a2fa421923392aadb4df2742064b6248John Porto
915d0acff3a2fa421923392aadb4df2742064b6248John Porto    GPRRegister rm() const {
925d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<GPRRegister>(encoding_at(0) & 7);
935d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
945d0acff3a2fa421923392aadb4df2742064b6248John Porto
955d0acff3a2fa421923392aadb4df2742064b6248John Porto    ScaleFactor scale() const {
965d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<ScaleFactor>((encoding_at(1) >> 6) & 3);
975d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
985d0acff3a2fa421923392aadb4df2742064b6248John Porto
995d0acff3a2fa421923392aadb4df2742064b6248John Porto    GPRRegister index() const {
1005d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<GPRRegister>((encoding_at(1) >> 3) & 7);
1015d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1025d0acff3a2fa421923392aadb4df2742064b6248John Porto
1035d0acff3a2fa421923392aadb4df2742064b6248John Porto    GPRRegister base() const {
1045d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<GPRRegister>(encoding_at(1) & 7);
1055d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1065d0acff3a2fa421923392aadb4df2742064b6248John Porto
1075d0acff3a2fa421923392aadb4df2742064b6248John Porto    int8_t disp8() const {
1085d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ >= 2);
1095d0acff3a2fa421923392aadb4df2742064b6248John Porto      return static_cast<int8_t>(encoding_[length_ - 1]);
1105d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1115d0acff3a2fa421923392aadb4df2742064b6248John Porto
1125d0acff3a2fa421923392aadb4df2742064b6248John Porto    int32_t disp32() const {
1135d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ >= 5);
1145d0acff3a2fa421923392aadb4df2742064b6248John Porto      return bit_copy<int32_t>(encoding_[length_ - 4]);
1155d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1165d0acff3a2fa421923392aadb4df2742064b6248John Porto
1175d0acff3a2fa421923392aadb4df2742064b6248John Porto    AssemblerFixup *fixup() const { return fixup_; }
1185d0acff3a2fa421923392aadb4df2742064b6248John Porto
1195d0acff3a2fa421923392aadb4df2742064b6248John Porto  protected:
120921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Operand() : fixup_(nullptr), length_(0) {} // Needed by subclass Address.
1215d0acff3a2fa421923392aadb4df2742064b6248John Porto
1225d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetModRM(int mod, GPRRegister rm) {
1235d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert((mod & ~3) == 0);
1245d0acff3a2fa421923392aadb4df2742064b6248John Porto      encoding_[0] = (mod << 6) | rm;
1255d0acff3a2fa421923392aadb4df2742064b6248John Porto      length_ = 1;
1265d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1275d0acff3a2fa421923392aadb4df2742064b6248John Porto
1285d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetSIB(ScaleFactor scale, GPRRegister index, GPRRegister base) {
1295d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ == 1);
1305d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert((scale & ~3) == 0);
1315d0acff3a2fa421923392aadb4df2742064b6248John Porto      encoding_[1] = (scale << 6) | (index << 3) | base;
1325d0acff3a2fa421923392aadb4df2742064b6248John Porto      length_ = 2;
1335d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1345d0acff3a2fa421923392aadb4df2742064b6248John Porto
1355d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetDisp8(int8_t disp) {
1365d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ == 1 || length_ == 2);
1375d0acff3a2fa421923392aadb4df2742064b6248John Porto      encoding_[length_++] = static_cast<uint8_t>(disp);
1385d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1395d0acff3a2fa421923392aadb4df2742064b6248John Porto
1405d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetDisp32(int32_t disp) {
1415d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(length_ == 1 || length_ == 2);
1425d0acff3a2fa421923392aadb4df2742064b6248John Porto      intptr_t disp_size = sizeof(disp);
1435d0acff3a2fa421923392aadb4df2742064b6248John Porto      memmove(&encoding_[length_], &disp, disp_size);
1445d0acff3a2fa421923392aadb4df2742064b6248John Porto      length_ += disp_size;
1455d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1465d0acff3a2fa421923392aadb4df2742064b6248John Porto
1475d0acff3a2fa421923392aadb4df2742064b6248John Porto    void SetFixup(AssemblerFixup *fixup) { fixup_ = fixup; }
1485d0acff3a2fa421923392aadb4df2742064b6248John Porto
1495d0acff3a2fa421923392aadb4df2742064b6248John Porto  private:
1505d0acff3a2fa421923392aadb4df2742064b6248John Porto    AssemblerFixup *fixup_;
151921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    uint8_t encoding_[6];
152921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    uint8_t length_;
1535d0acff3a2fa421923392aadb4df2742064b6248John Porto
1545d0acff3a2fa421923392aadb4df2742064b6248John Porto    explicit Operand(GPRRegister reg) : fixup_(nullptr) { SetModRM(3, reg); }
1555d0acff3a2fa421923392aadb4df2742064b6248John Porto
156921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// Get the operand encoding byte at the given index.
1575d0acff3a2fa421923392aadb4df2742064b6248John Porto    uint8_t encoding_at(intptr_t index) const {
1585d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(index >= 0 && index < length_);
1595d0acff3a2fa421923392aadb4df2742064b6248John Porto      return encoding_[index];
1605d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1615d0acff3a2fa421923392aadb4df2742064b6248John Porto
162921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// Returns whether or not this operand is really the given register in
163921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// disguise. Used from the assembler to generate better encodings.
1645d0acff3a2fa421923392aadb4df2742064b6248John Porto    bool IsRegister(GPRRegister reg) const {
1655d0acff3a2fa421923392aadb4df2742064b6248John Porto      return ((encoding_[0] & 0xF8) ==
1665d0acff3a2fa421923392aadb4df2742064b6248John Porto              0xC0) // Addressing mode is register only.
1675d0acff3a2fa421923392aadb4df2742064b6248John Porto             &&
1685d0acff3a2fa421923392aadb4df2742064b6248John Porto             ((encoding_[0] & 0x07) == reg); // Register codes match.
1695d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1705d0acff3a2fa421923392aadb4df2742064b6248John Porto
1715d0acff3a2fa421923392aadb4df2742064b6248John Porto    template <class> friend class AssemblerX86Base;
1725d0acff3a2fa421923392aadb4df2742064b6248John Porto  };
1735d0acff3a2fa421923392aadb4df2742064b6248John Porto
1745d0acff3a2fa421923392aadb4df2742064b6248John Porto  class Address : public Operand {
1755d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address() = delete;
1765d0acff3a2fa421923392aadb4df2742064b6248John Porto
1775d0acff3a2fa421923392aadb4df2742064b6248John Porto  public:
1785d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address(const Address &other) : Operand(other) {}
1795d0acff3a2fa421923392aadb4df2742064b6248John Porto
1805d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address &operator=(const Address &other) {
1815d0acff3a2fa421923392aadb4df2742064b6248John Porto      Operand::operator=(other);
1825d0acff3a2fa421923392aadb4df2742064b6248John Porto      return *this;
1835d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
1845d0acff3a2fa421923392aadb4df2742064b6248John Porto
1855d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address(GPRRegister base, int32_t disp) {
1865d0acff3a2fa421923392aadb4df2742064b6248John Porto      if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
1875d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetModRM(0, base);
1885d0acff3a2fa421923392aadb4df2742064b6248John Porto        if (base == RegX8632::Encoded_Reg_esp)
1895d0acff3a2fa421923392aadb4df2742064b6248John Porto          SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
1905d0acff3a2fa421923392aadb4df2742064b6248John Porto      } else if (Utils::IsInt(8, disp)) {
1915d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetModRM(1, base);
1925d0acff3a2fa421923392aadb4df2742064b6248John Porto        if (base == RegX8632::Encoded_Reg_esp)
1935d0acff3a2fa421923392aadb4df2742064b6248John Porto          SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
1945d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetDisp8(disp);
1955d0acff3a2fa421923392aadb4df2742064b6248John Porto      } else {
1965d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetModRM(2, base);
1975d0acff3a2fa421923392aadb4df2742064b6248John Porto        if (base == RegX8632::Encoded_Reg_esp)
1985d0acff3a2fa421923392aadb4df2742064b6248John Porto          SetSIB(TIMES_1, RegX8632::Encoded_Reg_esp, base);
1995d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetDisp32(disp);
2005d0acff3a2fa421923392aadb4df2742064b6248John Porto      }
2015d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2025d0acff3a2fa421923392aadb4df2742064b6248John Porto
2035d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address(GPRRegister index, ScaleFactor scale, int32_t disp) {
2045d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
2055d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetModRM(0, RegX8632::Encoded_Reg_esp);
2065d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetSIB(scale, index, RegX8632::Encoded_Reg_ebp);
2075d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetDisp32(disp);
2085d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2095d0acff3a2fa421923392aadb4df2742064b6248John Porto
2105d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address(GPRRegister base, GPRRegister index, ScaleFactor scale,
2115d0acff3a2fa421923392aadb4df2742064b6248John Porto            int32_t disp) {
2125d0acff3a2fa421923392aadb4df2742064b6248John Porto      assert(index != RegX8632::Encoded_Reg_esp); // Illegal addressing mode.
2135d0acff3a2fa421923392aadb4df2742064b6248John Porto      if (disp == 0 && base != RegX8632::Encoded_Reg_ebp) {
2145d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetModRM(0, RegX8632::Encoded_Reg_esp);
2155d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetSIB(scale, index, base);
2165d0acff3a2fa421923392aadb4df2742064b6248John Porto      } else if (Utils::IsInt(8, disp)) {
2175d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetModRM(1, RegX8632::Encoded_Reg_esp);
2185d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetSIB(scale, index, base);
2195d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetDisp8(disp);
2205d0acff3a2fa421923392aadb4df2742064b6248John Porto      } else {
2215d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetModRM(2, RegX8632::Encoded_Reg_esp);
2225d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetSIB(scale, index, base);
2235d0acff3a2fa421923392aadb4df2742064b6248John Porto        SetDisp32(disp);
2245d0acff3a2fa421923392aadb4df2742064b6248John Porto      }
2255d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2265d0acff3a2fa421923392aadb4df2742064b6248John Porto
227921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// AbsoluteTag is a special tag used by clients to create an absolute
228921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// Address.
2295d0acff3a2fa421923392aadb4df2742064b6248John Porto    enum AbsoluteTag { ABSOLUTE };
2305d0acff3a2fa421923392aadb4df2742064b6248John Porto
2315d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address(AbsoluteTag, const uintptr_t Addr) {
2325d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetModRM(0, RegX8632::Encoded_Reg_ebp);
2335d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetDisp32(Addr);
2345d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2355d0acff3a2fa421923392aadb4df2742064b6248John Porto
2365d0acff3a2fa421923392aadb4df2742064b6248John Porto    // TODO(jpp): remove this.
2375d0acff3a2fa421923392aadb4df2742064b6248John Porto    static Address Absolute(const uintptr_t Addr) {
2385d0acff3a2fa421923392aadb4df2742064b6248John Porto      return Address(ABSOLUTE, Addr);
2395d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2405d0acff3a2fa421923392aadb4df2742064b6248John Porto
2415d0acff3a2fa421923392aadb4df2742064b6248John Porto    Address(AbsoluteTag, RelocOffsetT Offset, AssemblerFixup *Fixup) {
2425d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetModRM(0, RegX8632::Encoded_Reg_ebp);
2435d0acff3a2fa421923392aadb4df2742064b6248John Porto      // Use the Offset in the displacement for now. If we decide to process
2445d0acff3a2fa421923392aadb4df2742064b6248John Porto      // fixups later, we'll need to patch up the emitted displacement.
2455d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetDisp32(Offset);
2465d0acff3a2fa421923392aadb4df2742064b6248John Porto      SetFixup(Fixup);
2475d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2485d0acff3a2fa421923392aadb4df2742064b6248John Porto
2495d0acff3a2fa421923392aadb4df2742064b6248John Porto    // TODO(jpp): remove this.
2505d0acff3a2fa421923392aadb4df2742064b6248John Porto    static Address Absolute(RelocOffsetT Offset, AssemblerFixup *Fixup) {
2515d0acff3a2fa421923392aadb4df2742064b6248John Porto      return Address(ABSOLUTE, Offset, Fixup);
2525d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2535d0acff3a2fa421923392aadb4df2742064b6248John Porto
2545d0acff3a2fa421923392aadb4df2742064b6248John Porto    static Address ofConstPool(Assembler *Asm, const Constant *Imm) {
2555d0acff3a2fa421923392aadb4df2742064b6248John Porto      AssemblerFixup *Fixup = Asm->createFixup(llvm::ELF::R_386_32, Imm);
2565d0acff3a2fa421923392aadb4df2742064b6248John Porto      const RelocOffsetT Offset = 0;
2575d0acff3a2fa421923392aadb4df2742064b6248John Porto      return Address(ABSOLUTE, Offset, Fixup);
2585d0acff3a2fa421923392aadb4df2742064b6248John Porto    }
2595d0acff3a2fa421923392aadb4df2742064b6248John Porto  };
2605d0acff3a2fa421923392aadb4df2742064b6248John Porto
2615d0acff3a2fa421923392aadb4df2742064b6248John Porto  //----------------------------------------------------------------------------
2625d0acff3a2fa421923392aadb4df2742064b6248John Porto  //     __      ______  __     __  ______  ______  __  __   __  ______
2635d0acff3a2fa421923392aadb4df2742064b6248John Porto  //    /\ \    /\  __ \/\ \  _ \ \/\  ___\/\  == \/\ \/\ "-.\ \/\  ___\
2645d0acff3a2fa421923392aadb4df2742064b6248John Porto  //    \ \ \___\ \ \/\ \ \ \/ ".\ \ \  __\\ \  __<\ \ \ \ \-.  \ \ \__ \
2655d0acff3a2fa421923392aadb4df2742064b6248John Porto  //     \ \_____\ \_____\ \__/".~\_\ \_____\ \_\ \_\ \_\ \_\\"\_\ \_____\
2665d0acff3a2fa421923392aadb4df2742064b6248John Porto  //      \/_____/\/_____/\/_/   \/_/\/_____/\/_/ /_/\/_/\/_/ \/_/\/_____/
2675d0acff3a2fa421923392aadb4df2742064b6248John Porto  //
2685d0acff3a2fa421923392aadb4df2742064b6248John Porto  //----------------------------------------------------------------------------
2695d0acff3a2fa421923392aadb4df2742064b6248John Porto  enum InstructionSet {
2705d0acff3a2fa421923392aadb4df2742064b6248John Porto    Begin,
2715d0acff3a2fa421923392aadb4df2742064b6248John Porto    // SSE2 is the PNaCl baseline instruction set.
2725d0acff3a2fa421923392aadb4df2742064b6248John Porto    SSE2 = Begin,
2735d0acff3a2fa421923392aadb4df2742064b6248John Porto    SSE4_1,
2745d0acff3a2fa421923392aadb4df2742064b6248John Porto    End
2755d0acff3a2fa421923392aadb4df2742064b6248John Porto  };
2765d0acff3a2fa421923392aadb4df2742064b6248John Porto
277921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const char *TargetName;
2781d235425dab1f3dd059973fc53f1b1d5879469e3John Porto  static constexpr Type WordType = IceType_i32;
279921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
280921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static IceString getRegName(SizeT RegNum, Type Ty) {
281921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    assert(RegNum < RegisterSet::Reg_NUM);
282921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static const char *RegNames8[] = {
283921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr,      \
284921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          frameptr, isI8, isInt, isFP)                                         \
285921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  name8,
286921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        REGX8632_TABLE
287921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
288921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    };
289921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
290921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static const char *RegNames16[] = {
291921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr,      \
292921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          frameptr, isI8, isInt, isFP)                                         \
293921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  name16,
294921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        REGX8632_TABLE
295921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
296921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    };
297921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
298921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static const char *RegNames[] = {
299921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr,      \
300921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          frameptr, isI8, isInt, isFP)                                         \
301921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  name,
302921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        REGX8632_TABLE
303921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
304921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    };
305921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
306921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    switch (Ty) {
307921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    case IceType_i1:
308921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    case IceType_i8:
309921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return RegNames8[RegNum];
310921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    case IceType_i16:
311921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return RegNames16[RegNum];
312921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    default:
313921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return RegNames[RegNum];
314921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
315921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
316921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
317bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  static void initRegisterSet(
318bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto      std::array<llvm::SmallBitVector, IceType_NUM> *TypeToRegisterSet,
319bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto      std::array<llvm::SmallBitVector, RegisterSet::Reg_NUM> *RegisterAliases,
320bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto      llvm::SmallBitVector *ScratchRegs) {
321bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    llvm::SmallBitVector IntegerRegisters(RegisterSet::Reg_NUM);
322bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    llvm::SmallBitVector IntegerRegistersI8(RegisterSet::Reg_NUM);
323bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    llvm::SmallBitVector FloatRegisters(RegisterSet::Reg_NUM);
324bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    llvm::SmallBitVector VectorRegisters(RegisterSet::Reg_NUM);
325bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    llvm::SmallBitVector InvalidRegisters(RegisterSet::Reg_NUM);
326bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    ScratchRegs->resize(RegisterSet::Reg_NUM);
327921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr,      \
328921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          frameptr, isI8, isInt, isFP)                                         \
329bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  (IntegerRegisters)[RegisterSet::val] = isInt;                                \
330bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  (IntegerRegistersI8)[RegisterSet::val] = isI8;                               \
331bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  (FloatRegisters)[RegisterSet::val] = isFP;                                   \
332bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  (VectorRegisters)[RegisterSet::val] = isFP;                                  \
333bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  (*RegisterAliases)[RegisterSet::val].resize(RegisterSet::Reg_NUM);           \
334bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto  (*RegisterAliases)[RegisterSet::val].set(RegisterSet::val);                  \
335921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  (*ScratchRegs)[RegisterSet::val] = scratch;
336921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    REGX8632_TABLE;
337921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
338bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto
339bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_void] = InvalidRegisters;
340bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_i1] = IntegerRegistersI8;
341bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_i8] = IntegerRegistersI8;
342bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_i16] = IntegerRegisters;
343bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_i32] = IntegerRegisters;
344bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_i64] = IntegerRegisters;
345bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_f32] = FloatRegisters;
346bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_f64] = FloatRegisters;
347bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_v4i1] = VectorRegisters;
348bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_v8i1] = VectorRegisters;
349bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_v16i1] = VectorRegisters;
350bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_v16i8] = VectorRegisters;
351bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_v8i16] = VectorRegisters;
352bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_v4i32] = VectorRegisters;
353bb0a5fe31a71fdc5b3292d62169f428d531437a4John Porto    (*TypeToRegisterSet)[IceType_v4f32] = VectorRegisters;
354921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
355921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
356921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static llvm::SmallBitVector
357921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  getRegisterSet(TargetLowering::RegSetMask Include,
358921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto                 TargetLowering::RegSetMask Exclude) {
359921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    llvm::SmallBitVector Registers(RegisterSet::Reg_NUM);
360921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
361921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr,      \
362921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          frameptr, isI8, isInt, isFP)                                         \
363921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (scratch && (Include & ::Ice::TargetLowering::RegSet_CallerSave))         \
364921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = true;                                        \
365921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (preserved && (Include & ::Ice::TargetLowering::RegSet_CalleeSave))       \
366921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = true;                                        \
367921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (stackptr && (Include & ::Ice::TargetLowering::RegSet_StackPointer))      \
368921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = true;                                        \
369921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (frameptr && (Include & ::Ice::TargetLowering::RegSet_FramePointer))      \
370921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = true;                                        \
371921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (scratch && (Exclude & ::Ice::TargetLowering::RegSet_CallerSave))         \
372921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = false;                                       \
373921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (preserved && (Exclude & ::Ice::TargetLowering::RegSet_CalleeSave))       \
374921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = false;                                       \
375921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (stackptr && (Exclude & ::Ice::TargetLowering::RegSet_StackPointer))      \
376921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = false;                                       \
377921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (frameptr && (Exclude & ::Ice::TargetLowering::RegSet_FramePointer))      \
378921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Registers[RegisterSet::val] = false;
379921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
380921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    REGX8632_TABLE
381921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
382921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
383921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
384921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    return Registers;
385921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
386921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
387921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static void
388921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  makeRandomRegisterPermutation(GlobalContext *Ctx, Cfg *Func,
389921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto                                llvm::SmallVectorImpl<int32_t> &Permutation,
390aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu                                const llvm::SmallBitVector &ExcludeRegisters,
391aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu                                uint64_t Salt) {
392921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // TODO(stichnot): Declaring Permutation this way loses type/size
393921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // information.  Fix this in conjunction with the caller-side TODO.
394921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    assert(Permutation.size() >= RegisterSet::Reg_NUM);
395921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // Expected upper bound on the number of registers in a single equivalence
396921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // class.  For x86-32, this would comprise the 8 XMM registers.  This is for
397921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // performance, not correctness.
398921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static const unsigned MaxEquivalenceClassSize = 8;
399921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    typedef llvm::SmallVector<int32_t, MaxEquivalenceClassSize> RegisterList;
400921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    typedef std::map<uint32_t, RegisterList> EquivalenceClassMap;
401921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    EquivalenceClassMap EquivalenceClasses;
402921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    SizeT NumShuffled = 0, NumPreserved = 0;
403921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
404921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto// Build up the equivalence classes of registers by looking at the register
405921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto// properties as well as whether the registers should be explicitly excluded
406921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto// from shuffling.
407921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, encode, name, name16, name8, scratch, preserved, stackptr,      \
408921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          frameptr, isI8, isInt, isFP)                                         \
409921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  if (ExcludeRegisters[RegisterSet::val]) {                                    \
410921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /* val stays the same in the resulting permutation. */                     \
411921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Permutation[RegisterSet::val] = RegisterSet::val;                          \
412921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    ++NumPreserved;                                                            \
413921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  } else {                                                                     \
414921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const uint32_t Index = (scratch << 0) | (preserved << 1) | (isI8 << 2) |   \
415921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto                           (isInt << 3) | (isFP << 4);                         \
416921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /* val is assigned to an equivalence class based on its properties. */     \
417921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    EquivalenceClasses[Index].push_back(RegisterSet::val);                     \
418921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
419921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    REGX8632_TABLE
420921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
421921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
422aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    // Create a random number generator for regalloc randomization.
423aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    RandomNumberGenerator RNG(Ctx->getFlags().getRandomSeed(),
424aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu                              RPE_RegAllocRandomization, Salt);
425aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu    RandomNumberGeneratorWrapper RNGW(RNG);
426921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
427921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // Shuffle the resulting equivalence classes.
428921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    for (auto I : EquivalenceClasses) {
429921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      const RegisterList &List = I.second;
430921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      RegisterList Shuffled(List);
431aee5fa8dd6aa948160a290c8237d7ae4875811fbQining Lu      RandomShuffle(Shuffled.begin(), Shuffled.end(), RNGW);
432921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      for (size_t SI = 0, SE = Shuffled.size(); SI < SE; ++SI) {
433921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        Permutation[List[SI]] = Shuffled[SI];
434921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        ++NumShuffled;
435921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      }
436921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
437921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
438921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    assert(NumShuffled + NumPreserved == RegisterSet::Reg_NUM);
439921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
440921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    if (Func->isVerbose(IceV_Random)) {
441921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      OstreamLocker L(Func->getContext());
442921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      Ostream &Str = Func->getContext()->getStrDump();
443921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      Str << "Register equivalence classes:\n";
444921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      for (auto I : EquivalenceClasses) {
445921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        Str << "{";
446921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        const RegisterList &List = I.second;
447921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        bool First = true;
448921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        for (int32_t Register : List) {
449921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          if (!First)
450921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto            Str << " ";
451921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          First = false;
452921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          Str << getRegName(Register, IceType_i32);
453921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        }
454921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        Str << "}\n";
455921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      }
456921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
457921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  }
458921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
459921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The maximum number of arguments to pass in XMM registers
4605d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const uint32_t X86_MAX_XMM_ARGS = 4;
461921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The number of bits in a byte
4625d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const uint32_t X86_CHAR_BIT = 8;
463921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// Stack alignment. This is defined in IceTargetLoweringX8632.cpp because it
464921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// is used as an argument to std::max(), and the default std::less<T> has an
465921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// operator(T const&, T const&) which requires this member to have an
466921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// address.
4675d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const uint32_t X86_STACK_ALIGNMENT_BYTES;
468921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// Size of the return address on the stack
4695d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const uint32_t X86_RET_IP_SIZE_BYTES = 4;
470921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The number of different NOP instructions
4715d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const uint32_t X86_NUM_NOP_VARIANTS = 5;
4725d0acff3a2fa421923392aadb4df2742064b6248John Porto
473cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// \name Limits for unrolling memory intrinsics.
474cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// @{
475cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMCPY_UNROLL_LIMIT = 8;
476cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMMOVE_UNROLL_LIMIT = 8;
477cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  static constexpr uint32_t MEMSET_UNROLL_LIMIT = 16;
478cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull  /// @}
479cfa628b5f7612d202de234980b21bd6d59a11998Andrew Scull
480921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// Value is in bytes. Return Value adjusted to the next highest multiple
481921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// of the stack alignment.
4825d0acff3a2fa421923392aadb4df2742064b6248John Porto  static uint32_t applyStackAlignment(uint32_t Value) {
4835d0acff3a2fa421923392aadb4df2742064b6248John Porto    return Utils::applyAlignment(Value, X86_STACK_ALIGNMENT_BYTES);
4845d0acff3a2fa421923392aadb4df2742064b6248John Porto  }
4855d0acff3a2fa421923392aadb4df2742064b6248John Porto
486921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// Return the type which the elements of the vector have in the X86
487921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// representation of the vector.
4885d0acff3a2fa421923392aadb4df2742064b6248John Porto  static Type getInVectorElementType(Type Ty) {
4895d0acff3a2fa421923392aadb4df2742064b6248John Porto    assert(isVectorType(Ty));
4905d0acff3a2fa421923392aadb4df2742064b6248John Porto    size_t Index = static_cast<size_t>(Ty);
4915d0acff3a2fa421923392aadb4df2742064b6248John Porto    (void)Index;
4925d0acff3a2fa421923392aadb4df2742064b6248John Porto    assert(Index < TableTypeX8632AttributesSize);
4935d0acff3a2fa421923392aadb4df2742064b6248John Porto    return TableTypeX8632Attributes[Ty].InVectorElementType;
4945d0acff3a2fa421923392aadb4df2742064b6248John Porto  }
4955d0acff3a2fa421923392aadb4df2742064b6248John Porto
4965d0acff3a2fa421923392aadb4df2742064b6248John Porto  // Note: The following data structures are defined in
4975d0acff3a2fa421923392aadb4df2742064b6248John Porto  // IceTargetLoweringX8632.cpp.
4985d0acff3a2fa421923392aadb4df2742064b6248John Porto
499921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The following table summarizes the logic for lowering the fcmp
500921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// instruction. There is one table entry for each of the 16 conditions.
501921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  ///
502921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The first four columns describe the case when the operands are floating
503921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// point scalar values.  A comment in lowerFcmp() describes the lowering
504921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// template.  In the most general case, there is a compare followed by two
505921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// conditional branches, because some fcmp conditions don't map to a single
506921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// x86 conditional branch.  However, in many cases it is possible to swap the
507921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// operands in the comparison and have a single conditional branch.  Since
508921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// it's quite tedious to validate the table by hand, good execution tests are
509921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// helpful.
510921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  ///
511921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The last two columns describe the case when the operands are vectors of
512921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// floating point values.  For most fcmp conditions, there is a clear mapping
513921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// to a single x86 cmpps instruction variant.  Some fcmp conditions require
514921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// special code to handle and these are marked in the table with a
515921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// Cmpps_Invalid predicate.
516921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// {@
5175d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const struct TableFcmpType {
5185d0acff3a2fa421923392aadb4df2742064b6248John Porto    uint32_t Default;
5195d0acff3a2fa421923392aadb4df2742064b6248John Porto    bool SwapScalarOperands;
520921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Cond::BrCond C1, C2;
5215d0acff3a2fa421923392aadb4df2742064b6248John Porto    bool SwapVectorOperands;
522921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Cond::CmppsCond Predicate;
5235d0acff3a2fa421923392aadb4df2742064b6248John Porto  } TableFcmp[];
5245d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const size_t TableFcmpSize;
525921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// @}
5265d0acff3a2fa421923392aadb4df2742064b6248John Porto
527921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The following table summarizes the logic for lowering the icmp instruction
528921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// for i32 and narrower types.  Each icmp condition has a clear mapping to an
529921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// x86 conditional branch instruction.
530921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// {@
531921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const struct TableIcmp32Type { Cond::BrCond Mapping; } TableIcmp32[];
5325d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const size_t TableIcmp32Size;
533921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// @}
5345d0acff3a2fa421923392aadb4df2742064b6248John Porto
535921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// The following table summarizes the logic for lowering the icmp instruction
536921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// for the i64 type.  For Eq and Ne, two separate 32-bit comparisons and
537921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// conditional branches are needed.  For the other conditions, three separate
538921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// conditional branches are needed.
539921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// {@
5405d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const struct TableIcmp64Type {
541921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Cond::BrCond C1, C2, C3;
5425d0acff3a2fa421923392aadb4df2742064b6248John Porto  } TableIcmp64[];
5435d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const size_t TableIcmp64Size;
544921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// @}
5455d0acff3a2fa421923392aadb4df2742064b6248John Porto
546921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static Cond::BrCond getIcmp32Mapping(InstIcmp::ICond Cond) {
5475d0acff3a2fa421923392aadb4df2742064b6248John Porto    size_t Index = static_cast<size_t>(Cond);
5485d0acff3a2fa421923392aadb4df2742064b6248John Porto    assert(Index < TableIcmp32Size);
5495d0acff3a2fa421923392aadb4df2742064b6248John Porto    return TableIcmp32[Index].Mapping;
5505d0acff3a2fa421923392aadb4df2742064b6248John Porto  }
5515d0acff3a2fa421923392aadb4df2742064b6248John Porto
5525d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const struct TableTypeX8632AttributesType {
5535d0acff3a2fa421923392aadb4df2742064b6248John Porto    Type InVectorElementType;
5545d0acff3a2fa421923392aadb4df2742064b6248John Porto  } TableTypeX8632Attributes[];
5555d0acff3a2fa421923392aadb4df2742064b6248John Porto  static const size_t TableTypeX8632AttributesSize;
556921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
557921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //----------------------------------------------------------------------------
558921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //      __  __   __  ______  ______
559921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //    /\ \/\ "-.\ \/\  ___\/\__  _\
560921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //    \ \ \ \ \-.  \ \___  \/_/\ \/
561921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //     \ \_\ \_\\"\_\/\_____\ \ \_\
562921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //      \/_/\/_/ \/_/\/_____/  \/_/
563921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //
564921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  //----------------------------------------------------------------------------
565921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  using Insts = ::Ice::X86Internal::Insts<TargetX8632>;
566921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
5675aeed955e17bac8cc44cc6d2b6ff7513cc714c2fJohn Porto  using TargetLowering = ::Ice::X86Internal::TargetX86Base<TargetX8632>;
568921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  using Assembler = X8632::AssemblerX8632;
569921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
570921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// X86Operand extends the Operand hierarchy.  Its subclasses are
571921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// X86OperandMem and VariableSplit.
572921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  class X86Operand : public ::Ice::Operand {
573921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86Operand() = delete;
574921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86Operand(const X86Operand &) = delete;
575921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86Operand &operator=(const X86Operand &) = delete;
576921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
577921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  public:
578921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    enum OperandKindX8632 { k__Start = ::Ice::Operand::kTarget, kMem, kSplit };
579921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    using ::Ice::Operand::dump;
580921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
581921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void dump(const Cfg *, Ostream &Str) const override;
582921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
583921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  protected:
584921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86Operand(OperandKindX8632 Kind, Type Ty)
585921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        : Operand(static_cast<::Ice::Operand::OperandKind>(Kind), Ty) {}
586921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  };
587921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
588921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// X86OperandMem represents the m32 addressing mode, with optional base and
589921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// index registers, a constant offset, and a fixed shift value for the index
590921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// register.
591921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  class X86OperandMem : public X86Operand {
592921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86OperandMem() = delete;
593921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86OperandMem(const X86OperandMem &) = delete;
594921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86OperandMem &operator=(const X86OperandMem &) = delete;
595921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
596921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  public:
597921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    enum SegmentRegisters {
598921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      DefaultSegment = -1,
599921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#define X(val, name, prefix) val,
600921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      SEG_REGX8632_TABLE
601921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto#undef X
602921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          SegReg_NUM
603921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    };
604921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static X86OperandMem *create(Cfg *Func, Type Ty, Variable *Base,
605921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto                                 Constant *Offset, Variable *Index = nullptr,
606921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto                                 uint16_t Shift = 0,
607921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto                                 SegmentRegisters SegmentReg = DefaultSegment) {
608921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return new (Func->allocate<X86OperandMem>())
609921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          X86OperandMem(Func, Ty, Base, Offset, Index, Shift, SegmentReg);
610921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
611921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *getBase() const { return Base; }
612921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Constant *getOffset() const { return Offset; }
613921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *getIndex() const { return Index; }
614921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    uint16_t getShift() const { return Shift; }
615921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    SegmentRegisters getSegmentRegister() const { return SegmentReg; }
616921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void emitSegmentOverride(Assembler *Asm) const;
617921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Address toAsmAddress(Assembler *Asm) const;
618921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
619921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void emit(const Cfg *Func) const override;
620921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    using X86Operand::dump;
621921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void dump(const Cfg *Func, Ostream &Str) const override;
622921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
623921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static bool classof(const Operand *Operand) {
624921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return Operand->getKind() == static_cast<OperandKind>(kMem);
625921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
626921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
627921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void setRandomized(bool R) { Randomized = R; }
628921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
629921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    bool getRandomized() const { return Randomized; }
630921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
631921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  private:
632921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    X86OperandMem(Cfg *Func, Type Ty, Variable *Base, Constant *Offset,
633921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto                  Variable *Index, uint16_t Shift, SegmentRegisters SegmentReg);
634921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
635921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *Base;
636921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Constant *Offset;
637921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *Index;
638921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    uint16_t Shift;
639921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    SegmentRegisters SegmentReg : 16;
640921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// A flag to show if this memory operand is a randomized one. Randomized
641921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// memory operands are generated in
642921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    /// TargetX86Base::randomizeOrPoolImmediate()
643921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    bool Randomized;
644921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  };
645921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
646921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// VariableSplit is a way to treat an f64 memory location as a pair of i32
647921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// locations (Low and High).  This is needed for some cases of the Bitcast
648921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// instruction.  Since it's not possible for integer registers to access the
649921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// XMM registers and vice versa, the lowering forces the f64 to be spilled to
650921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// the stack and then accesses through the VariableSplit.
651921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  // TODO(jpp): remove references to VariableSplit from IceInstX86Base as 64bit
652921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  // targets can natively handle these.
653921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  class VariableSplit : public X86Operand {
654921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    VariableSplit() = delete;
655921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    VariableSplit(const VariableSplit &) = delete;
656921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    VariableSplit &operator=(const VariableSplit &) = delete;
657921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
658921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  public:
659921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    enum Portion { Low, High };
660921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static VariableSplit *create(Cfg *Func, Variable *Var, Portion Part) {
661921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return new (Func->allocate<VariableSplit>())
662921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto          VariableSplit(Func, Var, Part);
663921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
664921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    int32_t getOffset() const { return Part == High ? 4 : 0; }
665921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
666921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Address toAsmAddress(const Cfg *Func) const;
667921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void emit(const Cfg *Func) const override;
668921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    using X86Operand::dump;
669921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void dump(const Cfg *Func, Ostream &Str) const override;
670921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
671921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static bool classof(const Operand *Operand) {
672921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return Operand->getKind() == static_cast<OperandKind>(kSplit);
673921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
674921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
675921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  private:
676921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    VariableSplit(Cfg *Func, Variable *Var, Portion Part)
677921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        : X86Operand(kSplit, IceType_i32), Var(Var), Part(Part) {
678921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      assert(Var->getType() == IceType_f64);
679921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      Vars = Func->allocateArrayOf<Variable *>(1);
680921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      Vars[0] = Var;
681921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      NumVars = 1;
682921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
683921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
684921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *Var;
685921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Portion Part;
686921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  };
687921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
688921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// SpillVariable decorates a Variable by linking it to another Variable.
689921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// When stack frame offsets are computed, the SpillVariable is given a
690921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// distinct stack slot only if its linked Variable has a register.  If the
691921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// linked Variable has a stack slot, then the Variable and SpillVariable
692921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  /// share that slot.
693921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  class SpillVariable : public Variable {
694921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    SpillVariable() = delete;
695921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    SpillVariable(const SpillVariable &) = delete;
696921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    SpillVariable &operator=(const SpillVariable &) = delete;
697921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
698921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  public:
699921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static SpillVariable *create(Cfg *Func, Type Ty, SizeT Index) {
700921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return new (Func->allocate<SpillVariable>()) SpillVariable(Ty, Index);
701921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
702921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const static OperandKind SpillVariableKind =
703921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        static_cast<OperandKind>(kVariable_Target);
704921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    static bool classof(const Operand *Operand) {
705921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto      return Operand->getKind() == SpillVariableKind;
706921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    }
707921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    void setLinkedTo(Variable *Var) { LinkedTo = Var; }
708921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *getLinkedTo() const { return LinkedTo; }
709921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    // Inherit dump() and emit() from Variable.
710921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
711921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  private:
712921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    SpillVariable(Type Ty, SizeT Index)
713921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto        : Variable(SpillVariableKind, Ty, Index), LinkedTo(nullptr) {}
714921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Variable *LinkedTo;
715921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  };
716921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
717921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  // Note: The following data structures are defined in IceInstX8632.cpp.
718921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
719921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const struct InstBrAttributesType {
720921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    Cond::BrCond Opposite;
721921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *DisplayString;
722921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *EmitString;
723921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  } InstBrAttributes[];
724921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
725921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const struct InstCmppsAttributesType {
726921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *EmitString;
727921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  } InstCmppsAttributes[];
728921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
729921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const struct TypeAttributesType {
730921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *CvtString;   // i (integer), s (single FP), d (double FP)
731921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *SdSsString;  // ss, sd, or <blank>
732921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *PackString;  // b, w, d, or <blank>
733921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *WidthString; // b, w, l, q, or <blank>
734921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto    const char *FldString;   // s, l, or <blank>
735921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  } TypeAttributes[];
736921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
737921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static const char *InstSegmentRegNames[];
738921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto
739921856d4e4bd4f0deedc7324d5f6a4ca0be3439fJohn Porto  static uint8_t InstSegmentPrefixes[];
7405d0acff3a2fa421923392aadb4df2742064b6248John Porto};
7415d0acff3a2fa421923392aadb4df2742064b6248John Porto
7425d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace X86Internal
7435d0acff3a2fa421923392aadb4df2742064b6248John Porto
7445d0acff3a2fa421923392aadb4df2742064b6248John Portonamespace X8632 {
7455d0acff3a2fa421923392aadb4df2742064b6248John Portousing Traits = ::Ice::X86Internal::MachineTraits<TargetX8632>;
7465d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace X8632
7475d0acff3a2fa421923392aadb4df2742064b6248John Porto
7485d0acff3a2fa421923392aadb4df2742064b6248John Porto} // end of namespace Ice
7495d0acff3a2fa421923392aadb4df2742064b6248John Porto
7505d0acff3a2fa421923392aadb4df2742064b6248John Porto#endif // SUBZERO_SRC_ICETARGETLOWERINGX8632TRAITS_H
751