summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-05-10 03:47:31 -0300
committerGravatar ameerj2021-07-22 21:51:31 -0400
commitdeda89372f78dc78b37e941bf86e3026708e3ea2 (patch)
tree070a356b32b84b57b9ef409869e2476b57c00bfb /src/shader_recompiler/backend
parentglasm: Implement SelectU64 on GLASM (diff)
downloadyuzu-deda89372f78dc78b37e941bf86e3026708e3ea2.tar.gz
yuzu-deda89372f78dc78b37e941bf86e3026708e3ea2.tar.xz
yuzu-deda89372f78dc78b37e941bf86e3026708e3ea2.zip
glasm: Fix register allocation when moving immediate on GLASM
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm.cpp50
-rw-r--r--src/shader_recompiler/backend/glasm/reg_alloc.cpp71
-rw-r--r--src/shader_recompiler/backend/glasm/reg_alloc.h10
3 files changed, 89 insertions, 42 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
index 8e5d575a9..ad27b8b06 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp
@@ -39,14 +39,16 @@ struct Identity {
39}; 39};
40 40
41template <bool scalar> 41template <bool scalar>
42struct RegWrapper { 42class RegWrapper {
43 RegWrapper(EmitContext& ctx, Value value) 43public:
44 : reg_alloc{ctx.reg_alloc}, allocated{value.type != Type::Register} { 44 RegWrapper(EmitContext& ctx, const IR::Value& ir_value) : reg_alloc{ctx.reg_alloc} {
45 if (allocated) { 45 const Value value{reg_alloc.Peek(ir_value)};
46 if (value.type == Type::Register) {
47 inst = ir_value.InstRecursive();
48 reg = Register{value};
49 } else {
46 const bool is_long{value.type == Type::F64 || value.type == Type::U64}; 50 const bool is_long{value.type == Type::F64 || value.type == Type::U64};
47 reg = is_long ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg(); 51 reg = is_long ? reg_alloc.AllocLongReg() : reg_alloc.AllocReg();
48 } else {
49 reg = Register{value};
50 } 52 }
51 switch (value.type) { 53 switch (value.type) {
52 case Type::Register: 54 case Type::Register:
@@ -68,8 +70,11 @@ struct RegWrapper {
68 break; 70 break;
69 } 71 }
70 } 72 }
73
71 ~RegWrapper() { 74 ~RegWrapper() {
72 if (allocated) { 75 if (inst) {
76 reg_alloc.Unref(*inst);
77 } else {
73 reg_alloc.FreeReg(reg); 78 reg_alloc.FreeReg(reg);
74 } 79 }
75 } 80 }
@@ -78,19 +83,42 @@ struct RegWrapper {
78 return std::conditional_t<scalar, ScalarRegister, Register>{Value{reg}}; 83 return std::conditional_t<scalar, ScalarRegister, Register>{Value{reg}};
79 } 84 }
80 85
86private:
81 RegAlloc& reg_alloc; 87 RegAlloc& reg_alloc;
88 IR::Inst* inst{};
82 Register reg{}; 89 Register reg{};
83 bool allocated{}; 90};
91
92template <typename ArgType>
93class ValueWrapper {
94public:
95 ValueWrapper(EmitContext& ctx, const IR::Value& ir_value_)
96 : reg_alloc{ctx.reg_alloc}, ir_value{ir_value_}, value{reg_alloc.Peek(ir_value)} {}
97
98 ~ValueWrapper() {
99 if (!ir_value.IsImmediate()) {
100 reg_alloc.Unref(*ir_value.InstRecursive());
101 }
102 }
103
104 ArgType Extract() {
105 return value;
106 }
107
108private:
109 RegAlloc& reg_alloc;
110 const IR::Value& ir_value;
111 ArgType value;
84}; 112};
85 113
86template <typename ArgType> 114template <typename ArgType>
87auto Arg(EmitContext& ctx, const IR::Value& arg) { 115auto Arg(EmitContext& ctx, const IR::Value& arg) {
88 if constexpr (std::is_same_v<ArgType, Register>) { 116 if constexpr (std::is_same_v<ArgType, Register>) {
89 return RegWrapper<false>{ctx, ctx.reg_alloc.Consume(arg)}; 117 return RegWrapper<false>{ctx, arg};
90 } else if constexpr (std::is_same_v<ArgType, ScalarRegister>) { 118 } else if constexpr (std::is_same_v<ArgType, ScalarRegister>) {
91 return RegWrapper<true>{ctx, ctx.reg_alloc.Consume(arg)}; 119 return RegWrapper<true>{ctx, arg};
92 } else if constexpr (std::is_base_of_v<Value, ArgType>) { 120 } else if constexpr (std::is_base_of_v<Value, ArgType>) {
93 return Identity{ArgType{ctx.reg_alloc.Consume(arg)}}; 121 return ValueWrapper<ArgType>{ctx, arg};
94 } else if constexpr (std::is_same_v<ArgType, const IR::Value&>) { 122 } else if constexpr (std::is_same_v<ArgType, const IR::Value&>) {
95 return Identity{arg}; 123 return Identity{arg};
96 } else if constexpr (std::is_same_v<ArgType, u32>) { 124 } else if constexpr (std::is_same_v<ArgType, u32>) {
diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.cpp b/src/shader_recompiler/backend/glasm/reg_alloc.cpp
index 1a65a5e7d..f556f3aee 100644
--- a/src/shader_recompiler/backend/glasm/reg_alloc.cpp
+++ b/src/shader_recompiler/backend/glasm/reg_alloc.cpp
@@ -21,10 +21,40 @@ Register RegAlloc::LongDefine(IR::Inst& inst) {
21 return Define(inst, true); 21 return Define(inst, true);
22} 22}
23 23
24Value RegAlloc::Peek(const IR::Value& value) {
25 return value.IsImmediate() ? MakeImm(value) : PeekInst(*value.InstRecursive());
26}
27
24Value RegAlloc::Consume(const IR::Value& value) { 28Value RegAlloc::Consume(const IR::Value& value) {
25 if (!value.IsImmediate()) { 29 return value.IsImmediate() ? MakeImm(value) : ConsumeInst(*value.InstRecursive());
26 return Consume(*value.InstRecursive()); 30}
31
32void RegAlloc::Unref(IR::Inst& inst) {
33 inst.DestructiveRemoveUsage();
34 if (!inst.HasUses()) {
35 Free(inst.Definition<Id>());
27 } 36 }
37}
38
39Register RegAlloc::AllocReg() {
40 Register ret;
41 ret.type = Type::Register;
42 ret.id = Alloc(false);
43 return ret;
44}
45
46Register RegAlloc::AllocLongReg() {
47 Register ret;
48 ret.type = Type::Register;
49 ret.id = Alloc(true);
50 return ret;
51}
52
53void RegAlloc::FreeReg(Register reg) {
54 Free(reg.id);
55}
56
57Value RegAlloc::MakeImm(const IR::Value& value) {
28 Value ret; 58 Value ret;
29 switch (value.Type()) { 59 switch (value.Type()) {
30 case IR::Type::U1: 60 case IR::Type::U1:
@@ -53,43 +83,24 @@ Value RegAlloc::Consume(const IR::Value& value) {
53 return ret; 83 return ret;
54} 84}
55 85
56Register RegAlloc::AllocReg() { 86Register RegAlloc::Define(IR::Inst& inst, bool is_long) {
57 Register ret; 87 inst.SetDefinition<Id>(Alloc(is_long));
58 ret.type = Type::Register; 88 return Register{PeekInst(inst)};
59 ret.id = Alloc(false);
60 return ret;
61}
62
63Register RegAlloc::AllocLongReg() {
64 Register ret;
65 ret.type = Type::Register;
66 ret.id = Alloc(true);
67 return ret;
68}
69
70void RegAlloc::FreeReg(Register reg) {
71 Free(reg.id);
72} 89}
73 90
74Register RegAlloc::Define(IR::Inst& inst, bool is_long) { 91Value RegAlloc::PeekInst(IR::Inst& inst) {
75 const Id id{Alloc(is_long)}; 92 Value ret;
76 inst.SetDefinition<Id>(id);
77 Register ret;
78 ret.type = Type::Register; 93 ret.type = Type::Register;
79 ret.id = id; 94 ret.id = inst.Definition<Id>();
80 return ret; 95 return ret;
81} 96}
82 97
83Value RegAlloc::Consume(IR::Inst& inst) { 98Value RegAlloc::ConsumeInst(IR::Inst& inst) {
84 const Id id{inst.Definition<Id>()};
85 inst.DestructiveRemoveUsage(); 99 inst.DestructiveRemoveUsage();
86 if (!inst.HasUses()) { 100 if (!inst.HasUses()) {
87 Free(id); 101 Free(inst.Definition<Id>());
88 } 102 }
89 Value ret; 103 return PeekInst(inst);
90 ret.type = Type::Register;
91 ret.id = id;
92 return ret;
93} 104}
94 105
95Id RegAlloc::Alloc(bool is_long) { 106Id RegAlloc::Alloc(bool is_long) {
diff --git a/src/shader_recompiler/backend/glasm/reg_alloc.h b/src/shader_recompiler/backend/glasm/reg_alloc.h
index 8df73ca18..5742436cf 100644
--- a/src/shader_recompiler/backend/glasm/reg_alloc.h
+++ b/src/shader_recompiler/backend/glasm/reg_alloc.h
@@ -99,8 +99,12 @@ public:
99 99
100 Register LongDefine(IR::Inst& inst); 100 Register LongDefine(IR::Inst& inst);
101 101
102 [[nodiscard]] Value Peek(const IR::Value& value);
103
102 Value Consume(const IR::Value& value); 104 Value Consume(const IR::Value& value);
103 105
106 void Unref(IR::Inst& inst);
107
104 [[nodiscard]] Register AllocReg(); 108 [[nodiscard]] Register AllocReg();
105 109
106 [[nodiscard]] Register AllocLongReg(); 110 [[nodiscard]] Register AllocLongReg();
@@ -123,9 +127,13 @@ private:
123 static constexpr size_t NUM_REGS = 4096; 127 static constexpr size_t NUM_REGS = 4096;
124 static constexpr size_t NUM_ELEMENTS = 4; 128 static constexpr size_t NUM_ELEMENTS = 4;
125 129
130 Value MakeImm(const IR::Value& value);
131
126 Register Define(IR::Inst& inst, bool is_long); 132 Register Define(IR::Inst& inst, bool is_long);
127 133
128 Value Consume(IR::Inst& inst); 134 Value PeekInst(IR::Inst& inst);
135
136 Value ConsumeInst(IR::Inst& inst);
129 137
130 Id Alloc(bool is_long); 138 Id Alloc(bool is_long);
131 139