mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
refactor(shader): compact paired 64-bit lowering
This commit is contained in:
@@ -27,7 +27,7 @@ bool Translator::TranslateStateOperation(const IR::Instruction& inst) {
|
||||
const auto result_high =
|
||||
inst.op == IR::Opcode::SaveexecB64 ? apply(old_high, src_high) : old_high;
|
||||
if (inst.op == IR::Opcode::SaveexecB64) {
|
||||
WriteOperand(inst.dst, ir.PackUint2x32(old_low, old_high));
|
||||
WriteU32Pair(inst.dst, {old_low, old_high});
|
||||
} else {
|
||||
WriteOperand(inst.dst, old_low);
|
||||
}
|
||||
@@ -157,12 +157,11 @@ bool Translator::TranslateMove(const IR::Instruction& inst) {
|
||||
WriteOperand(inst.dst, ReadOperand(inst.src[0], IR::Type::F32));
|
||||
return true;
|
||||
case IR::Opcode::MoveU64: {
|
||||
const bool scalar_pair = inst.dst.kind == IR::OperandKind::Register &&
|
||||
inst.src[0].kind == IR::OperandKind::Register &&
|
||||
inst.dst.reg.file == IR::RegisterFile::Scalar &&
|
||||
inst.src[0].reg.file == IR::RegisterFile::Scalar;
|
||||
WriteOperand(inst.dst, ReadOperand(inst.src[0], IR::Type::U64));
|
||||
if (scalar_pair) {
|
||||
WriteU32Pair(inst.dst, ReadU32Pair(inst.src[0]));
|
||||
if (inst.dst.kind == IR::OperandKind::Register &&
|
||||
inst.src[0].kind == IR::OperandKind::Register &&
|
||||
inst.dst.reg.file == IR::RegisterFile::Scalar &&
|
||||
inst.src[0].reg.file == IR::RegisterFile::Scalar) {
|
||||
ir.SetThreadBitScalarReg(
|
||||
static_cast<IR::ScalarReg>(inst.dst.reg.index),
|
||||
ir.GetThreadBitScalarReg(static_cast<IR::ScalarReg>(inst.src[0].reg.index)));
|
||||
@@ -171,8 +170,8 @@ bool Translator::TranslateMove(const IR::Instruction& inst) {
|
||||
}
|
||||
case IR::Opcode::WqmB64: {
|
||||
if (!current_per_invocation_masks) {
|
||||
const auto result = IR::U64(ir.Emit(
|
||||
IR::ValueOpcode::WqmU64, {ReadOperand(inst.src[0], IR::Type::U64)}));
|
||||
const auto result = IR::U64(
|
||||
ir.Emit(IR::ValueOpcode::WqmU64, {ReadOperand(inst.src[0], IR::Type::U64)}));
|
||||
WriteOperand(inst.dst, result);
|
||||
ir.SetScc(IR::U1(
|
||||
ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})})));
|
||||
|
||||
@@ -6,7 +6,8 @@ bool Translator::TranslateU64MaskOperation(const IR::Instruction& inst) {
|
||||
if (current_per_invocation_masks) {
|
||||
return TranslatePerInvocationU64Mask(inst);
|
||||
}
|
||||
return inst.op == IR::Opcode::BitwiseAndU64 || inst.op == IR::Opcode::BitwiseOrU64
|
||||
return inst.op == IR::Opcode::BitwiseAndU64 || inst.op == IR::Opcode::BitwiseOrU64 ||
|
||||
inst.op == IR::Opcode::BitwiseXorU64 || inst.op == IR::Opcode::BitwiseNotU64
|
||||
? TranslateSimpleInteger(inst)
|
||||
: TranslateComposedInteger(inst);
|
||||
}
|
||||
|
||||
@@ -157,6 +157,31 @@ bool Translator::TranslatePerInvocationU64Mask(const IR::Instruction& inst) {
|
||||
}
|
||||
|
||||
bool Translator::TranslateSimpleInteger(const IR::Instruction& inst) {
|
||||
if (inst.op == IR::Opcode::BitwiseAndU64 || inst.op == IR::Opcode::BitwiseOrU64 ||
|
||||
inst.op == IR::Opcode::BitwiseXorU64 || inst.op == IR::Opcode::BitwiseNotU64) {
|
||||
const auto lhs = ReadU32Pair(inst.src[0]);
|
||||
std::array<IR::U32, 2> result;
|
||||
if (inst.op == IR::Opcode::BitwiseNotU64) {
|
||||
result = {ir.BitwiseNot(lhs[0]), ir.BitwiseNot(lhs[1])};
|
||||
} else {
|
||||
const auto rhs = ReadU32Pair(inst.src[1]);
|
||||
for (uint32_t component = 0; component < 2; component++) {
|
||||
switch (inst.op) {
|
||||
case IR::Opcode::BitwiseAndU64:
|
||||
result[component] = ir.BitwiseAnd(lhs[component], rhs[component]);
|
||||
break;
|
||||
case IR::Opcode::BitwiseOrU64:
|
||||
result[component] = ir.BitwiseOr(lhs[component], rhs[component]);
|
||||
break;
|
||||
default:
|
||||
result[component] = ir.BitwiseXor(lhs[component], rhs[component]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
WriteU32Pair(inst.dst, result);
|
||||
return true;
|
||||
}
|
||||
IR::ValueOpcode opcode {};
|
||||
IR::Type type = IR::Type::U32;
|
||||
switch (inst.op) {
|
||||
@@ -187,14 +212,6 @@ bool Translator::TranslateSimpleInteger(const IR::Instruction& inst) {
|
||||
type = IR::Type::U64;
|
||||
break;
|
||||
case IR::Opcode::FindLsbU32: opcode = IR::ValueOpcode::FindILsb32; break;
|
||||
case IR::Opcode::BitwiseAndU64:
|
||||
opcode = IR::ValueOpcode::BitwiseAnd64;
|
||||
type = IR::Type::U64;
|
||||
break;
|
||||
case IR::Opcode::BitwiseOrU64:
|
||||
opcode = IR::ValueOpcode::BitwiseOr64;
|
||||
type = IR::Type::U64;
|
||||
break;
|
||||
case IR::Opcode::ShiftLeftLogicalU32: opcode = IR::ValueOpcode::ShiftLeftLogical32; break;
|
||||
case IR::Opcode::ShiftRightLogicalU32: opcode = IR::ValueOpcode::ShiftRightLogical32; break;
|
||||
case IR::Opcode::ShiftRightArithmeticI32:
|
||||
@@ -219,10 +236,6 @@ bool Translator::TranslateSimpleInteger(const IR::Instruction& inst) {
|
||||
opcode == IR::ValueOpcode::ShiftRightLogical32 ||
|
||||
opcode == IR::ValueOpcode::ShiftRightArithmetic32)) {
|
||||
args[index] = ir.BitwiseAnd(IR::U32(args[index]), IR::U32(IR::Value(31u)));
|
||||
} else if (index == 1u && (opcode == IR::ValueOpcode::ShiftLeftLogical64 ||
|
||||
opcode == IR::ValueOpcode::ShiftRightLogical64 ||
|
||||
opcode == IR::ValueOpcode::ShiftRightArithmetic64)) {
|
||||
args[index] = ir.BitwiseAnd(IR::U32(args[index]), IR::U32(IR::Value(63u)));
|
||||
}
|
||||
}
|
||||
IR::Value result;
|
||||
@@ -233,32 +246,46 @@ bool Translator::TranslateSimpleInteger(const IR::Instruction& inst) {
|
||||
default: EXIT("invalid simple integer source count: %u", inst.src_count);
|
||||
}
|
||||
WriteOperand(inst.dst, result);
|
||||
if (type == IR::Type::U64 && inst.dst.kind == IR::OperandKind::Register &&
|
||||
inst.dst.reg.file == IR::RegisterFile::Scalar) {
|
||||
IR::U1 mask;
|
||||
if (inst.op == IR::Opcode::BitwiseAndU64) {
|
||||
mask = ir.LogicalAnd(ReadMask(inst.src[0]), ReadMask(inst.src[1]));
|
||||
} else if (inst.op == IR::Opcode::BitwiseOrU64) {
|
||||
mask = ir.LogicalOr(ReadMask(inst.src[0]), ReadMask(inst.src[1]));
|
||||
}
|
||||
if (!mask.IsEmpty()) {
|
||||
ir.SetThreadBitScalarReg(static_cast<IR::ScalarReg>(inst.dst.reg.index), mask);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Translator::TranslateComposedInteger(const IR::Instruction& inst) {
|
||||
if (inst.op == IR::Opcode::BitwiseAndNotU64 || inst.op == IR::Opcode::BitwiseOrNotU64 ||
|
||||
inst.op == IR::Opcode::BitwiseNandU64 || inst.op == IR::Opcode::BitwiseNorU64 ||
|
||||
inst.op == IR::Opcode::BitwiseXnorU64) {
|
||||
const auto lhs = ReadU32Pair(inst.src[0]);
|
||||
const auto rhs = ReadU32Pair(inst.src[1]);
|
||||
std::array<IR::U32, 2> result;
|
||||
for (uint32_t component = 0; component < 2; component++) {
|
||||
switch (inst.op) {
|
||||
case IR::Opcode::BitwiseAndNotU64:
|
||||
result[component] =
|
||||
ir.BitwiseAnd(lhs[component], ir.BitwiseNot(rhs[component]));
|
||||
break;
|
||||
case IR::Opcode::BitwiseOrNotU64:
|
||||
result[component] = ir.BitwiseOr(lhs[component], ir.BitwiseNot(rhs[component]));
|
||||
break;
|
||||
case IR::Opcode::BitwiseNandU64:
|
||||
result[component] =
|
||||
ir.BitwiseNot(ir.BitwiseAnd(lhs[component], rhs[component]));
|
||||
break;
|
||||
case IR::Opcode::BitwiseNorU64:
|
||||
result[component] = ir.BitwiseNot(ir.BitwiseOr(lhs[component], rhs[component]));
|
||||
break;
|
||||
default:
|
||||
result[component] =
|
||||
ir.BitwiseNot(ir.BitwiseXor(lhs[component], rhs[component]));
|
||||
break;
|
||||
}
|
||||
}
|
||||
WriteU32Pair(inst.dst, result);
|
||||
return true;
|
||||
}
|
||||
const auto binary_u32 = [&](auto operation) {
|
||||
const auto lhs = ReadU32(inst.src[0]);
|
||||
const auto rhs = ReadU32(inst.src[1]);
|
||||
return operation(lhs, rhs);
|
||||
};
|
||||
const auto binary_u64 = [&](auto operation) {
|
||||
const auto lhs = UnpackU64(ReadU64(inst.src[0]));
|
||||
const auto rhs = UnpackU64(ReadU64(inst.src[1]));
|
||||
return ir.PackUint2x32(operation(lhs[0], rhs[0]), operation(lhs[1], rhs[1]));
|
||||
};
|
||||
|
||||
IR::Value result;
|
||||
switch (inst.op) {
|
||||
@@ -282,34 +309,6 @@ bool Translator::TranslateComposedInteger(const IR::Instruction& inst) {
|
||||
result = binary_u32(
|
||||
[&](IR::U32 lhs, IR::U32 rhs) { return ir.BitwiseNot(ir.BitwiseXor(lhs, rhs)); });
|
||||
break;
|
||||
case IR::Opcode::BitwiseXorU64:
|
||||
result = binary_u64([&](IR::U32 lhs, IR::U32 rhs) { return ir.BitwiseXor(lhs, rhs); });
|
||||
break;
|
||||
case IR::Opcode::BitwiseAndNotU64:
|
||||
result = binary_u64(
|
||||
[&](IR::U32 lhs, IR::U32 rhs) { return ir.BitwiseAnd(lhs, ir.BitwiseNot(rhs)); });
|
||||
break;
|
||||
case IR::Opcode::BitwiseOrNotU64:
|
||||
result = binary_u64(
|
||||
[&](IR::U32 lhs, IR::U32 rhs) { return ir.BitwiseOr(lhs, ir.BitwiseNot(rhs)); });
|
||||
break;
|
||||
case IR::Opcode::BitwiseNandU64:
|
||||
result = binary_u64(
|
||||
[&](IR::U32 lhs, IR::U32 rhs) { return ir.BitwiseNot(ir.BitwiseAnd(lhs, rhs)); });
|
||||
break;
|
||||
case IR::Opcode::BitwiseNorU64:
|
||||
result = binary_u64(
|
||||
[&](IR::U32 lhs, IR::U32 rhs) { return ir.BitwiseNot(ir.BitwiseOr(lhs, rhs)); });
|
||||
break;
|
||||
case IR::Opcode::BitwiseXnorU64:
|
||||
result = binary_u64(
|
||||
[&](IR::U32 lhs, IR::U32 rhs) { return ir.BitwiseNot(ir.BitwiseXor(lhs, rhs)); });
|
||||
break;
|
||||
case IR::Opcode::BitwiseNotU64: {
|
||||
const auto source = UnpackU64(ReadU64(inst.src[0]));
|
||||
result = ir.PackUint2x32(ir.BitwiseNot(source[0]), ir.BitwiseNot(source[1]));
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::BitwiseAndOrU32: {
|
||||
const auto lhs = ReadU32(inst.src[0]);
|
||||
const auto rhs = ReadU32(inst.src[1]);
|
||||
@@ -326,7 +325,7 @@ bool Translator::TranslateComposedInteger(const IR::Instruction& inst) {
|
||||
ReadU32(inst.src[2]));
|
||||
break;
|
||||
case IR::Opcode::FindLsbU64: {
|
||||
const auto source = UnpackU64(ReadU64(inst.src[0]));
|
||||
const auto source = ExtractU64(ReadU64(inst.src[0]));
|
||||
const auto low_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[0]}));
|
||||
const auto high_lsb = IR::U32(ir.Emit(IR::ValueOpcode::FindILsb32, {source[1]}));
|
||||
const auto high_position = ir.IAdd(high_lsb, IR::U32(IR::Value(32u)));
|
||||
@@ -349,44 +348,13 @@ bool Translator::TranslateComposedInteger(const IR::Instruction& inst) {
|
||||
const auto position = ir.ISub(IR::U32(IR::Value(63u)), msb);
|
||||
const auto nonzero = IR::U1(
|
||||
ir.Emit(IR::ValueOpcode::INotEqual64,
|
||||
{source, ir.PackUint2x32(IR::U32(IR::Value(0u)), IR::U32(IR::Value(0u)))}));
|
||||
{source, ir.ConstructU64(IR::U32(IR::Value(0u)), IR::U32(IR::Value(0u)))}));
|
||||
result = ir.Select(nonzero, position, IR::U32(IR::Value(0xffffffffu)));
|
||||
break;
|
||||
}
|
||||
default: return false;
|
||||
}
|
||||
WriteOperand(inst.dst, result);
|
||||
if (result.GetType() == IR::Type::U64 && inst.dst.kind == IR::OperandKind::Register &&
|
||||
inst.dst.reg.file == IR::RegisterFile::Scalar) {
|
||||
const auto lhs = ReadMask(inst.src[0]);
|
||||
IR::U1 mask;
|
||||
switch (inst.op) {
|
||||
case IR::Opcode::BitwiseXorU64:
|
||||
mask = IR::U1(ir.Emit(IR::ValueOpcode::LogicalXor, {lhs, ReadMask(inst.src[1])}));
|
||||
break;
|
||||
case IR::Opcode::BitwiseAndNotU64:
|
||||
mask = ir.LogicalAnd(lhs, ir.LogicalNot(ReadMask(inst.src[1])));
|
||||
break;
|
||||
case IR::Opcode::BitwiseOrNotU64:
|
||||
mask = ir.LogicalOr(lhs, ir.LogicalNot(ReadMask(inst.src[1])));
|
||||
break;
|
||||
case IR::Opcode::BitwiseNandU64:
|
||||
mask = ir.LogicalNot(ir.LogicalAnd(lhs, ReadMask(inst.src[1])));
|
||||
break;
|
||||
case IR::Opcode::BitwiseNorU64:
|
||||
mask = ir.LogicalNot(ir.LogicalOr(lhs, ReadMask(inst.src[1])));
|
||||
break;
|
||||
case IR::Opcode::BitwiseXnorU64:
|
||||
mask = ir.LogicalNot(
|
||||
IR::U1(ir.Emit(IR::ValueOpcode::LogicalXor, {lhs, ReadMask(inst.src[1])})));
|
||||
break;
|
||||
case IR::Opcode::BitwiseNotU64: mask = ir.LogicalNot(lhs); break;
|
||||
default: break;
|
||||
}
|
||||
if (!mask.IsEmpty()) {
|
||||
ir.SetThreadBitScalarReg(static_cast<IR::ScalarReg>(inst.dst.reg.index), mask);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -402,18 +370,12 @@ bool Translator::TranslateExtendedInteger(const IR::Instruction& inst) {
|
||||
return IR::U32(
|
||||
ir.Emit(IR::ValueOpcode::BitFieldInsert, {imm(0), imm(0xffffffffu), imm(0), count}));
|
||||
};
|
||||
const auto select_u64 = [&](IR::U1 condition, IR::U64 true_value, IR::U64 false_value) {
|
||||
const auto lhs = UnpackU64(true_value);
|
||||
const auto rhs = UnpackU64(false_value);
|
||||
return ir.PackUint2x32(ir.Select(condition, lhs[0], rhs[0]),
|
||||
ir.Select(condition, lhs[1], rhs[1]));
|
||||
};
|
||||
const auto right_mask64 = [&](IR::U32 count) {
|
||||
const auto below32 = IR::U1(ir.Emit(IR::ValueOpcode::ULessThan32, {count, imm(32)}));
|
||||
const auto above32 = IR::U1(ir.Emit(IR::ValueOpcode::UGreaterThan32, {count, imm(32)}));
|
||||
const auto low_count = ir.Select(below32, count, imm(32));
|
||||
const auto high_count = ir.Select(above32, ir.ISub(count, imm(32)), imm(0));
|
||||
return ir.PackUint2x32(right_mask32(low_count), right_mask32(high_count));
|
||||
return ir.ConstructU64(right_mask32(low_count), right_mask32(high_count));
|
||||
};
|
||||
|
||||
IR::Value result;
|
||||
@@ -436,7 +398,7 @@ bool Translator::TranslateExtendedInteger(const IR::Instruction& inst) {
|
||||
case IR::Opcode::UMadU64U32: {
|
||||
const auto lhs = ReadU32(inst.src[0]);
|
||||
const auto rhs = ReadU32(inst.src[1]);
|
||||
const auto add = UnpackU64(ReadU64(inst.src[2]));
|
||||
const auto add = ExtractU64(ReadU64(inst.src[2]));
|
||||
const auto mul_low = ir.IMul(lhs, rhs);
|
||||
const auto mul_high = IR::U32(ir.Emit(IR::ValueOpcode::UMulHi, {lhs, rhs}));
|
||||
const auto low = ir.IAdd(mul_low, add[0]);
|
||||
@@ -445,7 +407,7 @@ bool Translator::TranslateExtendedInteger(const IR::Instruction& inst) {
|
||||
const auto carry0 = ir.ULessThan(high0, mul_high);
|
||||
const auto high = ir.IAdd(high0, ir.Select(carry_low, imm(1), imm(0)));
|
||||
const auto carry1 = ir.ULessThan(high, high0);
|
||||
WriteOperand(inst.dst, ir.PackUint2x32(low, high));
|
||||
WriteOperand(inst.dst, ir.ConstructU64(low, high));
|
||||
if (inst.dst2.kind != IR::OperandKind::Null) {
|
||||
WriteMask(inst.dst2, ir.LogicalOr(carry0, carry1));
|
||||
}
|
||||
@@ -503,7 +465,7 @@ bool Translator::TranslateExtendedInteger(const IR::Instruction& inst) {
|
||||
return ir.BitwiseOr(bits, ir.ShiftLeftLogical(bits, imm(1)));
|
||||
};
|
||||
const auto source = ReadU32(inst.src[0]);
|
||||
result = ir.PackUint2x32(replicate(mask(source, 0xffffu)),
|
||||
result = ir.ConstructU64(replicate(mask(source, 0xffffu)),
|
||||
replicate(ir.ShiftRightLogical(source, imm(16))));
|
||||
break;
|
||||
}
|
||||
@@ -590,12 +552,12 @@ bool Translator::TranslateExtendedInteger(const IR::Instruction& inst) {
|
||||
const auto lo = ReadU32(inst.src[1]);
|
||||
const auto byte_offset = mask(ReadU32(inst.src[2]), 31u);
|
||||
const auto bit_offset = ir.ShiftLeftLogical(byte_offset, imm(3));
|
||||
const auto concatenated = ir.PackUint2x32(lo, hi);
|
||||
const auto concatenated = ir.ConstructU64(lo, hi);
|
||||
const auto shifted = IR::U64(ir.Emit(IR::ValueOpcode::ShiftRightLogical64,
|
||||
{concatenated, mask(bit_offset, 63u)}));
|
||||
const auto in_range =
|
||||
IR::U1(ir.Emit(IR::ValueOpcode::ULessThan32, {byte_offset, imm(8)}));
|
||||
result = ir.Select(in_range, UnpackU64(shifted)[0], imm(0));
|
||||
result = ir.Select(in_range, ExtractU64(shifted)[0], imm(0));
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::ShiftLeftAddU32:
|
||||
@@ -633,10 +595,14 @@ bool Translator::TranslateExtendedInteger(const IR::Instruction& inst) {
|
||||
ReadOperand(inst.src[2], IR::Type::F32)});
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::SelectU64:
|
||||
result =
|
||||
select_u64(ReadCondition(inst.src[0]), ReadU64(inst.src[1]), ReadU64(inst.src[2]));
|
||||
break;
|
||||
case IR::Opcode::SelectU64: {
|
||||
const auto condition = ReadCondition(inst.src[0]);
|
||||
const auto lhs = ReadU32Pair(inst.src[1]);
|
||||
const auto rhs = ReadU32Pair(inst.src[2]);
|
||||
WriteU32Pair(inst.dst, {ir.Select(condition, lhs[0], rhs[0]),
|
||||
ir.Select(condition, lhs[1], rhs[1])});
|
||||
return true;
|
||||
}
|
||||
case IR::Opcode::PackLowLowU16:
|
||||
case IR::Opcode::PackLowHighU16:
|
||||
case IR::Opcode::PackHighHighU16:
|
||||
|
||||
@@ -87,10 +87,7 @@ IR::U32 Translator::ReadPcRelativeU32(const IR::Operand& operand) {
|
||||
const auto address =
|
||||
ir.Emit(IR::ValueOpcode::IAdd64, {ir.Emit(IR::ValueOpcode::GetShaderBase),
|
||||
IR::Value(static_cast<uint64_t>(operand.imm))});
|
||||
const auto pair = ir.Emit(IR::ValueOpcode::UnpackUint2x32, {address});
|
||||
return IR::U32(
|
||||
ir.Emit(IR::ValueOpcode::CompositeExtractU32x2,
|
||||
{pair, IR::Value(operand.kind == IR::OperandKind::PcRelativeU32 ? 0u : 1u)}));
|
||||
return ir.CompositeExtract(address, operand.kind == IR::OperandKind::PcRelativeU32 ? 0u : 1u);
|
||||
}
|
||||
|
||||
std::array<IR::U32, 2> Translator::BallotMask(IR::U1 value) {
|
||||
@@ -205,22 +202,8 @@ IR::Value Translator::ReadOperand(const IR::Operand& operand, IR::Type type) {
|
||||
return ir.INotEqual(ReadRawU32(operand), IR::U32(IR::Value(0u)));
|
||||
}
|
||||
if (type == IR::Type::U64) {
|
||||
if (operand.kind == IR::OperandKind::Register &&
|
||||
operand.reg.file == IR::RegisterFile::Exec) {
|
||||
return ir.PackUint2x32(ir.GetExecLo(), ir.GetExecHi());
|
||||
}
|
||||
if (operand.kind == IR::OperandKind::Register &&
|
||||
operand.reg.file == IR::RegisterFile::Vcc) {
|
||||
return ir.PackUint2x32(ir.GetVccLo(), ir.GetVccHi());
|
||||
}
|
||||
const auto low = ApplyBitSourceModifiers(operand, ReadRawU32(operand));
|
||||
IR::U32 high(IR::Value(0u));
|
||||
if (operand.kind == IR::OperandKind::Register) {
|
||||
high = ReadRawU32(OffsetOperand(operand, 1));
|
||||
} else if (operand.kind == IR::OperandKind::ImmediateU32 && operand.sext_64) {
|
||||
high = IR::U32(IR::Value(0xffffffffu));
|
||||
}
|
||||
return ir.PackUint2x32(low, high);
|
||||
const auto pair = ReadU32Pair(operand);
|
||||
return ir.ConstructU64(pair[0], pair[1]);
|
||||
}
|
||||
auto bits = ApplyBitSourceModifiers(operand, ReadRawU32(operand));
|
||||
if (TypesOverlap(type, IR::Type::F32) && !TypesOverlap(type, IR::Type::U32)) {
|
||||
@@ -396,31 +379,7 @@ void Translator::WriteOperand(const IR::Operand& operand, IR::Value value) {
|
||||
return;
|
||||
}
|
||||
if (type == IR::Type::U64) {
|
||||
const auto unpacked = ir.Emit(IR::ValueOpcode::UnpackUint2x32, {value});
|
||||
const auto low = ir.CompositeExtract(unpacked, 0);
|
||||
const auto high = ir.CompositeExtract(unpacked, 1);
|
||||
if (operand.kind == IR::OperandKind::Register) {
|
||||
const auto thread_bit = ThreadBit(low, high);
|
||||
switch (operand.reg.file) {
|
||||
case IR::RegisterFile::Exec:
|
||||
ir.SetExec(thread_bit);
|
||||
ir.SetExecLo(low);
|
||||
ir.SetExecHi(high);
|
||||
return;
|
||||
case IR::RegisterFile::Vcc:
|
||||
ir.SetVcc(thread_bit);
|
||||
ir.SetVccLo(low);
|
||||
ir.SetVccHi(high);
|
||||
return;
|
||||
case IR::RegisterFile::Scalar:
|
||||
ir.SetThreadBitScalarReg(static_cast<IR::ScalarReg>(operand.reg.index),
|
||||
thread_bit);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
WriteRawU32(operand, low);
|
||||
WriteRawU32(OffsetOperand(operand, 1), high);
|
||||
WriteU32Pair(operand, {ir.CompositeExtract(value, 0), ir.CompositeExtract(value, 1)});
|
||||
return;
|
||||
}
|
||||
if (type == IR::Type::F32) {
|
||||
@@ -474,6 +433,25 @@ IR::U32 Translator::ReadU32(const IR::Operand& operand) {
|
||||
return IR::U32(ReadOperand(operand, IR::Type::U32));
|
||||
}
|
||||
|
||||
std::array<IR::U32, 2> Translator::ReadU32Pair(const IR::Operand& operand) {
|
||||
if (operand.kind == IR::OperandKind::Register) {
|
||||
if (operand.reg.file == IR::RegisterFile::Exec) {
|
||||
return {ir.GetExecLo(), ir.GetExecHi()};
|
||||
}
|
||||
if (operand.reg.file == IR::RegisterFile::Vcc) {
|
||||
return {ir.GetVccLo(), ir.GetVccHi()};
|
||||
}
|
||||
}
|
||||
const auto low = ApplyBitSourceModifiers(operand, ReadRawU32(operand));
|
||||
IR::U32 high(IR::Value(0u));
|
||||
if (operand.kind == IR::OperandKind::Register) {
|
||||
high = ReadRawU32(OffsetOperand(operand, 1));
|
||||
} else if (operand.kind == IR::OperandKind::ImmediateU32 && operand.sext_64) {
|
||||
high = IR::U32(IR::Value(0xffffffffu));
|
||||
}
|
||||
return {low, high};
|
||||
}
|
||||
|
||||
IR::U64 Translator::ReadU64(const IR::Operand& operand) {
|
||||
return IR::U64(ReadOperand(operand, IR::Type::U64));
|
||||
}
|
||||
@@ -560,9 +538,35 @@ IR::U32 Translator::ReadF16LaneBits(const IR::Operand& operand, bool high_lane)
|
||||
return value;
|
||||
}
|
||||
|
||||
std::array<IR::U32, 2> Translator::UnpackU64(IR::U64 value) {
|
||||
const auto unpacked = ir.Emit(IR::ValueOpcode::UnpackUint2x32, {value});
|
||||
return {ir.CompositeExtract(unpacked, 0), ir.CompositeExtract(unpacked, 1)};
|
||||
std::array<IR::U32, 2> Translator::ExtractU64(IR::U64 value) {
|
||||
return {ir.CompositeExtract(value, 0), ir.CompositeExtract(value, 1)};
|
||||
}
|
||||
|
||||
void Translator::WriteU32Pair(const IR::Operand& operand, const std::array<IR::U32, 2>& value) {
|
||||
if (operand.kind == IR::OperandKind::Null) {
|
||||
return;
|
||||
}
|
||||
if (operand.kind == IR::OperandKind::Register) {
|
||||
const auto thread_bit = ThreadBit(value[0], value[1]);
|
||||
switch (operand.reg.file) {
|
||||
case IR::RegisterFile::Exec:
|
||||
ir.SetExec(thread_bit);
|
||||
ir.SetExecLo(value[0]);
|
||||
ir.SetExecHi(value[1]);
|
||||
return;
|
||||
case IR::RegisterFile::Vcc:
|
||||
ir.SetVcc(thread_bit);
|
||||
ir.SetVccLo(value[0]);
|
||||
ir.SetVccHi(value[1]);
|
||||
return;
|
||||
case IR::RegisterFile::Scalar:
|
||||
ir.SetThreadBitScalarReg(static_cast<IR::ScalarReg>(operand.reg.index), thread_bit);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
WriteRawU32(operand, value[0]);
|
||||
WriteRawU32(OffsetOperand(operand, 1), value[1]);
|
||||
}
|
||||
|
||||
IR::U1 Translator::ThreadBit(IR::U32 low, IR::U32 high) {
|
||||
|
||||
@@ -36,6 +36,7 @@ private:
|
||||
void WriteF16(const IR::Operand& operand, IR::F32 value);
|
||||
void WriteU16(const IR::Operand& operand, IR::U32 value);
|
||||
IR::U32 ReadU32(const IR::Operand& operand);
|
||||
std::array<IR::U32, 2> ReadU32Pair(const IR::Operand& operand);
|
||||
IR::U64 ReadU64(const IR::Operand& operand);
|
||||
IR::F32 ReadF16LaneAsF32(const IR::Operand& operand, bool high_lane);
|
||||
IR::F32 ReadF16AsF32(const IR::Operand& operand);
|
||||
@@ -44,13 +45,14 @@ private:
|
||||
IR::U32 ReadU16LaneAsU32(const IR::Operand& operand, bool high_lane, bool sign_extend);
|
||||
IR::U32 ReadU16AsU32(const IR::Operand& operand, bool sign_extend);
|
||||
IR::U32 ReadF16LaneBits(const IR::Operand& operand, bool high_lane);
|
||||
std::array<IR::U32, 2> UnpackU64(IR::U64 value);
|
||||
IR::U1 ReadCondition(const IR::Operand& operand);
|
||||
IR::U32 ConditionBit(const IR::Operand& operand);
|
||||
IR::U1 ReadMask(const IR::Operand& operand);
|
||||
void WriteMask(const IR::Operand& operand, IR::U1 value);
|
||||
void WriteMask64(const IR::Operand& operand, IR::U1 value);
|
||||
void WriteCompareResult(const IR::Operand& operand, IR::U1 value);
|
||||
std::array<IR::U32, 2> ExtractU64(IR::U64 value);
|
||||
void WriteU32Pair(const IR::Operand& operand, const std::array<IR::U32, 2>& value);
|
||||
IR::U1 ReadCondition(const IR::Operand& operand);
|
||||
IR::U32 ConditionBit(const IR::Operand& operand);
|
||||
IR::U1 ReadMask(const IR::Operand& operand);
|
||||
void WriteMask(const IR::Operand& operand, IR::U1 value);
|
||||
void WriteMask64(const IR::Operand& operand, IR::U1 value);
|
||||
void WriteCompareResult(const IR::Operand& operand, IR::U1 value);
|
||||
|
||||
IR::MemoryFlags AddMemoryInfo(const IR::Instruction& inst);
|
||||
IR::ExportFlags AddExportInfo(const IR::Instruction& inst);
|
||||
@@ -82,13 +84,13 @@ private:
|
||||
IR::ValueOpcode BufferAtomicOpcode(IR::Opcode opcode);
|
||||
IR::ValueOpcode SharedAtomicOpcode(IR::Opcode opcode);
|
||||
bool TranslateScalarMemory(const IR::Instruction& inst);
|
||||
bool TranslateBufferLoad(const IR::Instruction& inst);
|
||||
bool TranslateBufferStore(const IR::Instruction& inst);
|
||||
bool TranslateAtomicMemory(const IR::Instruction& inst);
|
||||
bool TranslateFlatLoad(const IR::Instruction& inst);
|
||||
bool TranslateFlatStore(const IR::Instruction& inst);
|
||||
bool TranslateImageMemory(const IR::Instruction& inst);
|
||||
bool TranslateSharedMemory(const IR::Instruction& inst);
|
||||
bool TranslateBufferLoad(const IR::Instruction& inst);
|
||||
bool TranslateBufferStore(const IR::Instruction& inst);
|
||||
bool TranslateAtomicMemory(const IR::Instruction& inst);
|
||||
bool TranslateFlatLoad(const IR::Instruction& inst);
|
||||
bool TranslateFlatStore(const IR::Instruction& inst);
|
||||
bool TranslateImageMemory(const IR::Instruction& inst);
|
||||
bool TranslateSharedMemory(const IR::Instruction& inst);
|
||||
|
||||
IR::F32 SelectF32(IR::U1 condition, IR::F32 true_value, IR::F32 false_value);
|
||||
IR::U32 ConvertF32ToU32Saturated(IR::F32 value, float upper_bound, float safe_upper,
|
||||
|
||||
Reference in New Issue
Block a user