summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/glasm/reg_alloc.cpp
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-05-25 02:22:21 -0300
committerGravatar ameerj2021-07-22 21:51:33 -0400
commitca05a13c62ad7693f8be924c168e400e8139b0d2 (patch)
tree813638ab0c537089f3493f824707417dd429a48f /src/shader_recompiler/backend/glasm/reg_alloc.cpp
parentglasm: Fix usage counting on phi nodes (diff)
downloadyuzu-ca05a13c62ad7693f8be924c168e400e8139b0d2.tar.gz
yuzu-ca05a13c62ad7693f8be924c168e400e8139b0d2.tar.xz
yuzu-ca05a13c62ad7693f8be924c168e400e8139b0d2.zip
glasm: Catch more register leaks
Add support for null registers. These are used when an instruction has no usages. This comes handy when an instruction is only used for its CC value, with the caveat of having to invalidate all pseudo-instructions before defining the instruction itself in the register allocator. This commits changes this. Workaround a bug on Nvidia's condition codes conditional execution using branches.
Diffstat (limited to 'src/shader_recompiler/backend/glasm/reg_alloc.cpp')
-rw-r--r--src/shader_recompiler/backend/glasm/reg_alloc.cpp28
1 files changed, 24 insertions, 4 deletions
diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp
index 707b22247..c55a833c6 100644
--- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp
+++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp
@@ -22,11 +22,19 @@ Register RegAlloc::LongDefine(IR::Inst& inst) {
22} 22}
23 23
24Value RegAlloc::Peek(const IR::Value& value) { 24Value RegAlloc::Peek(const IR::Value& value) {
25 return value.IsImmediate() ? MakeImm(value) : PeekInst(*value.InstRecursive()); 25 if (value.IsImmediate()) {
26 return MakeImm(value);
27 } else {
28 return PeekInst(*value.Inst());
29 }
26} 30}
27 31
28Value RegAlloc::Consume(const IR::Value& value) { 32Value RegAlloc::Consume(const IR::Value& value) {
29 return value.IsImmediate() ? MakeImm(value) : ConsumeInst(*value.InstRecursive()); 33 if (value.IsImmediate()) {
34 return MakeImm(value);
35 } else {
36 return ConsumeInst(*value.Inst());
37 }
30} 38}
31 39
32void RegAlloc::Unref(IR::Inst& inst) { 40void RegAlloc::Unref(IR::Inst& inst) {
@@ -88,7 +96,14 @@ Value RegAlloc::MakeImm(const IR::Value& value) {
88} 96}
89 97
90Register RegAlloc::Define(IR::Inst& inst, bool is_long) { 98Register RegAlloc::Define(IR::Inst& inst, bool is_long) {
91 inst.SetDefinition<Id>(Alloc(is_long)); 99 if (inst.HasUses()) {
100 inst.SetDefinition<Id>(Alloc(is_long));
101 } else {
102 Id id{};
103 id.is_long.Assign(is_long ? 1 : 0);
104 id.is_null.Assign(1);
105 inst.SetDefinition<Id>(id);
106 }
92 return Register{PeekInst(inst)}; 107 return Register{PeekInst(inst)};
93} 108}
94 109
@@ -115,10 +130,12 @@ Id RegAlloc::Alloc(bool is_long) {
115 num_regs = std::max(num_regs, reg + 1); 130 num_regs = std::max(num_regs, reg + 1);
116 use[reg] = true; 131 use[reg] = true;
117 Id ret{}; 132 Id ret{};
118 ret.index.Assign(static_cast<u32>(reg)); 133 ret.is_valid.Assign(1);
119 ret.is_long.Assign(is_long ? 1 : 0); 134 ret.is_long.Assign(is_long ? 1 : 0);
120 ret.is_spill.Assign(0); 135 ret.is_spill.Assign(0);
121 ret.is_condition_code.Assign(0); 136 ret.is_condition_code.Assign(0);
137 ret.is_null.Assign(0);
138 ret.index.Assign(static_cast<u32>(reg));
122 return ret; 139 return ret;
123 } 140 }
124 } 141 }
@@ -126,6 +143,9 @@ Id RegAlloc::Alloc(bool is_long) {
126} 143}
127 144
128void RegAlloc::Free(Id id) { 145void RegAlloc::Free(Id id) {
146 if (id.is_valid == 0) {
147 throw LogicError("Freeing invalid register");
148 }
129 if (id.is_spill != 0) { 149 if (id.is_spill != 0) {
130 throw NotImplementedException("Free spill"); 150 throw NotImplementedException("Free spill");
131 } 151 }