From 5c19013904ef0ae68c582cd6d77fe54331b36baa Mon Sep 17 00:00:00 2001 From: Gert Wollny Date: Fri, 27 Dec 2019 17:49:26 +0100 Subject: [PATCH] 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 Part-of: --- .../drivers/r600/sfn/sfn_instruction_alu.cpp | 29 ++++++++++++++ .../drivers/r600/sfn/sfn_instruction_alu.h | 4 ++ .../drivers/r600/sfn/sfn_instruction_base.cpp | 20 ++++++++++ .../drivers/r600/sfn/sfn_instruction_base.h | 38 +++++++++++++++++++ .../drivers/r600/sfn/sfn_instruction_cf.cpp | 1 + .../r600/sfn/sfn_instruction_export.cpp | 22 +++++++++++ .../drivers/r600/sfn/sfn_instruction_export.h | 5 +++ .../r600/sfn/sfn_instruction_fetch.cpp | 31 +++++++++++++++ .../drivers/r600/sfn/sfn_instruction_fetch.h | 2 + .../drivers/r600/sfn/sfn_instruction_tex.cpp | 15 ++++++++ .../drivers/r600/sfn/sfn_instruction_tex.h | 2 + .../drivers/r600/sfn/sfn_shader_base.h | 2 + 12 files changed, 171 insertions(+) diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp b/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp index dffc39b9164..4143b9c52d7 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_alu.cpp @@ -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& 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); diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_alu.h b/src/gallium/drivers/r600/sfn/sfn_instruction_alu.h index 67b641511b7..ea95f72fb07 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_alu.h +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_alu.h @@ -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& map, + ValueMap &values); EAluOp m_opcode; diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_base.cpp b/src/gallium/drivers/r600/sfn/sfn_instruction_base.cpp index 4e4e28f1436..22dfa5739f5 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_base.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_base.cpp @@ -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) { diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_base.h b/src/gallium/drivers/r600/sfn/sfn_instruction_base.h index e44154ebe91..c655de96ed5 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_base.h +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_base.h @@ -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& m, + ValueMap& values); + + void remap(PValue& v); + void remap(GPRVector& v); +private: + PValue remap_one_registers(PValue& reg); + + std::vector& m_map; + ValueMap& m_values; +}; + + using OutputRegisterMap = std::map; 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 m_mappable_src_registers; + std::vector m_mappable_src_vectors; + std::vector m_mappable_dst_registers; + std::vector m_mappable_dst_vectors; }; using PInstruction=Instruction::Pointer; diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_cf.cpp b/src/gallium/drivers/r600/sfn/sfn_instruction_cf.cpp index 82b0f47403a..0c10e162bee 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_cf.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_cf.cpp @@ -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 diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_export.cpp b/src/gallium/drivers/r600/sfn/sfn_instruction_export.cpp index 14ae52f325e..d3a07713fa7 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_export.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_export.cpp @@ -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& map, + UNUSED ValueMap& values) { } diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_export.h b/src/gallium/drivers/r600/sfn/sfn_instruction_export.h index 0ea493865af..1971e339135 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_export.h +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_export.h @@ -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& map, + ValueMap& values); GPRVector m_value; }; diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_fetch.cpp b/src/gallium/drivers/r600/sfn/sfn_instruction_fetch.cpp index 9bd23be809c..c41692639b9 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_fetch.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_fetch.cpp @@ -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; + } } diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_fetch.h b/src/gallium/drivers/r600/sfn/sfn_instruction_fetch.h index 0ed41316235..369094edfa7 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_fetch.h +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_fetch.h @@ -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; } diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_tex.cpp b/src/gallium/drivers/r600/sfn/sfn_instruction_tex.cpp index c0f37009f18..0e7b63db570 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_tex.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_tex.cpp @@ -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); diff --git a/src/gallium/drivers/r600/sfn/sfn_instruction_tex.h b/src/gallium/drivers/r600/sfn/sfn_instruction_tex.h index ff5ef1ee1f2..d6f35302499 100644 --- a/src/gallium/drivers/r600/sfn/sfn_instruction_tex.h +++ b/src/gallium/drivers/r600/sfn/sfn_instruction_tex.h @@ -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; diff --git a/src/gallium/drivers/r600/sfn/sfn_shader_base.h b/src/gallium/drivers/r600/sfn/sfn_shader_base.h index 0a12d1ca835..b9184fda2fb 100644 --- a/src/gallium/drivers/r600/sfn/sfn_shader_base.h +++ b/src/gallium/drivers/r600/sfn/sfn_shader_base.h @@ -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: -- 2.30.2