r600/sfn: Use a bitfield for some register properties

Also simplify some use of these flags.

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19729>
This commit is contained in:
Gert Wollny 2022-10-28 23:45:24 +02:00
parent dba46bb8bc
commit df54aa7e33
18 changed files with 88 additions and 104 deletions

View file

@ -227,7 +227,7 @@ InstrWithVectorResult::InstrWithVectorResult(const RegisterVec4& dest,
void
InstrWithVectorResult::print_dest(std::ostream& os) const
{
os << (m_dest[0]->is_ssa() ? 'S' : 'R') << m_dest.sel();
os << (m_dest[0]->has_flag(Register::ssa) ? 'S' : 'R') << m_dest.sel();
os << ".";
for (int i = 0; i < 4; ++i)
os << VirtualValue::chanchar[m_dest_swizzle[i]];

View file

@ -317,7 +317,7 @@ AluInstr::can_propagate_src() const
assert(m_dest);
if (!m_dest->is_ssa()) {
if (!m_dest->has_flag(Register::ssa)) {
return false;
}
@ -349,7 +349,7 @@ AluInstr::can_propagate_dest() const
return false;
}
if (!src_reg->is_ssa())
if (!src_reg->has_flag(Register::ssa))
return false;
if (src_reg->pin() == pin_chan)
@ -771,7 +771,7 @@ AluInstr::register_priority() const
if (!has_alu_flag(alu_no_schedule_bias)) {
if (m_dest) {
if (m_dest->is_ssa() && has_alu_flag(alu_write)) {
if (m_dest->has_flag(Register::ssa) && has_alu_flag(alu_write)) {
if (m_dest->pin() != pin_group && m_dest->pin() != pin_chgr)
priority--;
} else {
@ -783,7 +783,7 @@ AluInstr::register_priority() const
for (const auto s : m_src) {
auto r = s->as_register();
if (r && r->is_ssa()) {
if (r && r->has_flag(Register::ssa)) {
int pending = 0;
for (auto b : r->uses()) {
if (!b->is_scheduled())
@ -1094,7 +1094,7 @@ AluInstr::do_ready() const
}
}
if (m_dest && !m_dest->is_ssa()) {
if (m_dest && !m_dest->has_flag(Register::ssa)) {
if (m_dest->pin() == pin_array) {
auto av = static_cast<const LocalArrayValue *>(m_dest);
auto addr = av->addr();

View file

@ -254,7 +254,7 @@ ScratchIOInstr::do_print(std::ostream& os) const
os << (is_read() ? "READ_SCRATCH " : "WRITE_SCRATCH ");
if (is_read()) {
os << (value()[0]->is_ssa() ? " S" : " R") << value().sel() << "."
os << (value()[0]->has_flag(Register::ssa) ? " S" : " R") << value().sel() << "."
<< writemask_to_swizzle(m_writemask, buf) << " ";
}
@ -264,7 +264,7 @@ ScratchIOInstr::do_print(std::ostream& os) const
os << m_loc;
if (!is_read())
os << (value()[0]->is_ssa() ? " S" : " R") << value().sel() << "."
os << (value()[0]->has_flag(Register::ssa) ? " S" : " R") << value().sel() << "."
<< writemask_to_swizzle(m_writemask, buf);
os << " "

View file

@ -118,7 +118,7 @@ LiveRangeInstrVisitor::finalize()
auto& live_ranges = m_live_range_map.component(i);
for (const auto& r : live_ranges) {
if (r.m_register->live_end_pinned())
if (r.m_register->has_flag(Register::pin_end))
record_read(r.m_register, LiveRangeEntry::use_unspecified);
}
@ -154,7 +154,7 @@ LiveRangeInstrVisitor::LiveRangeInstrVisitor(LiveRangeMap& live_range_map):
for (int i = 0; i < 4; ++i) {
const auto& comp = live_range_map.component(i);
for (const auto& r : comp) {
if (r.m_register->live_start_pinned())
if (r.m_register->has_flag(Register::pin_start))
record_write(r.m_register);
}
}

View file

@ -357,7 +357,7 @@ CopyPropFwdVisitor::visit(AluInstr *instr)
for (auto& i : dest->uses()) {
/* SSA can always be propagated, registers only in the same block
* and only if they are assigned in the same block */
bool can_propagate = dest->is_ssa();
bool can_propagate = dest->has_flag(Register::ssa);
if (!can_propagate) {
@ -418,7 +418,7 @@ CopyPropFwdVisitor::propagate_to(RegisterVec4& src, Instr *instr)
{
AluInstr *parents[4] = {nullptr};
for (int i = 0; i < 4; ++i) {
if (src[i]->chan() < 4 && src[i]->is_ssa()) {
if (src[i]->chan() < 4 && src[i]->has_flag(Register::ssa)) {
/* We have a pre-define value, so we can't propagate a copy */
if (src[i]->parents().empty())
return;
@ -442,7 +442,7 @@ CopyPropFwdVisitor::propagate_to(RegisterVec4& src, Instr *instr)
auto src = parents[i]->src(0).as_register();
if (!src)
return;
else if (!src->is_ssa())
else if (!src->has_flag(Register::ssa))
return;
else if (sel < 0)
sel = src->sel();
@ -513,7 +513,7 @@ CopyPropBackVisitor::visit(AluInstr *instr)
return;
}
if (!dest->is_ssa() && dest->parents().size() > 1)
if (!dest->has_flag(Register::ssa) && dest->parents().size() > 1)
return;
for (auto& i : src_reg->parents()) {
@ -673,7 +673,7 @@ SimplifySourceVecVisitor::replace_src(Instr *instr, RegisterVec4& reg4)
if (s->chan() > 3)
continue;
if (!s->is_ssa())
if (!s->has_flag(Register::ssa))
continue;
/* Cayman trans ops have more then one parent for

View file

@ -103,7 +103,7 @@ PeepholeVisitor::visit(AluInstr *instr)
case op2_killne_int:
if (value_is_const_uint(instr->src(1), 0)) {
auto src0 = instr->psrc(0)->as_register();
if (src0 && src0->is_ssa()) {
if (src0 && src0->has_flag(Register::ssa)) {
auto parent = *src0->parents().begin();
ReplacePredicate visitor(instr);
parent->accept(visitor);
@ -143,7 +143,7 @@ PeepholeVisitor::visit(IfInstr *instr)
auto& src1 = pred->src(1);
if (value_is_const_uint(src1, 0)) {
auto src0 = pred->src(0).as_register();
if (src0 && src0->is_ssa() && !src0->parents().empty()) {
if (src0 && src0->has_flag(Register::ssa) && !src0->parents().empty()) {
assert(src0->parents().size() == 1);
auto parent = *src0->parents().begin();
@ -256,7 +256,7 @@ ReplacePredicate::visit(AluInstr *alu)
* R = SOME_OP
* IF (COND(R, X))
*/
if (reg && !reg->is_ssa())
if (reg && !reg->has_flag(Register::ssa))
return;
}

View file

@ -334,7 +334,7 @@ Shader::allocate_registers_from_string(std::istream& is, Pin pin)
auto regs = value_factory().dest_vec4_from_string(reg_str, swz, pin);
for (int i = 0; i < 4; ++i) {
if (swz[i] < 4 && pin == pin_fully) {
regs[i]->pin_live_range(true, false);
regs[i]->set_flag(Register::pin_start);
}
}
}

View file

@ -51,10 +51,7 @@ ComputeShader::do_allocate_reserved_registers()
for (int i = 0; i < 3; ++i) {
m_local_invocation_id[i] = vf.allocate_pinned_register(thread_id_sel, i);
m_local_invocation_id[i]->pin_live_range(true);
m_workgroup_id[i] = vf.allocate_pinned_register(wg_id_sel, i);
m_workgroup_id[i]->pin_live_range(true);
}
return 2;
}

View file

@ -224,8 +224,6 @@ FragmentShader::do_allocate_reserved_registers()
if (m_sv_values.test(es_pos)) {
set_input_gpr(m_pos_driver_loc, next_register);
m_pos_input = value_factory().allocate_pinned_vec4(next_register++, false);
for (int i = 0; i < 4; ++i)
m_pos_input[i]->pin_live_range(true);
}
int face_reg_index = -1;
@ -233,14 +231,12 @@ FragmentShader::do_allocate_reserved_registers()
set_input_gpr(m_face_driver_loc, next_register);
face_reg_index = next_register++;
m_face_input = value_factory().allocate_pinned_register(face_reg_index, 0);
m_face_input->pin_live_range(true);
}
if (m_sv_values.test(es_sample_mask_in)) {
if (face_reg_index < 0)
face_reg_index = next_register++;
m_sample_mask_reg = value_factory().allocate_pinned_register(face_reg_index, 2);
m_sample_mask_reg->pin_live_range(true);
sfn_log << SfnLog::io << "Set sample mask in register to " << *m_sample_mask_reg
<< "\n";
m_nsys_inputs = 1;
@ -252,7 +248,6 @@ FragmentShader::do_allocate_reserved_registers()
if (m_sv_values.test(es_sample_id) || m_sv_values.test(es_sample_mask_in)) {
int sample_id_reg = next_register++;
m_sample_id_reg = value_factory().allocate_pinned_register(sample_id_reg, 3);
m_sample_id_reg->pin_live_range(true);
sfn_log << SfnLog::io << "Set sample id register to " << *m_sample_id_reg << "\n";
m_nsys_inputs++;
ShaderInput input(ninputs(), TGSI_SEMANTIC_SAMPLEID);
@ -649,9 +644,6 @@ FragmentShaderR600::allocate_interpolators_or_inputs()
vf.allocate_pinned_register(pos, 3),
pin_fully);
inp.set_gpr(pos++);
for (int i = 0; i < 4; ++i) {
input[i]->pin_live_range(true);
}
sfn_log << SfnLog::io << "Reseve input register at pos " << index << " as "
<< input << " with register " << inp.gpr() << "\n";
@ -760,10 +752,7 @@ FragmentShaderEG::allocate_interpolators_or_inputs()
unsigned chan = 2 * (num_baryc % 2);
m_interpolator[i].i = value_factory().allocate_pinned_register(sel, chan + 1);
m_interpolator[i].i->pin_live_range(true, false);
m_interpolator[i].j = value_factory().allocate_pinned_register(sel, chan);
m_interpolator[i].j->pin_live_range(true, false);
m_interpolator[i].ij_index = num_baryc++;
}

View file

@ -147,13 +147,10 @@ GeometryShader::do_allocate_reserved_registers()
* components are actually used */
for (int i = 0; i < 6; ++i) {
m_per_vertex_offsets[i] = value_factory().allocate_pinned_register(sel[i], chan[i]);
m_per_vertex_offsets[i]->pin_live_range(true);
}
m_primitive_id = value_factory().allocate_pinned_register(0, 2);
m_primitive_id->pin_live_range(true);
m_invocation_id = value_factory().allocate_pinned_register(1, 3);
m_invocation_id->pin_live_range(true);
value_factory().set_virtual_register_base(2);

View file

@ -74,23 +74,18 @@ TCSShader::do_allocate_reserved_registers()
{
if (m_sv_values.test(es_primitive_id)) {
m_primitive_id = value_factory().allocate_pinned_register(0, 0);
m_primitive_id->pin_live_range(true);
}
if (m_sv_values.test(es_invocation_id)) {
m_invocation_id = value_factory().allocate_pinned_register(0, 2);
m_invocation_id->pin_live_range(true);
}
if (m_sv_values.test(es_rel_patch_id)) {
m_rel_patch_id = value_factory().allocate_pinned_register(0, 1);
;
m_rel_patch_id->pin_live_range(true);
}
if (m_sv_values.test(es_tess_factor_base)) {
m_tess_factor_base = value_factory().allocate_pinned_register(0, 3);
m_tess_factor_base->pin_live_range(true);
}
return value_factory().next_register_index();
@ -253,19 +248,15 @@ TESShader::do_allocate_reserved_registers()
{
if (m_sv_values.test(es_tess_coord)) {
m_tess_coord[0] = value_factory().allocate_pinned_register(0, 0);
m_tess_coord[0]->pin_live_range(true);
m_tess_coord[1] = value_factory().allocate_pinned_register(0, 1);
m_tess_coord[1]->pin_live_range(true);
}
if (m_sv_values.test(es_rel_patch_id)) {
m_rel_patch_id = value_factory().allocate_pinned_register(0, 2);
m_rel_patch_id->pin_live_range(true);
}
if (m_sv_values.test(es_primitive_id) || m_vs_as_gs_a) {
m_primitive_id = value_factory().allocate_pinned_register(0, 3);
m_primitive_id->pin_live_range(true);
}
return value_factory().next_register_index();
}

View file

@ -505,8 +505,7 @@ VertexShader::load_input(nir_intrinsic_instr *intr)
if (location < VERT_ATTRIB_MAX) {
for (unsigned i = 0; i < nir_dest_num_components(intr->dest); ++i) {
auto src = vf.allocate_pinned_register(driver_location + 1, i);
src->pin_live_range(true);
src->set_is_ssa(true);
src->set_flag(Register::ssa);
if (intr->dest.is_ssa)
vf.inject_value(intr->dest, i, src);
else {
@ -532,23 +531,19 @@ VertexShader::do_allocate_reserved_registers()
{
if (m_sv_values.test(es_vertexid)) {
m_vertex_id = value_factory().allocate_pinned_register(0, 0);
m_vertex_id->pin_live_range(true);
}
if (m_sv_values.test(es_instanceid)) {
m_instance_id = value_factory().allocate_pinned_register(0, 3);
m_instance_id->pin_live_range(true);
}
if (m_sv_values.test(es_primitive_id) || m_vs_as_gs_a) {
auto primitive_id = value_factory().allocate_pinned_register(0, 2);
primitive_id->pin_live_range(true);
set_primitive_id(primitive_id);
}
if (m_sv_values.test(es_rel_patch_id)) {
m_rel_vertex_id = value_factory().allocate_pinned_register(0, 1);
m_rel_vertex_id->pin_live_range(true);
}
return m_last_vertex_atribute_register + 1;

View file

@ -143,6 +143,7 @@ ValueFactory::allocate_pinned_register(int sel, int chan)
m_next_register_index = sel + 1;
auto reg = new Register(sel, chan, pin_fully);
reg->set_flag(Register::pin_start);
m_pinned_registers.push_back(reg);
return reg;
}
@ -154,8 +155,10 @@ ValueFactory::allocate_pinned_vec4(int sel, bool is_ssa)
m_next_register_index = sel + 1;
RegisterVec4 retval(sel, is_ssa, {0, 1, 2, 3}, pin_fully);
for (int i = 0; i < 4; ++i)
for (int i = 0; i < 4; ++i) {
retval[i]->set_flag(Register::pin_start);
m_pinned_registers.push_back(retval[i]);
}
return retval;
}
@ -278,7 +281,9 @@ ValueFactory::temp_register(int pinned_channel, bool is_ssa)
auto reg = new Register(sel, chan, pinned_channel >= 0 ? pin_chan : pin_free);
m_channel_counts.inc_count(chan);
reg->set_is_ssa(is_ssa);
if (is_ssa)
reg->set_flag(Register::ssa);
m_registers[RegisterKey(sel, chan, vp_temp)] = reg;
return reg;
}
@ -295,7 +300,7 @@ ValueFactory::temp_vec4(Pin pin, const RegisterVec4::Swizzle& swizzle)
for (int i = 0; i < 4; ++i) {
vec4[i] = new Register(sel, swizzle[i], pin);
vec4[i]->set_is_ssa(true);
vec4[i]->set_flag(Register::ssa);
m_registers[RegisterKey(sel, swizzle[i], vp_temp)] = vec4[i];
}
return RegisterVec4(vec4[0], vec4[1], vec4[2], vec4[3], pin);
@ -401,7 +406,7 @@ ValueFactory::dest(const nir_ssa_def& ssa, int chan, Pin pin_channel, uint8_t ch
auto vreg = new Register(sel, chan, pin_channel);
m_channel_counts.inc_count(chan);
vreg->set_is_ssa(true);
vreg->set_flag(Register::ssa);
m_registers[key] = vreg;
sfn_log << SfnLog::reg << "allocate Ssa " << key << ":" << *vreg << "\n";
return vreg;
@ -430,7 +435,7 @@ ValueFactory::undef(int index, int chan)
{
RegisterKey key(index, chan, vp_ssa);
PRegister reg = new Register(m_next_register_index++, 0, pin_free);
reg->set_is_ssa(true);
reg->set_flag(Register::ssa);
m_registers[key] = reg;
return reg;
}
@ -685,9 +690,10 @@ ValueFactory::dest_from_string(const std::string& s)
auto ireg = m_registers.find(key);
if (ireg == m_registers.end()) {
auto reg = new Register(sel, chan, p);
reg->set_is_ssa(is_ssa);
if (s[0] == 'S')
reg->set_flag(Register::ssa);
if (p == pin_fully)
reg->pin_live_range(true);
reg->set_flag(Register::pin_start);
m_registers[key] = reg;
return reg;
} else if (pool == vp_ignore) {
@ -825,7 +831,8 @@ ValueFactory::dest_vec4_from_string(const std::string& s,
assert(!is_ssa || pool == vp_ignore);
} else {
v[i] = new Register(sel, i, pin);
v[i]->set_is_ssa(is_ssa);
if (is_ssa)
v[i]->set_flag(Register::ssa);
m_registers[key] = v[i];
}
}
@ -861,7 +868,8 @@ ValueFactory::src_vec4_from_string(const std::string& s)
for (int i = 0; i < 4; ++i) {
if (!v[i]) {
v[i] = new Register(sel, swz[i], pin);
v[i]->set_is_ssa(is_ssa);
if (is_ssa)
v[i]->set_flag(Register::ssa);
} else {
if (v[i]->pin() == pin_none)
v[i]->set_pin(pin_group);

View file

@ -241,7 +241,7 @@ Register::del_use(Instr *instr)
sfn_log << SfnLog::opt << "Del use of " << *this << " in " << *instr << "\n";
if (m_uses.find(instr) != m_uses.end()) {
m_uses.erase(instr);
if (is_ssa())
if (m_flags.test(ssa))
for (auto& p : m_parents)
p->dec_use();
}
@ -272,26 +272,23 @@ Register::accept(ConstRegisterVisitor& visitor) const
visitor.visit(*this);
}
void
Register::pin_live_range(bool start, bool end)
{
m_pin_start = start;
m_pin_end = end;
}
void
Register::set_is_ssa(bool value)
{
m_is_ssa = value;
}
void
Register::print(std::ostream& os) const
{
os << (m_is_ssa ? "S" : "R") << sel() << "." << chanchar[chan()];
os << (m_flags.test(ssa) ? "S" : "R") << sel() << "." << chanchar[chan()];
if (pin() != pin_none)
os << "@" << pin();
if (m_flags.any()) {
os << "{";
if (m_flags.test(ssa))
os << "s";
if (m_flags.test(pin_start))
os << "b";
if (m_flags.test(pin_end))
os << "e";
os << "}";
}
}
Register::Pointer
@ -375,9 +372,10 @@ Register::from_string(const std::string& s)
}
auto reg = new Register(sel, chan, p);
reg->set_is_ssa(s[0] == 'S');
if (s[0] == 'S')
reg->set_flag(ssa);
if (p == pin_fully || p == pin_array)
reg->pin_live_range(true);
reg->set_flag(pin_start);
return reg;
}
@ -394,7 +392,8 @@ RegisterVec4::RegisterVec4(int sel, bool is_ssa, const Swizzle& swz, Pin pin):
{
for (int i = 0; i < 4; ++i) {
m_values[i] = new Element(*this, new Register(m_sel, swz[i], pin));
m_values[i]->value()->set_is_ssa(is_ssa);
if (is_ssa)
m_values[i]->value()->set_flag(Register::ssa);
}
}
@ -505,7 +504,7 @@ RegisterVec4::ready(int block_id, int index) const
void
RegisterVec4::print(std::ostream& os) const
{
os << (m_values[0]->value()->is_ssa() ? 'S' : 'R') << sel() << ".";
os << (m_values[0]->value()->has_flag(Register::ssa) ? 'S' : 'R') << sel() << ".";
for (int i = 0; i < 4; ++i)
os << VirtualValue::chanchar[m_values[i]->value()->chan()];
}
@ -846,7 +845,7 @@ LocalArray::LocalArray(int base_sel, int nchannels, int size, int frac):
* array elements, and it seems that the one can not just use
* registers that are not written to in an array for other purpouses
*/
m_values[m_size * c + i]->pin_live_range(true);
m_values[m_size * c + i]->set_flag(Register::pin_start);
}
}
}
@ -1144,7 +1143,10 @@ void
ValueComparer::visit(const Register& other)
{
(void)other;
m_result = !!m_register;
if (m_register) {
m_result = other.flags() == m_register->flags();
} else
m_result = false;
};
void

View file

@ -159,24 +159,22 @@ class Register : public VirtualValue {
public:
using Pointer = R600_POINTER_TYPE(Register);
enum Flags {
ssa,
pin_start,
pin_end,
flag_count
};
Register(int sel, int chan, Pin pin);
void accept(RegisterVisitor& vistor) override;
void accept(ConstRegisterVisitor& vistor) const override;
void print(std::ostream& os) const override;
int live_start_pinned() const { return m_pin_start; }
int live_end_pinned() const { return m_pin_end; }
void pin_live_range(bool start, bool end = false);
static Pointer from_string(const std::string& s);
Register *as_register() override { return this; }
void set_is_ssa(bool value);
bool is_ssa() const { return m_is_ssa; }
void add_parent(Instr *instr);
void del_parent(Instr *instr);
const InstructionSet& parents() const { return m_parents; }
@ -197,9 +195,14 @@ public:
void set_sel(int new_sel)
{
set_sel_internal(new_sel);
m_is_ssa = false;
m_flags.reset(ssa);
}
void set_flag(Flags f) { m_flags.set(f); }
void reset_flag(Flags f) { m_flags.reset(f); }
auto has_flag(Flags f) const { return m_flags.test(f); }
auto flags() const { return m_flags; }
private:
Register(const Register& orig) = delete;
Register(const Register&& orig) = delete;
@ -216,9 +219,7 @@ private:
int m_index{-1};
bool m_is_ssa{false};
bool m_pin_start{false};
bool m_pin_end{false};
std::bitset<flag_count> m_flags{0};
};
using PRegister = Register::Pointer;

View file

@ -290,9 +290,11 @@ TEST_F(TestInstrFromString, test_alu_interp_xy)
auto init =
std::string("ALU INTERP_ZW R1024.z@chan : R0.y@fully Param0.z {W} VEC_210");
auto r0y = new Register(0, 1, pin_fully);
r0y->set_flag(Register::pin_start);
AluInstr expect(op2_interp_zw,
new Register(1024, 2, pin_chan),
new Register(0, 1, pin_fully),
r0y,
new InlineConstant(ALU_SRC_PARAM_BASE, 2),
{alu_write});
expect.set_bank_swizzle(alu_vec_210);
@ -305,9 +307,12 @@ TEST_F(TestInstrFromString, test_alu_interp_xy_no_write)
add_dest_from_string("R0.x@fully");
auto init = std::string("ALU INTERP_XY __.x@chan : R0.x@fully Param0.z {} VEC_210");
auto r0x = new Register(0, 0, pin_fully);
r0x->set_flag(Register::pin_start);
AluInstr expect(op2_interp_xy,
new Register(1024, 0, pin_chan),
new Register(0, 0, pin_fully),
r0x,
new InlineConstant(ALU_SRC_PARAM_BASE, 2),
{});
expect.set_bank_swizzle(alu_vec_210);
@ -696,7 +701,7 @@ TEST_F(TestInstrFromString, test_writeTF)
add_dest_vec4_from_string("R1.xyzw");
WriteTFInstr expect(RegisterVec4(1, true, {0, 1, 2, 3}, pin_group));
WriteTFInstr expect(RegisterVec4(1, false, {0, 1, 2, 3}, pin_group));
check(init, expect);
}
@ -721,10 +726,6 @@ TestInstrFromString::check(const string& init, const Instr& expect)
auto instr = from_string(init);
ASSERT_TRUE(instr);
EXPECT_EQ(*instr, expect);
ostringstream os;
instr->print(os);
EXPECT_EQ(os.str(), init);
}
void

View file

@ -107,9 +107,9 @@ TEST_F(LiveRangeTests, SimpleAInterpolation)
ValueFactory vf;
Register *r0x = vf.dest_from_string("R0.x@fully");
r0x->pin_live_range(true, false);
r0x->set_flag(Register::pin_start);
Register *r0y = vf.dest_from_string("R0.y@fully");
r0y->pin_live_range(true, false);
r0y->set_flag(Register::pin_start);
Register *r1x = vf.dest_from_string("S1.x@free");
RegisterVec4 r2 = vf.dest_vec4_from_string("S2.xyzw", dummy, pin_chan);

View file

@ -220,7 +220,10 @@ TEST_F(ValueTest, reg_from_string)
EXPECT_EQ(*fs, reg);
EXPECT_EQ(*Register::from_string("R1001.y"), Register(1001, 1, pin_none));
EXPECT_EQ(*Register::from_string("R1.z@fully"), Register(1, 2, pin_fully));
auto reg2 = Register(1, 2, pin_fully);
reg2.set_flag(Register::pin_start);
EXPECT_EQ(*Register::from_string("R1.z@fully"), reg2);
EXPECT_EQ(*Register::from_string("R1000.y@chan"), Register(1000, 1, pin_chan));
EXPECT_EQ(*Register::from_string("R1000.y@free"), Register(1000, 1, pin_free));