From cb3ac95d030066e9965a693363911e678c413e03 Mon Sep 17 00:00:00 2001 From: Christian Gmeiner Date: Sun, 28 May 2023 14:42:57 +0200 Subject: [PATCH] etnaviv: nir: improve uniform usage for ALU opc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code in lower_alu(..) counts how many const values are used by one ALU opc. If there are used more then one the compiler tries to fix this issues by e.g. resolve with a single combined const src. We are doing this as some GPUs only allow one const src per ISA instruction. But it is allowed to use the same const for multiple srcs. Lets have a closer look at a real world shader: impl main { /* preds: */ vec1 32 ssa_0 = load_const (0x3f800000 = 1.000000) vec1 32 ssa_1 = load_const (0x00000000 = 0.000000) vec4 32 ssa_2 = intrinsic load_uniform (ssa_1) (base=0, range=1, dest_type=bool32 /*38*/) /* u_var */ vec1 32 ssa_4 = fmul ssa_2.x, ssa_2.y vec1 32 ssa_11 = load_const (0x00000000 = 0.000000) vec1 32 ssa_13 = seq ssa_2.w, ssa_11 vec1 32 ssa_6 = fmul ssa_2.z, ssa_13 vec1 32 ssa_7 = fmul ssa_4, ssa_6 vec1 32 ssa_9 = deref_var &gl_FragColor (shader_out vec4) vec4 32 ssa_10 = vec4 ssa_7, ssa_7, ssa_7, ssa_0 intrinsic store_deref (ssa_9, ssa_10) (wrmask=xyzw /*15*/, access=0) /* succs: block_1 */ block block_1: } The current compiler transforms it to: impl main { block block_0: /* preds: */ vec1 32 ssa_0 = load_const (0x3f800000 = 1.000000) vec4 32 ssa_14 = load_const (0x00000000, 0x00000001, 0x00000002, 0x00000003) = (0.000000, 0.000000, 0.000000, 0.000000) vec2 32 ssa_15 = load_const (0x00000000, 0x00000001) = (0.000000, 0.000000) vec1 32 ssa_4 = fmul ssa_15.x, ssa_15.y vec2 32 ssa_16 = load_const (0x00000003, 0x00000000) = (0.000000, 0.000000) vec1 32 ssa_13 = seq ssa_16.x, ssa_16.y vec1 32 ssa_6 = fmul ssa_14.z, ssa_13 vec1 32 ssa_7 = fmul ssa_4, ssa_6 vec1 32 ssa_9 = deref_var &gl_FragColor (shader_out vec4) vec1 32 ssa_17 = mov ssa_0 vec4 32 ssa_10 = vec4 ssa_7, ssa_7, ssa_7, ssa_17 intrinsic store_deref (ssa_9, ssa_10) (wrmask=xyzw /*15*/, access=0) /* succs: block_1 */ block block_1: } There is no need to create ssa_15 as we can use ssa_14 for the first fmul. With this change the compiler creates the following shader: impl main { block block_0: /* preds: */ vec1 32 ssa_0 = load_const (0x3f800000 = 1.000000) vec4 32 ssa_14 = load_const (0x00000000, 0x00000001, 0x00000002, 0x00000003) = (0.000000, 0.000000, 0.000000, 0.000000) vec1 32 ssa_4 = fmul ssa_14.x, ssa_14.y vec2 32 ssa_15 = load_const (0x00000003, 0x00000000) = (0.000000, 0.000000) vec1 32 ssa_13 = seq ssa_15.x, ssa_15.y vec1 32 ssa_6 = fmul ssa_14.z, ssa_13 vec1 32 ssa_7 = fmul ssa_4, ssa_6 vec1 32 ssa_9 = deref_var &gl_FragColor (shader_out vec4) vec1 32 ssa_16 = mov ssa_0 vec4 32 ssa_10 = vec4 ssa_7, ssa_7, ssa_7, ssa_16 intrinsic store_deref (ssa_9, ssa_10) (wrmask=xyzw /*15*/, access=0) /* succs: block_1 */ block block_1: } This change reduces immediate pressure and reduces spend CPU cycles. No piglit or deqp regression seen. shader-db results for GC2000: total instructions in shared programs: 955128 -> 955128 (0.00%) instructions in affected programs: 0 -> 0 helped: 0 HURT: 0 total temps in shared programs: 85689 -> 85689 (0.00%) temps in affected programs: 0 -> 0 helped: 0 HURT: 0 total immediates in shared programs: 155428 -> 155240 (-0.12%) immediates in affected programs: 1840 -> 1652 (-10.22%) helped: 34 HURT: 1 helped stats (abs) min: 4 max: 16 x̄: 5.65 x̃: 4 helped stats (rel) min: 2.94% max: 33.33% x̄: 16.92% x̃: 16.67% HURT stats (abs) min: 4 max: 4 x̄: 4.00 x̃: 4 HURT stats (rel) min: 14.29% max: 14.29% x̄: 14.29% x̃: 14.29% 95% mean confidence interval for immediates value: -6.57 -4.17 95% mean confidence interval for immediates %-change: -19.83% -12.23% Immediates are helped. total loops in shared programs: 0 -> 0 loops in affected programs: 0 -> 0 helped: 0 HURT: 0 LOST: 0 GAINED: 0 Total CPU time (seconds): 102.55 -> 96.35 (-6.05%) Signed-off-by: Christian Gmeiner Reviewed-by: Lucas Stach Part-of: --- src/gallium/drivers/etnaviv/etnaviv_compiler_nir.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/etnaviv/etnaviv_compiler_nir.c b/src/gallium/drivers/etnaviv/etnaviv_compiler_nir.c index 0fb7dbd44ab..93204103838 100644 --- a/src/gallium/drivers/etnaviv/etnaviv_compiler_nir.c +++ b/src/gallium/drivers/etnaviv/etnaviv_compiler_nir.c @@ -763,7 +763,8 @@ lower_alu(struct etna_compile *c, nir_alu_instr *alu) nir_const_value value[4] = {}; uint8_t swizzle[4][4] = {}; - unsigned swiz_max = 0, num_const = 0; + unsigned swiz_max = 0, num_different_const_srcs = 0; + int first_const = -1; for (unsigned i = 0; i < info->num_inputs; i++) { nir_const_value *cv = nir_src_as_const_value(alu->src[i].src); @@ -776,11 +777,16 @@ lower_alu(struct etna_compile *c, nir_alu_instr *alu) swizzle[i][j] = idx; swiz_max = MAX2(swiz_max, (unsigned) idx); } - num_const++; + + if (first_const == -1) + first_const = i; + + if (!nir_srcs_equal(alu->src[first_const].src, alu->src[i].src)) + num_different_const_srcs++; } /* nothing to do */ - if (num_const <= 1) + if (num_different_const_srcs == 0) return; /* resolve with single combined const src */ @@ -801,7 +807,7 @@ lower_alu(struct etna_compile *c, nir_alu_instr *alu) } /* resolve with movs */ - num_const = 0; + unsigned num_const = 0; for (unsigned i = 0; i < info->num_inputs; i++) { nir_const_value *cv = nir_src_as_const_value(alu->src[i].src); if (!cv)