diff --git a/src/gallium/drivers/r600/sfn/sfn_optimizer.cpp b/src/gallium/drivers/r600/sfn/sfn_optimizer.cpp index 37dc0c4fe7e..0b4ae5d41aa 100644 --- a/src/gallium/drivers/r600/sfn/sfn_optimizer.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_optimizer.cpp @@ -34,6 +34,8 @@ #include "sfn_instr_lds.h" #include "sfn_instr_tex.h" #include "sfn_peephole.h" +#include "sfn_valuefactory.h" +#include "sfn_virtualvalues.h" #include @@ -235,7 +237,7 @@ DCEVisitor::visit(Block *block) class CopyPropFwdVisitor : public InstrVisitor { public: - CopyPropFwdVisitor(); + CopyPropFwdVisitor(ValueFactory& vf); void visit(AluInstr *instr) override; void visit(AluGroup *instr) override; @@ -258,7 +260,9 @@ public: void visit(LDSReadInstr *instr) override { (void)instr; }; void propagate_to(RegisterVec4& src, Instr *instr); + bool assigned_in_block_and_direct(PRegister reg, int block_id); + ValueFactory& value_factory; bool progress; }; @@ -291,7 +295,7 @@ bool copy_propagation_fwd(Shader& shader) { auto& root = shader.func(); - CopyPropFwdVisitor copy_prop; + CopyPropFwdVisitor copy_prop(shader.value_factory()); do { copy_prop.progress = false; @@ -330,8 +334,9 @@ copy_propagation_backward(Shader& shader) return copy_prop.progress; } -CopyPropFwdVisitor::CopyPropFwdVisitor(): - progress(false) +CopyPropFwdVisitor::CopyPropFwdVisitor(ValueFactory& vf): + value_factory(vf), + progress(false) { } @@ -413,6 +418,19 @@ CopyPropFwdVisitor::visit(ExportInstr *instr) propagate_to(instr->value(), instr); } +static bool register_sel_can_change(Pin pin) +{ + return pin == pin_free || pin == pin_none; +} + +static bool register_chan_is_pinned(Pin pin) +{ + return pin == pin_chan || + pin == pin_fully || + pin == pin_chgr; +} + + void CopyPropFwdVisitor::propagate_to(RegisterVec4& src, Instr *instr) { @@ -429,37 +447,75 @@ CopyPropFwdVisitor::propagate_to(RegisterVec4& src, Instr *instr) } PRegister new_src[4] = {0}; - int sel = -1; + uint8_t mask = 0; + int new_sel = -1; + bool all_sel_can_change = true; + + bool is_ssa = true; + int new_chan[4] = {0,0,0,0}; + for (int i = 0; i < 4; ++i) { + unsigned allowed_mask = 0xf & ~mask; if (!parents[i]) continue; if ((parents[i]->opcode() != op1_mov) || parents[i]->has_alu_flag(alu_src0_neg) || parents[i]->has_alu_flag(alu_src0_abs) || parents[i]->has_alu_flag(alu_dst_clamp) || - parents[i]->has_alu_flag(alu_src0_rel)) { + parents[i]->has_alu_flag(alu_src0_rel) || + std::get<0>(parents[i]->indirect_addr())) { return; } else { auto src = parents[i]->src(0).as_register(); if (!src) return; - else if (!src->has_flag(Register::ssa)) + if (src->pin() == pin_array) return; - else if (sel < 0) - sel = src->sel(); - else if (sel != src->sel()) + if (!src->has_flag(Register::ssa) && + !assigned_in_block_and_direct(src, instr->block_id())) { return; + } + if (register_chan_is_pinned(src->pin())) { + allowed_mask = 1 << src->chan(); + } + new_chan[i] = src->chan(); + for (auto p : src->parents()) { auto alu = p->as_alu(); - if (alu && !(alu->allowed_dest_chan_mask() & (1 << i))) + if (alu) + allowed_mask &= alu->allowed_dest_chan_mask(); + } + if (!allowed_mask) { + return; + } + + if (new_sel < 0) { + new_sel = src->sel(); + is_ssa = src->has_flag(Register::ssa); + new_chan[i] = src->chan(); + } else if (new_sel != src->sel()) { + if (all_sel_can_change && + register_sel_can_change(src->pin()) && + (is_ssa == src->has_flag(Register::ssa))) { + new_chan[i] = u_bit_scan(&allowed_mask); + new_sel = value_factory.new_register_index(); + } else return; } + new_src[i] = src; + mask |= 1 << new_chan[i]; + if (!register_sel_can_change(src->pin())) + all_sel_can_change = false; } } for (int i = 0; i < 4; ++i) { if (parents[i]) { src.del_use(instr); + new_src[i]->set_sel(new_sel); + if (is_ssa) + new_src[i]->set_flag(Register::ssa); + new_src[i]->set_chan(new_chan[i]); src.set_value(i, new_src[i]); if (new_src[i]->pin() != pin_fully) { if (new_src[i]->pin() == pin_chan) @@ -475,6 +531,22 @@ CopyPropFwdVisitor::propagate_to(RegisterVec4& src, Instr *instr) src.validate(); } +bool CopyPropFwdVisitor::assigned_in_block_and_direct(PRegister reg, int block_id) +{ + for (auto p: reg->parents()) { + if (p->as_alu()) { + auto [addr, is_regoffs, is_index] = p->as_alu()->indirect_addr(); + if (addr) { + return false; + } + } + + if (p->block_id() == block_id) + return true; + } + return false; +} + void CopyPropFwdVisitor::visit(FetchInstr *instr) { diff --git a/src/gallium/drivers/r600/sfn/sfn_valuefactory.cpp b/src/gallium/drivers/r600/sfn/sfn_valuefactory.cpp index 6a22ac257c7..765411afad9 100644 --- a/src/gallium/drivers/r600/sfn/sfn_valuefactory.cpp +++ b/src/gallium/drivers/r600/sfn/sfn_valuefactory.cpp @@ -136,6 +136,11 @@ ValueFactory::allocate_registers(const exec_list *registers) return has_arrays; } +int ValueFactory::new_register_index() +{ + return m_next_register_index++; +} + PRegister ValueFactory::allocate_pinned_register(int sel, int chan) { diff --git a/src/gallium/drivers/r600/sfn/sfn_valuefactory.h b/src/gallium/drivers/r600/sfn/sfn_valuefactory.h index 69fd63e1e2b..eaf6e7ed56b 100644 --- a/src/gallium/drivers/r600/sfn/sfn_valuefactory.h +++ b/src/gallium/drivers/r600/sfn/sfn_valuefactory.h @@ -220,6 +220,8 @@ public: void set_virtual_register_base(int base); + int new_register_index(); + bool allocate_registers(const exec_list *registers); PRegister allocate_pinned_register(int sel, int chan); RegisterVec4 allocate_pinned_vec4(int sel, bool is_ssa); diff --git a/src/gallium/drivers/r600/sfn/tests/sfn_optimizer_test.cpp b/src/gallium/drivers/r600/sfn/tests/sfn_optimizer_test.cpp index 710f3bc407d..87e9169c836 100644 --- a/src/gallium/drivers/r600/sfn/tests/sfn_optimizer_test.cpp +++ b/src/gallium/drivers/r600/sfn/tests/sfn_optimizer_test.cpp @@ -88,6 +88,49 @@ TEST_F(TestShaderFromNir, FullOPtimizeLoop) check(sh, vs_nexted_loop_from_nir_expect_opt); } + +TEST_F(TestShaderFromNir, CombineRegisterToTexSrc) +{ +const char *shader_input = + R"(FS +CHIPCLASS EVERGREEN +REGISTERS R0.x R1.x R2.x R3.x +PROP MAX_COLOR_EXPORTS:1 +PROP COLOR_EXPORTS:1 +PROP COLOR_EXPORT_MASK:15 +OUTPUT LOC:0 NAME:1 MASK:15 +SHADER +ALU ADD R2.x : R0.x R2.x {W} +ALU MUL R3.x : R0.x R3.x {WL} +ALU MOV S1.x@group : R2.x {W} +ALU MOV S1.y@group : R3.x {WL} +TEX SAMPLE S2.xyzw : S1.xy__ RID:18 SID:0 NNNN +EXPORT_DONE PIXEL 0 S2.xyzw +)"; + +const char *shader_expect = + R"(FS +CHIPCLASS EVERGREEN +REGISTERS R1024.x@group R1024.y@group R0.x +PROP MAX_COLOR_EXPORTS:1 +PROP COLOR_EXPORTS:1 +PROP COLOR_EXPORT_MASK:15 +OUTPUT LOC:0 NAME:1 MASK:15 +SHADER + +ALU ADD R1024.x@group : R0.x R1024.x@group {W} +ALU MUL R1024.y@group : R0.x R1024.y@group {WL} +TEX SAMPLE S2.xyzw : R1024.xy__ RID:18 SID:0 NNNN +EXPORT_DONE PIXEL 0 S2.xyzw +)"; + + auto sh = from_string(shader_input); + + optimize(*sh); + + check(sh, shader_expect); +} + TEST_F(TestShaderFromNir, OptimizeWithDestArrayValue) { auto sh = from_string(shader_with_dest_array); diff --git a/src/gallium/drivers/r600/sfn/tests/sfn_test_shaders.cpp b/src/gallium/drivers/r600/sfn/tests/sfn_test_shaders.cpp index a693cb46cd9..68bd2b99150 100644 --- a/src/gallium/drivers/r600/sfn/tests/sfn_test_shaders.cpp +++ b/src/gallium/drivers/r600/sfn/tests/sfn_test_shaders.cpp @@ -894,12 +894,12 @@ ALU ADD S30.z : KC0[3].z KC0[2].z {WL} ALU MULADD_IEEE S33.x : S25.x@free KC0[4].x S30.x {W} ALU MULADD_IEEE S33.y : S25.x@free KC0[4].y S30.y {W} ALU MULADD_IEEE S33.z : S25.x@free KC0[4].z S30.z {WL} -ALU MULADD_IEEE CLAMP S40.x@group : S27.x@free KC0[5].x S33.x {W} -ALU MULADD_IEEE CLAMP S40.y@group : S27.x@free KC0[5].y S33.y {W} -ALU MULADD_IEEE CLAMP S40.z@group : S27.x@free KC0[5].z S33.z {W} +ALU MULADD_IEEE CLAMP S1024.x@group : S27.x@free KC0[5].x S33.x {W} +ALU MULADD_IEEE CLAMP S1024.y@group : S27.x@free KC0[5].y S33.y {W} +ALU MULADD_IEEE CLAMP S1024.z@group : S27.x@free KC0[5].z S33.z {WL} EXPORT_DONE POS 0 S15.xyzw -ALU MOV CLAMP S40.w@group : KC0[2].w {WL} -EXPORT_DONE PARAM 0 S40.xyzw)"; +ALU MOV CLAMP S1024.w@group : KC0[2].w {WL} +EXPORT_DONE PARAM 0 S1024.xyzw)"; const char *vs_nexted_loop_nir = R"(shader: MESA_SHADER_VERTEX @@ -2263,12 +2263,10 @@ PROP COLOR_EXPORT_MASK:15 PROP WRITE_ALL_COLORS:1 OUTPUT LOC:0 NAME:1 MASK:15 SHADER -ALU DOT4_IEEE S5.x@group : KC0[0].y KC0[0].y + KC0[0].y KC0[0].y + I[0] I[0] + I[0] I[0] {W} -ALU DOT4_IEEE S3.x@free : KC0[0].x KC0[0].z + KC0[0].x KC0[0].w + I[0] I[0] + I[0] I[0] {WL} -ALU DOT4_IEEE S5.w@group : KC0[0].y KC0[0].w + KC0[0].w KC0[0].y + I[0] I[0] + I[0] I[0] {WL} -ALU MOV S5.y@group : S3.x@free {W} -ALU MOV S5.z@group : S3.x@free {W} -EXPORT_DONE PIXEL 0 S5.xyzw +ALU DOT4_IEEE S1026.x@group : KC0[0].y KC0[0].y + KC0[0].y KC0[0].y + I[0] I[0] + I[0] I[0] {WL} +ALU DOT4_IEEE S1026.z@group : KC0[0].x KC0[0].z + KC0[0].x KC0[0].w + I[0] I[0] + I[0] I[0] {WL} +ALU DOT4_IEEE S1026.w@group : KC0[0].y KC0[0].w + KC0[0].w KC0[0].y + I[0] I[0] + I[0] I[0] {WL} +EXPORT_DONE PIXEL 0 S1026.xzzw )"; const char *fs_with_grand_and_abs =