mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-02-03 17:20:26 +01:00
r600/sfn: add register remapping
Make use of the live range evaluation to merge registers. Since the live ranges are evaluated for register indices, the algorithm is not optimal, but for most piglits up to glsl-3.3 it does the job. Signed-off-by: Gert Wollny <gert.wollny@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3225>
This commit is contained in:
parent
393655d5cb
commit
5c19013904
12 changed files with 171 additions and 0 deletions
|
|
@ -62,6 +62,11 @@ AluInstruction::AluInstruction(EAluOp opcode, PValue dest,
|
|||
|
||||
if (alu_ops.at(opcode).nsrc == 3)
|
||||
m_flags.set(alu_op3);
|
||||
|
||||
for (auto &s: m_src)
|
||||
add_remappable_src_value(&s);
|
||||
|
||||
add_remappable_dst_value(&m_dest);
|
||||
}
|
||||
|
||||
AluInstruction::AluInstruction(EAluOp opcode, PValue dest, PValue src0,
|
||||
|
|
@ -106,6 +111,30 @@ bool AluInstruction::is_equal_to(const Instruction& lhs) const
|
|||
return (m_flags == oth.m_flags && m_cf_type == oth.m_cf_type);
|
||||
}
|
||||
|
||||
void AluInstruction::replace_values(const ValueSet& candiates, PValue new_value)
|
||||
{
|
||||
for (auto c: candiates) {
|
||||
if (*c == *m_dest)
|
||||
m_dest = new_value;
|
||||
|
||||
for (auto& s: m_src) {
|
||||
if (*c == *s)
|
||||
s = new_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PValue AluInstruction::remap_one_registers(PValue reg, std::vector<rename_reg_pair>& map,
|
||||
ValueMap &values)
|
||||
{
|
||||
auto new_index = map[reg->sel()];
|
||||
if (new_index.valid)
|
||||
reg = values.get_or_inject(new_index.new_reg, reg->chan());
|
||||
map[reg->sel()].used = true;
|
||||
return reg;
|
||||
}
|
||||
|
||||
|
||||
void AluInstruction::set_flag(AluModifiers flag)
|
||||
{
|
||||
m_flags.set(flag);
|
||||
|
|
|
|||
|
|
@ -117,10 +117,14 @@ public:
|
|||
ECFAluOpCode cf_type() const {return m_cf_type;}
|
||||
void set_cf_type(ECFAluOpCode cf_type){ m_cf_type = cf_type; }
|
||||
|
||||
void replace_values(const ValueSet& candiates, PValue new_value) override;
|
||||
|
||||
private:
|
||||
|
||||
bool is_equal_to(const Instruction& lhs) const override;
|
||||
void do_print(std::ostream& os) const override;
|
||||
PValue remap_one_registers(PValue reg, std::vector<rename_reg_pair>& map,
|
||||
ValueMap &values);
|
||||
|
||||
|
||||
EAluOp m_opcode;
|
||||
|
|
|
|||
|
|
@ -118,6 +118,26 @@ void Instruction::remap_registers(ValueRemapper& map)
|
|||
sfn_log << SfnLog::merge << "TO " << *this << "\n\n";
|
||||
}
|
||||
|
||||
void Instruction::add_remappable_src_value(PValue *v)
|
||||
{
|
||||
m_mappable_src_registers.push_back(v);
|
||||
}
|
||||
|
||||
void Instruction::add_remappable_src_value(GPRVector *v)
|
||||
{
|
||||
m_mappable_src_vectors.push_back(v);
|
||||
}
|
||||
|
||||
void Instruction::add_remappable_dst_value(PValue *v)
|
||||
{
|
||||
m_mappable_dst_registers.push_back(v);
|
||||
}
|
||||
|
||||
void Instruction::add_remappable_dst_value(GPRVector *v)
|
||||
{
|
||||
m_mappable_dst_vectors.push_back(v);
|
||||
}
|
||||
|
||||
void Instruction::replace_values(UNUSED const ValueSet& candiates, UNUSED PValue new_value)
|
||||
{
|
||||
|
||||
|
|
|
|||
|
|
@ -39,8 +39,31 @@
|
|||
namespace r600 {
|
||||
|
||||
|
||||
struct rename_reg_pair {
|
||||
bool valid;
|
||||
bool used;
|
||||
int new_reg;
|
||||
};
|
||||
|
||||
class LiverangeEvaluator;
|
||||
class ValueMap;
|
||||
|
||||
|
||||
class ValueRemapper {
|
||||
public:
|
||||
ValueRemapper(std::vector<rename_reg_pair>& m,
|
||||
ValueMap& values);
|
||||
|
||||
void remap(PValue& v);
|
||||
void remap(GPRVector& v);
|
||||
private:
|
||||
PValue remap_one_registers(PValue& reg);
|
||||
|
||||
std::vector<rename_reg_pair>& m_map;
|
||||
ValueMap& m_values;
|
||||
};
|
||||
|
||||
|
||||
using OutputRegisterMap = std::map<unsigned, const GPRVector *>;
|
||||
|
||||
class Instruction {
|
||||
|
|
@ -80,8 +103,19 @@ public:
|
|||
|
||||
void print(std::ostream& os) const;
|
||||
|
||||
virtual void replace_values(const ValueSet& candiates, PValue new_value);
|
||||
|
||||
void evalue_liveness(LiverangeEvaluator& eval) const;
|
||||
|
||||
void remap_registers(ValueRemapper& map);
|
||||
|
||||
protected:
|
||||
|
||||
void add_remappable_src_value(PValue *v);
|
||||
void add_remappable_src_value(GPRVector *v);
|
||||
void add_remappable_dst_value(PValue *v);
|
||||
void add_remappable_dst_value(GPRVector *v);
|
||||
|
||||
private:
|
||||
|
||||
virtual void do_evalue_liveness(LiverangeEvaluator& eval) const;
|
||||
|
|
@ -92,6 +126,10 @@ private:
|
|||
|
||||
virtual void do_print(std::ostream& os) const = 0;
|
||||
|
||||
std::vector<PValue*> m_mappable_src_registers;
|
||||
std::vector<GPRVector*> m_mappable_src_vectors;
|
||||
std::vector<PValue*> m_mappable_dst_registers;
|
||||
std::vector<GPRVector*> m_mappable_dst_vectors;
|
||||
};
|
||||
|
||||
using PInstruction=Instruction::Pointer;
|
||||
|
|
|
|||
|
|
@ -45,6 +45,7 @@ IfInstruction::IfInstruction(AluInstruction *pred):
|
|||
m_pred(pred)
|
||||
{
|
||||
PValue *v = m_pred->psrc(0);
|
||||
add_remappable_src_value(v);
|
||||
}
|
||||
|
||||
void IfInstruction::do_evalue_liveness(LiverangeEvaluator& eval) const
|
||||
|
|
|
|||
|
|
@ -34,6 +34,28 @@ namespace r600 {
|
|||
WriteoutInstruction::WriteoutInstruction(instr_type t, const GPRVector& value):
|
||||
Instruction(t),
|
||||
m_value(value)
|
||||
{
|
||||
add_remappable_src_value(&m_value);
|
||||
}
|
||||
|
||||
void WriteoutInstruction::replace_values(const ValueSet& candiates, PValue new_value)
|
||||
{
|
||||
// I wonder whether we can actually end up here ...
|
||||
for (auto c: candiates) {
|
||||
if (*c == *m_value.reg_i(c->chan()))
|
||||
m_value.set_reg_i(c->chan(), new_value);
|
||||
}
|
||||
|
||||
replace_values_child(candiates, new_value);
|
||||
}
|
||||
|
||||
void WriteoutInstruction::replace_values_child(UNUSED const ValueSet& candiates,
|
||||
UNUSED PValue new_value)
|
||||
{
|
||||
}
|
||||
|
||||
void WriteoutInstruction::remap_registers_child(UNUSED std::vector<rename_reg_pair>& map,
|
||||
UNUSED ValueMap& values)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,10 +33,15 @@ namespace r600 {
|
|||
|
||||
class WriteoutInstruction: public Instruction {
|
||||
public:
|
||||
void replace_values(const ValueSet& candiates, PValue new_value) override;
|
||||
const GPRVector& gpr() const {return m_value;}
|
||||
const GPRVector *gpr_ptr() const {return &m_value;}
|
||||
protected:
|
||||
WriteoutInstruction(instr_type t, const GPRVector& value);
|
||||
private:
|
||||
virtual void replace_values_child(const ValueSet& candiates, PValue new_value);
|
||||
virtual void remap_registers_child(std::vector<rename_reg_pair>& map,
|
||||
ValueMap& values);
|
||||
|
||||
GPRVector m_value;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -69,6 +69,10 @@ FetchInstruction::FetchInstruction(EVFetchInstr op,
|
|||
m_num_format = vtx_nf_scaled;
|
||||
}
|
||||
|
||||
add_remappable_src_value(&m_src);
|
||||
add_remappable_src_value(&m_buffer_offset);
|
||||
|
||||
add_remappable_dst_value(&m_dst);
|
||||
}
|
||||
|
||||
/* Resource query */
|
||||
|
|
@ -115,6 +119,9 @@ FetchInstruction::FetchInstruction(EVFetchInstr vc_opcode,
|
|||
m_buffer_offset(buffer_offset),
|
||||
m_dest_swizzle(dest_swizzle)
|
||||
{
|
||||
add_remappable_src_value(&m_src);
|
||||
add_remappable_dst_value(&m_dst);
|
||||
add_remappable_src_value(&m_buffer_offset);
|
||||
}
|
||||
|
||||
FetchInstruction::FetchInstruction(GPRVector dst,
|
||||
|
|
@ -146,6 +153,10 @@ FetchInstruction::FetchInstruction(GPRVector dst,
|
|||
m_dest_swizzle({0,1,2,3})
|
||||
{
|
||||
m_flags.set(vtx_format_comp_signed);
|
||||
|
||||
add_remappable_src_value(&m_src);
|
||||
add_remappable_dst_value(&m_dst);
|
||||
add_remappable_src_value(&m_buffer_offset);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -177,6 +188,9 @@ FetchInstruction::FetchInstruction(GPRVector dst,
|
|||
m_dest_swizzle({0,1,2,3})
|
||||
{
|
||||
m_flags.set(vtx_format_comp_signed);
|
||||
add_remappable_src_value(&m_src);
|
||||
add_remappable_dst_value(&m_dst);
|
||||
add_remappable_src_value(&m_buffer_offset);
|
||||
}
|
||||
|
||||
FetchInstruction::FetchInstruction(GPRVector dst, PValue src, int scratch_size):
|
||||
|
|
@ -212,6 +226,23 @@ FetchInstruction::FetchInstruction(GPRVector dst, PValue src, int scratch_size):
|
|||
m_indexed = true;
|
||||
m_array_size = scratch_size - 1;
|
||||
}
|
||||
add_remappable_src_value(&m_src);
|
||||
add_remappable_dst_value(&m_dst);
|
||||
add_remappable_src_value(&m_buffer_offset);
|
||||
}
|
||||
|
||||
void FetchInstruction::replace_values(const ValueSet& candiates, PValue new_value)
|
||||
{
|
||||
if (!m_src)
|
||||
return;
|
||||
for (auto c: candiates) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
if (*c == *m_dst.reg_i(i))
|
||||
m_dst.set_reg_i(i, new_value);
|
||||
}
|
||||
if (*m_src == *c)
|
||||
m_src = new_value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ public:
|
|||
|
||||
FetchInstruction(GPRVector dst, PValue src, int scratch_size);
|
||||
|
||||
void replace_values(const ValueSet& candiates, PValue new_value) override;
|
||||
EVFetchInstr vc_opcode() const { return m_vc_opcode;}
|
||||
EVFetchType fetch_type() const { return m_fetch_type;}
|
||||
|
||||
|
|
@ -111,6 +112,7 @@ public:
|
|||
|
||||
void set_buffer_offset(PValue buffer_offset) {
|
||||
m_buffer_offset = buffer_offset;
|
||||
add_remappable_src_value(&m_buffer_offset);
|
||||
}
|
||||
PValue buffer_offset() const { return m_buffer_offset; }
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,10 @@ TexInstruction::TexInstruction(Opcode op, const GPRVector &dest, const GPRVector
|
|||
|
||||
{
|
||||
memset(m_offset, 0, sizeof (m_offset));
|
||||
|
||||
add_remappable_src_value(&m_src);
|
||||
add_remappable_src_value(&m_sampler_offset);
|
||||
add_remappable_dst_value(&m_dst);
|
||||
}
|
||||
|
||||
void TexInstruction::set_gather_comp(int cmp)
|
||||
|
|
@ -52,6 +56,17 @@ void TexInstruction::set_gather_comp(int cmp)
|
|||
m_inst_mode = cmp;
|
||||
}
|
||||
|
||||
void TexInstruction::replace_values(const ValueSet& candiates, PValue new_value)
|
||||
{
|
||||
// I wonder whether we can actually end up here ...
|
||||
for (auto c: candiates) {
|
||||
if (*c == *m_src.reg_i(c->chan()))
|
||||
m_src.set_reg_i(c->chan(), new_value);
|
||||
if (*c == *m_dst.reg_i(c->chan()))
|
||||
m_dst.set_reg_i(c->chan(), new_value);
|
||||
}
|
||||
}
|
||||
|
||||
void TexInstruction::set_offset(unsigned index, int32_t val)
|
||||
{
|
||||
assert(index < 3);
|
||||
|
|
|
|||
|
|
@ -81,6 +81,8 @@ public:
|
|||
unsigned sampler_id() const {return m_sampler_id;}
|
||||
unsigned resource_id() const {return m_resource_id;}
|
||||
|
||||
void replace_values(const ValueSet& candiates, PValue new_value) override;
|
||||
|
||||
void set_offset(unsigned index, int32_t val);
|
||||
int get_offset(unsigned index) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ public:
|
|||
void split_constants(nir_alu_instr* instr);
|
||||
void load_uniform(const nir_alu_src& src);
|
||||
|
||||
void remap_registers();
|
||||
|
||||
const nir_variable *get_deref_location(const nir_src& src) const;
|
||||
protected:
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue