summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/frontend/ir
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/frontend/ir')
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp133
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h21
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp73
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.h22
-rw-r--r--src/shader_recompiler/frontend/ir/modifiers.h10
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.cpp2
-rw-r--r--src/shader_recompiler/frontend/ir/opcodes.inc569
-rw-r--r--src/shader_recompiler/frontend/ir/reg.h11
-rw-r--r--src/shader_recompiler/frontend/ir/value.h1
9 files changed, 537 insertions, 305 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index f38b46bac..ae3354c66 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -7,11 +7,24 @@
7#include "shader_recompiler/frontend/ir/value.h" 7#include "shader_recompiler/frontend/ir/value.h"
8 8
9namespace Shader::IR { 9namespace Shader::IR {
10 10namespace {
11[[noreturn]] static void ThrowInvalidType(Type type) { 11[[noreturn]] void ThrowInvalidType(Type type) {
12 throw InvalidArgument("Invalid type {}", type); 12 throw InvalidArgument("Invalid type {}", type);
13} 13}
14 14
15Value MakeLodClampPair(IREmitter& ir, const F32& bias_lod, const F32& lod_clamp) {
16 if (!bias_lod.IsEmpty() && !lod_clamp.IsEmpty()) {
17 return ir.CompositeConstruct(bias_lod, lod_clamp);
18 } else if (!bias_lod.IsEmpty()) {
19 return bias_lod;
20 } else if (!lod_clamp.IsEmpty()) {
21 return lod_clamp;
22 } else {
23 return Value{};
24 }
25}
26} // Anonymous namespace
27
15U1 IREmitter::Imm1(bool value) const { 28U1 IREmitter::Imm1(bool value) const {
16 return U1{Value{value}}; 29 return U1{Value{value}};
17} 30}
@@ -261,6 +274,10 @@ U1 IREmitter::GetOverflowFromOp(const Value& op) {
261 return Inst<U1>(Opcode::GetOverflowFromOp, op); 274 return Inst<U1>(Opcode::GetOverflowFromOp, op);
262} 275}
263 276
277U1 IREmitter::GetSparseFromOp(const Value& op) {
278 return Inst<U1>(Opcode::GetSparseFromOp, op);
279}
280
264F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) { 281F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) {
265 if (a.Type() != a.Type()) { 282 if (a.Type() != a.Type()) {
266 throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); 283 throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type());
@@ -1035,6 +1052,82 @@ U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& v
1035 } 1052 }
1036} 1053}
1037 1054
1055F16F32F64 IREmitter::ConvertSToF(size_t bitsize, const U32U64& value) {
1056 switch (bitsize) {
1057 case 16:
1058 switch (value.Type()) {
1059 case Type::U32:
1060 return Inst<F16>(Opcode::ConvertF16S32, value);
1061 case Type::U64:
1062 return Inst<F16>(Opcode::ConvertF16S64, value);
1063 default:
1064 ThrowInvalidType(value.Type());
1065 }
1066 case 32:
1067 switch (value.Type()) {
1068 case Type::U32:
1069 return Inst<F32>(Opcode::ConvertF32S32, value);
1070 case Type::U64:
1071 return Inst<F32>(Opcode::ConvertF32S64, value);
1072 default:
1073 ThrowInvalidType(value.Type());
1074 }
1075 case 64:
1076 switch (value.Type()) {
1077 case Type::U32:
1078 return Inst<F16>(Opcode::ConvertF64S32, value);
1079 case Type::U64:
1080 return Inst<F16>(Opcode::ConvertF64S64, value);
1081 default:
1082 ThrowInvalidType(value.Type());
1083 }
1084 default:
1085 throw InvalidArgument("Invalid destination bitsize {}", bitsize);
1086 }
1087}
1088
1089F16F32F64 IREmitter::ConvertUToF(size_t bitsize, const U32U64& value) {
1090 switch (bitsize) {
1091 case 16:
1092 switch (value.Type()) {
1093 case Type::U32:
1094 return Inst<F16>(Opcode::ConvertF16U32, value);
1095 case Type::U64:
1096 return Inst<F16>(Opcode::ConvertF16U64, value);
1097 default:
1098 ThrowInvalidType(value.Type());
1099 }
1100 case 32:
1101 switch (value.Type()) {
1102 case Type::U32:
1103 return Inst<F32>(Opcode::ConvertF32U32, value);
1104 case Type::U64:
1105 return Inst<F32>(Opcode::ConvertF32U64, value);
1106 default:
1107 ThrowInvalidType(value.Type());
1108 }
1109 case 64:
1110 switch (value.Type()) {
1111 case Type::U32:
1112 return Inst<F16>(Opcode::ConvertF64U32, value);
1113 case Type::U64:
1114 return Inst<F16>(Opcode::ConvertF64U64, value);
1115 default:
1116 ThrowInvalidType(value.Type());
1117 }
1118 default:
1119 throw InvalidArgument("Invalid destination bitsize {}", bitsize);
1120 }
1121}
1122
1123F16F32F64 IREmitter::ConvertIToF(size_t bitsize, bool is_signed, const U32U64& value) {
1124 if (is_signed) {
1125 return ConvertSToF(bitsize, value);
1126 } else {
1127 return ConvertUToF(bitsize, value);
1128 }
1129}
1130
1038U32U64 IREmitter::UConvert(size_t result_bitsize, const U32U64& value) { 1131U32U64 IREmitter::UConvert(size_t result_bitsize, const U32U64& value) {
1039 switch (result_bitsize) { 1132 switch (result_bitsize) {
1040 case 32: 1133 case 32:
@@ -1107,4 +1200,40 @@ F16F32F64 IREmitter::FPConvert(size_t result_bitsize, const F16F32F64& value) {
1107 throw NotImplementedException("Conversion from {} to {} bits", value.Type(), result_bitsize); 1200 throw NotImplementedException("Conversion from {} to {} bits", value.Type(), result_bitsize);
1108} 1201}
1109 1202
1203Value IREmitter::ImageSampleImplicitLod(const Value& handle, const Value& coords, const F32& bias,
1204 const Value& offset, const F32& lod_clamp,
1205 TextureInstInfo info) {
1206 const Value bias_lc{MakeLodClampPair(*this, bias, lod_clamp)};
1207 const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleImplicitLod
1208 : Opcode::BindlessImageSampleImplicitLod};
1209 return Inst(op, Flags{info}, handle, coords, bias_lc, offset);
1210}
1211
1212Value IREmitter::ImageSampleExplicitLod(const Value& handle, const Value& coords, const F32& lod,
1213 const Value& offset, const F32& lod_clamp,
1214 TextureInstInfo info) {
1215 const Value lod_lc{MakeLodClampPair(*this, lod, lod_clamp)};
1216 const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleExplicitLod
1217 : Opcode::BindlessImageSampleExplicitLod};
1218 return Inst(op, Flags{info}, handle, coords, lod_lc, offset);
1219}
1220
1221F32 IREmitter::ImageSampleDrefImplicitLod(const Value& handle, const Value& coords, const F32& dref,
1222 const F32& bias, const Value& offset,
1223 const F32& lod_clamp, TextureInstInfo info) {
1224 const Value bias_lc{MakeLodClampPair(*this, bias, lod_clamp)};
1225 const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleDrefImplicitLod
1226 : Opcode::BindlessImageSampleDrefImplicitLod};
1227 return Inst<F32>(op, Flags{info}, handle, coords, dref, bias_lc, offset);
1228}
1229
1230F32 IREmitter::ImageSampleDrefExplicitLod(const Value& handle, const Value& coords, const F32& dref,
1231 const F32& lod, const Value& offset, const F32& lod_clamp,
1232 TextureInstInfo info) {
1233 const Value lod_lc{MakeLodClampPair(*this, lod, lod_clamp)};
1234 const Opcode op{handle.IsImmediate() ? Opcode::BoundImageSampleDrefExplicitLod
1235 : Opcode::BindlessImageSampleDrefExplicitLod};
1236 return Inst<F32>(op, Flags{info}, handle, coords, dref, lod_lc, offset);
1237}
1238
1110} // namespace Shader::IR 1239} // namespace Shader::IR
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index 6e29bf0e2..cb2a7710a 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -91,6 +91,7 @@ public:
91 [[nodiscard]] U1 GetSignFromOp(const Value& op); 91 [[nodiscard]] U1 GetSignFromOp(const Value& op);
92 [[nodiscard]] U1 GetCarryFromOp(const Value& op); 92 [[nodiscard]] U1 GetCarryFromOp(const Value& op);
93 [[nodiscard]] U1 GetOverflowFromOp(const Value& op); 93 [[nodiscard]] U1 GetOverflowFromOp(const Value& op);
94 [[nodiscard]] U1 GetSparseFromOp(const Value& op);
94 95
95 [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2); 96 [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2);
96 [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3); 97 [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3);
@@ -159,7 +160,7 @@ public:
159 [[nodiscard]] U32 BitFieldInsert(const U32& base, const U32& insert, const U32& offset, 160 [[nodiscard]] U32 BitFieldInsert(const U32& base, const U32& insert, const U32& offset,
160 const U32& count); 161 const U32& count);
161 [[nodiscard]] U32 BitFieldExtract(const U32& base, const U32& offset, const U32& count, 162 [[nodiscard]] U32 BitFieldExtract(const U32& base, const U32& offset, const U32& count,
162 bool is_signed); 163 bool is_signed = false);
163 [[nodiscard]] U32 BitReverse(const U32& value); 164 [[nodiscard]] U32 BitReverse(const U32& value);
164 [[nodiscard]] U32 BitCount(const U32& value); 165 [[nodiscard]] U32 BitCount(const U32& value);
165 [[nodiscard]] U32 BitwiseNot(const U32& value); 166 [[nodiscard]] U32 BitwiseNot(const U32& value);
@@ -186,10 +187,28 @@ public:
186 [[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const F16F32F64& value); 187 [[nodiscard]] U32U64 ConvertFToS(size_t bitsize, const F16F32F64& value);
187 [[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const F16F32F64& value); 188 [[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const F16F32F64& value);
188 [[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value); 189 [[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const F16F32F64& value);
190 [[nodiscard]] F16F32F64 ConvertSToF(size_t bitsize, const U32U64& value);
191 [[nodiscard]] F16F32F64 ConvertUToF(size_t bitsize, const U32U64& value);
192 [[nodiscard]] F16F32F64 ConvertIToF(size_t bitsize, bool is_signed, const U32U64& value);
189 193
190 [[nodiscard]] U32U64 UConvert(size_t result_bitsize, const U32U64& value); 194 [[nodiscard]] U32U64 UConvert(size_t result_bitsize, const U32U64& value);
191 [[nodiscard]] F16F32F64 FPConvert(size_t result_bitsize, const F16F32F64& value); 195 [[nodiscard]] F16F32F64 FPConvert(size_t result_bitsize, const F16F32F64& value);
192 196
197 [[nodiscard]] Value ImageSampleImplicitLod(const Value& handle, const Value& coords,
198 const F32& bias, const Value& offset,
199 const F32& lod_clamp, TextureInstInfo info);
200 [[nodiscard]] Value ImageSampleExplicitLod(const Value& handle, const Value& coords,
201 const F32& lod, const Value& offset,
202 const F32& lod_clamp, TextureInstInfo info);
203 [[nodiscard]] F32 ImageSampleDrefImplicitLod(const Value& handle, const Value& coords,
204 const F32& dref, const F32& bias,
205 const Value& offset, const F32& lod_clamp,
206 TextureInstInfo info);
207 [[nodiscard]] F32 ImageSampleDrefExplicitLod(const Value& handle, const Value& coords,
208 const F32& dref, const F32& lod,
209 const Value& offset, const F32& lod_clamp,
210 TextureInstInfo info);
211
193private: 212private:
194 IR::Block::iterator insertion_point; 213 IR::Block::iterator insertion_point;
195 214
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index d6a9be87d..88e186f21 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -10,26 +10,27 @@
10#include "shader_recompiler/frontend/ir/type.h" 10#include "shader_recompiler/frontend/ir/type.h"
11 11
12namespace Shader::IR { 12namespace Shader::IR {
13 13namespace {
14static void CheckPseudoInstruction(IR::Inst* inst, IR::Opcode opcode) { 14void CheckPseudoInstruction(IR::Inst* inst, IR::Opcode opcode) {
15 if (inst && inst->Opcode() != opcode) { 15 if (inst && inst->Opcode() != opcode) {
16 throw LogicError("Invalid pseudo-instruction"); 16 throw LogicError("Invalid pseudo-instruction");
17 } 17 }
18} 18}
19 19
20static void SetPseudoInstruction(IR::Inst*& dest_inst, IR::Inst* pseudo_inst) { 20void SetPseudoInstruction(IR::Inst*& dest_inst, IR::Inst* pseudo_inst) {
21 if (dest_inst) { 21 if (dest_inst) {
22 throw LogicError("Only one of each type of pseudo-op allowed"); 22 throw LogicError("Only one of each type of pseudo-op allowed");
23 } 23 }
24 dest_inst = pseudo_inst; 24 dest_inst = pseudo_inst;
25} 25}
26 26
27static void RemovePseudoInstruction(IR::Inst*& inst, IR::Opcode expected_opcode) { 27void RemovePseudoInstruction(IR::Inst*& inst, IR::Opcode expected_opcode) {
28 if (inst->Opcode() != expected_opcode) { 28 if (inst->Opcode() != expected_opcode) {
29 throw LogicError("Undoing use of invalid pseudo-op"); 29 throw LogicError("Undoing use of invalid pseudo-op");
30 } 30 }
31 inst = nullptr; 31 inst = nullptr;
32} 32}
33} // Anonymous namespace
33 34
34Inst::Inst(IR::Opcode op_, u32 flags_) noexcept : op{op_}, flags{flags_} { 35Inst::Inst(IR::Opcode op_, u32 flags_) noexcept : op{op_}, flags{flags_} {
35 if (op == Opcode::Phi) { 36 if (op == Opcode::Phi) {
@@ -82,6 +83,7 @@ bool Inst::IsPseudoInstruction() const noexcept {
82 case Opcode::GetSignFromOp: 83 case Opcode::GetSignFromOp:
83 case Opcode::GetCarryFromOp: 84 case Opcode::GetCarryFromOp:
84 case Opcode::GetOverflowFromOp: 85 case Opcode::GetOverflowFromOp:
86 case Opcode::GetSparseFromOp:
85 return true; 87 return true;
86 default: 88 default:
87 return false; 89 return false;
@@ -96,25 +98,26 @@ bool Inst::AreAllArgsImmediates() const {
96 [](const IR::Value& value) { return value.IsImmediate(); }); 98 [](const IR::Value& value) { return value.IsImmediate(); });
97} 99}
98 100
99bool Inst::HasAssociatedPseudoOperation() const noexcept {
100 return zero_inst || sign_inst || carry_inst || overflow_inst;
101}
102
103Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) { 101Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) {
104 // This is faster than doing a search through the block. 102 if (!associated_insts) {
103 return nullptr;
104 }
105 switch (opcode) { 105 switch (opcode) {
106 case Opcode::GetZeroFromOp: 106 case Opcode::GetZeroFromOp:
107 CheckPseudoInstruction(zero_inst, Opcode::GetZeroFromOp); 107 CheckPseudoInstruction(associated_insts->zero_inst, Opcode::GetZeroFromOp);
108 return zero_inst; 108 return associated_insts->zero_inst;
109 case Opcode::GetSignFromOp: 109 case Opcode::GetSignFromOp:
110 CheckPseudoInstruction(sign_inst, Opcode::GetSignFromOp); 110 CheckPseudoInstruction(associated_insts->sign_inst, Opcode::GetSignFromOp);
111 return sign_inst; 111 return associated_insts->sign_inst;
112 case Opcode::GetCarryFromOp: 112 case Opcode::GetCarryFromOp:
113 CheckPseudoInstruction(carry_inst, Opcode::GetCarryFromOp); 113 CheckPseudoInstruction(associated_insts->carry_inst, Opcode::GetCarryFromOp);
114 return carry_inst; 114 return associated_insts->carry_inst;
115 case Opcode::GetOverflowFromOp: 115 case Opcode::GetOverflowFromOp:
116 CheckPseudoInstruction(overflow_inst, Opcode::GetOverflowFromOp); 116 CheckPseudoInstruction(associated_insts->overflow_inst, Opcode::GetOverflowFromOp);
117 return overflow_inst; 117 return associated_insts->overflow_inst;
118 case Opcode::GetSparseFromOp:
119 CheckPseudoInstruction(associated_insts->sparse_inst, Opcode::GetSparseFromOp);
120 return associated_insts->sparse_inst;
118 default: 121 default:
119 throw InvalidArgument("{} is not a pseudo-instruction", opcode); 122 throw InvalidArgument("{} is not a pseudo-instruction", opcode);
120 } 123 }
@@ -220,22 +223,37 @@ void Inst::ReplaceOpcode(IR::Opcode opcode) {
220 op = opcode; 223 op = opcode;
221} 224}
222 225
226void AllocAssociatedInsts(std::unique_ptr<AssociatedInsts>& associated_insts) {
227 if (!associated_insts) {
228 associated_insts = std::make_unique<AssociatedInsts>();
229 }
230}
231
223void Inst::Use(const Value& value) { 232void Inst::Use(const Value& value) {
224 Inst* const inst{value.Inst()}; 233 Inst* const inst{value.Inst()};
225 ++inst->use_count; 234 ++inst->use_count;
226 235
236 std::unique_ptr<AssociatedInsts>& assoc_inst{inst->associated_insts};
227 switch (op) { 237 switch (op) {
228 case Opcode::GetZeroFromOp: 238 case Opcode::GetZeroFromOp:
229 SetPseudoInstruction(inst->zero_inst, this); 239 AllocAssociatedInsts(assoc_inst);
240 SetPseudoInstruction(assoc_inst->zero_inst, this);
230 break; 241 break;
231 case Opcode::GetSignFromOp: 242 case Opcode::GetSignFromOp:
232 SetPseudoInstruction(inst->sign_inst, this); 243 AllocAssociatedInsts(assoc_inst);
244 SetPseudoInstruction(assoc_inst->sign_inst, this);
233 break; 245 break;
234 case Opcode::GetCarryFromOp: 246 case Opcode::GetCarryFromOp:
235 SetPseudoInstruction(inst->carry_inst, this); 247 AllocAssociatedInsts(assoc_inst);
248 SetPseudoInstruction(assoc_inst->carry_inst, this);
236 break; 249 break;
237 case Opcode::GetOverflowFromOp: 250 case Opcode::GetOverflowFromOp:
238 SetPseudoInstruction(inst->overflow_inst, this); 251 AllocAssociatedInsts(assoc_inst);
252 SetPseudoInstruction(assoc_inst->overflow_inst, this);
253 break;
254 case Opcode::GetSparseFromOp:
255 AllocAssociatedInsts(assoc_inst);
256 SetPseudoInstruction(assoc_inst->sparse_inst, this);
239 break; 257 break;
240 default: 258 default:
241 break; 259 break;
@@ -246,18 +264,23 @@ void Inst::UndoUse(const Value& value) {
246 Inst* const inst{value.Inst()}; 264 Inst* const inst{value.Inst()};
247 --inst->use_count; 265 --inst->use_count;
248 266
267 std::unique_ptr<AssociatedInsts>& assoc_inst{inst->associated_insts};
249 switch (op) { 268 switch (op) {
250 case Opcode::GetZeroFromOp: 269 case Opcode::GetZeroFromOp:
251 RemovePseudoInstruction(inst->zero_inst, Opcode::GetZeroFromOp); 270 AllocAssociatedInsts(assoc_inst);
271 RemovePseudoInstruction(assoc_inst->zero_inst, Opcode::GetZeroFromOp);
252 break; 272 break;
253 case Opcode::GetSignFromOp: 273 case Opcode::GetSignFromOp:
254 RemovePseudoInstruction(inst->sign_inst, Opcode::GetSignFromOp); 274 AllocAssociatedInsts(assoc_inst);
275 RemovePseudoInstruction(assoc_inst->sign_inst, Opcode::GetSignFromOp);
255 break; 276 break;
256 case Opcode::GetCarryFromOp: 277 case Opcode::GetCarryFromOp:
257 RemovePseudoInstruction(inst->carry_inst, Opcode::GetCarryFromOp); 278 AllocAssociatedInsts(assoc_inst);
279 RemovePseudoInstruction(assoc_inst->carry_inst, Opcode::GetCarryFromOp);
258 break; 280 break;
259 case Opcode::GetOverflowFromOp: 281 case Opcode::GetOverflowFromOp:
260 RemovePseudoInstruction(inst->overflow_inst, Opcode::GetOverflowFromOp); 282 AllocAssociatedInsts(assoc_inst);
283 RemovePseudoInstruction(assoc_inst->overflow_inst, Opcode::GetOverflowFromOp);
261 break; 284 break;
262 default: 285 default:
263 break; 286 break;
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.h b/src/shader_recompiler/frontend/ir/microinstruction.h
index 321393dd7..d5336c438 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.h
+++ b/src/shader_recompiler/frontend/ir/microinstruction.h
@@ -22,7 +22,7 @@ namespace Shader::IR {
22 22
23class Block; 23class Block;
24 24
25constexpr size_t MAX_ARG_COUNT = 4; 25struct AssociatedInsts;
26 26
27class Inst : public boost::intrusive::list_base_hook<> { 27class Inst : public boost::intrusive::list_base_hook<> {
28public: 28public:
@@ -50,6 +50,11 @@ public:
50 return op; 50 return op;
51 } 51 }
52 52
53 /// Determines if there is a pseudo-operation associated with this instruction.
54 [[nodiscard]] bool HasAssociatedPseudoOperation() const noexcept {
55 return associated_insts != nullptr;
56 }
57
53 /// Determines whether or not this instruction may have side effects. 58 /// Determines whether or not this instruction may have side effects.
54 [[nodiscard]] bool MayHaveSideEffects() const noexcept; 59 [[nodiscard]] bool MayHaveSideEffects() const noexcept;
55 60
@@ -60,8 +65,6 @@ public:
60 /// Determines if all arguments of this instruction are immediates. 65 /// Determines if all arguments of this instruction are immediates.
61 [[nodiscard]] bool AreAllArgsImmediates() const; 66 [[nodiscard]] bool AreAllArgsImmediates() const;
62 67
63 /// Determines if there is a pseudo-operation associated with this instruction.
64 [[nodiscard]] bool HasAssociatedPseudoOperation() const noexcept;
65 /// Gets a pseudo-operation associated with this instruction 68 /// Gets a pseudo-operation associated with this instruction
66 [[nodiscard]] Inst* GetAssociatedPseudoOperation(IR::Opcode opcode); 69 [[nodiscard]] Inst* GetAssociatedPseudoOperation(IR::Opcode opcode);
67 70
@@ -122,14 +125,21 @@ private:
122 u32 definition{}; 125 u32 definition{};
123 union { 126 union {
124 NonTriviallyDummy dummy{}; 127 NonTriviallyDummy dummy{};
125 std::array<Value, MAX_ARG_COUNT> args;
126 std::vector<std::pair<Block*, Value>> phi_args; 128 std::vector<std::pair<Block*, Value>> phi_args;
129 std::array<Value, 5> args;
130 };
131 std::unique_ptr<AssociatedInsts> associated_insts;
132};
133static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased");
134
135struct AssociatedInsts {
136 union {
137 Inst* sparse_inst;
138 Inst* zero_inst{};
127 }; 139 };
128 Inst* zero_inst{};
129 Inst* sign_inst{}; 140 Inst* sign_inst{};
130 Inst* carry_inst{}; 141 Inst* carry_inst{};
131 Inst* overflow_inst{}; 142 Inst* overflow_inst{};
132}; 143};
133static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased its size");
134 144
135} // namespace Shader::IR 145} // namespace Shader::IR
diff --git a/src/shader_recompiler/frontend/ir/modifiers.h b/src/shader_recompiler/frontend/ir/modifiers.h
index 44652eae7..ad07700ae 100644
--- a/src/shader_recompiler/frontend/ir/modifiers.h
+++ b/src/shader_recompiler/frontend/ir/modifiers.h
@@ -4,7 +4,9 @@
4 4
5#pragma once 5#pragma once
6 6
7#include "common/bit_field.h"
7#include "common/common_types.h" 8#include "common/common_types.h"
9#include "shader_recompiler/shader_info.h"
8 10
9namespace Shader::IR { 11namespace Shader::IR {
10 12
@@ -30,4 +32,12 @@ struct FpControl {
30}; 32};
31static_assert(sizeof(FpControl) <= sizeof(u32)); 33static_assert(sizeof(FpControl) <= sizeof(u32));
32 34
35union TextureInstInfo {
36 u32 raw;
37 BitField<0, 8, TextureType> type;
38 BitField<8, 1, u32> has_bias;
39 BitField<16, 1, u32> has_lod_clamp;
40};
41static_assert(sizeof(TextureInstInfo) <= sizeof(u32));
42
33} // namespace Shader::IR 43} // namespace Shader::IR
diff --git a/src/shader_recompiler/frontend/ir/opcodes.cpp b/src/shader_recompiler/frontend/ir/opcodes.cpp
index 1f188411a..8492a13d5 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.cpp
+++ b/src/shader_recompiler/frontend/ir/opcodes.cpp
@@ -14,7 +14,7 @@ namespace {
14struct OpcodeMeta { 14struct OpcodeMeta {
15 std::string_view name; 15 std::string_view name;
16 Type type; 16 Type type;
17 std::array<Type, 4> arg_types; 17 std::array<Type, 5> arg_types;
18}; 18};
19 19
20using enum Type; 20using enum Type;
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc
index c4e72c84d..aa011fab1 100644
--- a/src/shader_recompiler/frontend/ir/opcodes.inc
+++ b/src/shader_recompiler/frontend/ir/opcodes.inc
@@ -2,301 +2,330 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// opcode name, return type, arg1 type, arg2 type, arg3 type, arg4 type, ... 5// opcode name, return type, arg1 type, arg2 type, arg3 type, arg4 type, arg4 type, ...
6OPCODE(Phi, Opaque, ) 6OPCODE(Phi, Opaque, )
7OPCODE(Identity, Opaque, Opaque, ) 7OPCODE(Identity, Opaque, Opaque, )
8OPCODE(Void, Void, ) 8OPCODE(Void, Void, )
9 9
10// Control flow 10// Control flow
11OPCODE(Branch, Void, Label, ) 11OPCODE(Branch, Void, Label, )
12OPCODE(BranchConditional, Void, U1, Label, Label, ) 12OPCODE(BranchConditional, Void, U1, Label, Label, )
13OPCODE(LoopMerge, Void, Label, Label, ) 13OPCODE(LoopMerge, Void, Label, Label, )
14OPCODE(SelectionMerge, Void, Label, ) 14OPCODE(SelectionMerge, Void, Label, )
15OPCODE(Return, Void, ) 15OPCODE(Return, Void, )
16 16
17// Context getters/setters 17// Context getters/setters
18OPCODE(GetRegister, U32, Reg, ) 18OPCODE(GetRegister, U32, Reg, )
19OPCODE(SetRegister, Void, Reg, U32, ) 19OPCODE(SetRegister, Void, Reg, U32, )
20OPCODE(GetPred, U1, Pred, ) 20OPCODE(GetPred, U1, Pred, )
21OPCODE(SetPred, Void, Pred, U1, ) 21OPCODE(SetPred, Void, Pred, U1, )
22OPCODE(GetGotoVariable, U1, U32, ) 22OPCODE(GetGotoVariable, U1, U32, )
23OPCODE(SetGotoVariable, Void, U32, U1, ) 23OPCODE(SetGotoVariable, Void, U32, U1, )
24OPCODE(GetCbuf, U32, U32, U32, ) 24OPCODE(GetCbuf, U32, U32, U32, )
25OPCODE(GetAttribute, U32, Attribute, ) 25OPCODE(GetAttribute, U32, Attribute, )
26OPCODE(SetAttribute, Void, Attribute, U32, ) 26OPCODE(SetAttribute, Void, Attribute, U32, )
27OPCODE(GetAttributeIndexed, U32, U32, ) 27OPCODE(GetAttributeIndexed, U32, U32, )
28OPCODE(SetAttributeIndexed, Void, U32, U32, ) 28OPCODE(SetAttributeIndexed, Void, U32, U32, )
29OPCODE(GetZFlag, U1, Void, ) 29OPCODE(GetZFlag, U1, Void, )
30OPCODE(GetSFlag, U1, Void, ) 30OPCODE(GetSFlag, U1, Void, )
31OPCODE(GetCFlag, U1, Void, ) 31OPCODE(GetCFlag, U1, Void, )
32OPCODE(GetOFlag, U1, Void, ) 32OPCODE(GetOFlag, U1, Void, )
33OPCODE(SetZFlag, Void, U1, ) 33OPCODE(SetZFlag, Void, U1, )
34OPCODE(SetSFlag, Void, U1, ) 34OPCODE(SetSFlag, Void, U1, )
35OPCODE(SetCFlag, Void, U1, ) 35OPCODE(SetCFlag, Void, U1, )
36OPCODE(SetOFlag, Void, U1, ) 36OPCODE(SetOFlag, Void, U1, )
37OPCODE(WorkgroupId, U32x3, ) 37OPCODE(WorkgroupId, U32x3, )
38OPCODE(LocalInvocationId, U32x3, ) 38OPCODE(LocalInvocationId, U32x3, )
39 39
40// Undefined 40// Undefined
41OPCODE(UndefU1, U1, ) 41OPCODE(UndefU1, U1, )
42OPCODE(UndefU8, U8, ) 42OPCODE(UndefU8, U8, )
43OPCODE(UndefU16, U16, ) 43OPCODE(UndefU16, U16, )
44OPCODE(UndefU32, U32, ) 44OPCODE(UndefU32, U32, )
45OPCODE(UndefU64, U64, ) 45OPCODE(UndefU64, U64, )
46 46
47// Memory operations 47// Memory operations
48OPCODE(LoadGlobalU8, U32, U64, ) 48OPCODE(LoadGlobalU8, U32, U64, )
49OPCODE(LoadGlobalS8, U32, U64, ) 49OPCODE(LoadGlobalS8, U32, U64, )
50OPCODE(LoadGlobalU16, U32, U64, ) 50OPCODE(LoadGlobalU16, U32, U64, )
51OPCODE(LoadGlobalS16, U32, U64, ) 51OPCODE(LoadGlobalS16, U32, U64, )
52OPCODE(LoadGlobal32, U32, U64, ) 52OPCODE(LoadGlobal32, U32, U64, )
53OPCODE(LoadGlobal64, U32x2, U64, ) 53OPCODE(LoadGlobal64, U32x2, U64, )
54OPCODE(LoadGlobal128, U32x4, U64, ) 54OPCODE(LoadGlobal128, U32x4, U64, )
55OPCODE(WriteGlobalU8, Void, U64, U32, ) 55OPCODE(WriteGlobalU8, Void, U64, U32, )
56OPCODE(WriteGlobalS8, Void, U64, U32, ) 56OPCODE(WriteGlobalS8, Void, U64, U32, )
57OPCODE(WriteGlobalU16, Void, U64, U32, ) 57OPCODE(WriteGlobalU16, Void, U64, U32, )
58OPCODE(WriteGlobalS16, Void, U64, U32, ) 58OPCODE(WriteGlobalS16, Void, U64, U32, )
59OPCODE(WriteGlobal32, Void, U64, U32, ) 59OPCODE(WriteGlobal32, Void, U64, U32, )
60OPCODE(WriteGlobal64, Void, U64, U32x2, ) 60OPCODE(WriteGlobal64, Void, U64, U32x2, )
61OPCODE(WriteGlobal128, Void, U64, U32x4, ) 61OPCODE(WriteGlobal128, Void, U64, U32x4, )
62 62
63// Storage buffer operations 63// Storage buffer operations
64OPCODE(LoadStorageU8, U32, U32, U32, ) 64OPCODE(LoadStorageU8, U32, U32, U32, )
65OPCODE(LoadStorageS8, U32, U32, U32, ) 65OPCODE(LoadStorageS8, U32, U32, U32, )
66OPCODE(LoadStorageU16, U32, U32, U32, ) 66OPCODE(LoadStorageU16, U32, U32, U32, )
67OPCODE(LoadStorageS16, U32, U32, U32, ) 67OPCODE(LoadStorageS16, U32, U32, U32, )
68OPCODE(LoadStorage32, U32, U32, U32, ) 68OPCODE(LoadStorage32, U32, U32, U32, )
69OPCODE(LoadStorage64, U32x2, U32, U32, ) 69OPCODE(LoadStorage64, U32x2, U32, U32, )
70OPCODE(LoadStorage128, U32x4, U32, U32, ) 70OPCODE(LoadStorage128, U32x4, U32, U32, )
71OPCODE(WriteStorageU8, Void, U32, U32, U32, ) 71OPCODE(WriteStorageU8, Void, U32, U32, U32, )
72OPCODE(WriteStorageS8, Void, U32, U32, U32, ) 72OPCODE(WriteStorageS8, Void, U32, U32, U32, )
73OPCODE(WriteStorageU16, Void, U32, U32, U32, ) 73OPCODE(WriteStorageU16, Void, U32, U32, U32, )
74OPCODE(WriteStorageS16, Void, U32, U32, U32, ) 74OPCODE(WriteStorageS16, Void, U32, U32, U32, )
75OPCODE(WriteStorage32, Void, U32, U32, U32, ) 75OPCODE(WriteStorage32, Void, U32, U32, U32, )
76OPCODE(WriteStorage64, Void, U32, U32, U32x2, ) 76OPCODE(WriteStorage64, Void, U32, U32, U32x2, )
77OPCODE(WriteStorage128, Void, U32, U32, U32x4, ) 77OPCODE(WriteStorage128, Void, U32, U32, U32x4, )
78 78
79// Vector utility 79// Vector utility
80OPCODE(CompositeConstructU32x2, U32x2, U32, U32, ) 80OPCODE(CompositeConstructU32x2, U32x2, U32, U32, )
81OPCODE(CompositeConstructU32x3, U32x3, U32, U32, U32, ) 81OPCODE(CompositeConstructU32x3, U32x3, U32, U32, U32, )
82OPCODE(CompositeConstructU32x4, U32x4, U32, U32, U32, U32, ) 82OPCODE(CompositeConstructU32x4, U32x4, U32, U32, U32, U32, )
83OPCODE(CompositeExtractU32x2, U32, U32x2, U32, ) 83OPCODE(CompositeExtractU32x2, U32, U32x2, U32, )
84OPCODE(CompositeExtractU32x3, U32, U32x3, U32, ) 84OPCODE(CompositeExtractU32x3, U32, U32x3, U32, )
85OPCODE(CompositeExtractU32x4, U32, U32x4, U32, ) 85OPCODE(CompositeExtractU32x4, U32, U32x4, U32, )
86OPCODE(CompositeInsertU32x2, U32x2, U32x2, U32, U32, ) 86OPCODE(CompositeInsertU32x2, U32x2, U32x2, U32, U32, )
87OPCODE(CompositeInsertU32x3, U32x3, U32x3, U32, U32, ) 87OPCODE(CompositeInsertU32x3, U32x3, U32x3, U32, U32, )
88OPCODE(CompositeInsertU32x4, U32x4, U32x4, U32, U32, ) 88OPCODE(CompositeInsertU32x4, U32x4, U32x4, U32, U32, )
89OPCODE(CompositeConstructF16x2, F16x2, F16, F16, ) 89OPCODE(CompositeConstructF16x2, F16x2, F16, F16, )
90OPCODE(CompositeConstructF16x3, F16x3, F16, F16, F16, ) 90OPCODE(CompositeConstructF16x3, F16x3, F16, F16, F16, )
91OPCODE(CompositeConstructF16x4, F16x4, F16, F16, F16, F16, ) 91OPCODE(CompositeConstructF16x4, F16x4, F16, F16, F16, F16, )
92OPCODE(CompositeExtractF16x2, F16, F16x2, U32, ) 92OPCODE(CompositeExtractF16x2, F16, F16x2, U32, )
93OPCODE(CompositeExtractF16x3, F16, F16x3, U32, ) 93OPCODE(CompositeExtractF16x3, F16, F16x3, U32, )
94OPCODE(CompositeExtractF16x4, F16, F16x4, U32, ) 94OPCODE(CompositeExtractF16x4, F16, F16x4, U32, )
95OPCODE(CompositeInsertF16x2, F16x2, F16x2, F16, U32, ) 95OPCODE(CompositeInsertF16x2, F16x2, F16x2, F16, U32, )
96OPCODE(CompositeInsertF16x3, F16x3, F16x3, F16, U32, ) 96OPCODE(CompositeInsertF16x3, F16x3, F16x3, F16, U32, )
97OPCODE(CompositeInsertF16x4, F16x4, F16x4, F16, U32, ) 97OPCODE(CompositeInsertF16x4, F16x4, F16x4, F16, U32, )
98OPCODE(CompositeConstructF32x2, F32x2, F32, F32, ) 98OPCODE(CompositeConstructF32x2, F32x2, F32, F32, )
99OPCODE(CompositeConstructF32x3, F32x3, F32, F32, F32, ) 99OPCODE(CompositeConstructF32x3, F32x3, F32, F32, F32, )
100OPCODE(CompositeConstructF32x4, F32x4, F32, F32, F32, F32, ) 100OPCODE(CompositeConstructF32x4, F32x4, F32, F32, F32, F32, )
101OPCODE(CompositeExtractF32x2, F32, F32x2, U32, ) 101OPCODE(CompositeExtractF32x2, F32, F32x2, U32, )
102OPCODE(CompositeExtractF32x3, F32, F32x3, U32, ) 102OPCODE(CompositeExtractF32x3, F32, F32x3, U32, )
103OPCODE(CompositeExtractF32x4, F32, F32x4, U32, ) 103OPCODE(CompositeExtractF32x4, F32, F32x4, U32, )
104OPCODE(CompositeInsertF32x2, F32x2, F32x2, F32, U32, ) 104OPCODE(CompositeInsertF32x2, F32x2, F32x2, F32, U32, )
105OPCODE(CompositeInsertF32x3, F32x3, F32x3, F32, U32, ) 105OPCODE(CompositeInsertF32x3, F32x3, F32x3, F32, U32, )
106OPCODE(CompositeInsertF32x4, F32x4, F32x4, F32, U32, ) 106OPCODE(CompositeInsertF32x4, F32x4, F32x4, F32, U32, )
107OPCODE(CompositeConstructF64x2, F64x2, F64, F64, ) 107OPCODE(CompositeConstructF64x2, F64x2, F64, F64, )
108OPCODE(CompositeConstructF64x3, F64x3, F64, F64, F64, ) 108OPCODE(CompositeConstructF64x3, F64x3, F64, F64, F64, )
109OPCODE(CompositeConstructF64x4, F64x4, F64, F64, F64, F64, ) 109OPCODE(CompositeConstructF64x4, F64x4, F64, F64, F64, F64, )
110OPCODE(CompositeExtractF64x2, F64, F64x2, U32, ) 110OPCODE(CompositeExtractF64x2, F64, F64x2, U32, )
111OPCODE(CompositeExtractF64x3, F64, F64x3, U32, ) 111OPCODE(CompositeExtractF64x3, F64, F64x3, U32, )
112OPCODE(CompositeExtractF64x4, F64, F64x4, U32, ) 112OPCODE(CompositeExtractF64x4, F64, F64x4, U32, )
113OPCODE(CompositeInsertF64x2, F64x2, F64x2, F64, U32, ) 113OPCODE(CompositeInsertF64x2, F64x2, F64x2, F64, U32, )
114OPCODE(CompositeInsertF64x3, F64x3, F64x3, F64, U32, ) 114OPCODE(CompositeInsertF64x3, F64x3, F64x3, F64, U32, )
115OPCODE(CompositeInsertF64x4, F64x4, F64x4, F64, U32, ) 115OPCODE(CompositeInsertF64x4, F64x4, F64x4, F64, U32, )
116 116
117// Select operations 117// Select operations
118OPCODE(SelectU1, U1, U1, U1, U1, ) 118OPCODE(SelectU1, U1, U1, U1, U1, )
119OPCODE(SelectU8, U8, U1, U8, U8, ) 119OPCODE(SelectU8, U8, U1, U8, U8, )
120OPCODE(SelectU16, U16, U1, U16, U16, ) 120OPCODE(SelectU16, U16, U1, U16, U16, )
121OPCODE(SelectU32, U32, U1, U32, U32, ) 121OPCODE(SelectU32, U32, U1, U32, U32, )
122OPCODE(SelectU64, U64, U1, U64, U64, ) 122OPCODE(SelectU64, U64, U1, U64, U64, )
123OPCODE(SelectF16, F16, U1, F16, F16, ) 123OPCODE(SelectF16, F16, U1, F16, F16, )
124OPCODE(SelectF32, F32, U1, F32, F32, ) 124OPCODE(SelectF32, F32, U1, F32, F32, )
125 125
126// Bitwise conversions 126// Bitwise conversions
127OPCODE(BitCastU16F16, U16, F16, ) 127OPCODE(BitCastU16F16, U16, F16, )
128OPCODE(BitCastU32F32, U32, F32, ) 128OPCODE(BitCastU32F32, U32, F32, )
129OPCODE(BitCastU64F64, U64, F64, ) 129OPCODE(BitCastU64F64, U64, F64, )
130OPCODE(BitCastF16U16, F16, U16, ) 130OPCODE(BitCastF16U16, F16, U16, )
131OPCODE(BitCastF32U32, F32, U32, ) 131OPCODE(BitCastF32U32, F32, U32, )
132OPCODE(BitCastF64U64, F64, U64, ) 132OPCODE(BitCastF64U64, F64, U64, )
133OPCODE(PackUint2x32, U64, U32x2, ) 133OPCODE(PackUint2x32, U64, U32x2, )
134OPCODE(UnpackUint2x32, U32x2, U64, ) 134OPCODE(UnpackUint2x32, U32x2, U64, )
135OPCODE(PackFloat2x16, U32, F16x2, ) 135OPCODE(PackFloat2x16, U32, F16x2, )
136OPCODE(UnpackFloat2x16, F16x2, U32, ) 136OPCODE(UnpackFloat2x16, F16x2, U32, )
137OPCODE(PackHalf2x16, U32, F32x2, ) 137OPCODE(PackHalf2x16, U32, F32x2, )
138OPCODE(UnpackHalf2x16, F32x2, U32, ) 138OPCODE(UnpackHalf2x16, F32x2, U32, )
139OPCODE(PackDouble2x32, F64, U32x2, ) 139OPCODE(PackDouble2x32, F64, U32x2, )
140OPCODE(UnpackDouble2x32, U32x2, F64, ) 140OPCODE(UnpackDouble2x32, U32x2, F64, )
141 141
142// Pseudo-operation, handled specially at final emit 142// Pseudo-operation, handled specially at final emit
143OPCODE(GetZeroFromOp, U1, Opaque, ) 143OPCODE(GetZeroFromOp, U1, Opaque, )
144OPCODE(GetSignFromOp, U1, Opaque, ) 144OPCODE(GetSignFromOp, U1, Opaque, )
145OPCODE(GetCarryFromOp, U1, Opaque, ) 145OPCODE(GetCarryFromOp, U1, Opaque, )
146OPCODE(GetOverflowFromOp, U1, Opaque, ) 146OPCODE(GetOverflowFromOp, U1, Opaque, )
147OPCODE(GetSparseFromOp, U1, Opaque, )
147 148
148// Floating-point operations 149// Floating-point operations
149OPCODE(FPAbs16, F16, F16, ) 150OPCODE(FPAbs16, F16, F16, )
150OPCODE(FPAbs32, F32, F32, ) 151OPCODE(FPAbs32, F32, F32, )
151OPCODE(FPAbs64, F64, F64, ) 152OPCODE(FPAbs64, F64, F64, )
152OPCODE(FPAdd16, F16, F16, F16, ) 153OPCODE(FPAdd16, F16, F16, F16, )
153OPCODE(FPAdd32, F32, F32, F32, ) 154OPCODE(FPAdd32, F32, F32, F32, )
154OPCODE(FPAdd64, F64, F64, F64, ) 155OPCODE(FPAdd64, F64, F64, F64, )
155OPCODE(FPFma16, F16, F16, F16, F16, ) 156OPCODE(FPFma16, F16, F16, F16, F16, )
156OPCODE(FPFma32, F32, F32, F32, F32, ) 157OPCODE(FPFma32, F32, F32, F32, F32, )
157OPCODE(FPFma64, F64, F64, F64, F64, ) 158OPCODE(FPFma64, F64, F64, F64, F64, )
158OPCODE(FPMax32, F32, F32, F32, ) 159OPCODE(FPMax32, F32, F32, F32, )
159OPCODE(FPMax64, F64, F64, F64, ) 160OPCODE(FPMax64, F64, F64, F64, )
160OPCODE(FPMin32, F32, F32, F32, ) 161OPCODE(FPMin32, F32, F32, F32, )
161OPCODE(FPMin64, F64, F64, F64, ) 162OPCODE(FPMin64, F64, F64, F64, )
162OPCODE(FPMul16, F16, F16, F16, ) 163OPCODE(FPMul16, F16, F16, F16, )
163OPCODE(FPMul32, F32, F32, F32, ) 164OPCODE(FPMul32, F32, F32, F32, )
164OPCODE(FPMul64, F64, F64, F64, ) 165OPCODE(FPMul64, F64, F64, F64, )
165OPCODE(FPNeg16, F16, F16, ) 166OPCODE(FPNeg16, F16, F16, )
166OPCODE(FPNeg32, F32, F32, ) 167OPCODE(FPNeg32, F32, F32, )
167OPCODE(FPNeg64, F64, F64, ) 168OPCODE(FPNeg64, F64, F64, )
168OPCODE(FPRecip32, F32, F32, ) 169OPCODE(FPRecip32, F32, F32, )
169OPCODE(FPRecip64, F64, F64, ) 170OPCODE(FPRecip64, F64, F64, )
170OPCODE(FPRecipSqrt32, F32, F32, ) 171OPCODE(FPRecipSqrt32, F32, F32, )
171OPCODE(FPRecipSqrt64, F64, F64, ) 172OPCODE(FPRecipSqrt64, F64, F64, )
172OPCODE(FPSqrt, F32, F32, ) 173OPCODE(FPSqrt, F32, F32, )
173OPCODE(FPSin, F32, F32, ) 174OPCODE(FPSin, F32, F32, )
174OPCODE(FPExp2, F32, F32, ) 175OPCODE(FPExp2, F32, F32, )
175OPCODE(FPCos, F32, F32, ) 176OPCODE(FPCos, F32, F32, )
176OPCODE(FPLog2, F32, F32, ) 177OPCODE(FPLog2, F32, F32, )
177OPCODE(FPSaturate16, F16, F16, ) 178OPCODE(FPSaturate16, F16, F16, )
178OPCODE(FPSaturate32, F32, F32, ) 179OPCODE(FPSaturate32, F32, F32, )
179OPCODE(FPSaturate64, F64, F64, ) 180OPCODE(FPSaturate64, F64, F64, )
180OPCODE(FPRoundEven16, F16, F16, ) 181OPCODE(FPRoundEven16, F16, F16, )
181OPCODE(FPRoundEven32, F32, F32, ) 182OPCODE(FPRoundEven32, F32, F32, )
182OPCODE(FPRoundEven64, F64, F64, ) 183OPCODE(FPRoundEven64, F64, F64, )
183OPCODE(FPFloor16, F16, F16, ) 184OPCODE(FPFloor16, F16, F16, )
184OPCODE(FPFloor32, F32, F32, ) 185OPCODE(FPFloor32, F32, F32, )
185OPCODE(FPFloor64, F64, F64, ) 186OPCODE(FPFloor64, F64, F64, )
186OPCODE(FPCeil16, F16, F16, ) 187OPCODE(FPCeil16, F16, F16, )
187OPCODE(FPCeil32, F32, F32, ) 188OPCODE(FPCeil32, F32, F32, )
188OPCODE(FPCeil64, F64, F64, ) 189OPCODE(FPCeil64, F64, F64, )
189OPCODE(FPTrunc16, F16, F16, ) 190OPCODE(FPTrunc16, F16, F16, )
190OPCODE(FPTrunc32, F32, F32, ) 191OPCODE(FPTrunc32, F32, F32, )
191OPCODE(FPTrunc64, F64, F64, ) 192OPCODE(FPTrunc64, F64, F64, )
192 193
193OPCODE(FPOrdEqual16, U1, F16, F16, ) 194OPCODE(FPOrdEqual16, U1, F16, F16, )
194OPCODE(FPOrdEqual32, U1, F32, F32, ) 195OPCODE(FPOrdEqual32, U1, F32, F32, )
195OPCODE(FPOrdEqual64, U1, F64, F64, ) 196OPCODE(FPOrdEqual64, U1, F64, F64, )
196OPCODE(FPUnordEqual16, U1, F16, F16, ) 197OPCODE(FPUnordEqual16, U1, F16, F16, )
197OPCODE(FPUnordEqual32, U1, F32, F32, ) 198OPCODE(FPUnordEqual32, U1, F32, F32, )
198OPCODE(FPUnordEqual64, U1, F64, F64, ) 199OPCODE(FPUnordEqual64, U1, F64, F64, )
199OPCODE(FPOrdNotEqual16, U1, F16, F16, ) 200OPCODE(FPOrdNotEqual16, U1, F16, F16, )
200OPCODE(FPOrdNotEqual32, U1, F32, F32, ) 201OPCODE(FPOrdNotEqual32, U1, F32, F32, )
201OPCODE(FPOrdNotEqual64, U1, F64, F64, ) 202OPCODE(FPOrdNotEqual64, U1, F64, F64, )
202OPCODE(FPUnordNotEqual16, U1, F16, F16, ) 203OPCODE(FPUnordNotEqual16, U1, F16, F16, )
203OPCODE(FPUnordNotEqual32, U1, F32, F32, ) 204OPCODE(FPUnordNotEqual32, U1, F32, F32, )
204OPCODE(FPUnordNotEqual64, U1, F64, F64, ) 205OPCODE(FPUnordNotEqual64, U1, F64, F64, )
205OPCODE(FPOrdLessThan16, U1, F16, F16, ) 206OPCODE(FPOrdLessThan16, U1, F16, F16, )
206OPCODE(FPOrdLessThan32, U1, F32, F32, ) 207OPCODE(FPOrdLessThan32, U1, F32, F32, )
207OPCODE(FPOrdLessThan64, U1, F64, F64, ) 208OPCODE(FPOrdLessThan64, U1, F64, F64, )
208OPCODE(FPUnordLessThan16, U1, F16, F16, ) 209OPCODE(FPUnordLessThan16, U1, F16, F16, )
209OPCODE(FPUnordLessThan32, U1, F32, F32, ) 210OPCODE(FPUnordLessThan32, U1, F32, F32, )
210OPCODE(FPUnordLessThan64, U1, F64, F64, ) 211OPCODE(FPUnordLessThan64, U1, F64, F64, )
211OPCODE(FPOrdGreaterThan16, U1, F16, F16, ) 212OPCODE(FPOrdGreaterThan16, U1, F16, F16, )
212OPCODE(FPOrdGreaterThan32, U1, F32, F32, ) 213OPCODE(FPOrdGreaterThan32, U1, F32, F32, )
213OPCODE(FPOrdGreaterThan64, U1, F64, F64, ) 214OPCODE(FPOrdGreaterThan64, U1, F64, F64, )
214OPCODE(FPUnordGreaterThan16, U1, F16, F16, ) 215OPCODE(FPUnordGreaterThan16, U1, F16, F16, )
215OPCODE(FPUnordGreaterThan32, U1, F32, F32, ) 216OPCODE(FPUnordGreaterThan32, U1, F32, F32, )
216OPCODE(FPUnordGreaterThan64, U1, F64, F64, ) 217OPCODE(FPUnordGreaterThan64, U1, F64, F64, )
217OPCODE(FPOrdLessThanEqual16, U1, F16, F16, ) 218OPCODE(FPOrdLessThanEqual16, U1, F16, F16, )
218OPCODE(FPOrdLessThanEqual32, U1, F32, F32, ) 219OPCODE(FPOrdLessThanEqual32, U1, F32, F32, )
219OPCODE(FPOrdLessThanEqual64, U1, F64, F64, ) 220OPCODE(FPOrdLessThanEqual64, U1, F64, F64, )
220OPCODE(FPUnordLessThanEqual16, U1, F16, F16, ) 221OPCODE(FPUnordLessThanEqual16, U1, F16, F16, )
221OPCODE(FPUnordLessThanEqual32, U1, F32, F32, ) 222OPCODE(FPUnordLessThanEqual32, U1, F32, F32, )
222OPCODE(FPUnordLessThanEqual64, U1, F64, F64, ) 223OPCODE(FPUnordLessThanEqual64, U1, F64, F64, )
223OPCODE(FPOrdGreaterThanEqual16, U1, F16, F16, ) 224OPCODE(FPOrdGreaterThanEqual16, U1, F16, F16, )
224OPCODE(FPOrdGreaterThanEqual32, U1, F32, F32, ) 225OPCODE(FPOrdGreaterThanEqual32, U1, F32, F32, )
225OPCODE(FPOrdGreaterThanEqual64, U1, F64, F64, ) 226OPCODE(FPOrdGreaterThanEqual64, U1, F64, F64, )
226OPCODE(FPUnordGreaterThanEqual16, U1, F16, F16, ) 227OPCODE(FPUnordGreaterThanEqual16, U1, F16, F16, )
227OPCODE(FPUnordGreaterThanEqual32, U1, F32, F32, ) 228OPCODE(FPUnordGreaterThanEqual32, U1, F32, F32, )
228OPCODE(FPUnordGreaterThanEqual64, U1, F64, F64, ) 229OPCODE(FPUnordGreaterThanEqual64, U1, F64, F64, )
229 230
230// Integer operations 231// Integer operations
231OPCODE(IAdd32, U32, U32, U32, ) 232OPCODE(IAdd32, U32, U32, U32, )
232OPCODE(IAdd64, U64, U64, U64, ) 233OPCODE(IAdd64, U64, U64, U64, )
233OPCODE(ISub32, U32, U32, U32, ) 234OPCODE(ISub32, U32, U32, U32, )
234OPCODE(ISub64, U64, U64, U64, ) 235OPCODE(ISub64, U64, U64, U64, )
235OPCODE(IMul32, U32, U32, U32, ) 236OPCODE(IMul32, U32, U32, U32, )
236OPCODE(INeg32, U32, U32, ) 237OPCODE(INeg32, U32, U32, )
237OPCODE(INeg64, U64, U64, ) 238OPCODE(INeg64, U64, U64, )
238OPCODE(IAbs32, U32, U32, ) 239OPCODE(IAbs32, U32, U32, )
239OPCODE(ShiftLeftLogical32, U32, U32, U32, ) 240OPCODE(ShiftLeftLogical32, U32, U32, U32, )
240OPCODE(ShiftLeftLogical64, U64, U64, U32, ) 241OPCODE(ShiftLeftLogical64, U64, U64, U32, )
241OPCODE(ShiftRightLogical32, U32, U32, U32, ) 242OPCODE(ShiftRightLogical32, U32, U32, U32, )
242OPCODE(ShiftRightLogical64, U64, U64, U32, ) 243OPCODE(ShiftRightLogical64, U64, U64, U32, )
243OPCODE(ShiftRightArithmetic32, U32, U32, U32, ) 244OPCODE(ShiftRightArithmetic32, U32, U32, U32, )
244OPCODE(ShiftRightArithmetic64, U64, U64, U32, ) 245OPCODE(ShiftRightArithmetic64, U64, U64, U32, )
245OPCODE(BitwiseAnd32, U32, U32, U32, ) 246OPCODE(BitwiseAnd32, U32, U32, U32, )
246OPCODE(BitwiseOr32, U32, U32, U32, ) 247OPCODE(BitwiseOr32, U32, U32, U32, )
247OPCODE(BitwiseXor32, U32, U32, U32, ) 248OPCODE(BitwiseXor32, U32, U32, U32, )
248OPCODE(BitFieldInsert, U32, U32, U32, U32, U32, ) 249OPCODE(BitFieldInsert, U32, U32, U32, U32, U32, )
249OPCODE(BitFieldSExtract, U32, U32, U32, U32, ) 250OPCODE(BitFieldSExtract, U32, U32, U32, U32, )
250OPCODE(BitFieldUExtract, U32, U32, U32, U32, ) 251OPCODE(BitFieldUExtract, U32, U32, U32, U32, )
251OPCODE(BitReverse32, U32, U32, ) 252OPCODE(BitReverse32, U32, U32, )
252OPCODE(BitCount32, U32, U32, ) 253OPCODE(BitCount32, U32, U32, )
253OPCODE(BitwiseNot32, U32, U32, ) 254OPCODE(BitwiseNot32, U32, U32, )
254 255
255OPCODE(FindSMsb32, U32, U32, ) 256OPCODE(FindSMsb32, U32, U32, )
256OPCODE(FindUMsb32, U32, U32, ) 257OPCODE(FindUMsb32, U32, U32, )
257OPCODE(SMin32, U32, U32, U32, ) 258OPCODE(SMin32, U32, U32, U32, )
258OPCODE(UMin32, U32, U32, U32, ) 259OPCODE(UMin32, U32, U32, U32, )
259OPCODE(SMax32, U32, U32, U32, ) 260OPCODE(SMax32, U32, U32, U32, )
260OPCODE(UMax32, U32, U32, U32, ) 261OPCODE(UMax32, U32, U32, U32, )
261OPCODE(SLessThan, U1, U32, U32, ) 262OPCODE(SLessThan, U1, U32, U32, )
262OPCODE(ULessThan, U1, U32, U32, ) 263OPCODE(ULessThan, U1, U32, U32, )
263OPCODE(IEqual, U1, U32, U32, ) 264OPCODE(IEqual, U1, U32, U32, )
264OPCODE(SLessThanEqual, U1, U32, U32, ) 265OPCODE(SLessThanEqual, U1, U32, U32, )
265OPCODE(ULessThanEqual, U1, U32, U32, ) 266OPCODE(ULessThanEqual, U1, U32, U32, )
266OPCODE(SGreaterThan, U1, U32, U32, ) 267OPCODE(SGreaterThan, U1, U32, U32, )
267OPCODE(UGreaterThan, U1, U32, U32, ) 268OPCODE(UGreaterThan, U1, U32, U32, )
268OPCODE(INotEqual, U1, U32, U32, ) 269OPCODE(INotEqual, U1, U32, U32, )
269OPCODE(SGreaterThanEqual, U1, U32, U32, ) 270OPCODE(SGreaterThanEqual, U1, U32, U32, )
270OPCODE(UGreaterThanEqual, U1, U32, U32, ) 271OPCODE(UGreaterThanEqual, U1, U32, U32, )
271 272
272// Logical operations 273// Logical operations
273OPCODE(LogicalOr, U1, U1, U1, ) 274OPCODE(LogicalOr, U1, U1, U1, )
274OPCODE(LogicalAnd, U1, U1, U1, ) 275OPCODE(LogicalAnd, U1, U1, U1, )
275OPCODE(LogicalXor, U1, U1, U1, ) 276OPCODE(LogicalXor, U1, U1, U1, )
276OPCODE(LogicalNot, U1, U1, ) 277OPCODE(LogicalNot, U1, U1, )
277 278
278// Conversion operations 279// Conversion operations
279OPCODE(ConvertS16F16, U32, F16, ) 280OPCODE(ConvertS16F16, U32, F16, )
280OPCODE(ConvertS16F32, U32, F32, ) 281OPCODE(ConvertS16F32, U32, F32, )
281OPCODE(ConvertS16F64, U32, F64, ) 282OPCODE(ConvertS16F64, U32, F64, )
282OPCODE(ConvertS32F16, U32, F16, ) 283OPCODE(ConvertS32F16, U32, F16, )
283OPCODE(ConvertS32F32, U32, F32, ) 284OPCODE(ConvertS32F32, U32, F32, )
284OPCODE(ConvertS32F64, U32, F64, ) 285OPCODE(ConvertS32F64, U32, F64, )
285OPCODE(ConvertS64F16, U64, F16, ) 286OPCODE(ConvertS64F16, U64, F16, )
286OPCODE(ConvertS64F32, U64, F32, ) 287OPCODE(ConvertS64F32, U64, F32, )
287OPCODE(ConvertS64F64, U64, F64, ) 288OPCODE(ConvertS64F64, U64, F64, )
288OPCODE(ConvertU16F16, U32, F16, ) 289OPCODE(ConvertU16F16, U32, F16, )
289OPCODE(ConvertU16F32, U32, F32, ) 290OPCODE(ConvertU16F32, U32, F32, )
290OPCODE(ConvertU16F64, U32, F64, ) 291OPCODE(ConvertU16F64, U32, F64, )
291OPCODE(ConvertU32F16, U32, F16, ) 292OPCODE(ConvertU32F16, U32, F16, )
292OPCODE(ConvertU32F32, U32, F32, ) 293OPCODE(ConvertU32F32, U32, F32, )
293OPCODE(ConvertU32F64, U32, F64, ) 294OPCODE(ConvertU32F64, U32, F64, )
294OPCODE(ConvertU64F16, U64, F16, ) 295OPCODE(ConvertU64F16, U64, F16, )
295OPCODE(ConvertU64F32, U64, F32, ) 296OPCODE(ConvertU64F32, U64, F32, )
296OPCODE(ConvertU64F64, U64, F64, ) 297OPCODE(ConvertU64F64, U64, F64, )
297OPCODE(ConvertU64U32, U64, U32, ) 298OPCODE(ConvertU64U32, U64, U32, )
298OPCODE(ConvertU32U64, U32, U64, ) 299OPCODE(ConvertU32U64, U32, U64, )
299OPCODE(ConvertF16F32, F16, F32, ) 300OPCODE(ConvertF16F32, F16, F32, )
300OPCODE(ConvertF32F16, F32, F16, ) 301OPCODE(ConvertF32F16, F32, F16, )
301OPCODE(ConvertF32F64, F32, F64, ) 302OPCODE(ConvertF32F64, F32, F64, )
302OPCODE(ConvertF64F32, F64, F32, ) 303OPCODE(ConvertF64F32, F64, F32, )
304OPCODE(ConvertF16S32, F16, U32, )
305OPCODE(ConvertF16S64, F16, U64, )
306OPCODE(ConvertF16U32, F16, U32, )
307OPCODE(ConvertF16U64, F16, U64, )
308OPCODE(ConvertF32S32, F32, U32, )
309OPCODE(ConvertF32S64, F32, U64, )
310OPCODE(ConvertF32U32, F32, U32, )
311OPCODE(ConvertF32U64, F32, U64, )
312OPCODE(ConvertF64S32, F64, U32, )
313OPCODE(ConvertF64S64, F64, U64, )
314OPCODE(ConvertF64U32, F64, U32, )
315OPCODE(ConvertF64U64, F64, U64, )
316
317// Image operations
318OPCODE(BindlessImageSampleImplicitLod, F32x4, U32, Opaque, Opaque, Opaque, )
319OPCODE(BindlessImageSampleExplicitLod, F32x4, U32, Opaque, Opaque, Opaque, )
320OPCODE(BindlessImageSampleDrefImplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, )
321OPCODE(BindlessImageSampleDrefExplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, )
322
323OPCODE(BoundImageSampleImplicitLod, F32x4, U32, Opaque, Opaque, Opaque, )
324OPCODE(BoundImageSampleExplicitLod, F32x4, U32, Opaque, Opaque, Opaque, )
325OPCODE(BoundImageSampleDrefImplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, )
326OPCODE(BoundImageSampleDrefExplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, )
327
328OPCODE(ImageSampleImplicitLod, F32x4, U32, Opaque, Opaque, Opaque, )
329OPCODE(ImageSampleExplicitLod, F32x4, U32, Opaque, Opaque, Opaque, )
330OPCODE(ImageSampleDrefImplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, )
331OPCODE(ImageSampleDrefExplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, )
diff --git a/src/shader_recompiler/frontend/ir/reg.h b/src/shader_recompiler/frontend/ir/reg.h
index 771094eb9..8fea05f7b 100644
--- a/src/shader_recompiler/frontend/ir/reg.h
+++ b/src/shader_recompiler/frontend/ir/reg.h
@@ -293,6 +293,17 @@ constexpr size_t NUM_REGS = 256;
293 return reg + (-num); 293 return reg + (-num);
294} 294}
295 295
296[[nodiscard]] constexpr Reg operator++(Reg& reg) {
297 reg = reg + 1;
298 return reg;
299}
300
301[[nodiscard]] constexpr Reg operator++(Reg& reg, int) {
302 const Reg copy{reg};
303 reg = reg + 1;
304 return copy;
305}
306
296[[nodiscard]] constexpr size_t RegIndex(Reg reg) noexcept { 307[[nodiscard]] constexpr size_t RegIndex(Reg reg) noexcept {
297 return static_cast<size_t>(reg); 308 return static_cast<size_t>(reg);
298} 309}
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index 9b7e1480b..3602883d6 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -75,6 +75,7 @@ private:
75 f64 imm_f64; 75 f64 imm_f64;
76 }; 76 };
77}; 77};
78static_assert(std::is_trivially_copyable_v<Value>);
78 79
79template <IR::Type type_> 80template <IR::Type type_>
80class TypedValue : public Value { 81class TypedValue : public Value {