aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/CodeGen/TargetRegisterInfo.h
blob: 9357eb2b5e8dae9949a413c5a03cbf4130bb5188 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef RCC_CODEGEN_TARGETREGISTERINFO_H
#define RCC_CODEGEN_TARGETREGISTERINFO_H

#include "rcc/CodeGen/MachineIRTypes.h"
#include "rcc/CodeGen/Register.h"
#include "rcc/CodeGen/RegisterMask.h"
#include "rcc/Support/Error.h"

#include <cstddef>
#include <cstdint>
#include <optional>
#include <span>
#include <string>
#include <string_view>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

namespace rcc {

struct RegisterUnitDesc final {
  RegisterUnitID ID;
  std::string Name;
};

struct RegisterUnitLane final {
  RegisterUnitID Unit;
  LaneMask Lanes;
};

struct PhysicalRegisterDesc final {
  PhysicalRegister Reg;
  std::string Name;
  std::uint32_t Encoding = 0;
  std::vector<RegisterUnitLane> Units;
  bool IsConstant = false;
  bool IsArtificial = false;
};

struct SubRegIndexDesc final {
  SubRegIndex ID;
  std::string Name;
  LaneMask Lanes;
  std::uint32_t SizeInBits = 0;
  std::uint32_t OffsetInBits = 0;
};

struct PhysicalSubRegisterDesc final {
  PhysicalRegister SuperReg;
  SubRegIndex Index;
  PhysicalRegister SubReg;
};

struct SubRegIndexComposition final {
  SubRegIndex First;
  SubRegIndex Second;
  SubRegIndex Result;
};

struct RegisterClassDesc final {
  RegisterClassID ID;
  std::string Name;
  std::vector<PhysicalRegister> Registers;
  std::vector<PhysicalRegister> AllocationOrder;
  std::uint32_t SizeInBits = 0;
  std::uint32_t SpillSizeInBits = 0;
  std::uint32_t SpillAlignmentInBits = 0;
  LaneMask Lanes;
  std::vector<SubRegIndex> SupportedSubRegs;
  std::vector<RegisterClassID> SuperClasses;
  RegisterBankID DefaultBank;
  bool Allocatable = true;
  std::uint32_t CopyCost = 1;
  bool CoveredBySubRegs = false;
};

struct SubRegClassMapping final {
  RegisterClassID SourceClass;
  SubRegIndex Index;
  RegisterClassID ResultClass;
};

struct RegisterBankDesc final {
  RegisterBankID ID;
  std::string Name;
  std::uint32_t MaximumSizeInBits = 0;
  std::vector<RegisterClassID> RegisterClasses;
};

struct TargetRegisterInfoDesc final {
  std::vector<RegisterUnitDesc> RegisterUnits;
  std::vector<PhysicalRegisterDesc> PhysicalRegisters;
  std::vector<SubRegIndexDesc> SubRegIndices;
  std::vector<PhysicalSubRegisterDesc> PhysicalSubRegisters;
  std::vector<SubRegIndexComposition> SubRegCompositions;
  std::vector<RegisterClassDesc> RegisterClasses;
  std::vector<SubRegClassMapping> SubRegClassMappings;
  std::vector<RegisterBankDesc> RegisterBanks;
};

class TargetRegisterInfo final {
public:
  [[nodiscard]] static Expected<TargetRegisterInfo> create(TargetRegisterInfoDesc Description);

  [[nodiscard]] std::span<const RegisterUnitDesc> registerUnits() const noexcept {
    return Description.RegisterUnits;
  }

  [[nodiscard]] std::span<const PhysicalRegisterDesc> physicalRegisters() const noexcept {
    return Description.PhysicalRegisters;
  }

  [[nodiscard]] std::span<const SubRegIndexDesc> subRegIndices() const noexcept {
    return Description.SubRegIndices;
  }

  [[nodiscard]] std::span<const RegisterClassDesc> registerClasses() const noexcept {
    return Description.RegisterClasses;
  }

  [[nodiscard]] std::span<const RegisterBankDesc> registerBanks() const noexcept {
    return Description.RegisterBanks;
  }

  [[nodiscard]] const RegisterUnitDesc *registerUnit(RegisterUnitID ID) const noexcept;
  [[nodiscard]] const PhysicalRegisterDesc *physicalRegister(PhysicalRegister Reg) const noexcept;
  [[nodiscard]] const PhysicalRegisterDesc *physicalRegister(std::string_view Name) const noexcept;
  [[nodiscard]] const SubRegIndexDesc *subRegIndex(SubRegIndex Index) const noexcept;
  [[nodiscard]] const SubRegIndexDesc *subRegIndex(std::string_view Name) const noexcept;
  [[nodiscard]] const RegisterClassDesc *registerClass(RegisterClassID ID) const noexcept;
  [[nodiscard]] const RegisterClassDesc *registerClass(std::string_view Name) const noexcept;
  [[nodiscard]] const RegisterBankDesc *registerBank(RegisterBankID ID) const noexcept;
  [[nodiscard]] const RegisterBankDesc *registerBank(std::string_view Name) const noexcept;

  [[nodiscard]] std::optional<std::string_view>
  physicalRegisterMIRName(PhysicalRegister Reg) const noexcept;
  [[nodiscard]] std::optional<std::string_view>
  registerClassMIRName(RegisterClassID ID) const noexcept;
  [[nodiscard]] std::optional<std::string_view>
  registerBankMIRName(RegisterBankID ID) const noexcept;

  [[nodiscard]] bool isKnownPhysicalRegister(PhysicalRegister Reg) const noexcept {
    return physicalRegister(Reg) != nullptr;
  }

  [[nodiscard]] LaneMask registerLaneMask(PhysicalRegister Reg) const noexcept;
  [[nodiscard]] bool isValidLaneMask(PhysicalRegister Reg, LaneMask Lanes) const noexcept;
  [[nodiscard]] bool regsOverlap(PhysicalRegister Left, PhysicalRegister Right) const noexcept;
  [[nodiscard]] std::span<const PhysicalRegister> aliases(PhysicalRegister Reg) const noexcept;

  [[nodiscard]] std::optional<PhysicalRegister> subRegister(PhysicalRegister SuperReg,
                                                            SubRegIndex Index) const noexcept;
  [[nodiscard]] bool isSubRegister(PhysicalRegister SuperReg,
                                   PhysicalRegister SubReg) const noexcept;
  [[nodiscard]] std::span<const PhysicalRegister>
  superRegisters(PhysicalRegister Reg) const noexcept;
  [[nodiscard]] std::optional<SubRegIndex> composeSubRegIndices(SubRegIndex First,
                                                                SubRegIndex Second) const noexcept;

  [[nodiscard]] bool registerClassContains(RegisterClassID Class,
                                           PhysicalRegister Reg) const noexcept;
  [[nodiscard]] bool isSubclass(RegisterClassID Candidate, RegisterClassID Required) const noexcept;
  [[nodiscard]] bool registerClassesOverlap(RegisterClassID Left,
                                            RegisterClassID Right) const noexcept;
  [[nodiscard]] std::optional<RegisterClassID> subRegClass(RegisterClassID Source,
                                                           SubRegIndex Index) const noexcept;

  [[nodiscard]] bool bankCoversClass(RegisterBankID Bank, RegisterClassID Class) const noexcept;
  [[nodiscard]] bool bankContainsRegister(RegisterBankID Bank, PhysicalRegister Reg) const noexcept;
  [[nodiscard]] bool registerBanksOverlap(RegisterBankID Left, RegisterBankID Right) const noexcept;

  [[nodiscard]] Expected<void> validateRegisterMask(const RegisterMask &Mask) const;

private:
  explicit TargetRegisterInfo(TargetRegisterInfoDesc Description)
      : Description(std::move(Description)) {}

  [[nodiscard]] static std::uint64_t pairKey(std::uint32_t First, std::uint32_t Second) noexcept {
    return (static_cast<std::uint64_t>(First) << 32U) | Second;
  }

  TargetRegisterInfoDesc Description;
  std::unordered_map<RegisterUnitID, std::size_t> UnitToIndex;
  std::unordered_map<PhysicalRegister, std::size_t> RegisterToIndex;
  std::unordered_map<std::string, std::size_t> RegisterNameToIndex;
  std::unordered_map<SubRegIndex, std::size_t> SubRegIndexToIndex;
  std::unordered_map<std::string, std::size_t> SubRegNameToIndex;
  std::unordered_map<RegisterClassID, std::size_t> ClassToIndex;
  std::unordered_map<std::string, std::size_t> ClassNameToIndex;
  std::unordered_map<RegisterBankID, std::size_t> BankToIndex;
  std::unordered_map<std::string, std::size_t> BankNameToIndex;
  std::unordered_map<std::uint64_t, PhysicalRegister> SubRegisterMap;
  std::unordered_map<std::uint64_t, SubRegIndex> CompositionMap;
  std::unordered_map<std::uint64_t, RegisterClassID> SubRegClassMap;
  std::unordered_set<std::uint64_t> SubclassRelations;
  std::vector<std::vector<PhysicalRegister>> Aliases;
  std::vector<std::vector<PhysicalRegister>> SuperRegisters;
  std::vector<std::string> RegisterMIRNames;
  std::vector<std::string> ClassMIRNames;
  std::vector<std::string> BankMIRNames;
};

} // namespace rcc

#endif // RCC_CODEGEN_TARGETREGISTERINFO_H