shader: read float inline constants on 64-bit operands as f64 bits (#1576)

A float inline constant (240-248) read by a 64-bit operand is the f64 bit
pattern for integer B64 opcodes too: AMD's compilers emit
v_lshrrev_b64 v[4:5], v0, 1.0 for 0x3ff0000000000000 >> lane. ReadU32Pair
returned {f32 bits, 0}, so only F64-typed reads had the right value.

Based on TheCruZ's 284deab28 (closed #1219).

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Nawid3333
2026-10-17 05:21:06 +02:00
committed by GitHub
parent ba8b0c85b8
commit b82512be06
2 changed files with 37 additions and 7 deletions
@@ -233,13 +233,6 @@ IR::Value Translator::ReadOperand(const Decoder::Operand& operand, IR::Type type
if (type == IR::Type::F64) {
if (operand.kind == Decoder::OperandKind::LiteralConstant) {
pair = {IR::U32(IR::Value(0u)), IR::U32(IR::Value(operand.value))};
} else if (operand.kind == Decoder::OperandKind::FloatInlineConstant) {
const auto bits = operand.value == 0x3e22f983u
? 0x3fc45f306dc9c882ull
: std::bit_cast<uint64_t>(static_cast<double>(
std::bit_cast<float>(operand.value)));
pair = {IR::U32(IR::Value(static_cast<uint32_t>(bits))),
IR::U32(IR::Value(static_cast<uint32_t>(bits >> 32u)))};
}
if (operand.absolute) {
pair[1] = ir.BitwiseAnd(pair[1], IR::U32(IR::Value(0x7fffffffu)));
@@ -488,6 +481,14 @@ std::array<IR::U32, 2> Translator::ReadU32Pair(const Decoder::Operand& operand)
if (operand.kind == Decoder::OperandKind::VccLo) {
return {ir.GetVccLo(), ir.GetVccHi()};
}
if (operand.kind == Decoder::OperandKind::FloatInlineConstant) {
const auto bits =
operand.value == 0x3e22f983u
? 0x3fc45f306dc9c882ull
: std::bit_cast<uint64_t>(static_cast<double>(std::bit_cast<float>(operand.value)));
return {IR::U32(IR::Value(static_cast<uint32_t>(bits))),
IR::U32(IR::Value(static_cast<uint32_t>(bits >> 32u)))};
}
const auto low = ApplyBitSourceModifiers(operand, ReadRawU32(operand));
IR::U32 high(IR::Value(0u));
if (operand.kind == Decoder::OperandKind::Sgpr || operand.kind == Decoder::OperandKind::Vgpr) {
+29
View File
@@ -25192,6 +25192,34 @@ TestCase VectorCarryAndBitCountOps() {
O::S_ENDPGM}};
}
TestCase ScalarVector64BitFloatInlineConstants() {
using O = ShaderOpcode;
std::vector<u32> code;
code.push_back(EncodeSop1(0x04, 40, 242));
code.push_back(EncodeSop2(0x11, 42, 240, InlineU32(0)));
code.push_back(EncodeSop1(0x04, 44, 248));
AppendVop3(&code, 0x300, 2, InlineU32(32), 244);
code.push_back(EncodeSMovB32(46, InlineU32(0)));
AppendSMovLiteral(&code, 47, 0x3ff00000u);
code.push_back(EncodeSopc(0x12, 46, 242));
code.push_back(EncodeSMovB32(48, 253));
AppendStoreSgprPair(&code, 40, 0);
AppendStoreSgprPair(&code, 42, 2);
AppendStoreVgpr(&code, 2, 4);
AppendStoreVgpr(&code, 3, 5);
AppendStoreSgprPair(&code, 44, 6);
AppendStoreSgpr(&code, 48, 8);
AppendEnd(&code);
TestCase test;
test.name = "ScalarVector64BitFloatInlineConstants";
test.code = std::move(code);
test.expected = {0u, 0x3ff00000u, 0u, 0x3fe00000u, 0x40000000u, 0u, 0x6dc9c882u, 0x3fc45f30u, 1u};
test.opcodes = {O::S_MOV_B64, O::S_OR_B64, O::V_LSHRREV_B64, O::S_MOV_B32, O::S_CMP_EQ_U64,
O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM};
return test;
}
TestCase VectorMbcntUsesThreadMask() {
using O = ShaderOpcode;
@@ -42017,6 +42045,7 @@ std::vector<TestCase> MakeCases() {
AddCase(VectorBfeI32SignExtendsField);
AddCase(VectorAlignByteUsesTwoBitByteOffset);
AddCase(VectorCarryAndBitCountOps);
AddCase(ScalarVector64BitFloatInlineConstants);
AddCase(VectorMbcntUsesThreadMask);
AddCase(VectorAddcWritesPerLaneCarryOut);
AddCase(VectorAddcUsesPerLaneCarryIn);