summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/frontend/ir
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2021-02-05 09:58:02 +0100
committerameerj <52414509+ameerj@users.noreply.github.com>2021-07-23 03:51:21 +0200
commite81739493a0cacc1efe3295f9d287d5d31b1a989 (patch)
tree11a3d04ce9def535414a00226030798f337c053c /src/shader_recompiler/frontend/ir
parentshader: Initial instruction support (diff)
downloadyuzu-e81739493a0cacc1efe3295f9d287d5d31b1a989.tar
yuzu-e81739493a0cacc1efe3295f9d287d5d31b1a989.tar.gz
yuzu-e81739493a0cacc1efe3295f9d287d5d31b1a989.tar.bz2
yuzu-e81739493a0cacc1efe3295f9d287d5d31b1a989.tar.lz
yuzu-e81739493a0cacc1efe3295f9d287d5d31b1a989.tar.xz
yuzu-e81739493a0cacc1efe3295f9d287d5d31b1a989.tar.zst
yuzu-e81739493a0cacc1efe3295f9d287d5d31b1a989.zip
Diffstat (limited to 'src/shader_recompiler/frontend/ir')
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.cpp20
-rw-r--r--src/shader_recompiler/frontend/ir/ir_emitter.h5
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.cpp26
-rw-r--r--src/shader_recompiler/frontend/ir/microinstruction.h4
-rw-r--r--src/shader_recompiler/frontend/ir/opcode.inc22
-rw-r--r--src/shader_recompiler/frontend/ir/type.cpp2
-rw-r--r--src/shader_recompiler/frontend/ir/type.h1
-rw-r--r--src/shader_recompiler/frontend/ir/value.cpp17
-rw-r--r--src/shader_recompiler/frontend/ir/value.h1
9 files changed, 73 insertions, 25 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
index 87b253c9a..1c5ae0109 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp
@@ -504,6 +504,20 @@ U32U64 IREmitter::IAdd(const U32U64& a, const U32U64& b) {
}
}
+U32U64 IREmitter::ISub(const U32U64& a, const U32U64& b) {
+ if (a.Type() != b.Type()) {
+ throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type());
+ }
+ switch (a.Type()) {
+ case Type::U32:
+ return Inst<U32>(Opcode::ISub32, a, b);
+ case Type::U64:
+ return Inst<U64>(Opcode::ISub64, a, b);
+ default:
+ ThrowInvalidType(a.Type());
+ }
+}
+
U32 IREmitter::IMul(const U32& a, const U32& b) {
return Inst<U32>(Opcode::IMul32, a, b);
}
@@ -679,8 +693,8 @@ U32U64 IREmitter::ConvertFToI(size_t bitsize, bool is_signed, const U16U32U64& v
}
}
-U32U64 IREmitter::ConvertU(size_t bitsize, const U32U64& value) {
- switch (bitsize) {
+U32U64 IREmitter::ConvertU(size_t result_bitsize, const U32U64& value) {
+ switch (result_bitsize) {
case 32:
switch (value.Type()) {
case Type::U32:
@@ -703,7 +717,7 @@ U32U64 IREmitter::ConvertU(size_t bitsize, const U32U64& value) {
break;
}
}
- throw NotImplementedException("Conversion from {} to {} bits", value.Type(), bitsize);
+ throw NotImplementedException("Conversion from {} to {} bits", value.Type(), result_bitsize);
}
} // namespace Shader::IR
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h
index 7ff763ecf..84b844898 100644
--- a/src/shader_recompiler/frontend/ir/ir_emitter.h
+++ b/src/shader_recompiler/frontend/ir/ir_emitter.h
@@ -17,6 +17,8 @@ namespace Shader::IR {
class IREmitter {
public:
explicit IREmitter(Block& block_) : block{block_}, insertion_point{block.end()} {}
+ explicit IREmitter(Block& block_, Block::iterator insertion_point_)
+ : block{block_}, insertion_point{insertion_point_} {}
Block& block;
@@ -125,6 +127,7 @@ public:
[[nodiscard]] U16U32U64 FPTrunc(const U16U32U64& value);
[[nodiscard]] U32U64 IAdd(const U32U64& a, const U32U64& b);
+ [[nodiscard]] U32U64 ISub(const U32U64& a, const U32U64& b);
[[nodiscard]] U32 IMul(const U32& a, const U32& b);
[[nodiscard]] U32 INeg(const U32& value);
[[nodiscard]] U32 IAbs(const U32& value);
@@ -155,7 +158,7 @@ public:
[[nodiscard]] U32U64 ConvertFToU(size_t bitsize, const U16U32U64& value);
[[nodiscard]] U32U64 ConvertFToI(size_t bitsize, bool is_signed, const U16U32U64& value);
- [[nodiscard]] U32U64 ConvertU(size_t bitsize, const U32U64& value);
+ [[nodiscard]] U32U64 ConvertU(size_t result_bitsize, const U32U64& value);
private:
IR::Block::iterator insertion_point;
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp
index ecf76e23d..de953838c 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.cpp
+++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
+
#include "shader_recompiler/exception.h"
#include "shader_recompiler/frontend/ir/microinstruction.h"
#include "shader_recompiler/frontend/ir/type.h"
@@ -44,6 +46,13 @@ bool Inst::MayHaveSideEffects() const noexcept {
case Opcode::WriteGlobal32:
case Opcode::WriteGlobal64:
case Opcode::WriteGlobal128:
+ case Opcode::WriteStorageU8:
+ case Opcode::WriteStorageS8:
+ case Opcode::WriteStorageU16:
+ case Opcode::WriteStorageS16:
+ case Opcode::WriteStorage32:
+ case Opcode::WriteStorage64:
+ case Opcode::WriteStorage128:
return true;
default:
return false;
@@ -56,15 +65,19 @@ bool Inst::IsPseudoInstruction() const noexcept {
case Opcode::GetSignFromOp:
case Opcode::GetCarryFromOp:
case Opcode::GetOverflowFromOp:
- case Opcode::GetZSCOFromOp:
return true;
default:
return false;
}
}
+bool Inst::AreAllArgsImmediates() const noexcept {
+ return std::all_of(args.begin(), args.begin() + NumArgs(),
+ [](const IR::Value& value) { return value.IsImmediate(); });
+}
+
bool Inst::HasAssociatedPseudoOperation() const noexcept {
- return zero_inst || sign_inst || carry_inst || overflow_inst || zsco_inst;
+ return zero_inst || sign_inst || carry_inst || overflow_inst;
}
Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) {
@@ -82,9 +95,6 @@ Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) {
case Opcode::GetOverflowFromOp:
CheckPseudoInstruction(overflow_inst, Opcode::GetOverflowFromOp);
return overflow_inst;
- case Opcode::GetZSCOFromOp:
- CheckPseudoInstruction(zsco_inst, Opcode::GetZSCOFromOp);
- return zsco_inst;
default:
throw InvalidArgument("{} is not a pseudo-instruction", opcode);
}
@@ -176,9 +186,6 @@ void Inst::Use(const Value& value) {
case Opcode::GetOverflowFromOp:
SetPseudoInstruction(value.Inst()->overflow_inst, this);
break;
- case Opcode::GetZSCOFromOp:
- SetPseudoInstruction(value.Inst()->zsco_inst, this);
- break;
default:
break;
}
@@ -200,9 +207,6 @@ void Inst::UndoUse(const Value& value) {
case Opcode::GetOverflowFromOp:
RemovePseudoInstruction(value.Inst()->overflow_inst, Opcode::GetOverflowFromOp);
break;
- case Opcode::GetZSCOFromOp:
- RemovePseudoInstruction(value.Inst()->zsco_inst, Opcode::GetZSCOFromOp);
- break;
default:
break;
}
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.h b/src/shader_recompiler/frontend/ir/microinstruction.h
index 61849695a..22101c9e2 100644
--- a/src/shader_recompiler/frontend/ir/microinstruction.h
+++ b/src/shader_recompiler/frontend/ir/microinstruction.h
@@ -49,6 +49,9 @@ public:
/// Pseudo-instructions depend on their parent instructions for their semantics.
[[nodiscard]] bool IsPseudoInstruction() const noexcept;
+ /// Determines if all arguments of this instruction are immediates.
+ [[nodiscard]] bool AreAllArgsImmediates() const noexcept;
+
/// Determines if there is a pseudo-operation associated with this instruction.
[[nodiscard]] bool HasAssociatedPseudoOperation() const noexcept;
/// Gets a pseudo-operation associated with this instruction
@@ -94,7 +97,6 @@ private:
Inst* sign_inst{};
Inst* carry_inst{};
Inst* overflow_inst{};
- Inst* zsco_inst{};
std::vector<std::pair<Block*, Value>> phi_operands;
u64 flags{};
};
diff --git a/src/shader_recompiler/frontend/ir/opcode.inc b/src/shader_recompiler/frontend/ir/opcode.inc
index 4ecb5e936..4596bf39f 100644
--- a/src/shader_recompiler/frontend/ir/opcode.inc
+++ b/src/shader_recompiler/frontend/ir/opcode.inc
@@ -24,9 +24,6 @@ OPCODE(GetAttribute, U32, Attr
OPCODE(SetAttribute, U32, Attribute, )
OPCODE(GetAttributeIndexed, U32, U32, )
OPCODE(SetAttributeIndexed, U32, U32, )
-OPCODE(GetZSCORaw, U32, )
-OPCODE(SetZSCORaw, Void, U32, )
-OPCODE(SetZSCO, Void, ZSCO, )
OPCODE(GetZFlag, U1, Void, )
OPCODE(GetSFlag, U1, Void, )
OPCODE(GetCFlag, U1, Void, )
@@ -65,6 +62,22 @@ OPCODE(WriteGlobal32, Void, U64,
OPCODE(WriteGlobal64, Void, U64, Opaque, )
OPCODE(WriteGlobal128, Void, U64, Opaque, )
+// Storage buffer operations
+OPCODE(LoadStorageU8, U32, U32, U32, )
+OPCODE(LoadStorageS8, U32, U32, U32, )
+OPCODE(LoadStorageU16, U32, U32, U32, )
+OPCODE(LoadStorageS16, U32, U32, U32, )
+OPCODE(LoadStorage32, U32, U32, U32, )
+OPCODE(LoadStorage64, Opaque, U32, U32, )
+OPCODE(LoadStorage128, Opaque, U32, U32, )
+OPCODE(WriteStorageU8, Void, U32, U32, U32, )
+OPCODE(WriteStorageS8, Void, U32, U32, U32, )
+OPCODE(WriteStorageU16, Void, U32, U32, U32, )
+OPCODE(WriteStorageS16, Void, U32, U32, U32, )
+OPCODE(WriteStorage32, Void, U32, U32, U32, )
+OPCODE(WriteStorage64, Void, U32, U32, Opaque, )
+OPCODE(WriteStorage128, Void, U32, U32, Opaque, )
+
// Vector utility
OPCODE(CompositeConstruct2, Opaque, Opaque, Opaque, )
OPCODE(CompositeConstruct3, Opaque, Opaque, Opaque, Opaque, )
@@ -90,7 +103,6 @@ OPCODE(GetZeroFromOp, U1, Opaq
OPCODE(GetSignFromOp, U1, Opaque, )
OPCODE(GetCarryFromOp, U1, Opaque, )
OPCODE(GetOverflowFromOp, U1, Opaque, )
-OPCODE(GetZSCOFromOp, ZSCO, Opaque, )
// Floating-point operations
OPCODE(FPAbs16, U16, U16, )
@@ -143,6 +155,8 @@ OPCODE(FPTrunc64, U64, U64,
// Integer operations
OPCODE(IAdd32, U32, U32, U32, )
OPCODE(IAdd64, U64, U64, U64, )
+OPCODE(ISub32, U32, U32, U32, )
+OPCODE(ISub64, U64, U64, U64, )
OPCODE(IMul32, U32, U32, U32, )
OPCODE(INeg32, U32, U32, )
OPCODE(IAbs32, U32, U32, )
diff --git a/src/shader_recompiler/frontend/ir/type.cpp b/src/shader_recompiler/frontend/ir/type.cpp
index da1e2a0f6..13cc09195 100644
--- a/src/shader_recompiler/frontend/ir/type.cpp
+++ b/src/shader_recompiler/frontend/ir/type.cpp
@@ -11,7 +11,7 @@ namespace Shader::IR {
std::string NameOf(Type type) {
static constexpr std::array names{
- "Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32", "U64", "ZSCO",
+ "Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32", "U64",
};
const size_t bits{static_cast<size_t>(type)};
if (bits == 0) {
diff --git a/src/shader_recompiler/frontend/ir/type.h b/src/shader_recompiler/frontend/ir/type.h
index f753628e8..397875018 100644
--- a/src/shader_recompiler/frontend/ir/type.h
+++ b/src/shader_recompiler/frontend/ir/type.h
@@ -25,7 +25,6 @@ enum class Type {
U16 = 1 << 7,
U32 = 1 << 8,
U64 = 1 << 9,
- ZSCO = 1 << 10,
};
DECLARE_ENUM_FLAG_OPERATORS(Type)
diff --git a/src/shader_recompiler/frontend/ir/value.cpp b/src/shader_recompiler/frontend/ir/value.cpp
index 1e974e88c..59a9b10dc 100644
--- a/src/shader_recompiler/frontend/ir/value.cpp
+++ b/src/shader_recompiler/frontend/ir/value.cpp
@@ -91,26 +91,41 @@ IR::Attribute Value::Attribute() const {
}
bool Value::U1() const {
+ if (IsIdentity()) {
+ return inst->Arg(0).U1();
+ }
ValidateAccess(Type::U1);
return imm_u1;
}
u8 Value::U8() const {
+ if (IsIdentity()) {
+ return inst->Arg(0).U8();
+ }
ValidateAccess(Type::U8);
return imm_u8;
}
u16 Value::U16() const {
+ if (IsIdentity()) {
+ return inst->Arg(0).U16();
+ }
ValidateAccess(Type::U16);
return imm_u16;
}
u32 Value::U32() const {
+ if (IsIdentity()) {
+ return inst->Arg(0).U32();
+ }
ValidateAccess(Type::U32);
return imm_u32;
}
u64 Value::U64() const {
+ if (IsIdentity()) {
+ return inst->Arg(0).U64();
+ }
ValidateAccess(Type::U64);
return imm_u64;
}
@@ -142,8 +157,6 @@ bool Value::operator==(const Value& other) const {
return imm_u32 == other.imm_u32;
case Type::U64:
return imm_u64 == other.imm_u64;
- case Type::ZSCO:
- throw NotImplementedException("ZSCO comparison");
}
throw LogicError("Invalid type {}", type);
}
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h
index 368119921..31f831794 100644
--- a/src/shader_recompiler/frontend/ir/value.h
+++ b/src/shader_recompiler/frontend/ir/value.h
@@ -96,6 +96,5 @@ using U64 = TypedValue<Type::U64>;
using U32U64 = TypedValue<Type::U32 | Type::U64>;
using U16U32U64 = TypedValue<Type::U16 | Type::U32 | Type::U64>;
using UAny = TypedValue<Type::U8 | Type::U16 | Type::U32 | Type::U64>;
-using ZSCO = TypedValue<Type::ZSCO>;
} // namespace Shader::IR