mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
Revert "shader: preserve raw VCC bits in S_MOV_B64 (#418)"
This reverts commit 6758d67942.
An EXEC pair loses its mask provenance and falls into the raw high-word path. The saved all-ones high word then keeps waterfall branches true and wedges GPU work.
This commit is contained in:
@@ -12,7 +12,6 @@ void Translator::EmitCompareResult(const Decoder::Instruction& inst, IR::U1 valu
|
|||||||
if (cmpx) {
|
if (cmpx) {
|
||||||
const auto mask = BallotMask(masked);
|
const auto mask = BallotMask(masked);
|
||||||
ir.SetExec(masked);
|
ir.SetExec(masked);
|
||||||
ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
|
||||||
ir.SetExecLo(mask[0]);
|
ir.SetExecLo(mask[0]);
|
||||||
ir.SetExecHi(mask[1]);
|
ir.SetExecHi(mask[1]);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -24,28 +24,18 @@ Decoder::Operand ConditionOperand(Decoder::OperandKind kind) {
|
|||||||
|
|
||||||
void Translator::S_SAVEEXEC(const Decoder::Instruction& inst, IR::ValueOpcode operation,
|
void Translator::S_SAVEEXEC(const Decoder::Instruction& inst, IR::ValueOpcode operation,
|
||||||
bool negate_exec, bool negate_source, bool write_64) {
|
bool negate_exec, bool negate_source, bool write_64) {
|
||||||
if (write_64) {
|
|
||||||
const auto exec_operand = ConditionOperand(Decoder::OperandKind::ExecLo);
|
|
||||||
const auto old = ReadScalarU64(exec_operand);
|
|
||||||
const auto bit_operation = operation == IR::ValueOpcode::LogicalAnd
|
|
||||||
? IR::ValueOpcode::BitwiseAnd32
|
|
||||||
: IR::ValueOpcode::BitwiseOr32;
|
|
||||||
const auto result = BinaryScalarU64(old, ReadScalarU64(inst.src0), operation, bit_operation,
|
|
||||||
negate_exec, negate_source, false);
|
|
||||||
WriteScalarU64(inst.dst, old);
|
|
||||||
WriteScalarU64(exec_operand, result);
|
|
||||||
ir.SetScc(ScalarU64NonZero(result));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const auto old = ir.GetExec();
|
const auto old = ir.GetExec();
|
||||||
const auto src = ReadMask(inst.src0);
|
const auto src = ReadMask(inst.src0);
|
||||||
const auto lhs = negate_exec ? ir.LogicalNot(old) : old;
|
const auto lhs = negate_exec ? ir.LogicalNot(old) : old;
|
||||||
const auto rhs = negate_source ? ir.LogicalNot(src) : src;
|
const auto rhs = negate_source ? ir.LogicalNot(src) : src;
|
||||||
const auto result = IR::U1(ir.Emit(operation, {lhs, rhs}));
|
const auto result = IR::U1(ir.Emit(operation, {lhs, rhs}));
|
||||||
WriteMask(inst.dst, old);
|
if (write_64) {
|
||||||
|
WriteMask64(inst.dst, old);
|
||||||
|
} else {
|
||||||
|
WriteMask(inst.dst, old);
|
||||||
|
}
|
||||||
const auto mask = BallotMask(result);
|
const auto mask = BallotMask(result);
|
||||||
ir.SetExec(result);
|
ir.SetExec(result);
|
||||||
ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
|
||||||
ir.SetExecLo(mask[0]);
|
ir.SetExecLo(mask[0]);
|
||||||
ir.SetExecHi(mask[1]);
|
ir.SetExecHi(mask[1]);
|
||||||
ir.SetScc(result);
|
ir.SetScc(result);
|
||||||
@@ -201,21 +191,30 @@ void Translator::S_CSELECT_B32(const Decoder::Instruction& inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Translator::S_CSELECT_B64(const Decoder::Instruction& inst) {
|
void Translator::S_CSELECT_B64(const Decoder::Instruction& inst) {
|
||||||
const auto condition = ir.GetScc();
|
const auto condition = ir.GetScc();
|
||||||
const auto lhs = ReadScalarU64(inst.src0);
|
const auto lhs = ReadU32Pair(inst.src0);
|
||||||
const auto rhs = ReadScalarU64(inst.src1);
|
const auto rhs = ReadU32Pair(inst.src1);
|
||||||
WriteScalarU64(inst.dst, SelectScalarU64(condition, lhs, rhs));
|
const auto selected_mask = IR::U1(
|
||||||
|
ir.Emit(IR::ValueOpcode::SelectU1, {condition, ReadMask(inst.src0), ReadMask(inst.src1)}));
|
||||||
|
const auto selected_mask_valid =
|
||||||
|
IR::U1(ir.Emit(IR::ValueOpcode::SelectU1,
|
||||||
|
{condition, ReadMaskValid(inst.src0), ReadMaskValid(inst.src1)}));
|
||||||
|
if (IsExecOrVcc(inst.dst)) {
|
||||||
|
WriteMask64(inst.dst, selected_mask);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
WriteU32Pair(inst.dst,
|
||||||
|
{ir.Select(condition, lhs[0], rhs[0]), ir.Select(condition, lhs[1], rhs[1])});
|
||||||
|
if (inst.dst.kind == Decoder::OperandKind::Sgpr) {
|
||||||
|
const auto dst = static_cast<IR::ScalarReg>(inst.dst.reg);
|
||||||
|
ir.SetThreadBitScalarReg(dst, selected_mask);
|
||||||
|
ir.SetScalarMaskTag(dst, selected_mask_valid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::MOV_B32(const Decoder::Instruction& inst, bool apply_float_modifiers) {
|
void Translator::MOV_B32(const Decoder::Instruction& inst, bool apply_float_modifiers) {
|
||||||
if (inst.src0.kind == Decoder::OperandKind::Sgpr &&
|
|
||||||
inst.dst.kind == Decoder::OperandKind::Sgpr && inst.src0.reg == inst.dst.reg) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (IsExecOrVcc(inst.src0) && IsExecOrVcc(inst.dst)) {
|
if (IsExecOrVcc(inst.src0) && IsExecOrVcc(inst.dst)) {
|
||||||
if (inst.src0.kind != inst.dst.kind) {
|
WriteMask(inst.dst, ReadMask(inst.src0));
|
||||||
WriteRawU32(inst.dst, ReadRawU32(inst.src0));
|
|
||||||
}
|
|
||||||
} else if (apply_float_modifiers && (inst.src0.negate || inst.src0.absolute)) {
|
} else if (apply_float_modifiers && (inst.src0.negate || inst.src0.absolute)) {
|
||||||
WriteOperand(DestinationOperand(inst), ReadOperand(inst.src0, IR::Type::F32));
|
WriteOperand(DestinationOperand(inst), ReadOperand(inst.src0, IR::Type::F32));
|
||||||
} else {
|
} else {
|
||||||
@@ -224,17 +223,50 @@ void Translator::MOV_B32(const Decoder::Instruction& inst, bool apply_float_modi
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Translator::S_MOV_B64(const Decoder::Instruction& inst) {
|
void Translator::S_MOV_B64(const Decoder::Instruction& inst) {
|
||||||
WriteScalarU64(inst.dst, ReadScalarU64(inst.src0));
|
if (IsExecOrVcc(inst.dst) || IsExecOrVcc(inst.src0)) {
|
||||||
|
WriteMask64(inst.dst, ReadMask(inst.src0));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const bool scalar_copy =
|
||||||
|
inst.dst.kind == Decoder::OperandKind::Sgpr && inst.src0.kind == Decoder::OperandKind::Sgpr;
|
||||||
|
IR::U1 source_mask;
|
||||||
|
IR::U1 source_mask_valid;
|
||||||
|
if (scalar_copy) {
|
||||||
|
source_mask = ir.GetThreadBitScalarReg(static_cast<IR::ScalarReg>(inst.src0.reg));
|
||||||
|
source_mask_valid = ir.GetScalarMaskTag(static_cast<IR::ScalarReg>(inst.src0.reg));
|
||||||
|
}
|
||||||
|
WriteU32Pair(inst.dst, ReadU32Pair(inst.src0));
|
||||||
|
if (scalar_copy) {
|
||||||
|
ir.SetThreadBitScalarReg(static_cast<IR::ScalarReg>(inst.dst.reg), source_mask);
|
||||||
|
ir.SetScalarMaskTag(static_cast<IR::ScalarReg>(inst.dst.reg), source_mask_valid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::S_WQM_B64(const Decoder::Instruction& inst) {
|
void Translator::S_WQM_B64(const Decoder::Instruction& inst) {
|
||||||
const auto source = ReadScalarU64(inst.src0);
|
if (!IsExecOrVcc(inst.dst) && !IsExecOrVcc(inst.src0)) {
|
||||||
const auto raw = ExtractU64(
|
const auto mask_valid = ReadMaskValid(inst.src0);
|
||||||
IR::U64(ir.Emit(IR::ValueOpcode::WqmU64, {ir.ConstructU64(source.raw[0], source.raw[1])})));
|
const auto invocation_result =
|
||||||
const auto invocation = IR::U1(ir.Emit(IR::ValueOpcode::WqmMask, {source.invocation}));
|
IR::U1(ir.Emit(IR::ValueOpcode::WqmMask, {ReadMask(inst.src0)}));
|
||||||
const auto result = MakeScalarU64Result(raw, invocation, source.mask_valid);
|
const auto result =
|
||||||
WriteScalarU64(inst.dst, result);
|
IR::U64(ir.Emit(IR::ValueOpcode::WqmU64, {ReadOperand(inst.src0, IR::Type::U64)}));
|
||||||
ir.SetScc(ScalarU64NonZero(result));
|
WriteOperand(DestinationOperand(inst), result);
|
||||||
|
if (inst.dst.kind == Decoder::OperandKind::Sgpr) {
|
||||||
|
const auto dst = static_cast<IR::ScalarReg>(inst.dst.reg);
|
||||||
|
ir.SetThreadBitScalarReg(dst, invocation_result);
|
||||||
|
ir.SetScalarMaskTag(dst, mask_valid);
|
||||||
|
const auto raw_nonzero =
|
||||||
|
IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})}));
|
||||||
|
ir.SetScc(IR::U1(
|
||||||
|
ir.Emit(IR::ValueOpcode::SelectU1, {mask_valid, invocation_result, raw_nonzero})));
|
||||||
|
} else {
|
||||||
|
ir.SetScc(
|
||||||
|
IR::U1(ir.Emit(IR::ValueOpcode::INotEqual64, {result, IR::Value(uint64_t {0})})));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto result = IR::U1(ir.Emit(IR::ValueOpcode::WqmMask, {ReadMask(inst.src0)}));
|
||||||
|
WriteMask64(inst.dst, result);
|
||||||
|
ir.SetScc(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::V_MOVRELS_B32(const Decoder::Instruction& inst) {
|
void Translator::V_MOVRELS_B32(const Decoder::Instruction& inst) {
|
||||||
|
|||||||
@@ -77,15 +77,68 @@ bool Translator::PackedInteger16MinMax(const Decoder::Instruction& inst, IR::Val
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IR::U1 Translator::U64MaskBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
|
||||||
|
bool negate_rhs, bool negate_result) {
|
||||||
|
const auto lhs = ReadMask(inst.src0);
|
||||||
|
auto rhs = ReadMask(inst.src1);
|
||||||
|
if (negate_rhs) {
|
||||||
|
rhs = ir.LogicalNot(rhs);
|
||||||
|
}
|
||||||
|
auto result = IR::U1(ir.Emit(opcode, {lhs, rhs}));
|
||||||
|
return negate_result ? ir.LogicalNot(result) : result;
|
||||||
|
}
|
||||||
|
|
||||||
bool Translator::S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode,
|
bool Translator::S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode,
|
||||||
IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result,
|
IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result,
|
||||||
bool unary) {
|
bool unary) {
|
||||||
const auto lhs = ReadScalarU64(inst.src0);
|
const auto invocation_result =
|
||||||
const auto result = unary ? NotScalarU64(lhs)
|
unary ? ir.LogicalNot(ReadMask(inst.src0))
|
||||||
: BinaryScalarU64(lhs, ReadScalarU64(inst.src1), logical_opcode,
|
: U64MaskBinary(inst, logical_opcode, negate_rhs, negate_result);
|
||||||
bit_opcode, false, negate_rhs, negate_result);
|
const auto is_exec_or_vcc = [](const Decoder::Operand& operand) {
|
||||||
WriteScalarU64(inst.dst, result);
|
switch (operand.kind) {
|
||||||
ir.SetScc(ScalarU64NonZero(result));
|
case Decoder::OperandKind::ExecLo:
|
||||||
|
case Decoder::OperandKind::ExecHi:
|
||||||
|
case Decoder::OperandKind::VccLo:
|
||||||
|
case Decoder::OperandKind::VccHi: return true;
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (is_exec_or_vcc(inst.dst) || is_exec_or_vcc(inst.src0) ||
|
||||||
|
(inst.src_count > 1u && is_exec_or_vcc(inst.src1))) {
|
||||||
|
WriteMask64(inst.dst, invocation_result);
|
||||||
|
ir.SetScc(invocation_result);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto lhs = ReadU32Pair(inst.src0);
|
||||||
|
auto mask_valid = ReadMaskValid(inst.src0);
|
||||||
|
if (inst.src_count > 1u) {
|
||||||
|
mask_valid = ir.LogicalAnd(mask_valid, ReadMaskValid(inst.src1));
|
||||||
|
}
|
||||||
|
std::array<IR::U32, 2> result;
|
||||||
|
if (unary) {
|
||||||
|
result = {ir.BitwiseNot(lhs[0]), ir.BitwiseNot(lhs[1])};
|
||||||
|
} else {
|
||||||
|
const auto rhs = ReadU32Pair(inst.src1);
|
||||||
|
for (uint32_t component = 0; component < 2u; component++) {
|
||||||
|
auto value = ir.Emit(
|
||||||
|
bit_opcode, {lhs[component], negate_rhs ? IR::Value(ir.BitwiseNot(rhs[component]))
|
||||||
|
: IR::Value(rhs[component])});
|
||||||
|
result[component] = negate_result ? ir.BitwiseNot(IR::U32(value)) : IR::U32(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WriteU32Pair(inst.dst, result);
|
||||||
|
if (inst.dst.kind == Decoder::OperandKind::Sgpr) {
|
||||||
|
const auto dst = static_cast<IR::ScalarReg>(inst.dst.reg);
|
||||||
|
ir.SetThreadBitScalarReg(dst, invocation_result);
|
||||||
|
ir.SetScalarMaskTag(dst, mask_valid);
|
||||||
|
const auto raw_nonzero =
|
||||||
|
ir.INotEqual(ir.BitwiseOr(result[0], result[1]), IR::U32(IR::Value(0u)));
|
||||||
|
ir.SetScc(IR::U1(
|
||||||
|
ir.Emit(IR::ValueOpcode::SelectU1, {mask_valid, invocation_result, raw_nonzero})));
|
||||||
|
} else {
|
||||||
|
ir.SetScc(ir.INotEqual(ir.BitwiseOr(result[0], result[1]), IR::U32(IR::Value(0u))));
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,14 +55,11 @@ uint32_t ResourceIndexFromOperand(const Decoder::Operand& operand) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Decoder::Operand RawScalarLoadBase(const Decoder::Operand& operand) {
|
uint32_t RawScalarLoadBase(const Decoder::Operand& operand) {
|
||||||
if (operand.kind != Decoder::OperandKind::M0) {
|
if (operand.kind == Decoder::OperandKind::Sgpr) {
|
||||||
return operand;
|
return operand.reg;
|
||||||
}
|
}
|
||||||
auto result = operand;
|
return operand.kind == Decoder::OperandKind::VccLo ? 106u : 0u;
|
||||||
// The compressed SBASE value 62 decodes as code 124, but means NULL for S_LOAD.
|
|
||||||
result.kind = Decoder::OperandKind::Null;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceKind FlatSegmentResourceKind(uint32_t segment) {
|
ResourceKind FlatSegmentResourceKind(uint32_t segment) {
|
||||||
@@ -322,9 +319,8 @@ Translator::AddressOperands Translator::ReadAddressOperands(const Decoder::Instr
|
|||||||
return {GetAddressResource(low, high), low, high};
|
return {GetAddressResource(low, high), low, high};
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::Value Translator::GetScalarAddressResource(const Decoder::Operand& base) {
|
IR::Value Translator::GetScalarAddressResource(uint32_t base) {
|
||||||
const auto raw = ReadU32Pair(base);
|
return GetAddressResource(ReadScalarCode(base), ReadScalarCode(base + 1u));
|
||||||
return GetAddressResource(raw[0], raw[1]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IR::Value Translator::GetImageResource(const IR::MemoryInfo& memory) {
|
IR::Value Translator::GetImageResource(const IR::MemoryInfo& memory) {
|
||||||
|
|||||||
@@ -151,8 +151,11 @@ IR::U32 Translator::ReadScalarCode(uint32_t code) {
|
|||||||
case 106u: return ir.GetVccLo();
|
case 106u: return ir.GetVccLo();
|
||||||
case 107u: return ir.GetVccHi();
|
case 107u: return ir.GetVccHi();
|
||||||
case 124u: return ir.GetM0();
|
case 124u: return ir.GetM0();
|
||||||
case 126u: return ir.GetExecLo();
|
case 126u:
|
||||||
case 127u: return ir.GetExecHi();
|
case 127u: {
|
||||||
|
const auto mask = BallotMask(ir.GetExec());
|
||||||
|
return mask[code - 126u];
|
||||||
|
}
|
||||||
default: return IR::U32(IR::Value(0u));
|
default: return IR::U32(IR::Value(0u));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,23 +315,19 @@ void Translator::WriteRawU32(const Decoder::Operand& operand, IR::U32 value) {
|
|||||||
case Decoder::OperandKind::VccLo:
|
case Decoder::OperandKind::VccLo:
|
||||||
ir.SetVccLo(IR::U32(value));
|
ir.SetVccLo(IR::U32(value));
|
||||||
ir.SetVcc(ThreadBit(IR::U32(value)));
|
ir.SetVcc(ThreadBit(IR::U32(value)));
|
||||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(false)));
|
|
||||||
break;
|
break;
|
||||||
case Decoder::OperandKind::VccHi:
|
case Decoder::OperandKind::VccHi:
|
||||||
ir.SetVccHi(IR::U32(value));
|
ir.SetVccHi(IR::U32(value));
|
||||||
ir.SetVcc(ThreadBit(ir.GetVccLo()));
|
ir.SetVcc(ThreadBit(ir.GetVccLo()));
|
||||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(false)));
|
|
||||||
break;
|
break;
|
||||||
case Decoder::OperandKind::M0: ir.SetM0(IR::U32(value)); break;
|
case Decoder::OperandKind::M0: ir.SetM0(IR::U32(value)); break;
|
||||||
case Decoder::OperandKind::ExecLo:
|
case Decoder::OperandKind::ExecLo:
|
||||||
ir.SetExecLo(IR::U32(value));
|
ir.SetExecLo(IR::U32(value));
|
||||||
ir.SetExec(ThreadBit(IR::U32(value)));
|
ir.SetExec(ThreadBit(IR::U32(value)));
|
||||||
ir.SetExecMaskTag(IR::U1(IR::Value(false)));
|
|
||||||
break;
|
break;
|
||||||
case Decoder::OperandKind::ExecHi:
|
case Decoder::OperandKind::ExecHi:
|
||||||
ir.SetExecHi(IR::U32(value));
|
ir.SetExecHi(IR::U32(value));
|
||||||
ir.SetExec(ThreadBit(ir.GetExecLo()));
|
ir.SetExec(ThreadBit(ir.GetExecLo()));
|
||||||
ir.SetExecMaskTag(IR::U1(IR::Value(false)));
|
|
||||||
break;
|
break;
|
||||||
case Decoder::OperandKind::Scc:
|
case Decoder::OperandKind::Scc:
|
||||||
ir.SetScc(ir.INotEqual(value, IR::U32(IR::Value(0u))));
|
ir.SetScc(ir.INotEqual(value, IR::U32(IR::Value(0u))));
|
||||||
@@ -373,7 +372,6 @@ void Translator::WriteOperand(const Decoder::Operand& operand, IR::Value value)
|
|||||||
case Decoder::OperandKind::ExecHi: {
|
case Decoder::OperandKind::ExecHi: {
|
||||||
const auto mask = BallotMask(IR::U1(value));
|
const auto mask = BallotMask(IR::U1(value));
|
||||||
ir.SetExec(IR::U1(value));
|
ir.SetExec(IR::U1(value));
|
||||||
ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
|
||||||
ir.SetExecLo(mask[0]);
|
ir.SetExecLo(mask[0]);
|
||||||
ir.SetExecHi(mask[1]);
|
ir.SetExecHi(mask[1]);
|
||||||
return;
|
return;
|
||||||
@@ -382,7 +380,6 @@ void Translator::WriteOperand(const Decoder::Operand& operand, IR::Value value)
|
|||||||
case Decoder::OperandKind::VccHi: {
|
case Decoder::OperandKind::VccHi: {
|
||||||
const auto mask = BallotMask(IR::U1(value));
|
const auto mask = BallotMask(IR::U1(value));
|
||||||
ir.SetVcc(IR::U1(value));
|
ir.SetVcc(IR::U1(value));
|
||||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(true)));
|
|
||||||
ir.SetVccLo(mask[0]);
|
ir.SetVccLo(mask[0]);
|
||||||
ir.SetVccHi(mask[1]);
|
ir.SetVccHi(mask[1]);
|
||||||
return;
|
return;
|
||||||
@@ -583,13 +580,11 @@ void Translator::WriteU32Pair(const Decoder::Operand& operand,
|
|||||||
switch (operand.kind) {
|
switch (operand.kind) {
|
||||||
case Decoder::OperandKind::ExecLo:
|
case Decoder::OperandKind::ExecLo:
|
||||||
ir.SetExec(thread_bit);
|
ir.SetExec(thread_bit);
|
||||||
ir.SetExecMaskTag(IR::U1(IR::Value(false)));
|
|
||||||
ir.SetExecLo(value[0]);
|
ir.SetExecLo(value[0]);
|
||||||
ir.SetExecHi(value[1]);
|
ir.SetExecHi(value[1]);
|
||||||
return;
|
return;
|
||||||
case Decoder::OperandKind::VccLo:
|
case Decoder::OperandKind::VccLo:
|
||||||
ir.SetVcc(thread_bit);
|
ir.SetVcc(thread_bit);
|
||||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(false)));
|
|
||||||
ir.SetVccLo(value[0]);
|
ir.SetVccLo(value[0]);
|
||||||
ir.SetVccHi(value[1]);
|
ir.SetVccHi(value[1]);
|
||||||
return;
|
return;
|
||||||
@@ -600,87 +595,6 @@ void Translator::WriteU32Pair(const Decoder::Operand& operand,
|
|||||||
WriteRawU32(OffsetOperand(operand, 1), value[1]);
|
WriteRawU32(OffsetOperand(operand, 1), value[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Translator::ScalarU64 Translator::ReadScalarU64(const Decoder::Operand& operand) {
|
|
||||||
return {ReadU32Pair(operand), ReadMask(operand), ReadMaskValid(operand)};
|
|
||||||
}
|
|
||||||
|
|
||||||
Translator::ScalarU64 Translator::MakeScalarU64Mask(IR::U1 value) {
|
|
||||||
return {BallotMask(value), value, IR::U1(IR::Value(true))};
|
|
||||||
}
|
|
||||||
|
|
||||||
Translator::ScalarU64 Translator::MakeScalarU64Result(const std::array<IR::U32, 2>& raw,
|
|
||||||
IR::U1 invocation, IR::U1 mask_valid) {
|
|
||||||
return {raw,
|
|
||||||
IR::U1(ir.Emit(IR::ValueOpcode::SelectU1, {mask_valid, invocation, ThreadBit(raw[0])})),
|
|
||||||
mask_valid};
|
|
||||||
}
|
|
||||||
|
|
||||||
Translator::ScalarU64 Translator::SelectScalarU64(IR::U1 condition, const ScalarU64& lhs,
|
|
||||||
const ScalarU64& rhs) {
|
|
||||||
return {
|
|
||||||
{ir.Select(condition, lhs.raw[0], rhs.raw[0]),
|
|
||||||
ir.Select(condition, lhs.raw[1], rhs.raw[1])},
|
|
||||||
IR::U1(ir.Emit(IR::ValueOpcode::SelectU1, {condition, lhs.invocation, rhs.invocation})),
|
|
||||||
IR::U1(ir.Emit(IR::ValueOpcode::SelectU1, {condition, lhs.mask_valid, rhs.mask_valid}))};
|
|
||||||
}
|
|
||||||
|
|
||||||
Translator::ScalarU64 Translator::NotScalarU64(const ScalarU64& value) {
|
|
||||||
return MakeScalarU64Result({ir.BitwiseNot(value.raw[0]), ir.BitwiseNot(value.raw[1])},
|
|
||||||
ir.LogicalNot(value.invocation), value.mask_valid);
|
|
||||||
}
|
|
||||||
|
|
||||||
Translator::ScalarU64 Translator::BinaryScalarU64(const ScalarU64& lhs, const ScalarU64& rhs,
|
|
||||||
IR::ValueOpcode logical_opcode,
|
|
||||||
IR::ValueOpcode bit_opcode, bool negate_lhs,
|
|
||||||
bool negate_rhs, bool negate_result) {
|
|
||||||
auto lhs_mask = negate_lhs ? ir.LogicalNot(lhs.invocation) : lhs.invocation;
|
|
||||||
auto rhs_mask = negate_rhs ? ir.LogicalNot(rhs.invocation) : rhs.invocation;
|
|
||||||
auto mask = IR::U1(ir.Emit(logical_opcode, {lhs_mask, rhs_mask}));
|
|
||||||
if (negate_result) {
|
|
||||||
mask = ir.LogicalNot(mask);
|
|
||||||
}
|
|
||||||
std::array<IR::U32, 2> raw;
|
|
||||||
for (uint32_t component = 0; component < raw.size(); component++) {
|
|
||||||
auto lhs_raw = negate_lhs ? ir.BitwiseNot(lhs.raw[component]) : lhs.raw[component];
|
|
||||||
auto rhs_raw = negate_rhs ? ir.BitwiseNot(rhs.raw[component]) : rhs.raw[component];
|
|
||||||
raw[component] = IR::U32(ir.Emit(bit_opcode, {lhs_raw, rhs_raw}));
|
|
||||||
if (negate_result) {
|
|
||||||
raw[component] = ir.BitwiseNot(raw[component]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MakeScalarU64Result(raw, mask, ir.LogicalAnd(lhs.mask_valid, rhs.mask_valid));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Translator::WriteScalarU64(const Decoder::Operand& operand, const ScalarU64& value) {
|
|
||||||
WriteU32Pair(operand, value.raw);
|
|
||||||
switch (operand.kind) {
|
|
||||||
case Decoder::OperandKind::ExecLo:
|
|
||||||
case Decoder::OperandKind::ExecHi:
|
|
||||||
ir.SetExec(value.invocation);
|
|
||||||
ir.SetExecMaskTag(value.mask_valid);
|
|
||||||
break;
|
|
||||||
case Decoder::OperandKind::VccLo:
|
|
||||||
case Decoder::OperandKind::VccHi:
|
|
||||||
ir.SetVcc(value.invocation);
|
|
||||||
ir.SetVccMaskValidTag(value.mask_valid);
|
|
||||||
break;
|
|
||||||
case Decoder::OperandKind::Sgpr: {
|
|
||||||
const auto reg = static_cast<IR::ScalarReg>(operand.reg);
|
|
||||||
ir.SetThreadBitScalarReg(reg, value.invocation);
|
|
||||||
ir.SetScalarMaskTag(reg, value.mask_valid);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U1 Translator::ScalarU64NonZero(const ScalarU64& value) {
|
|
||||||
const auto raw_nonzero =
|
|
||||||
ir.INotEqual(ir.BitwiseOr(value.raw[0], value.raw[1]), IR::U32(IR::Value(0u)));
|
|
||||||
return IR::U1(
|
|
||||||
ir.Emit(IR::ValueOpcode::SelectU1, {value.mask_valid, value.invocation, raw_nonzero}));
|
|
||||||
}
|
|
||||||
|
|
||||||
IR::U1 Translator::ThreadBit(IR::U32 low) {
|
IR::U1 Translator::ThreadBit(IR::U32 low) {
|
||||||
return ir.INotEqual(low, IR::U32(IR::Value(0u)));
|
return ir.INotEqual(low, IR::U32(IR::Value(0u)));
|
||||||
}
|
}
|
||||||
@@ -736,9 +650,9 @@ IR::U1 Translator::ReadMaskValid(const Decoder::Operand& operand) {
|
|||||||
case Decoder::OperandKind::Sgpr:
|
case Decoder::OperandKind::Sgpr:
|
||||||
return ir.GetScalarMaskTag(static_cast<IR::ScalarReg>(operand.reg));
|
return ir.GetScalarMaskTag(static_cast<IR::ScalarReg>(operand.reg));
|
||||||
case Decoder::OperandKind::ExecLo:
|
case Decoder::OperandKind::ExecLo:
|
||||||
case Decoder::OperandKind::ExecHi: return ir.GetExecMaskTag();
|
case Decoder::OperandKind::ExecHi:
|
||||||
case Decoder::OperandKind::VccLo:
|
case Decoder::OperandKind::VccLo:
|
||||||
case Decoder::OperandKind::VccHi: return ir.GetVccMaskValidTag();
|
case Decoder::OperandKind::VccHi:
|
||||||
case Decoder::OperandKind::VccZ:
|
case Decoder::OperandKind::VccZ:
|
||||||
case Decoder::OperandKind::ExecZ:
|
case Decoder::OperandKind::ExecZ:
|
||||||
case Decoder::OperandKind::Scc: return IR::U1(IR::Value(true));
|
case Decoder::OperandKind::Scc: return IR::U1(IR::Value(true));
|
||||||
@@ -771,7 +685,6 @@ void Translator::WriteMask(const Decoder::Operand& operand, IR::U1 value) {
|
|||||||
case Decoder::OperandKind::ExecHi: {
|
case Decoder::OperandKind::ExecHi: {
|
||||||
const auto mask = BallotMask(value);
|
const auto mask = BallotMask(value);
|
||||||
ir.SetExec(value);
|
ir.SetExec(value);
|
||||||
ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
|
||||||
ir.SetExecLo(mask[0]);
|
ir.SetExecLo(mask[0]);
|
||||||
ir.SetExecHi(mask[1]);
|
ir.SetExecHi(mask[1]);
|
||||||
return;
|
return;
|
||||||
@@ -780,7 +693,6 @@ void Translator::WriteMask(const Decoder::Operand& operand, IR::U1 value) {
|
|||||||
case Decoder::OperandKind::VccHi: {
|
case Decoder::OperandKind::VccHi: {
|
||||||
const auto mask = BallotMask(value);
|
const auto mask = BallotMask(value);
|
||||||
ir.SetVcc(value);
|
ir.SetVcc(value);
|
||||||
ir.SetVccMaskValidTag(IR::U1(IR::Value(true)));
|
|
||||||
ir.SetVccLo(mask[0]);
|
ir.SetVccLo(mask[0]);
|
||||||
ir.SetVccHi(mask[1]);
|
ir.SetVccHi(mask[1]);
|
||||||
return;
|
return;
|
||||||
@@ -794,7 +706,25 @@ void Translator::WriteMask(const Decoder::Operand& operand, IR::U1 value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Translator::WriteMask64(const Decoder::Operand& operand, IR::U1 value) {
|
void Translator::WriteMask64(const Decoder::Operand& operand, IR::U1 value) {
|
||||||
WriteScalarU64(operand, MakeScalarU64Mask(value));
|
if (operand.kind != Decoder::OperandKind::Sgpr) {
|
||||||
|
WriteMask(operand, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto reg = static_cast<IR::ScalarReg>(operand.reg);
|
||||||
|
const auto mask = BallotMask(value);
|
||||||
|
ir.SetThreadBitScalarReg(reg, value);
|
||||||
|
ir.SetScalarMaskTag(reg, IR::U1(IR::Value(true)));
|
||||||
|
if (IR::RegIndex(reg) > 0u) {
|
||||||
|
ir.SetScalarMaskTag(static_cast<IR::ScalarReg>(IR::RegIndex(reg) - 1u),
|
||||||
|
IR::U1(IR::Value(false)));
|
||||||
|
}
|
||||||
|
ir.SetScalarReg(reg, mask[0]);
|
||||||
|
if (IR::RegIndex(reg) + 1u < IR::NumScalarRegs) {
|
||||||
|
const auto high = static_cast<IR::ScalarReg>(IR::RegIndex(reg) + 1u);
|
||||||
|
ir.SetScalarReg(high, mask[1]);
|
||||||
|
ir.SetThreadBitScalarReg(high, IR::U1(IR::Value(false)));
|
||||||
|
ir.SetScalarMaskTag(high, IR::U1(IR::Value(false)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::WriteCompareResult(const Decoder::Operand& operand, IR::U1 value) {
|
void Translator::WriteCompareResult(const Decoder::Operand& operand, IR::U1 value) {
|
||||||
@@ -1095,7 +1025,6 @@ IR::Program TranslateProgram(const Decoder::Program& decoded, const CFG::Graph&
|
|||||||
entry_ir.SetScalarMaskTag(reg, IR::U1(IR::Value(false)));
|
entry_ir.SetScalarMaskTag(reg, IR::U1(IR::Value(false)));
|
||||||
}
|
}
|
||||||
entry_ir.SetExec(IR::U1(IR::Value(true)));
|
entry_ir.SetExec(IR::U1(IR::Value(true)));
|
||||||
entry_ir.SetExecMaskTag(IR::U1(IR::Value(true)));
|
|
||||||
entry_ir.SetExecLo(IR::U32(IR::Value(1u)));
|
entry_ir.SetExecLo(IR::U32(IR::Value(1u)));
|
||||||
entry_ir.SetExecHi(IR::U32(IR::Value(0u)));
|
entry_ir.SetExecHi(IR::U32(IR::Value(0u)));
|
||||||
if (options.stage == ShaderType::Compute) {
|
if (options.stage == ShaderType::Compute) {
|
||||||
|
|||||||
@@ -19,14 +19,6 @@ public:
|
|||||||
void AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo& info);
|
void AddBranchCondition(const CFG::BasicBlock& source, IR::BlockInfo& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ScalarU64 {
|
|
||||||
std::array<IR::U32, 2> raw;
|
|
||||||
// Raw words and Kyty's per-invocation mask model remain independent.
|
|
||||||
// mask_valid selects invocation for logical consumers and SCC.
|
|
||||||
IR::U1 invocation;
|
|
||||||
IR::U1 mask_valid;
|
|
||||||
};
|
|
||||||
|
|
||||||
Decoder::Operand SourceAt(const Decoder::Instruction& inst, uint32_t index);
|
Decoder::Operand SourceAt(const Decoder::Instruction& inst, uint32_t index);
|
||||||
Decoder::Operand DestinationOperand(const Decoder::Instruction& inst);
|
Decoder::Operand DestinationOperand(const Decoder::Instruction& inst);
|
||||||
Decoder::Operand OffsetOperand(const Decoder::Operand& operand, uint32_t offset);
|
Decoder::Operand OffsetOperand(const Decoder::Operand& operand, uint32_t offset);
|
||||||
@@ -56,25 +48,14 @@ private:
|
|||||||
IR::U32 ReadU16AsU32(const Decoder::Operand& operand, bool sign_extend);
|
IR::U32 ReadU16AsU32(const Decoder::Operand& operand, bool sign_extend);
|
||||||
IR::U32 ReadF16LaneBits(const Decoder::Operand& operand, bool high_lane);
|
IR::U32 ReadF16LaneBits(const Decoder::Operand& operand, bool high_lane);
|
||||||
std::array<IR::U32, 2> ExtractU64(IR::U64 value);
|
std::array<IR::U32, 2> ExtractU64(IR::U64 value);
|
||||||
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
|
void WriteU32Pair(const Decoder::Operand& operand, const std::array<IR::U32, 2>& value);
|
||||||
ScalarU64 ReadScalarU64(const Decoder::Operand& operand);
|
IR::U1 ReadCondition(const Decoder::Operand& operand);
|
||||||
ScalarU64 MakeScalarU64Mask(IR::U1 value);
|
IR::U32 ConditionBit(const Decoder::Operand& operand);
|
||||||
ScalarU64 MakeScalarU64Result(const std::array<IR::U32, 2>& raw, IR::U1 invocation,
|
IR::U1 ReadMask(const Decoder::Operand& operand);
|
||||||
IR::U1 mask_valid);
|
IR::U1 ReadMaskValid(const Decoder::Operand& operand);
|
||||||
ScalarU64 SelectScalarU64(IR::U1 condition, const ScalarU64& lhs, const ScalarU64& rhs);
|
void WriteMask(const Decoder::Operand& operand, IR::U1 value);
|
||||||
ScalarU64 NotScalarU64(const ScalarU64& value);
|
void WriteMask64(const Decoder::Operand& operand, IR::U1 value);
|
||||||
ScalarU64 BinaryScalarU64(const ScalarU64& lhs, const ScalarU64& rhs,
|
void WriteCompareResult(const Decoder::Operand& operand, IR::U1 value);
|
||||||
IR::ValueOpcode logical_opcode, IR::ValueOpcode bit_opcode,
|
|
||||||
bool negate_lhs, bool negate_rhs, bool negate_result);
|
|
||||||
void WriteScalarU64(const Decoder::Operand& operand, const ScalarU64& value);
|
|
||||||
IR::U1 ScalarU64NonZero(const ScalarU64& value);
|
|
||||||
IR::U1 ReadCondition(const Decoder::Operand& operand);
|
|
||||||
IR::U32 ConditionBit(const Decoder::Operand& operand);
|
|
||||||
IR::U1 ReadMask(const Decoder::Operand& operand);
|
|
||||||
IR::U1 ReadMaskValid(const Decoder::Operand& operand);
|
|
||||||
void WriteMask(const Decoder::Operand& operand, IR::U1 value);
|
|
||||||
void WriteMask64(const Decoder::Operand& operand, IR::U1 value);
|
|
||||||
void WriteCompareResult(const Decoder::Operand& operand, IR::U1 value);
|
|
||||||
|
|
||||||
IR::MemoryFlags AddMemoryInfo(const IR::MemoryInfo& memory, uint32_t pc);
|
IR::MemoryFlags AddMemoryInfo(const IR::MemoryInfo& memory, uint32_t pc);
|
||||||
IR::ExportFlags AddExportInfo(const Decoder::Instruction& inst);
|
IR::ExportFlags AddExportInfo(const Decoder::Instruction& inst);
|
||||||
@@ -92,7 +73,7 @@ private:
|
|||||||
IR::U32 GetResourceDword(uint32_t index, uint32_t dword);
|
IR::U32 GetResourceDword(uint32_t index, uint32_t dword);
|
||||||
IR::Value GetBufferResource(const IR::MemoryInfo& memory);
|
IR::Value GetBufferResource(const IR::MemoryInfo& memory);
|
||||||
IR::Value GetAddressResource(IR::Value low, IR::Value high);
|
IR::Value GetAddressResource(IR::Value low, IR::Value high);
|
||||||
IR::Value GetScalarAddressResource(const Decoder::Operand& base);
|
IR::Value GetScalarAddressResource(uint32_t base);
|
||||||
IR::Value GetImageResource(const IR::MemoryInfo& memory);
|
IR::Value GetImageResource(const IR::MemoryInfo& memory);
|
||||||
IR::Value GetSamplerResource(const IR::MemoryInfo& memory);
|
IR::Value GetSamplerResource(const IR::MemoryInfo& memory);
|
||||||
IR::Value MakeImageAddress(const Decoder::Instruction& inst, const Decoder::Operand& base);
|
IR::Value MakeImageAddress(const Decoder::Instruction& inst, const Decoder::Operand& base);
|
||||||
@@ -194,6 +175,8 @@ private:
|
|||||||
bool PackedInteger16MinMax(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool sign);
|
bool PackedInteger16MinMax(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool sign);
|
||||||
bool S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode,
|
bool S_U64_MASK(const Decoder::Instruction& inst, IR::ValueOpcode logical_opcode,
|
||||||
IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result, bool unary);
|
IR::ValueOpcode bit_opcode, bool negate_rhs, bool negate_result, bool unary);
|
||||||
|
IR::U1 U64MaskBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool negate_rhs,
|
||||||
|
bool negate_result);
|
||||||
bool SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode opcode, IR::Type type,
|
bool SimpleInteger(const Decoder::Instruction& inst, IR::ValueOpcode opcode, IR::Type type,
|
||||||
bool reverse, bool mask_shift_count, bool update_scc);
|
bool reverse, bool mask_shift_count, bool update_scc);
|
||||||
bool ComposedIntegerBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
|
bool ComposedIntegerBinary(const Decoder::Instruction& inst, IR::ValueOpcode opcode,
|
||||||
|
|||||||
@@ -76,14 +76,6 @@ void IREmitter::SetExec(U1 value) {
|
|||||||
Emit(ValueOpcode::SetExec, {value});
|
Emit(ValueOpcode::SetExec, {value});
|
||||||
}
|
}
|
||||||
|
|
||||||
U1 IREmitter::GetExecMaskTag() {
|
|
||||||
return U1(Emit(ValueOpcode::GetExecMaskTag));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetExecMaskTag(U1 value) {
|
|
||||||
Emit(ValueOpcode::SetExecMaskTag, {value});
|
|
||||||
}
|
|
||||||
|
|
||||||
U32 IREmitter::GetExecLo() {
|
U32 IREmitter::GetExecLo() {
|
||||||
return U32(Emit(ValueOpcode::GetExecLo));
|
return U32(Emit(ValueOpcode::GetExecLo));
|
||||||
}
|
}
|
||||||
@@ -108,14 +100,6 @@ void IREmitter::SetVcc(U1 value) {
|
|||||||
Emit(ValueOpcode::SetVcc, {value});
|
Emit(ValueOpcode::SetVcc, {value});
|
||||||
}
|
}
|
||||||
|
|
||||||
U1 IREmitter::GetVccMaskValidTag() {
|
|
||||||
return U1(Emit(ValueOpcode::GetVccMaskValidTag));
|
|
||||||
}
|
|
||||||
|
|
||||||
void IREmitter::SetVccMaskValidTag(U1 value) {
|
|
||||||
Emit(ValueOpcode::SetVccMaskValidTag, {value});
|
|
||||||
}
|
|
||||||
|
|
||||||
U32 IREmitter::GetVccLo() {
|
U32 IREmitter::GetVccLo() {
|
||||||
return U32(Emit(ValueOpcode::GetVccLo));
|
return U32(Emit(ValueOpcode::GetVccLo));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,16 +39,12 @@ public:
|
|||||||
void SetScc(U1 value);
|
void SetScc(U1 value);
|
||||||
U1 GetExec();
|
U1 GetExec();
|
||||||
void SetExec(U1 value);
|
void SetExec(U1 value);
|
||||||
U1 GetExecMaskTag();
|
|
||||||
void SetExecMaskTag(U1 value);
|
|
||||||
U32 GetExecLo();
|
U32 GetExecLo();
|
||||||
void SetExecLo(U32 value);
|
void SetExecLo(U32 value);
|
||||||
U32 GetExecHi();
|
U32 GetExecHi();
|
||||||
void SetExecHi(U32 value);
|
void SetExecHi(U32 value);
|
||||||
U1 GetVcc();
|
U1 GetVcc();
|
||||||
void SetVcc(U1 value);
|
void SetVcc(U1 value);
|
||||||
U1 GetVccMaskValidTag();
|
|
||||||
void SetVccMaskValidTag(U1 value);
|
|
||||||
U32 GetVccLo();
|
U32 GetVccLo();
|
||||||
void SetVccLo(U32 value);
|
void SetVccLo(U32 value);
|
||||||
U32 GetVccHi();
|
U32 GetVccHi();
|
||||||
|
|||||||
@@ -33,16 +33,12 @@ bool IsRegisterStatePseudo(ValueOpcode opcode) {
|
|||||||
case ValueOpcode::SetScc:
|
case ValueOpcode::SetScc:
|
||||||
case ValueOpcode::GetExec:
|
case ValueOpcode::GetExec:
|
||||||
case ValueOpcode::SetExec:
|
case ValueOpcode::SetExec:
|
||||||
case ValueOpcode::GetExecMaskTag:
|
|
||||||
case ValueOpcode::SetExecMaskTag:
|
|
||||||
case ValueOpcode::GetExecLo:
|
case ValueOpcode::GetExecLo:
|
||||||
case ValueOpcode::SetExecLo:
|
case ValueOpcode::SetExecLo:
|
||||||
case ValueOpcode::GetExecHi:
|
case ValueOpcode::GetExecHi:
|
||||||
case ValueOpcode::SetExecHi:
|
case ValueOpcode::SetExecHi:
|
||||||
case ValueOpcode::GetVcc:
|
case ValueOpcode::GetVcc:
|
||||||
case ValueOpcode::SetVcc:
|
case ValueOpcode::SetVcc:
|
||||||
case ValueOpcode::GetVccMaskValidTag:
|
|
||||||
case ValueOpcode::SetVccMaskValidTag:
|
|
||||||
case ValueOpcode::GetVccLo:
|
case ValueOpcode::GetVccLo:
|
||||||
case ValueOpcode::SetVccLo:
|
case ValueOpcode::SetVccLo:
|
||||||
case ValueOpcode::GetVccHi:
|
case ValueOpcode::GetVccHi:
|
||||||
|
|||||||
@@ -23,16 +23,12 @@ VALUE_OPCODE(GetScc, U1)
|
|||||||
VALUE_OPCODE(SetScc, Void, U1)
|
VALUE_OPCODE(SetScc, Void, U1)
|
||||||
VALUE_OPCODE(GetExec, U1)
|
VALUE_OPCODE(GetExec, U1)
|
||||||
VALUE_OPCODE(SetExec, Void, U1)
|
VALUE_OPCODE(SetExec, Void, U1)
|
||||||
VALUE_OPCODE(GetExecMaskTag, U1)
|
|
||||||
VALUE_OPCODE(SetExecMaskTag, Void, U1)
|
|
||||||
VALUE_OPCODE(GetExecLo, U32)
|
VALUE_OPCODE(GetExecLo, U32)
|
||||||
VALUE_OPCODE(SetExecLo, Void, U32)
|
VALUE_OPCODE(SetExecLo, Void, U32)
|
||||||
VALUE_OPCODE(GetExecHi, U32)
|
VALUE_OPCODE(GetExecHi, U32)
|
||||||
VALUE_OPCODE(SetExecHi, Void, U32)
|
VALUE_OPCODE(SetExecHi, Void, U32)
|
||||||
VALUE_OPCODE(GetVcc, U1)
|
VALUE_OPCODE(GetVcc, U1)
|
||||||
VALUE_OPCODE(SetVcc, Void, U1)
|
VALUE_OPCODE(SetVcc, Void, U1)
|
||||||
VALUE_OPCODE(GetVccMaskValidTag, U1)
|
|
||||||
VALUE_OPCODE(SetVccMaskValidTag, Void, U1)
|
|
||||||
VALUE_OPCODE(GetVccLo, U32)
|
VALUE_OPCODE(GetVccLo, U32)
|
||||||
VALUE_OPCODE(SetVccLo, Void, U32)
|
VALUE_OPCODE(SetVccLo, Void, U32)
|
||||||
VALUE_OPCODE(GetVccHi, U32)
|
VALUE_OPCODE(GetVccHi, U32)
|
||||||
|
|||||||
@@ -22,9 +22,6 @@ struct ScalarMaskTag {
|
|||||||
struct ExecTag {
|
struct ExecTag {
|
||||||
auto operator<=>(const ExecTag&) const = default;
|
auto operator<=>(const ExecTag&) const = default;
|
||||||
};
|
};
|
||||||
struct ExecMaskTag {
|
|
||||||
auto operator<=>(const ExecMaskTag&) const = default;
|
|
||||||
};
|
|
||||||
struct ExecLoTag {
|
struct ExecLoTag {
|
||||||
auto operator<=>(const ExecLoTag&) const = default;
|
auto operator<=>(const ExecLoTag&) const = default;
|
||||||
};
|
};
|
||||||
@@ -34,9 +31,6 @@ struct ExecHiTag {
|
|||||||
struct VccTag {
|
struct VccTag {
|
||||||
auto operator<=>(const VccTag&) const = default;
|
auto operator<=>(const VccTag&) const = default;
|
||||||
};
|
};
|
||||||
struct VccMaskValidTag {
|
|
||||||
auto operator<=>(const VccMaskValidTag&) const = default;
|
|
||||||
};
|
|
||||||
struct VccLoTag {
|
struct VccLoTag {
|
||||||
auto operator<=>(const VccLoTag&) const = default;
|
auto operator<=>(const VccLoTag&) const = default;
|
||||||
};
|
};
|
||||||
@@ -51,9 +45,9 @@ struct GotoVariable {
|
|||||||
auto operator<=>(const GotoVariable&) const = default;
|
auto operator<=>(const GotoVariable&) const = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Variable = std::variant<ScalarReg, ThreadBitScalarReg, ScalarMaskTag, VectorReg, GotoVariable,
|
using Variable =
|
||||||
SccTag, ExecTag, ExecMaskTag, ExecLoTag, ExecHiTag, VccTag,
|
std::variant<ScalarReg, ThreadBitScalarReg, ScalarMaskTag, VectorReg, GotoVariable, SccTag,
|
||||||
VccMaskValidTag, VccLoTag, VccHiTag, M0Tag>;
|
ExecTag, ExecLoTag, ExecHiTag, VccTag, VccLoTag, VccHiTag, M0Tag>;
|
||||||
using ValueMap = std::unordered_map<Block*, Value>;
|
using ValueMap = std::unordered_map<Block*, Value>;
|
||||||
|
|
||||||
struct DefTable {
|
struct DefTable {
|
||||||
@@ -105,16 +99,12 @@ struct DefTable {
|
|||||||
void Set(Block* block, SccTag, Value value) { scc[block] = value; }
|
void Set(Block* block, SccTag, Value value) { scc[block] = value; }
|
||||||
const Value& Get(Block* block, ExecTag) { return exec[block]; }
|
const Value& Get(Block* block, ExecTag) { return exec[block]; }
|
||||||
void Set(Block* block, ExecTag, Value value) { exec[block] = value; }
|
void Set(Block* block, ExecTag, Value value) { exec[block] = value; }
|
||||||
const Value& Get(Block* block, ExecMaskTag) { return exec_mask_tag[block]; }
|
|
||||||
void Set(Block* block, ExecMaskTag, Value value) { exec_mask_tag[block] = value; }
|
|
||||||
const Value& Get(Block* block, ExecLoTag) { return exec_lo[block]; }
|
const Value& Get(Block* block, ExecLoTag) { return exec_lo[block]; }
|
||||||
void Set(Block* block, ExecLoTag, Value value) { exec_lo[block] = value; }
|
void Set(Block* block, ExecLoTag, Value value) { exec_lo[block] = value; }
|
||||||
const Value& Get(Block* block, ExecHiTag) { return exec_hi[block]; }
|
const Value& Get(Block* block, ExecHiTag) { return exec_hi[block]; }
|
||||||
void Set(Block* block, ExecHiTag, Value value) { exec_hi[block] = value; }
|
void Set(Block* block, ExecHiTag, Value value) { exec_hi[block] = value; }
|
||||||
const Value& Get(Block* block, VccTag) { return vcc[block]; }
|
const Value& Get(Block* block, VccTag) { return vcc[block]; }
|
||||||
void Set(Block* block, VccTag, Value value) { vcc[block] = value; }
|
void Set(Block* block, VccTag, Value value) { vcc[block] = value; }
|
||||||
const Value& Get(Block* block, VccMaskValidTag) { return vcc_mask_valid_tag[block]; }
|
|
||||||
void Set(Block* block, VccMaskValidTag, Value value) { vcc_mask_valid_tag[block] = value; }
|
|
||||||
const Value& Get(Block* block, VccLoTag) { return vcc_lo[block]; }
|
const Value& Get(Block* block, VccLoTag) { return vcc_lo[block]; }
|
||||||
void Set(Block* block, VccLoTag, Value value) { vcc_lo[block] = value; }
|
void Set(Block* block, VccLoTag, Value value) { vcc_lo[block] = value; }
|
||||||
const Value& Get(Block* block, VccHiTag) { return vcc_hi[block]; }
|
const Value& Get(Block* block, VccHiTag) { return vcc_hi[block]; }
|
||||||
@@ -124,11 +114,9 @@ struct DefTable {
|
|||||||
|
|
||||||
ValueMap scc;
|
ValueMap scc;
|
||||||
ValueMap exec;
|
ValueMap exec;
|
||||||
ValueMap exec_mask_tag;
|
|
||||||
ValueMap exec_lo;
|
ValueMap exec_lo;
|
||||||
ValueMap exec_hi;
|
ValueMap exec_hi;
|
||||||
ValueMap vcc;
|
ValueMap vcc;
|
||||||
ValueMap vcc_mask_valid_tag;
|
|
||||||
ValueMap vcc_lo;
|
ValueMap vcc_lo;
|
||||||
ValueMap vcc_hi;
|
ValueMap vcc_hi;
|
||||||
ValueMap m0;
|
ValueMap m0;
|
||||||
@@ -156,9 +144,6 @@ ValueOpcode UndefOpcode(SccTag) {
|
|||||||
ValueOpcode UndefOpcode(ExecTag) {
|
ValueOpcode UndefOpcode(ExecTag) {
|
||||||
return ValueOpcode::UndefU1;
|
return ValueOpcode::UndefU1;
|
||||||
}
|
}
|
||||||
ValueOpcode UndefOpcode(ExecMaskTag) {
|
|
||||||
return ValueOpcode::UndefU1;
|
|
||||||
}
|
|
||||||
ValueOpcode UndefOpcode(ExecLoTag) {
|
ValueOpcode UndefOpcode(ExecLoTag) {
|
||||||
return ValueOpcode::UndefU32;
|
return ValueOpcode::UndefU32;
|
||||||
}
|
}
|
||||||
@@ -168,9 +153,6 @@ ValueOpcode UndefOpcode(ExecHiTag) {
|
|||||||
ValueOpcode UndefOpcode(VccTag) {
|
ValueOpcode UndefOpcode(VccTag) {
|
||||||
return ValueOpcode::UndefU1;
|
return ValueOpcode::UndefU1;
|
||||||
}
|
}
|
||||||
ValueOpcode UndefOpcode(VccMaskValidTag) {
|
|
||||||
return ValueOpcode::UndefU1;
|
|
||||||
}
|
|
||||||
ValueOpcode UndefOpcode(VccLoTag) {
|
ValueOpcode UndefOpcode(VccLoTag) {
|
||||||
return ValueOpcode::UndefU32;
|
return ValueOpcode::UndefU32;
|
||||||
}
|
}
|
||||||
@@ -202,9 +184,6 @@ Value InitialValue(SccTag) {
|
|||||||
Value InitialValue(ExecTag) {
|
Value InitialValue(ExecTag) {
|
||||||
return Value(false);
|
return Value(false);
|
||||||
}
|
}
|
||||||
Value InitialValue(ExecMaskTag) {
|
|
||||||
return Value(false);
|
|
||||||
}
|
|
||||||
Value InitialValue(ExecLoTag) {
|
Value InitialValue(ExecLoTag) {
|
||||||
return Value(0u);
|
return Value(0u);
|
||||||
}
|
}
|
||||||
@@ -214,9 +193,6 @@ Value InitialValue(ExecHiTag) {
|
|||||||
Value InitialValue(VccTag) {
|
Value InitialValue(VccTag) {
|
||||||
return Value(false);
|
return Value(false);
|
||||||
}
|
}
|
||||||
Value InitialValue(VccMaskValidTag) {
|
|
||||||
return Value(false);
|
|
||||||
}
|
|
||||||
Value InitialValue(VccLoTag) {
|
Value InitialValue(VccLoTag) {
|
||||||
return Value(0u);
|
return Value(0u);
|
||||||
}
|
}
|
||||||
@@ -375,15 +351,9 @@ void VisitInstruction(Pass& pass, Block* block, Inst& inst) {
|
|||||||
break;
|
break;
|
||||||
case ValueOpcode::SetScc: pass.Write(SccTag {}, block, inst.Arg(0)); break;
|
case ValueOpcode::SetScc: pass.Write(SccTag {}, block, inst.Arg(0)); break;
|
||||||
case ValueOpcode::SetExec: pass.Write(ExecTag {}, block, inst.Arg(0)); break;
|
case ValueOpcode::SetExec: pass.Write(ExecTag {}, block, inst.Arg(0)); break;
|
||||||
case ValueOpcode::SetExecMaskTag:
|
|
||||||
pass.Write(ExecMaskTag {}, block, inst.Arg(0));
|
|
||||||
break;
|
|
||||||
case ValueOpcode::SetExecLo: pass.Write(ExecLoTag {}, block, inst.Arg(0)); break;
|
case ValueOpcode::SetExecLo: pass.Write(ExecLoTag {}, block, inst.Arg(0)); break;
|
||||||
case ValueOpcode::SetExecHi: pass.Write(ExecHiTag {}, block, inst.Arg(0)); break;
|
case ValueOpcode::SetExecHi: pass.Write(ExecHiTag {}, block, inst.Arg(0)); break;
|
||||||
case ValueOpcode::SetVcc: pass.Write(VccTag {}, block, inst.Arg(0)); break;
|
case ValueOpcode::SetVcc: pass.Write(VccTag {}, block, inst.Arg(0)); break;
|
||||||
case ValueOpcode::SetVccMaskValidTag:
|
|
||||||
pass.Write(VccMaskValidTag {}, block, inst.Arg(0));
|
|
||||||
break;
|
|
||||||
case ValueOpcode::SetVccLo: pass.Write(VccLoTag {}, block, inst.Arg(0)); break;
|
case ValueOpcode::SetVccLo: pass.Write(VccLoTag {}, block, inst.Arg(0)); break;
|
||||||
case ValueOpcode::SetVccHi: pass.Write(VccHiTag {}, block, inst.Arg(0)); break;
|
case ValueOpcode::SetVccHi: pass.Write(VccHiTag {}, block, inst.Arg(0)); break;
|
||||||
case ValueOpcode::SetM0: pass.Write(M0Tag {}, block, inst.Arg(0)); break;
|
case ValueOpcode::SetM0: pass.Write(M0Tag {}, block, inst.Arg(0)); break;
|
||||||
@@ -405,15 +375,9 @@ void VisitInstruction(Pass& pass, Block* block, Inst& inst) {
|
|||||||
break;
|
break;
|
||||||
case ValueOpcode::GetScc: inst.ReplaceUsesWith(pass.Read(SccTag {}, block)); break;
|
case ValueOpcode::GetScc: inst.ReplaceUsesWith(pass.Read(SccTag {}, block)); break;
|
||||||
case ValueOpcode::GetExec: inst.ReplaceUsesWith(pass.Read(ExecTag {}, block)); break;
|
case ValueOpcode::GetExec: inst.ReplaceUsesWith(pass.Read(ExecTag {}, block)); break;
|
||||||
case ValueOpcode::GetExecMaskTag:
|
|
||||||
inst.ReplaceUsesWith(pass.Read(ExecMaskTag {}, block));
|
|
||||||
break;
|
|
||||||
case ValueOpcode::GetExecLo: inst.ReplaceUsesWith(pass.Read(ExecLoTag {}, block)); break;
|
case ValueOpcode::GetExecLo: inst.ReplaceUsesWith(pass.Read(ExecLoTag {}, block)); break;
|
||||||
case ValueOpcode::GetExecHi: inst.ReplaceUsesWith(pass.Read(ExecHiTag {}, block)); break;
|
case ValueOpcode::GetExecHi: inst.ReplaceUsesWith(pass.Read(ExecHiTag {}, block)); break;
|
||||||
case ValueOpcode::GetVcc: inst.ReplaceUsesWith(pass.Read(VccTag {}, block)); break;
|
case ValueOpcode::GetVcc: inst.ReplaceUsesWith(pass.Read(VccTag {}, block)); break;
|
||||||
case ValueOpcode::GetVccMaskValidTag:
|
|
||||||
inst.ReplaceUsesWith(pass.Read(VccMaskValidTag {}, block));
|
|
||||||
break;
|
|
||||||
case ValueOpcode::GetVccLo: inst.ReplaceUsesWith(pass.Read(VccLoTag {}, block)); break;
|
case ValueOpcode::GetVccLo: inst.ReplaceUsesWith(pass.Read(VccLoTag {}, block)); break;
|
||||||
case ValueOpcode::GetVccHi: inst.ReplaceUsesWith(pass.Read(VccHiTag {}, block)); break;
|
case ValueOpcode::GetVccHi: inst.ReplaceUsesWith(pass.Read(VccHiTag {}, block)); break;
|
||||||
case ValueOpcode::GetM0: inst.ReplaceUsesWith(pass.Read(M0Tag {}, block)); break;
|
case ValueOpcode::GetM0: inst.ReplaceUsesWith(pass.Read(M0Tag {}, block)); break;
|
||||||
|
|||||||
@@ -12840,160 +12840,6 @@ TestCase ScalarNotB64UpdatesScc() {
|
|||||||
O::S_ENDPGM}};
|
O::S_ENDPGM}};
|
||||||
}
|
}
|
||||||
|
|
||||||
TestCase ScalarMovB64PreservesRawSpecialData() {
|
|
||||||
using O = ShaderOpcode;
|
|
||||||
|
|
||||||
std::vector<u32> code;
|
|
||||||
AppendSMovLiteral(&code, 0, 0x09500000u);
|
|
||||||
AppendSMovLiteral(&code, 1, 0x81234567u);
|
|
||||||
code.push_back(EncodeSop1(0x04, 106, 0)); // s_mov_b64 vcc, s[0:1]
|
|
||||||
code.push_back(EncodeSop1(0x04, 2, 106)); // s_mov_b64 s[2:3], vcc
|
|
||||||
code.push_back(EncodeSop1(0x08, 4, 2)); // s_not_b64 s[4:5], s[2:3]
|
|
||||||
code.push_back(EncodeSop2(0x0a, 6, InlineU32(1), InlineU32(0)));
|
|
||||||
|
|
||||||
AppendStoreSgprPair(&code, 2, 0);
|
|
||||||
AppendStoreSgprPair(&code, 4, 2);
|
|
||||||
AppendStoreSgpr(&code, 6, 4);
|
|
||||||
|
|
||||||
AppendSMovLiteral(&code, 8, 0x09500001u);
|
|
||||||
AppendSMovLiteral(&code, 9, 0x81234567u);
|
|
||||||
code.push_back(EncodeSop1(0x04, 126, 8)); // s_mov_b64 exec, s[8:9]
|
|
||||||
code.push_back(EncodeSop1(0x04, 10, 126)); // s_mov_b64 s[10:11], exec
|
|
||||||
code.push_back(EncodeSop1(0x08, 12, 10)); // s_not_b64 s[12:13], s[10:11]
|
|
||||||
code.push_back(EncodeSop2(0x0a, 14, InlineU32(1), InlineU32(0)));
|
|
||||||
|
|
||||||
AppendStoreSgprPair(&code, 10, 5);
|
|
||||||
AppendStoreSgprPair(&code, 12, 7);
|
|
||||||
AppendStoreSgpr(&code, 14, 9);
|
|
||||||
AppendEnd(&code);
|
|
||||||
|
|
||||||
return {"ScalarMovB64PreservesRawSpecialData",
|
|
||||||
code,
|
|
||||||
{},
|
|
||||||
{0x09500000u, 0x81234567u, 0xf6afffffu, 0x7edcba98u, 1u,
|
|
||||||
0x09500001u, 0x81234567u, 0xf6affffeu, 0x7edcba98u, 1u},
|
|
||||||
{O::S_MOV_B32, O::S_MOV_B64, O::S_NOT_B64, O::S_CSELECT_B32,
|
|
||||||
O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
|
||||||
}
|
|
||||||
|
|
||||||
TestCase Scalar64RawSpecialOps() {
|
|
||||||
using O = ShaderOpcode;
|
|
||||||
|
|
||||||
std::vector<u32> code;
|
|
||||||
const auto capture_scc = [&](u32 dst) {
|
|
||||||
code.push_back(EncodeSop2(0x0a, dst, InlineU32(1), InlineU32(0)));
|
|
||||||
};
|
|
||||||
|
|
||||||
AppendSMovLiteral(&code, 0, 0x09500001u);
|
|
||||||
AppendSMovLiteral(&code, 1, 0x81234567u);
|
|
||||||
AppendSMovLiteral(&code, 2, 0xff00ff01u);
|
|
||||||
AppendSMovLiteral(&code, 3, 0x0f0f0f0fu);
|
|
||||||
code.push_back(EncodeSop1(0x04, 126, 0));
|
|
||||||
code.push_back(EncodeSop2(0x0f, 106, 126, 2));
|
|
||||||
code.push_back(EncodeSop1(0x04, 4, 106));
|
|
||||||
capture_scc(6);
|
|
||||||
code.push_back(EncodeSop1(0x08, 106, 106));
|
|
||||||
code.push_back(EncodeSop1(0x04, 8, 106));
|
|
||||||
capture_scc(10);
|
|
||||||
|
|
||||||
AppendSMovLiteral(&code, 12, 0x80000011u);
|
|
||||||
AppendSMovLiteral(&code, 13, 0x80000001u);
|
|
||||||
code.push_back(EncodeSop1(0x04, 106, 12));
|
|
||||||
code.push_back(EncodeSop1(0x0a, 106, 106));
|
|
||||||
code.push_back(EncodeSop1(0x04, 14, 106));
|
|
||||||
capture_scc(16);
|
|
||||||
|
|
||||||
code.push_back(EncodeSop1(0x0a, 26, 193u));
|
|
||||||
capture_scc(28);
|
|
||||||
|
|
||||||
code.push_back(EncodeSMovB32(18, InlineU32(1)));
|
|
||||||
code.push_back(EncodeSMovB32(19, InlineU32(0)));
|
|
||||||
code.push_back(EncodeSopc(0x06, InlineU32(1), InlineU32(1)));
|
|
||||||
code.push_back(EncodeSop2(0x0b, 126, 0, 18));
|
|
||||||
code.push_back(EncodeSop1(0x04, 20, 126));
|
|
||||||
code.push_back(EncodeSop1(0x08, 106, 126));
|
|
||||||
code.push_back(EncodeSop1(0x04, 22, 106));
|
|
||||||
capture_scc(24);
|
|
||||||
code.push_back(EncodeSop1(0x04, 126, 18));
|
|
||||||
|
|
||||||
AppendStoreSgprPair(&code, 4, 0);
|
|
||||||
AppendStoreSgpr(&code, 6, 2);
|
|
||||||
AppendStoreSgprPair(&code, 8, 3);
|
|
||||||
AppendStoreSgpr(&code, 10, 5);
|
|
||||||
AppendStoreSgprPair(&code, 14, 6);
|
|
||||||
AppendStoreSgpr(&code, 16, 8);
|
|
||||||
AppendStoreSgprPair(&code, 26, 9);
|
|
||||||
AppendStoreSgpr(&code, 28, 11);
|
|
||||||
AppendStoreSgprPair(&code, 20, 12);
|
|
||||||
AppendStoreSgprPair(&code, 22, 14);
|
|
||||||
AppendStoreSgpr(&code, 24, 16);
|
|
||||||
AppendEnd(&code);
|
|
||||||
|
|
||||||
return {"Scalar64RawSpecialOps",
|
|
||||||
code,
|
|
||||||
{},
|
|
||||||
{0x09000001u, 0x01030507u, 1, 0xf6fffffeu, 0xfefcfaf8u, 1,
|
|
||||||
0xf00000ffu, 0xf000000fu, 1, 0xffffffffu, 0xffffffffu, 1,
|
|
||||||
0x09500001u, 0x81234567u, 0xf6affffeu, 0x7edcba98u, 1},
|
|
||||||
{O::S_MOV_B32, O::S_MOV_B64, O::S_AND_B64, O::S_NOT_B64,
|
|
||||||
O::S_CSELECT_B32, O::S_WQM_B64, O::S_CMP_EQ_U32, O::S_CSELECT_B64,
|
|
||||||
O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
|
||||||
}
|
|
||||||
|
|
||||||
TestCase ScalarMovB32SpecialAliases() {
|
|
||||||
using O = ShaderOpcode;
|
|
||||||
|
|
||||||
std::vector<u32> code;
|
|
||||||
const auto capture_scc = [&](u32 dst) {
|
|
||||||
code.push_back(EncodeSop2(0x0a, dst, InlineU32(1), InlineU32(0)));
|
|
||||||
};
|
|
||||||
|
|
||||||
AppendSMovLiteral(&code, 0, 0x09500001u);
|
|
||||||
AppendSMovLiteral(&code, 1, 0x81234567u);
|
|
||||||
AppendSMovLiteral(&code, 2, 0xaaaaaaaau);
|
|
||||||
AppendSMovLiteral(&code, 3, 0xbbbbbbbbu);
|
|
||||||
code.push_back(EncodeSMovB32(4, InlineU32(1)));
|
|
||||||
code.push_back(EncodeSMovB32(5, InlineU32(0)));
|
|
||||||
code.push_back(EncodeSop1(0x04, 126, 0));
|
|
||||||
code.push_back(EncodeSop1(0x04, 106, 2));
|
|
||||||
code.push_back(EncodeSMovB32(107, 126));
|
|
||||||
code.push_back(EncodeSop1(0x04, 6, 106));
|
|
||||||
code.push_back(EncodeSop1(0x08, 8, 106));
|
|
||||||
capture_scc(10);
|
|
||||||
|
|
||||||
AppendSMovLiteral(&code, 12, 0x13579bdfu);
|
|
||||||
AppendSMovLiteral(&code, 13, 0x2468ace0u);
|
|
||||||
code.push_back(EncodeSop1(0x04, 106, 12));
|
|
||||||
code.push_back(EncodeSMovB32(126, 106));
|
|
||||||
code.push_back(EncodeSop1(0x04, 14, 126));
|
|
||||||
code.push_back(EncodeSop1(0x04, 126, 4));
|
|
||||||
|
|
||||||
code.push_back(EncodeVopc(0xc2, InlineU32(0), 0));
|
|
||||||
code.push_back(EncodeSMovB32(106, 106));
|
|
||||||
code.push_back(EncodeSop1(0x08, 16, 106));
|
|
||||||
capture_scc(18);
|
|
||||||
code.push_back(EncodeSop1(0x04, 20, 106));
|
|
||||||
code.push_back(EncodeSMovB32(20, 20));
|
|
||||||
code.push_back(EncodeSop1(0x08, 22, 20));
|
|
||||||
capture_scc(24);
|
|
||||||
|
|
||||||
AppendStoreSgprPair(&code, 6, 0);
|
|
||||||
AppendStoreSgprPair(&code, 8, 2);
|
|
||||||
AppendStoreSgpr(&code, 10, 4);
|
|
||||||
AppendStoreSgprPair(&code, 14, 5);
|
|
||||||
AppendStoreSgpr(&code, 18, 7);
|
|
||||||
AppendStoreSgpr(&code, 24, 8);
|
|
||||||
AppendEnd(&code);
|
|
||||||
|
|
||||||
return {"ScalarMovB32SpecialAliases",
|
|
||||||
code,
|
|
||||||
{},
|
|
||||||
{0xaaaaaaaau, 0x09500001u, 0x55555555u, 0xf6affffeu, 1, 0x13579bdfu,
|
|
||||||
0x81234567u, 0, 0},
|
|
||||||
{O::S_MOV_B32, O::S_MOV_B64, O::S_NOT_B64, O::S_CSELECT_B32,
|
|
||||||
O::V_CMP_EQ_U32, O::V_MOV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
|
||||||
}
|
|
||||||
|
|
||||||
TestCase ScalarQuadmaskB64() {
|
TestCase ScalarQuadmaskB64() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -13122,7 +12968,8 @@ TestCase ScalarSaveExecOps() {
|
|||||||
return {"ScalarSaveExecOps",
|
return {"ScalarSaveExecOps",
|
||||||
code,
|
code,
|
||||||
{},
|
{},
|
||||||
{1, 0, 1, 0, 0xffffffffu, 0xffffffffu, 1, 1, 0, 1, 0, 0, 0},
|
// EXEC and saved EXEC values are invocation-local Booleans.
|
||||||
|
{1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 0},
|
||||||
{O::S_MOV_B32, O::S_AND_SAVEEXEC_B64, O::S_ORN2_SAVEEXEC_B64,
|
{O::S_MOV_B32, O::S_AND_SAVEEXEC_B64, O::S_ORN2_SAVEEXEC_B64,
|
||||||
O::S_ANDN1_SAVEEXEC_B64, O::S_AND_SAVEEXEC_B32,
|
O::S_ANDN1_SAVEEXEC_B64, O::S_AND_SAVEEXEC_B32,
|
||||||
O::S_ANDN1_SAVEEXEC_B32, O::S_MOV_B64, O::V_MOV_B32,
|
O::S_ANDN1_SAVEEXEC_B32, O::S_MOV_B64, O::V_MOV_B32,
|
||||||
@@ -13149,7 +12996,7 @@ TestCase ScalarOrn2SaveexecUsesSourceOrNotExec() {
|
|||||||
return {"ScalarOrn2SaveexecUsesSourceOrNotExec",
|
return {"ScalarOrn2SaveexecUsesSourceOrNotExec",
|
||||||
code,
|
code,
|
||||||
{},
|
{},
|
||||||
{0x0000000cu, 0x80000000u, 0xfffffff3u, 0x7fffffffu, 1},
|
{1, 0, 1, 0, 1},
|
||||||
{O::S_MOV_B32, O::S_ORN2_SAVEEXEC_B64, O::S_MOV_B64, O::V_MOV_B32,
|
{O::S_MOV_B32, O::S_ORN2_SAVEEXEC_B64, O::S_MOV_B64, O::V_MOV_B32,
|
||||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||||
}
|
}
|
||||||
@@ -16835,30 +16682,6 @@ TestCase ScalarMemoryLoadVariants() {
|
|||||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||||
}
|
}
|
||||||
|
|
||||||
TestCase ScalarLoadUsesRawExecAddress() {
|
|
||||||
using O = ShaderOpcode;
|
|
||||||
|
|
||||||
std::vector<u32> code;
|
|
||||||
code.push_back(EncodeSMovB32(0, InlineU32(0)));
|
|
||||||
code.push_back(EncodeSMovB32(1, InlineU32(0)));
|
|
||||||
code.push_back(EncodeSMovB32(2, InlineU32(4)));
|
|
||||||
code.push_back(EncodeSMovB32(3, InlineU32(0)));
|
|
||||||
code.push_back(EncodeSop1(0x04, 126, 2));
|
|
||||||
code.push_back(EncodeSmem0(0x00, 20, 63));
|
|
||||||
code.push_back(EncodeSmem1(0));
|
|
||||||
code.push_back(EncodeSMovB32(2, InlineU32(1)));
|
|
||||||
code.push_back(EncodeSop1(0x04, 126, 2));
|
|
||||||
AppendStoreSgpr(&code, 20, 0);
|
|
||||||
AppendEnd(&code);
|
|
||||||
|
|
||||||
return {"ScalarLoadUsesRawExecAddress",
|
|
||||||
code,
|
|
||||||
{0x11111111u, 0x22222222u},
|
|
||||||
{0x22222222u, 0x22222222u},
|
|
||||||
{O::S_MOV_B32, O::S_MOV_B64, O::S_LOAD_DWORD, O::V_MOV_B32,
|
|
||||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
|
||||||
}
|
|
||||||
|
|
||||||
TestCase ScalarLoadSignedImmediateOffsetAddsSoffset() {
|
TestCase ScalarLoadSignedImmediateOffsetAddsSoffset() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -21302,9 +21125,6 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(ScalarCompareOps);
|
AddCase(ScalarCompareOps);
|
||||||
AddCase(ScalarShiftAddAndMaskOps);
|
AddCase(ScalarShiftAddAndMaskOps);
|
||||||
AddCase(ScalarNotB64UpdatesScc);
|
AddCase(ScalarNotB64UpdatesScc);
|
||||||
AddCase(ScalarMovB64PreservesRawSpecialData);
|
|
||||||
AddCase(Scalar64RawSpecialOps);
|
|
||||||
AddCase(ScalarMovB32SpecialAliases);
|
|
||||||
AddCase(ScalarQuadmaskB64);
|
AddCase(ScalarQuadmaskB64);
|
||||||
AddCase(ScalarFlbitI32B64Gpu);
|
AddCase(ScalarFlbitI32B64Gpu);
|
||||||
AddCase(ScalarFlbitI32B32Gpu);
|
AddCase(ScalarFlbitI32B32Gpu);
|
||||||
@@ -21421,7 +21241,6 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(BranchVccnzUsesInvocationMask);
|
AddCase(BranchVccnzUsesInvocationMask);
|
||||||
AddCase(BranchVccnzUsesCarryProducedInvocationMask);
|
AddCase(BranchVccnzUsesCarryProducedInvocationMask);
|
||||||
AddCase(ScalarMemoryLoadVariants);
|
AddCase(ScalarMemoryLoadVariants);
|
||||||
AddCase(ScalarLoadUsesRawExecAddress);
|
|
||||||
AddCase(ScalarLoadSignedImmediateOffsetAddsSoffset);
|
AddCase(ScalarLoadSignedImmediateOffsetAddsSoffset);
|
||||||
AddCase(ScalarLoadAlignsComponentsAndMasksAddress);
|
AddCase(ScalarLoadAlignsComponentsAndMasksAddress);
|
||||||
AddCase(BufferLoadStore);
|
AddCase(BufferLoadStore);
|
||||||
|
|||||||
+11
-17
@@ -9059,12 +9059,10 @@ void TestTypedEntryStateIsMinimal() {
|
|||||||
translate_options);
|
translate_options);
|
||||||
|
|
||||||
uint32_t set_exec = 0;
|
uint32_t set_exec = 0;
|
||||||
uint32_t set_exec_mask_tag = 0;
|
|
||||||
uint32_t set_exec_lo = 0;
|
uint32_t set_exec_lo = 0;
|
||||||
uint32_t set_exec_hi = 0;
|
uint32_t set_exec_hi = 0;
|
||||||
uint32_t ballots = 0;
|
uint32_t ballots = 0;
|
||||||
IR::Value exec;
|
IR::Value exec;
|
||||||
IR::Value exec_mask_tag;
|
|
||||||
IR::Value exec_lo;
|
IR::Value exec_lo;
|
||||||
IR::Value exec_hi;
|
IR::Value exec_hi;
|
||||||
for (const auto *block : values.blocks) {
|
for (const auto *block : values.blocks) {
|
||||||
@@ -9077,10 +9075,6 @@ void TestTypedEntryStateIsMinimal() {
|
|||||||
set_exec++;
|
set_exec++;
|
||||||
exec = inst.Arg(0).Resolve();
|
exec = inst.Arg(0).Resolve();
|
||||||
break;
|
break;
|
||||||
case IR::ValueOpcode::SetExecMaskTag:
|
|
||||||
set_exec_mask_tag++;
|
|
||||||
exec_mask_tag = inst.Arg(0).Resolve();
|
|
||||||
break;
|
|
||||||
case IR::ValueOpcode::SetExecLo:
|
case IR::ValueOpcode::SetExecLo:
|
||||||
set_exec_lo++;
|
set_exec_lo++;
|
||||||
exec_lo = inst.Arg(0).Resolve();
|
exec_lo = inst.Arg(0).Resolve();
|
||||||
@@ -9095,7 +9089,6 @@ void TestTypedEntryStateIsMinimal() {
|
|||||||
case IR::ValueOpcode::SetVectorRegister:
|
case IR::ValueOpcode::SetVectorRegister:
|
||||||
case IR::ValueOpcode::SetScc:
|
case IR::ValueOpcode::SetScc:
|
||||||
case IR::ValueOpcode::SetVcc:
|
case IR::ValueOpcode::SetVcc:
|
||||||
case IR::ValueOpcode::SetVccMaskValidTag:
|
|
||||||
case IR::ValueOpcode::SetVccLo:
|
case IR::ValueOpcode::SetVccLo:
|
||||||
case IR::ValueOpcode::SetVccHi:
|
case IR::ValueOpcode::SetVccHi:
|
||||||
case IR::ValueOpcode::SetM0:
|
case IR::ValueOpcode::SetM0:
|
||||||
@@ -9106,9 +9099,8 @@ void TestTypedEntryStateIsMinimal() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Check(set_exec == 1u && set_exec_mask_tag == 1u && set_exec_lo == 1u &&
|
Check(set_exec == 1u && set_exec_lo == 1u && set_exec_hi == 1u &&
|
||||||
set_exec_hi == 1u && ballots == 0u && exec.IsImmediate() &&
|
ballots == 0u && exec.IsImmediate() && exec.U1() &&
|
||||||
exec.U1() && exec_mask_tag.IsImmediate() && exec_mask_tag.U1() &&
|
|
||||||
exec_lo.IsImmediate() && exec_lo.U32() == 1u &&
|
exec_lo.IsImmediate() && exec_lo.U32() == 1u &&
|
||||||
exec_hi.IsImmediate() && exec_hi.U32() == 0u,
|
exec_hi.IsImmediate() && exec_hi.U32() == 0u,
|
||||||
"typed entry is not the local {1,0} invocation mask");
|
"typed entry is not the local {1,0} invocation mask");
|
||||||
@@ -9937,16 +9929,18 @@ void TestNewShaderRecompilerPerInvocationMasksWithoutMirrors() {
|
|||||||
result = ShaderRecompiler::Recompile(wqm_shader, options);
|
result = ShaderRecompiler::Recompile(wqm_shader, options);
|
||||||
CheckSpirvBinaryValidates(result.spirv);
|
CheckSpirvBinaryValidates(result.spirv);
|
||||||
const auto wqm_source = DisassembleSpirvBinary(result.spirv);
|
const auto wqm_source = DisassembleSpirvBinary(result.spirv);
|
||||||
Check(!Common::ContainsStr(wqm_source, "OpGroupNonUniformBallot"),
|
Check(Common::ContainsStr(wqm_source, "OpCapability GroupNonUniformBallot") &&
|
||||||
"raw scalar WQM reconstructed its source from invocation provenance");
|
Common::ContainsStr(wqm_source, "OpGroupNonUniformBallot"),
|
||||||
|
"per-invocation scalar WQM omitted its subgroup ballot capability");
|
||||||
|
Check(SpirvInstructionOpcodeCount(result.spirv, 132u) == 2u,
|
||||||
|
"wave64 WQM did not compact exactly two ballot words");
|
||||||
|
|
||||||
auto wave32_options = options;
|
auto wave32_options = options;
|
||||||
wave32_options.wave_size = 32u;
|
wave32_options.wave_size = 32u;
|
||||||
result = ShaderRecompiler::Recompile(wqm_shader, wave32_options);
|
result = ShaderRecompiler::Recompile(wqm_shader, wave32_options);
|
||||||
CheckSpirvBinaryValidates(result.spirv);
|
CheckSpirvBinaryValidates(result.spirv);
|
||||||
Check(!Common::ContainsStr(DisassembleSpirvBinary(result.spirv),
|
Check(SpirvInstructionOpcodeCount(result.spirv, 132u) == 1u,
|
||||||
"OpGroupNonUniformBallot"),
|
"wave32 WQM retained the unused high ballot-word expansion");
|
||||||
"wave32 raw scalar WQM reconstructed invocation provenance");
|
|
||||||
|
|
||||||
const uint32_t cross_lane_shader[] = {
|
const uint32_t cross_lane_shader[] = {
|
||||||
EncodeSop2(0x25, 126, 132, 128), // s_bfm_b64 exec, 4, 0
|
EncodeSop2(0x25, 126, 132, 128), // s_bfm_b64 exec, 4, 0
|
||||||
@@ -11868,8 +11862,8 @@ void TestNewShaderRecompilerSpirvSizeBaselines() {
|
|||||||
.conditional_branches = 1,
|
.conditional_branches = 1,
|
||||||
.ballots = 1},
|
.ballots = 1},
|
||||||
ShaderType::Vertex);
|
ShaderType::Vertex);
|
||||||
Check(Common::ContainsStr(wqm_result.ir_dump, "WqmU64"),
|
Check(Common::ContainsStr(wqm_result.ir_dump, "WqmMask"),
|
||||||
"WQM size fixture no longer reaches raw WqmU64 IR");
|
"WQM size fixture no longer reaches per-invocation WqmMask IR");
|
||||||
|
|
||||||
const uint32_t dispatcher[] = {
|
const uint32_t dispatcher[] = {
|
||||||
EncodeSopp(0x05, 2), // entry -> B, fallthrough A
|
EncodeSopp(0x05, 2), // entry -> B, fallthrough A
|
||||||
|
|||||||
Reference in New Issue
Block a user