feat(shader): implement the missing non-f64 VOPC compares
Fifty VOPC opcodes threw in the decoder: cmpx f/o/u/tru for f32, cmpx f/t for i32/u32, the 64-bit integer compares except the seven already present, and the f16 f/o/u/nge/nlg/ngt/nle/nlt/tru compares and their cmpx forms. 64-bit gt/le/ge are built from SLessThan64/ULessThan64 by swapping and negating, as the IR has no other 64-bit orderings. emitFloatOrderedCompare gains the f16 and cmpx forms. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
8ed454d2fa
commit
b6376737bb
|
|
@ -0,0 +1,237 @@
|
|||
#include "prx/libSceAgcDriver/Execution/include/VulkanDevice.hpp"
|
||||
#include "prx/libSceAgcDriver/Graphics/include/Draw.hpp"
|
||||
#include "Recompiler.hpp"
|
||||
#include "VulkanTestDevice.hpp"
|
||||
#include <array>
|
||||
#include <bit>
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
using AgcDriver::Graphics::Require;
|
||||
using ShaderRecompiler::ShaderStage;
|
||||
|
||||
constexpr std::uint32_t Threads = 32;
|
||||
constexpr std::uint32_t Inputs = 8;
|
||||
constexpr std::uint32_t Results = 4;
|
||||
alignas(256) std::array<std::uint32_t, Threads * Inputs> Input{};
|
||||
alignas(256) std::array<std::uint32_t, Threads * Results> Output{};
|
||||
|
||||
alignas(256) constexpr std::array<std::uint32_t, 364> CompareCode{
|
||||
0x34020083, 0x34060082, 0xe0302000, 0x80000401, 0xe0302004, 0x80000501, 0xe0302008, 0x80000601,
|
||||
0xe030200c, 0x80000701, 0xe0302010, 0x80000801, 0xe0302014, 0x80000901, 0xe0302018, 0x80000e01,
|
||||
0xe030201c, 0x80000f01, 0x7e140280, 0x7e160280, 0xbf8c3f70, 0xbe9e037e, 0x7e280280, 0x7c200b04,
|
||||
0x7e280281, 0xbefe031e, 0xd76f000a, 0x04290114, 0xbe9e037e, 0x7e280280, 0x7c2e0b04, 0x7e280281,
|
||||
0xbefe031e, 0xd76f000a, 0x04290314, 0xbe9e037e, 0x7e280280, 0x7c300b04, 0x7e280281, 0xbefe031e,
|
||||
0xd76f000a, 0x04290514, 0xbe9e037e, 0x7e280280, 0x7c3e0b04, 0x7e280281, 0xbefe031e, 0xd76f000a,
|
||||
0x04290714, 0xbe9e037e, 0x7e280280, 0x7d200b04, 0x7e280281, 0xbefe031e, 0xd76f000a, 0x04290914,
|
||||
0xbe9e037e, 0x7e280280, 0x7d2e0b04, 0x7e280281, 0xbefe031e, 0xd76f000a, 0x04290b14, 0xbe9e037e,
|
||||
0x7e280280, 0x7da00b04, 0x7e280281, 0xbefe031e, 0xd76f000a, 0x04290d14, 0xbe9e037e, 0x7e280280,
|
||||
0x7dae0b04, 0x7e280281, 0xbefe031e, 0xd76f000a, 0x04290f14, 0x7d401106, 0xd5010014, 0x01a90280,
|
||||
0xd76f000a, 0x04291114, 0x7d421106, 0xd5010014, 0x01a90280, 0xd76f000a, 0x04291314, 0x7d461106,
|
||||
0xd5010014, 0x01a90280, 0xd76f000a, 0x04291514, 0x7d481106, 0xd5010014, 0x01a90280, 0xd76f000a,
|
||||
0x04291714, 0x7d4a1106, 0xd5010014, 0x01a90280, 0xd76f000a, 0x04291914, 0x7d4c1106, 0xd5010014,
|
||||
0x01a90280, 0xd76f000a, 0x04291b14, 0x7d4e1106, 0xd5010014, 0x01a90280, 0xd76f000a, 0x04291d14,
|
||||
0xbe9e037e, 0x7e280280, 0x7d601106, 0x7e280281, 0xbefe031e, 0xd76f000a, 0x04291f14, 0xbe9e037e,
|
||||
0x7e280280, 0x7d621106, 0x7e280281, 0xbefe031e, 0xd76f000a, 0x04292114, 0xbe9e037e, 0x7e280280,
|
||||
0x7d641106, 0x7e280281, 0xbefe031e, 0xd76f000a, 0x04292314, 0xbe9e037e, 0x7e280280, 0x7d661106,
|
||||
0x7e280281, 0xbefe031e, 0xd76f000a, 0x04292514, 0xbe9e037e, 0x7e280280, 0x7d681106, 0x7e280281,
|
||||
0xbefe031e, 0xd76f000a, 0x04292714, 0xbe9e037e, 0x7e280280, 0x7d6c1106, 0x7e280281, 0xbefe031e,
|
||||
0xd76f000a, 0x04292914, 0xbe9e037e, 0x7e280280, 0x7d6e1106, 0x7e280281, 0xbefe031e, 0xd76f000a,
|
||||
0x04292b14, 0x7dc01106, 0xd5010014, 0x01a90280, 0xd76f000a, 0x04292d14, 0x7dc61106, 0xd5010014,
|
||||
0x01a90280, 0xd76f000a, 0x04292f14, 0x7dcc1106, 0xd5010014, 0x01a90280, 0xd76f000a, 0x04293114,
|
||||
0x7dce1106, 0xd5010014, 0x01a90280, 0xd76f000a, 0x04293314, 0xbe9e037e, 0x7e280280, 0x7de01106,
|
||||
0x7e280281, 0xbefe031e, 0xd76f000a, 0x04293514, 0xbe9e037e, 0x7e280280, 0x7de21106, 0x7e280281,
|
||||
0xbefe031e, 0xd76f000a, 0x04293714, 0xbe9e037e, 0x7e280280, 0x7de41106, 0x7e280281, 0xbefe031e,
|
||||
0xd76f000a, 0x04293914, 0xbe9e037e, 0x7e280280, 0x7de61106, 0x7e280281, 0xbefe031e, 0xd76f000a,
|
||||
0x04293b14, 0xbe9e037e, 0x7e280280, 0x7de81106, 0x7e280281, 0xbefe031e, 0xd76f000a, 0x04293d14,
|
||||
0xbe9e037e, 0x7e280280, 0x7dec1106, 0x7e280281, 0xbefe031e, 0xd76f000a, 0x04293f14, 0xbe9e037e,
|
||||
0x7e280280, 0x7dee1106, 0x7e280281, 0xbefe031e, 0xd76f000b, 0x042d0114, 0x7d901f0e, 0xd5010014,
|
||||
0x01a90280, 0xd76f000b, 0x042d0314, 0x7d9e1f0e, 0xd5010014, 0x01a90280, 0xd76f000b, 0x042d0514,
|
||||
0x7dd01f0e, 0xd5010014, 0x01a90280, 0xd76f000b, 0x042d0714, 0x7dd21f0e, 0xd5010014, 0x01a90280,
|
||||
0xd76f000b, 0x042d0914, 0x7dd41f0e, 0xd5010014, 0x01a90280, 0xd76f000b, 0x042d0b14, 0x7dd61f0e,
|
||||
0xd5010014, 0x01a90280, 0xd76f000b, 0x042d0d14, 0x7dd81f0e, 0xd5010014, 0x01a90280, 0xd76f000b,
|
||||
0x042d0f14, 0x7ddc1f0e, 0xd5010014, 0x01a90280, 0xd76f000b, 0x042d1114, 0x7dde1f0e, 0xd5010014,
|
||||
0x01a90280, 0xd76f000b, 0x042d1314, 0xbe9e037e, 0x7e280280, 0x7db01f0e, 0x7e280281, 0xbefe031e,
|
||||
0xd76f000b, 0x042d1514, 0xbe9e037e, 0x7e280280, 0x7dba1f0e, 0x7e280281, 0xbefe031e, 0xd76f000b,
|
||||
0x042d1714, 0xbe9e037e, 0x7e280280, 0x7dbe1f0e, 0x7e280281, 0xbefe031e, 0xd76f000b, 0x042d1914,
|
||||
0xbe9e037e, 0x7e280280, 0x7df01f0e, 0x7e280281, 0xbefe031e, 0xd76f000b, 0x042d1b14, 0xbe9e037e,
|
||||
0x7e280280, 0x7df21f0e, 0x7e280281, 0xbefe031e, 0xd76f000b, 0x042d1d14, 0xbe9e037e, 0x7e280280,
|
||||
0x7df41f0e, 0x7e280281, 0xbefe031e, 0xd76f000b, 0x042d1f14, 0xbe9e037e, 0x7e280280, 0x7df81f0e,
|
||||
0x7e280281, 0xbefe031e, 0xd76f000b, 0x042d2114, 0xbe9e037e, 0x7e280280, 0x7dfe1f0e, 0x7e280281,
|
||||
0xbefe031e, 0xd76f000b, 0x042d2314, 0xd4e9026a, 0x00021f0e, 0xd5010014, 0x01a90280, 0xd76f000b,
|
||||
0x042d2514, 0xd4a3006a, 0x00020d08, 0xd5010014, 0x01a90280, 0xd76f000b, 0x042d2714, 0xbe9e037e,
|
||||
0x7e280280, 0xd4f6007e, 0x00020d08, 0x7e280281, 0xbefe031e, 0xd76f000b, 0x042d2914, 0xbe9e037e,
|
||||
0x7e280280, 0xd417017e, 0x00020b04, 0x7e280281, 0xbefe031e, 0xd76f000b, 0x042d2b14, 0xe0702000,
|
||||
0x80010a03, 0xe0702004, 0x80010b03, 0xbf810000,
|
||||
};
|
||||
|
||||
constexpr std::array<std::uint32_t, 12> FloatEdges{
|
||||
0x7fc00000u, 0x3f800000u, 0x80000000u, 0x00000000u, 0x7f800000u, 0xff800000u,
|
||||
0xbf800000u, 0x3f800000u, 0x00000001u, 0x40490fdbu, 0xffc00001u, 0xc0000000u,
|
||||
};
|
||||
|
||||
constexpr std::array<std::uint16_t, 12> HalfEdges{
|
||||
0x7e00u, 0x3c00u, 0x8000u, 0x0000u, 0x7c00u, 0xfc00u, 0xbc00u, 0x3c00u, 0x0001u, 0x4248u, 0xfe01u, 0xc000u,
|
||||
};
|
||||
|
||||
constexpr std::array<std::uint64_t, 8> IntegerEdges{
|
||||
0u, ~0ull, 0x8000000000000000ull, 0x7fffffffffffffffull, 1u, 0x00000001ffffffffull, 0x0000000100000000ull, 0xffffffff00000000ull,
|
||||
};
|
||||
|
||||
float HalfValue(std::uint32_t bits) {
|
||||
const auto exponent = (bits >> 10u) & 0x1fu;
|
||||
const auto fraction = bits & 0x3ffu;
|
||||
float magnitude = 0.0f;
|
||||
if (exponent == 0x1fu) {
|
||||
magnitude = fraction != 0u ? std::numeric_limits<float>::quiet_NaN() : std::numeric_limits<float>::infinity();
|
||||
} else {
|
||||
magnitude = exponent == 0u ? std::ldexp(static_cast<float>(fraction), -24) : std::ldexp(static_cast<float>(fraction | 0x400u), static_cast<int>(exponent) - 25);
|
||||
}
|
||||
return (bits & 0x8000u) != 0u ? -magnitude : magnitude;
|
||||
}
|
||||
|
||||
void FillInput() {
|
||||
std::uint64_t state = 0x853c49e6748fea9bull;
|
||||
const auto next = [&] {
|
||||
state = state * 6364136223846793005ull + 1442695040888963407ull;
|
||||
return static_cast<std::uint32_t>(state >> 33u);
|
||||
};
|
||||
for (std::uint32_t tid = 0; tid < Threads; ++tid) {
|
||||
auto* words = &Input[tid * Inputs];
|
||||
words[0] = FloatEdges[tid % FloatEdges.size()];
|
||||
words[1] = FloatEdges[(tid / FloatEdges.size() + tid) % FloatEdges.size()];
|
||||
const std::uint64_t a = tid < 16u ? IntegerEdges[tid % IntegerEdges.size()] : (static_cast<std::uint64_t>(next()) << 32u) | next();
|
||||
const std::uint64_t b = tid < 16u ? IntegerEdges[(tid / IntegerEdges.size() + tid * 3u) % IntegerEdges.size()] : (tid % 5u == 0u ? a : (static_cast<std::uint64_t>(next()) << 32u) | next());
|
||||
words[2] = static_cast<std::uint32_t>(a);
|
||||
words[3] = static_cast<std::uint32_t>(a >> 32u);
|
||||
words[4] = static_cast<std::uint32_t>(b);
|
||||
words[5] = static_cast<std::uint32_t>(b >> 32u);
|
||||
words[6] = 0xabcd0000u | HalfEdges[tid % HalfEdges.size()];
|
||||
words[7] = 0x12340000u | HalfEdges[(tid / HalfEdges.size() + tid * 5u) % HalfEdges.size()];
|
||||
}
|
||||
}
|
||||
|
||||
std::array<std::uint32_t, 4> BufferDescriptor(const void* data, std::uint32_t count) {
|
||||
const auto address = reinterpret_cast<std::uintptr_t>(data);
|
||||
return {static_cast<std::uint32_t>(address), static_cast<std::uint32_t>((address >> 32u) & 0xffffu) | (4u << 16u), count, 0x01016facu};
|
||||
}
|
||||
|
||||
void Run(AgcDriver::VulkanDevice& device) {
|
||||
Output.fill(0xdeadbeefu);
|
||||
std::vector<std::uint32_t> userData(8, 0u);
|
||||
const auto input = BufferDescriptor(Input.data(), static_cast<std::uint32_t>(Input.size()));
|
||||
const auto output = BufferDescriptor(Output.data(), static_cast<std::uint32_t>(Output.size()));
|
||||
std::copy(input.begin(), input.end(), userData.begin());
|
||||
std::copy(output.begin(), output.end(), userData.begin() + 4);
|
||||
const std::span<const std::uint32_t> code(CompareCode);
|
||||
const std::array<ShaderRecompiler::MemoryRegion, 1> memory{{{reinterpret_cast<std::uintptr_t>(code.data()), std::as_bytes(code)}}};
|
||||
const ShaderRecompiler::ShaderComputeStageInfo compute{{Threads, 1, 1}, 0, {false, false, false}, false, 1};
|
||||
ShaderRecompiler::RecompileRequest request{
|
||||
{ShaderStage::Compute, reinterpret_cast<std::uintptr_t>(code.data()), code, 0, {}},
|
||||
{32, 0, userData, compute, std::nullopt, std::nullopt, memory},
|
||||
device.Target(),
|
||||
{0, 0, 0, 128}
|
||||
};
|
||||
request.useCache = false;
|
||||
const auto result = ShaderRecompiler::Recompile(request);
|
||||
device.Dispatch(result, 1, 1, 1, {}, reinterpret_cast<std::uintptr_t>(code.data()));
|
||||
device.WaitIdle();
|
||||
}
|
||||
|
||||
void Check() {
|
||||
for (std::uint32_t tid = 0; tid < Threads; ++tid) {
|
||||
const auto* in = &Input[tid * Inputs];
|
||||
const float fa = std::bit_cast<float>(in[0]);
|
||||
const float fb = std::bit_cast<float>(in[1]);
|
||||
const std::uint64_t ua = in[2] | (static_cast<std::uint64_t>(in[3]) << 32u);
|
||||
const std::uint64_t ub = in[4] | (static_cast<std::uint64_t>(in[5]) << 32u);
|
||||
const auto sa = static_cast<std::int64_t>(ua);
|
||||
const auto sb = static_cast<std::int64_t>(ub);
|
||||
const float ha = HalfValue(in[6] & 0xffffu);
|
||||
const float hb = HalfValue(in[7] & 0xffffu);
|
||||
const std::array<bool, 54> expected{
|
||||
false,
|
||||
!std::isnan(fa) && !std::isnan(fb),
|
||||
std::isnan(fa) || std::isnan(fb),
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
sa < sb,
|
||||
sa <= sb,
|
||||
sa > sb,
|
||||
sa != sb,
|
||||
sa >= sb,
|
||||
true,
|
||||
false,
|
||||
sa < sb,
|
||||
sa == sb,
|
||||
sa <= sb,
|
||||
sa > sb,
|
||||
sa >= sb,
|
||||
true,
|
||||
false,
|
||||
ua <= ub,
|
||||
ua >= ub,
|
||||
true,
|
||||
false,
|
||||
ua < ub,
|
||||
ua == ub,
|
||||
ua <= ub,
|
||||
ua > ub,
|
||||
ua >= ub,
|
||||
true,
|
||||
false,
|
||||
!std::isnan(ha) && !std::isnan(hb),
|
||||
std::isnan(ha) || std::isnan(hb),
|
||||
!(ha >= hb),
|
||||
!(ha < hb || ha > hb),
|
||||
!(ha > hb),
|
||||
!(ha <= hb),
|
||||
!(ha < hb),
|
||||
true,
|
||||
false,
|
||||
ha < hb || ha > hb,
|
||||
!std::isnan(ha) && !std::isnan(hb),
|
||||
std::isnan(ha) || std::isnan(hb),
|
||||
!(ha >= hb),
|
||||
!(ha < hb || ha > hb),
|
||||
!(ha <= hb),
|
||||
true,
|
||||
!(ha >= std::fabs(hb)),
|
||||
sb <= sa,
|
||||
ub >= ua,
|
||||
!std::isnan(fa) && !std::isnan(fb),
|
||||
};
|
||||
for (std::uint32_t k = 0; k < expected.size(); ++k) {
|
||||
const bool actual = ((Output[tid * Results + k / 32u] >> (k % 32u)) & 1u) != 0u;
|
||||
Require(actual == expected[k], "vopc compares: thread " + std::to_string(tid) + " compare " + std::to_string(k) + " is " + std::to_string(actual) + ", expected " + std::to_string(expected[k]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main() {
|
||||
try {
|
||||
const auto device = OpenVulkanTestDevice();
|
||||
if (!device) return VulkanTestSkipped;
|
||||
FillInput();
|
||||
Run(*device);
|
||||
Check();
|
||||
std::puts("vopc compare tests passed");
|
||||
return 0;
|
||||
} catch (const std::exception& error) {
|
||||
std::cerr << error.what() << '\n';
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -453,6 +453,56 @@ enum class RdnaOpcode : std::uint16_t {
|
|||
VCmpNeU64,
|
||||
VCmpxNeI64,
|
||||
VCmpxNeU64,
|
||||
VCmpxFF32,
|
||||
VCmpxOF32,
|
||||
VCmpxUF32,
|
||||
VCmpxTruF32,
|
||||
VCmpxFI32,
|
||||
VCmpxTI32,
|
||||
VCmpxFU32,
|
||||
VCmpxTU32,
|
||||
VCmpFI64,
|
||||
VCmpLtI64,
|
||||
VCmpLeI64,
|
||||
VCmpGtI64,
|
||||
VCmpNeI64,
|
||||
VCmpGeI64,
|
||||
VCmpTI64,
|
||||
VCmpxFI64,
|
||||
VCmpxLtI64,
|
||||
VCmpxEqI64,
|
||||
VCmpxLeI64,
|
||||
VCmpxGtI64,
|
||||
VCmpxGeI64,
|
||||
VCmpxTI64,
|
||||
VCmpFU64,
|
||||
VCmpLeU64,
|
||||
VCmpGeU64,
|
||||
VCmpTU64,
|
||||
VCmpxFU64,
|
||||
VCmpxLtU64,
|
||||
VCmpxEqU64,
|
||||
VCmpxLeU64,
|
||||
VCmpxGtU64,
|
||||
VCmpxGeU64,
|
||||
VCmpxTU64,
|
||||
VCmpFF16,
|
||||
VCmpOF16,
|
||||
VCmpUF16,
|
||||
VCmpNgeF16,
|
||||
VCmpNlgF16,
|
||||
VCmpNgtF16,
|
||||
VCmpNleF16,
|
||||
VCmpNltF16,
|
||||
VCmpTruF16,
|
||||
VCmpxFF16,
|
||||
VCmpxLgF16,
|
||||
VCmpxOF16,
|
||||
VCmpxUF16,
|
||||
VCmpxNgeF16,
|
||||
VCmpxNlgF16,
|
||||
VCmpxNleF16,
|
||||
VCmpxTruF16,
|
||||
VCmpxLtU32,
|
||||
VCmpxEqU32,
|
||||
VCmpxLeU32,
|
||||
|
|
|
|||
|
|
@ -427,6 +427,56 @@ bool IsVectorAluOpcode(RdnaOpcode opcode) {
|
|||
case RdnaOpcode::VCmpGtU64:
|
||||
case RdnaOpcode::VCmpNeU64:
|
||||
case RdnaOpcode::VCmpxNeI64:
|
||||
case RdnaOpcode::VCmpxFF32:
|
||||
case RdnaOpcode::VCmpxOF32:
|
||||
case RdnaOpcode::VCmpxUF32:
|
||||
case RdnaOpcode::VCmpxTruF32:
|
||||
case RdnaOpcode::VCmpxFI32:
|
||||
case RdnaOpcode::VCmpxTI32:
|
||||
case RdnaOpcode::VCmpxFU32:
|
||||
case RdnaOpcode::VCmpxTU32:
|
||||
case RdnaOpcode::VCmpFI64:
|
||||
case RdnaOpcode::VCmpLtI64:
|
||||
case RdnaOpcode::VCmpLeI64:
|
||||
case RdnaOpcode::VCmpGtI64:
|
||||
case RdnaOpcode::VCmpNeI64:
|
||||
case RdnaOpcode::VCmpGeI64:
|
||||
case RdnaOpcode::VCmpTI64:
|
||||
case RdnaOpcode::VCmpxFI64:
|
||||
case RdnaOpcode::VCmpxLtI64:
|
||||
case RdnaOpcode::VCmpxEqI64:
|
||||
case RdnaOpcode::VCmpxLeI64:
|
||||
case RdnaOpcode::VCmpxGtI64:
|
||||
case RdnaOpcode::VCmpxGeI64:
|
||||
case RdnaOpcode::VCmpxTI64:
|
||||
case RdnaOpcode::VCmpFU64:
|
||||
case RdnaOpcode::VCmpLeU64:
|
||||
case RdnaOpcode::VCmpGeU64:
|
||||
case RdnaOpcode::VCmpTU64:
|
||||
case RdnaOpcode::VCmpxFU64:
|
||||
case RdnaOpcode::VCmpxLtU64:
|
||||
case RdnaOpcode::VCmpxEqU64:
|
||||
case RdnaOpcode::VCmpxLeU64:
|
||||
case RdnaOpcode::VCmpxGtU64:
|
||||
case RdnaOpcode::VCmpxGeU64:
|
||||
case RdnaOpcode::VCmpxTU64:
|
||||
case RdnaOpcode::VCmpFF16:
|
||||
case RdnaOpcode::VCmpOF16:
|
||||
case RdnaOpcode::VCmpUF16:
|
||||
case RdnaOpcode::VCmpNgeF16:
|
||||
case RdnaOpcode::VCmpNlgF16:
|
||||
case RdnaOpcode::VCmpNgtF16:
|
||||
case RdnaOpcode::VCmpNleF16:
|
||||
case RdnaOpcode::VCmpNltF16:
|
||||
case RdnaOpcode::VCmpTruF16:
|
||||
case RdnaOpcode::VCmpxFF16:
|
||||
case RdnaOpcode::VCmpxLgF16:
|
||||
case RdnaOpcode::VCmpxOF16:
|
||||
case RdnaOpcode::VCmpxUF16:
|
||||
case RdnaOpcode::VCmpxNgeF16:
|
||||
case RdnaOpcode::VCmpxNlgF16:
|
||||
case RdnaOpcode::VCmpxNleF16:
|
||||
case RdnaOpcode::VCmpxTruF16:
|
||||
case RdnaOpcode::VCmpxNeU64:
|
||||
case RdnaOpcode::VCmpxLtU32:
|
||||
case RdnaOpcode::VCmpxEqU32:
|
||||
|
|
|
|||
|
|
@ -314,6 +314,56 @@ constexpr VopcOpcodeInfo vopcOpcodes[] = {
|
|||
{0xfbu, RdnaOpcode::VCmpxNgtF16},
|
||||
{0xfdu, RdnaOpcode::VCmpxNeqF16},
|
||||
{0xfeu, RdnaOpcode::VCmpxNltF16},
|
||||
{0x10u, RdnaOpcode::VCmpxFF32},
|
||||
{0x17u, RdnaOpcode::VCmpxOF32},
|
||||
{0x18u, RdnaOpcode::VCmpxUF32},
|
||||
{0x1fu, RdnaOpcode::VCmpxTruF32},
|
||||
{0x90u, RdnaOpcode::VCmpxFI32},
|
||||
{0x97u, RdnaOpcode::VCmpxTI32},
|
||||
{0xd0u, RdnaOpcode::VCmpxFU32},
|
||||
{0xd7u, RdnaOpcode::VCmpxTU32},
|
||||
{0xa0u, RdnaOpcode::VCmpFI64, false},
|
||||
{0xa1u, RdnaOpcode::VCmpLtI64, false},
|
||||
{0xa3u, RdnaOpcode::VCmpLeI64, false},
|
||||
{0xa4u, RdnaOpcode::VCmpGtI64, false},
|
||||
{0xa5u, RdnaOpcode::VCmpNeI64, false},
|
||||
{0xa6u, RdnaOpcode::VCmpGeI64, false},
|
||||
{0xa7u, RdnaOpcode::VCmpTI64, false},
|
||||
{0xb0u, RdnaOpcode::VCmpxFI64, false},
|
||||
{0xb1u, RdnaOpcode::VCmpxLtI64, false},
|
||||
{0xb2u, RdnaOpcode::VCmpxEqI64, false},
|
||||
{0xb3u, RdnaOpcode::VCmpxLeI64, false},
|
||||
{0xb4u, RdnaOpcode::VCmpxGtI64, false},
|
||||
{0xb6u, RdnaOpcode::VCmpxGeI64, false},
|
||||
{0xb7u, RdnaOpcode::VCmpxTI64, false},
|
||||
{0xe0u, RdnaOpcode::VCmpFU64, false},
|
||||
{0xe3u, RdnaOpcode::VCmpLeU64, false},
|
||||
{0xe6u, RdnaOpcode::VCmpGeU64, false},
|
||||
{0xe7u, RdnaOpcode::VCmpTU64, false},
|
||||
{0xf0u, RdnaOpcode::VCmpxFU64, false},
|
||||
{0xf1u, RdnaOpcode::VCmpxLtU64, false},
|
||||
{0xf2u, RdnaOpcode::VCmpxEqU64, false},
|
||||
{0xf3u, RdnaOpcode::VCmpxLeU64, false},
|
||||
{0xf4u, RdnaOpcode::VCmpxGtU64, false},
|
||||
{0xf6u, RdnaOpcode::VCmpxGeU64, false},
|
||||
{0xf7u, RdnaOpcode::VCmpxTU64, false},
|
||||
{0xc8u, RdnaOpcode::VCmpFF16},
|
||||
{0xcfu, RdnaOpcode::VCmpOF16},
|
||||
{0xe8u, RdnaOpcode::VCmpUF16},
|
||||
{0xe9u, RdnaOpcode::VCmpNgeF16},
|
||||
{0xeau, RdnaOpcode::VCmpNlgF16},
|
||||
{0xebu, RdnaOpcode::VCmpNgtF16},
|
||||
{0xecu, RdnaOpcode::VCmpNleF16},
|
||||
{0xeeu, RdnaOpcode::VCmpNltF16},
|
||||
{0xefu, RdnaOpcode::VCmpTruF16},
|
||||
{0xd8u, RdnaOpcode::VCmpxFF16},
|
||||
{0xddu, RdnaOpcode::VCmpxLgF16},
|
||||
{0xdfu, RdnaOpcode::VCmpxOF16},
|
||||
{0xf8u, RdnaOpcode::VCmpxUF16},
|
||||
{0xf9u, RdnaOpcode::VCmpxNgeF16},
|
||||
{0xfau, RdnaOpcode::VCmpxNlgF16},
|
||||
{0xfcu, RdnaOpcode::VCmpxNleF16},
|
||||
{0xffu, RdnaOpcode::VCmpxTruF16},
|
||||
};
|
||||
|
||||
constexpr VectorOpcodeInfo vop3Opcodes[] = {
|
||||
|
|
@ -664,6 +714,27 @@ bool isVopcFloatCompareOpcode(RdnaOpcode opcode) {
|
|||
case RdnaOpcode::VCmpxNgtF16:
|
||||
case RdnaOpcode::VCmpxNeqF16:
|
||||
case RdnaOpcode::VCmpxNltF16:
|
||||
case RdnaOpcode::VCmpxFF32:
|
||||
case RdnaOpcode::VCmpxOF32:
|
||||
case RdnaOpcode::VCmpxUF32:
|
||||
case RdnaOpcode::VCmpxTruF32:
|
||||
case RdnaOpcode::VCmpFF16:
|
||||
case RdnaOpcode::VCmpOF16:
|
||||
case RdnaOpcode::VCmpUF16:
|
||||
case RdnaOpcode::VCmpNgeF16:
|
||||
case RdnaOpcode::VCmpNlgF16:
|
||||
case RdnaOpcode::VCmpNgtF16:
|
||||
case RdnaOpcode::VCmpNleF16:
|
||||
case RdnaOpcode::VCmpNltF16:
|
||||
case RdnaOpcode::VCmpTruF16:
|
||||
case RdnaOpcode::VCmpxFF16:
|
||||
case RdnaOpcode::VCmpxLgF16:
|
||||
case RdnaOpcode::VCmpxOF16:
|
||||
case RdnaOpcode::VCmpxUF16:
|
||||
case RdnaOpcode::VCmpxNgeF16:
|
||||
case RdnaOpcode::VCmpxNlgF16:
|
||||
case RdnaOpcode::VCmpxNleF16:
|
||||
case RdnaOpcode::VCmpxTruF16:
|
||||
case RdnaOpcode::VCmpClassF32:
|
||||
case RdnaOpcode::VCmpxClassF32: return true;
|
||||
default: return false;
|
||||
|
|
@ -1141,6 +1212,36 @@ bool isVopcCompareExec(RdnaOpcode opcode) {
|
|||
case RdnaOpcode::VCmpxGeU32:
|
||||
case RdnaOpcode::VCmpxNeI64:
|
||||
case RdnaOpcode::VCmpxNeU64:
|
||||
case RdnaOpcode::VCmpxFF32:
|
||||
case RdnaOpcode::VCmpxOF32:
|
||||
case RdnaOpcode::VCmpxUF32:
|
||||
case RdnaOpcode::VCmpxTruF32:
|
||||
case RdnaOpcode::VCmpxFI32:
|
||||
case RdnaOpcode::VCmpxTI32:
|
||||
case RdnaOpcode::VCmpxFU32:
|
||||
case RdnaOpcode::VCmpxTU32:
|
||||
case RdnaOpcode::VCmpxFI64:
|
||||
case RdnaOpcode::VCmpxLtI64:
|
||||
case RdnaOpcode::VCmpxEqI64:
|
||||
case RdnaOpcode::VCmpxLeI64:
|
||||
case RdnaOpcode::VCmpxGtI64:
|
||||
case RdnaOpcode::VCmpxGeI64:
|
||||
case RdnaOpcode::VCmpxTI64:
|
||||
case RdnaOpcode::VCmpxFU64:
|
||||
case RdnaOpcode::VCmpxLtU64:
|
||||
case RdnaOpcode::VCmpxEqU64:
|
||||
case RdnaOpcode::VCmpxLeU64:
|
||||
case RdnaOpcode::VCmpxGtU64:
|
||||
case RdnaOpcode::VCmpxGeU64:
|
||||
case RdnaOpcode::VCmpxTU64:
|
||||
case RdnaOpcode::VCmpxFF16:
|
||||
case RdnaOpcode::VCmpxLgF16:
|
||||
case RdnaOpcode::VCmpxOF16:
|
||||
case RdnaOpcode::VCmpxUF16:
|
||||
case RdnaOpcode::VCmpxNgeF16:
|
||||
case RdnaOpcode::VCmpxNlgF16:
|
||||
case RdnaOpcode::VCmpxNleF16:
|
||||
case RdnaOpcode::VCmpxTruF16:
|
||||
case RdnaOpcode::VCmpxLtI16:
|
||||
case RdnaOpcode::VCmpxEqI16:
|
||||
case RdnaOpcode::VCmpxLeI16:
|
||||
|
|
|
|||
|
|
@ -117,7 +117,8 @@ private:
|
|||
void emitIntegerCompare(const RdnaInstruction& inst, IrOpcode opcode, IrType type, bool scalar, bool cmpx);
|
||||
void emitInteger16Compare(const RdnaInstruction& inst, IrOpcode opcode, bool signedValue, bool cmpx);
|
||||
void emitFloatCompare(const RdnaInstruction& inst, IrOpcode opcode, bool half, bool cmpx);
|
||||
void emitFloatOrderedCompare(const RdnaInstruction& inst, bool ordered);
|
||||
void emitInteger64Order(const RdnaInstruction& inst, bool signedValue, bool swap, bool negate, bool cmpx);
|
||||
void emitFloatOrderedCompare(const RdnaInstruction& inst, bool ordered, bool half, bool cmpx);
|
||||
void emitFloatClassCompare(const RdnaInstruction& inst, bool cmpx);
|
||||
void vCvtF32Ubyte(const RdnaInstruction& inst, std::uint32_t byteIndex);
|
||||
void vCvtF32U32(const RdnaInstruction& inst);
|
||||
|
|
|
|||
|
|
@ -54,14 +54,21 @@ void TranslationContext::emitFloatCompare(const RdnaInstruction& inst, IrOpcode
|
|||
emitCompareResult(inst, IrU1(ir.Emit(opcode, IrType::U1, {lhs, rhs})), false, cmpx);
|
||||
}
|
||||
|
||||
void TranslationContext::emitFloatOrderedCompare(const RdnaInstruction& inst, bool ordered) {
|
||||
IrValue* lhs = readOperand(sourceAt(inst, 0u), IrType::F32);
|
||||
IrValue* rhs = readOperand(sourceAt(inst, 1u), IrType::F32);
|
||||
void TranslationContext::emitInteger64Order(const RdnaInstruction& inst, bool signedValue, bool swap, bool negate, bool cmpx) {
|
||||
IrValue* lhs = readOperand(sourceAt(inst, swap ? 1u : 0u), IrType::U64);
|
||||
IrValue* rhs = readOperand(sourceAt(inst, swap ? 0u : 1u), IrType::U64);
|
||||
IrValue& less = ir.Emit(signedValue ? IrOpcode::SLessThan64 : IrOpcode::ULessThan64, IrType::U1, {lhs, rhs});
|
||||
emitCompareResult(inst, IrU1(negate ? ir.LogicalNot(less) : less), false, cmpx);
|
||||
}
|
||||
|
||||
void TranslationContext::emitFloatOrderedCompare(const RdnaInstruction& inst, bool ordered, bool half, bool cmpx) {
|
||||
IrValue* lhs = half ? &readF16AsF32(sourceAt(inst, 0u)).Value() : readOperand(sourceAt(inst, 0u), IrType::F32);
|
||||
IrValue* rhs = half ? &readF16AsF32(sourceAt(inst, 1u)).Value() : readOperand(sourceAt(inst, 1u), IrType::F32);
|
||||
IrValue& lhsNan = ir.Emit(IrOpcode::FPIsNan32, IrType::U1, {lhs});
|
||||
IrValue& rhsNan = ir.Emit(IrOpcode::FPIsNan32, IrType::U1, {rhs});
|
||||
IrValue& unordered = ir.LogicalOr(lhsNan, rhsNan);
|
||||
IrValue& result = ordered ? ir.LogicalNot(unordered) : unordered;
|
||||
emitCompareResult(inst, IrU1(result), false, false);
|
||||
emitCompareResult(inst, IrU1(result), false, cmpx);
|
||||
}
|
||||
|
||||
void TranslationContext::emitFloatClassCompare(const RdnaInstruction& inst, bool cmpx) {
|
||||
|
|
|
|||
|
|
@ -145,6 +145,156 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) {
|
|||
case RdnaOpcode::VCmpxNeU64:
|
||||
emitIntegerCompare(inst, IrOpcode::INotEqual64, IrType::U64, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxFF32:
|
||||
emitCompareConstant(inst, false, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxOF32:
|
||||
emitFloatOrderedCompare(inst, true, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxUF32:
|
||||
emitFloatOrderedCompare(inst, false, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxTruF32:
|
||||
emitCompareConstant(inst, true, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxFI32:
|
||||
emitCompareConstant(inst, false, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxTI32:
|
||||
emitCompareConstant(inst, true, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxFU32:
|
||||
emitCompareConstant(inst, false, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxTU32:
|
||||
emitCompareConstant(inst, true, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpFI64:
|
||||
emitCompareConstant(inst, false, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpLtI64:
|
||||
emitInteger64Order(inst, true, false, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpLeI64:
|
||||
emitInteger64Order(inst, true, true, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpGtI64:
|
||||
emitInteger64Order(inst, true, true, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpNeI64:
|
||||
emitIntegerCompare(inst, IrOpcode::INotEqual64, IrType::U64, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpGeI64:
|
||||
emitInteger64Order(inst, true, false, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpTI64:
|
||||
emitCompareConstant(inst, true, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxFI64:
|
||||
emitCompareConstant(inst, false, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxLtI64:
|
||||
emitInteger64Order(inst, true, false, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxEqI64:
|
||||
emitIntegerCompare(inst, IrOpcode::IEqual64, IrType::U64, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxLeI64:
|
||||
emitInteger64Order(inst, true, true, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxGtI64:
|
||||
emitInteger64Order(inst, true, true, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxGeI64:
|
||||
emitInteger64Order(inst, true, false, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxTI64:
|
||||
emitCompareConstant(inst, true, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpFU64:
|
||||
emitCompareConstant(inst, false, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpLeU64:
|
||||
emitInteger64Order(inst, false, true, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpGeU64:
|
||||
emitInteger64Order(inst, false, false, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpTU64:
|
||||
emitCompareConstant(inst, true, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxFU64:
|
||||
emitCompareConstant(inst, false, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxLtU64:
|
||||
emitInteger64Order(inst, false, false, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxEqU64:
|
||||
emitIntegerCompare(inst, IrOpcode::IEqual64, IrType::U64, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxLeU64:
|
||||
emitInteger64Order(inst, false, true, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxGtU64:
|
||||
emitInteger64Order(inst, false, true, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxGeU64:
|
||||
emitInteger64Order(inst, false, false, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxTU64:
|
||||
emitCompareConstant(inst, true, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpFF16:
|
||||
emitCompareConstant(inst, false, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpOF16:
|
||||
emitFloatOrderedCompare(inst, true, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpUF16:
|
||||
emitFloatOrderedCompare(inst, false, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpNgeF16:
|
||||
emitFloatCompare(inst, IrOpcode::FPUnordLessThan32, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpNlgF16:
|
||||
emitFloatCompare(inst, IrOpcode::FPUnordEqual32, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpNgtF16:
|
||||
emitFloatCompare(inst, IrOpcode::FPUnordLessThanEqual32, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpNleF16:
|
||||
emitFloatCompare(inst, IrOpcode::FPUnordGreaterThan32, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpNltF16:
|
||||
emitFloatCompare(inst, IrOpcode::FPUnordGreaterThanEqual32, true, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpTruF16:
|
||||
emitCompareConstant(inst, true, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxFF16:
|
||||
emitCompareConstant(inst, false, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxLgF16:
|
||||
emitFloatCompare(inst, IrOpcode::FPOrdNotEqual32, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxOF16:
|
||||
emitFloatOrderedCompare(inst, true, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxUF16:
|
||||
emitFloatOrderedCompare(inst, false, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxNgeF16:
|
||||
emitFloatCompare(inst, IrOpcode::FPUnordLessThan32, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxNlgF16:
|
||||
emitFloatCompare(inst, IrOpcode::FPUnordEqual32, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxNleF16:
|
||||
emitFloatCompare(inst, IrOpcode::FPUnordGreaterThan32, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpxTruF16:
|
||||
emitCompareConstant(inst, true, false, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpEqU16:
|
||||
emitInteger16Compare(inst, IrOpcode::IEqual32, false, false);
|
||||
return true;
|
||||
|
|
@ -335,10 +485,10 @@ bool TranslationContext::emitVector(const RdnaInstruction& inst) {
|
|||
emitFloatCompare(inst, IrOpcode::FPUnordGreaterThanEqual32, true, true);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpOF32:
|
||||
emitFloatOrderedCompare(inst, true);
|
||||
emitFloatOrderedCompare(inst, true, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpUF32:
|
||||
emitFloatOrderedCompare(inst, false);
|
||||
emitFloatOrderedCompare(inst, false, false, false);
|
||||
return true;
|
||||
case RdnaOpcode::VCmpClassF32:
|
||||
emitFloatClassCompare(inst, false);
|
||||
|
|
|
|||
Loading…
Reference in New Issue