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,
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);
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;
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)
{
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 {
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;
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;
m_pred(pred)
{
PValue *v = m_pred->psrc(0);
+ add_remappable_src_value(v);
}
void IfInstruction::do_evalue_liveness(LiverangeEvaluator& eval) const
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)
{
}
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;
};
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 */
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,
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);
}
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):
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;
+ }
}
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;}
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; }
{
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)
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);
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;
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: