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: