nir: add helpers to skip idempotent passes

For example, in the loop:
while (more_late_algebraic) {
   more_late_algebraic = false;
   NIR_PASS(more_late_algebraic, nir, nir_opt_algebraic_late);
   NIR_PASS(_, nir, nir_opt_constant_folding);
   NIR_PASS(_, nir, nir_copy_prop);
   NIR_PASS(_, nir, nir_opt_dce);
   NIR_PASS(_, nir, nir_opt_cse);
}
if nir_opt_algebraic_late makes no progress, later passes might be
skippable depending on which ones made progress in the previous iteration.

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24197>
This commit is contained in:
Rhys Perry 2023-07-17 17:49:04 +01:00 committed by Marge Bot
parent faed5d647f
commit debddca134

View file

@ -4883,6 +4883,51 @@ should_print_nir(UNUSED nir_shader *shader)
nir_print_shader(nir, stdout); \
})
#define _NIR_LOOP_PASS(progress, idempotent, skip, nir, pass, ...) \
do { \
bool nir_loop_pass_progress = false; \
if (!_mesa_set_search(skip, (void (*)())&pass)) \
NIR_PASS(nir_loop_pass_progress, nir, pass, ##__VA_ARGS__); \
if (nir_loop_pass_progress) \
_mesa_set_clear(skip, NULL); \
if (idempotent || !nir_loop_pass_progress) \
_mesa_set_add(skip, (void (*)())&pass); \
UNUSED bool _ = false; \
progress |= nir_loop_pass_progress; \
} while (0)
/* Helper to skip a pass if no different passes have made progress since it was
* previously run. Note that two passes are considered the same if they have
* the same function pointer, even if they used different options.
*
* The usage of this is mostly identical to NIR_PASS. "skip" is a "struct set *"
* (created by _mesa_pointer_set_create) which the macro uses to keep track of
* already run passes.
*
* Example:
* bool progress = true;
* struct set *skip = _mesa_pointer_set_create(NULL);
* while (progress) {
* progress = false;
* NIR_LOOP_PASS(progress, skip, nir, pass1);
* NIR_LOOP_PASS_NOT_IDEMPOTENT(progress, skip, nir, nir_opt_algebraic);
* NIR_LOOP_PASS(progress, skip, nir, pass2);
* ...
* }
* _mesa_set_destroy(skip, NULL);
*
* You shouldn't mix usage of this with the NIR_PASS set of helpers, without
* using a new "skip" in-between.
*/
#define NIR_LOOP_PASS(progress, skip, nir, pass, ...) \
_NIR_LOOP_PASS(progress, true, skip, nir, pass, ##__VA_ARGS__)
/* Like NIR_LOOP_PASS, but use this for passes which may make further progress
* when repeated.
*/
#define NIR_LOOP_PASS_NOT_IDEMPOTENT(progress, skip, nir, pass, ...) \
_NIR_LOOP_PASS(progress, false, skip, nir, pass, ##__VA_ARGS__)
#define NIR_SKIP(name) should_skip_nir(#name)
/** An instruction filtering callback with writemask