diff options
-rw-r--r-- | .pick_status.json | 2 | ||||
-rw-r--r-- | src/broadcom/compiler/nir_to_vir.c | 62 | ||||
-rw-r--r-- | src/broadcom/compiler/v3d_compiler.h | 1 | ||||
-rw-r--r-- | src/broadcom/compiler/vir_register_allocate.c | 20 |
4 files changed, 61 insertions, 24 deletions
diff --git a/.pick_status.json b/.pick_status.json index 3035d562be3..4cf1ff0b2ce 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -1984,7 +1984,7 @@ "description": "broadcom/compiler: force a last thrsw for spilling", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null }, diff --git a/src/broadcom/compiler/nir_to_vir.c b/src/broadcom/compiler/nir_to_vir.c index 2a4dac723f6..223e7f00cc8 100644 --- a/src/broadcom/compiler/nir_to_vir.c +++ b/src/broadcom/compiler/nir_to_vir.c @@ -3900,9 +3900,25 @@ vir_remove_thrsw(struct v3d_compile *c) c->last_thrsw = NULL; } -void -vir_emit_last_thrsw(struct v3d_compile *c) +/** + * This makes sure we have a top-level last thread switch which signals the + * start of the last thread section, which may include adding a new thrsw + * instruction if needed. We don't allow spilling in the last thread section, so + * if we need to do any spills that inject additional thread switches later on, + * we ensure this thread switch will still be the last thread switch in the + * program, which makes last thread switch signalling a lot easier when we have + * spilling. If in the end we don't need to spill to compile the program and we + * injected a new thread switch instruction here only for that, we will + * eventually restore the previous last thread switch and remove the one we + * added here. + */ +static void +vir_emit_last_thrsw(struct v3d_compile *c, + struct qinst **restore_last_thrsw, + bool *restore_scoreboard_lock) { + *restore_last_thrsw = c->last_thrsw; + /* On V3D before 4.1, we need a TMU op to be outstanding when thread * switching, so disable threads if we didn't do any TMU ops (each of * which would have emitted a THRSW). @@ -3911,7 +3927,7 @@ vir_emit_last_thrsw(struct v3d_compile *c) c->threads = 1; if (c->last_thrsw) vir_remove_thrsw(c); - return; + *restore_last_thrsw = NULL; } /* If we're threaded and the last THRSW was in conditional code, then @@ -3934,8 +3950,34 @@ vir_emit_last_thrsw(struct v3d_compile *c) vir_emit_thrsw(c); } + /* If we have not inserted a last thread switch yet, do it now to ensure + * any potential spilling we do happens before this. If we don't spill + * in the end, we will restore the previous one. + */ + if (*restore_last_thrsw == c->last_thrsw) { + if (*restore_last_thrsw) + (*restore_last_thrsw)->is_last_thrsw = false; + *restore_scoreboard_lock = c->lock_scoreboard_on_first_thrsw; + vir_emit_thrsw(c); + } else { + *restore_last_thrsw = c->last_thrsw; + } + + assert(c->last_thrsw); + c->last_thrsw->is_last_thrsw = true; +} + +static void +vir_restore_last_thrsw(struct v3d_compile *c, + struct qinst *thrsw, + bool scoreboard_lock) +{ + assert(c->last_thrsw); + vir_remove_instruction(c, c->last_thrsw); + c->last_thrsw = thrsw; if (c->last_thrsw) c->last_thrsw->is_last_thrsw = true; + c->lock_scoreboard_on_first_thrsw = scoreboard_lock; } /* There's a flag in the shader for "center W is needed for reasons other than @@ -3973,8 +4015,14 @@ v3d_nir_to_vir(struct v3d_compile *c) nir_to_vir(c); + bool restore_scoreboard_lock = false; + struct qinst *restore_last_thrsw; + /* Emit the last THRSW before STVPM and TLB writes. */ - vir_emit_last_thrsw(c); + vir_emit_last_thrsw(c, + &restore_last_thrsw, + &restore_scoreboard_lock); + switch (c->s->info.stage) { case MESA_SHADER_FRAGMENT: @@ -4073,6 +4121,12 @@ v3d_nir_to_vir(struct v3d_compile *c) vir_remove_thrsw(c); } + /* If we didn't spill, then remove the last thread switch we injected + * artificially (if any) and restore the previous one. + */ + if (!c->spills && c->last_thrsw != restore_last_thrsw) + vir_restore_last_thrsw(c, restore_last_thrsw, restore_scoreboard_lock); + if (c->spills && (V3D_DEBUG & (V3D_DEBUG_VIR | v3d_debug_flag_for_shader_stage(c->s->info.stage)))) { diff --git a/src/broadcom/compiler/v3d_compiler.h b/src/broadcom/compiler/v3d_compiler.h index c1ea346bead..23a04c24dd9 100644 --- a/src/broadcom/compiler/v3d_compiler.h +++ b/src/broadcom/compiler/v3d_compiler.h @@ -1051,7 +1051,6 @@ void vir_set_unpack(struct qinst *inst, int src, void vir_set_pack(struct qinst *inst, enum v3d_qpu_output_pack pack); struct qreg vir_get_temp(struct v3d_compile *c); -void vir_emit_last_thrsw(struct v3d_compile *c); void vir_calculate_live_intervals(struct v3d_compile *c); int vir_get_nsrc(struct qinst *inst); bool vir_has_side_effects(struct v3d_compile *c, struct qinst *inst); diff --git a/src/broadcom/compiler/vir_register_allocate.c b/src/broadcom/compiler/vir_register_allocate.c index c55d8dc937d..60535c17a4b 100644 --- a/src/broadcom/compiler/vir_register_allocate.c +++ b/src/broadcom/compiler/vir_register_allocate.c @@ -251,7 +251,7 @@ v3d_spill_reg(struct v3d_compile *c, int spill_temp) } struct qinst *last_thrsw = c->last_thrsw; - assert(!last_thrsw || last_thrsw->is_last_thrsw); + assert(last_thrsw && last_thrsw->is_last_thrsw); int start_num_temps = c->num_temps; @@ -337,29 +337,13 @@ v3d_spill_reg(struct v3d_compile *c, int spill_temp) spill_offset); } } - - /* If we didn't have a last-thrsw inserted by nir_to_vir and - * we've been inserting thrsws, then insert a new last_thrsw - * right before we start the vpm/tlb sequence for the last - * thread segment. - */ - if (!is_uniform && !last_thrsw && c->last_thrsw && - (v3d_qpu_writes_vpm(&inst->qpu) || - v3d_qpu_uses_tlb(&inst->qpu))) { - c->cursor = vir_before_inst(inst); - vir_emit_thrsw(c); - - last_thrsw = c->last_thrsw; - last_thrsw->is_last_thrsw = true; - } } } /* Make sure c->last_thrsw is the actual last thrsw, not just one we * inserted in our most recent unspill. */ - if (last_thrsw) - c->last_thrsw = last_thrsw; + c->last_thrsw = last_thrsw; /* Don't allow spilling of our spilling instructions. There's no way * they can help get things colored. |