Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Roblox
GitHub Repository: Roblox/luau
Path: blob/master/CodeGen/include/Luau/IrRegAllocX64.h
2727 views
1
// This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details
2
#pragma once
3
4
#include "Luau/AssemblyBuilderX64.h"
5
#include "Luau/IrData.h"
6
#include "Luau/RegisterX64.h"
7
8
#include <array>
9
#include <initializer_list>
10
11
namespace Luau
12
{
13
namespace CodeGen
14
{
15
16
struct LoweringStats;
17
18
namespace X64
19
{
20
21
constexpr uint8_t kNoStackSlot = 0xff;
22
23
struct IrSpillX64
24
{
25
uint32_t instIdx = 0;
26
IrValueKind valueKind = IrValueKind::Unknown;
27
28
unsigned spillId = 0;
29
30
// Spill location can be a stack location or be empty
31
// When it's empty, it means that instruction value can be rematerialized
32
uint8_t stackSlot = kNoStackSlot;
33
34
RegisterX64 originalLoc = noreg;
35
};
36
37
struct IrRegAllocX64
38
{
39
IrRegAllocX64(AssemblyBuilderX64& build, IrFunction& function, LoweringStats* stats);
40
41
RegisterX64 allocReg(SizeX64 size, uint32_t instIdx);
42
RegisterX64 allocRegOrReuse(SizeX64 size, uint32_t instIdx, std::initializer_list<IrOp> oprefs);
43
RegisterX64 takeReg(RegisterX64 reg, uint32_t instIdx);
44
45
bool canTakeReg(RegisterX64 reg) const;
46
47
void freeReg(RegisterX64 reg);
48
void freeLastUseReg(IrInst& target, uint32_t instIdx);
49
void freeLastUseRegs(const IrInst& inst, uint32_t instIdx);
50
51
bool isLastUseReg(const IrInst& target, uint32_t instIdx) const;
52
53
bool shouldFreeGpr(RegisterX64 reg) const;
54
55
unsigned findSpillStackSlot(IrValueKind valueKind);
56
57
OperandX64 getRestoreAddress(const IrInst& inst, ValueRestoreLocation restoreLocation);
58
59
// Register used by instruction is about to be freed, have to find a way to restore value later
60
void preserve(IrInst& inst);
61
62
void restore(IrInst& inst, bool intoOriginalLocation);
63
64
void preserveAndFreeInstValues();
65
66
uint32_t findInstructionWithFurthestNextUse(const std::array<uint32_t, 16>& regInstUsers) const;
67
68
bool isExtraSpillSlot(unsigned slot) const;
69
int getExtraSpillAddressOffset(unsigned slot) const;
70
71
void assertFree(RegisterX64 reg) const;
72
void assertAllFree() const;
73
void assertNoSpills() const;
74
75
AssemblyBuilderX64& build;
76
IrFunction& function;
77
LoweringStats* stats = nullptr;
78
79
uint32_t currInstIdx = ~0u;
80
81
std::array<bool, 16> freeGprMap;
82
std::array<uint32_t, 16> gprInstUsers;
83
std::array<bool, 16> freeXmmMap;
84
std::array<uint32_t, 16> xmmInstUsers;
85
uint8_t usableXmmRegCount = 0;
86
87
std::bitset<512> usedSpillSlotHalfs; // A bit for every stack slot split in 4 byte halfs
88
unsigned maxUsedSlot = 0; // Maximum number of 8 byte stack slots used
89
90
unsigned nextSpillId = 1;
91
std::vector<IrSpillX64> spills;
92
};
93
94
struct ScopedRegX64
95
{
96
explicit ScopedRegX64(IrRegAllocX64& owner);
97
ScopedRegX64(IrRegAllocX64& owner, SizeX64 size);
98
ScopedRegX64(IrRegAllocX64& owner, RegisterX64 reg);
99
~ScopedRegX64();
100
101
ScopedRegX64(const ScopedRegX64&) = delete;
102
ScopedRegX64& operator=(const ScopedRegX64&) = delete;
103
104
void take(RegisterX64 reg);
105
void alloc(SizeX64 size);
106
void free();
107
108
RegisterX64 release();
109
110
IrRegAllocX64& owner;
111
RegisterX64 reg;
112
};
113
114
// When IR instruction makes a call under a condition that's not reflected as a real branch in IR,
115
// spilled values have to be restored to their exact original locations, so that both after a call
116
// and after the skip, values are found in the same place
117
struct ScopedSpills
118
{
119
explicit ScopedSpills(IrRegAllocX64& owner);
120
~ScopedSpills();
121
122
ScopedSpills(const ScopedSpills&) = delete;
123
ScopedSpills& operator=(const ScopedSpills&) = delete;
124
125
IrRegAllocX64& owner;
126
unsigned startSpillId = 0;
127
};
128
129
} // namespace X64
130
} // namespace CodeGen
131
} // namespace Luau
132
133