diff options
author | Kenneth Graunke <[email protected]> | 2015-11-03 00:31:22 -0800 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-11-18 12:28:32 -0800 |
commit | 9ff71b649b4b3808a9e17ce69743c6037fd6603c (patch) | |
tree | 43664cd40ec6c9edb84b72a59cae59cd6d90797a /src | |
parent | 7bc097899924f40140981567c7bb52297dd801f2 (diff) |
i965/nir: Validate that NIR passes call nir_metadata_preserve().
Failing to call nir_metadata_preserve() can have nasty consequences:
some pass breaks dominance information, but leaves it marked as valid,
causing some subsequent pass to go haywire and probably crash.
This pass adds a simple validation mechanism to ensure passes handle
this properly. We add a new bogus metadata flag that isn't used for
anything in particular, set it before each pass, and ensure it *isn't*
still set after the pass. nir_metadata_preserve will reset the flag,
so correct passes will work, and bad passes will assert fail.
(I would have made these functions static inline, but nir.h is included
in C++, so we can't bit-or enums without lots of casting...)
Thanks to Dylan Baker for the idea.
Signed-off-by: Kenneth Graunke <[email protected]>
Reviewed-by: Jason Ekstrand <[email protected]>
Reviewed-by: Iago Toral Quiroga <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/glsl/nir/nir.h | 5 | ||||
-rw-r--r-- | src/glsl/nir/nir_metadata.c | 36 | ||||
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_nir.c | 10 |
3 files changed, 48 insertions, 3 deletions
diff --git a/src/glsl/nir/nir.h b/src/glsl/nir/nir.h index 3d65128e751..7eccebe76c6 100644 --- a/src/glsl/nir/nir.h +++ b/src/glsl/nir/nir.h @@ -1312,6 +1312,7 @@ typedef enum { nir_metadata_block_index = 0x1, nir_metadata_dominance = 0x2, nir_metadata_live_ssa_defs = 0x4, + nir_metadata_not_properly_reset = 0x8, } nir_metadata; typedef struct { @@ -1891,8 +1892,12 @@ void nir_print_instr(const nir_instr *instr, FILE *fp); #ifdef DEBUG void nir_validate_shader(nir_shader *shader); +void nir_metadata_set_validation_flag(nir_shader *shader); +void nir_metadata_check_validation_flag(nir_shader *shader); #else static inline void nir_validate_shader(nir_shader *shader) { (void) shader; } +static inline void nir_metadata_set_validation_flag(nir_shader *shader) { (void) shader; } +static inline void nir_metadata_check_validation_flag(nir_shader *shader) { (void) shader; } #endif /* DEBUG */ void nir_calc_dominance_impl(nir_function_impl *impl); diff --git a/src/glsl/nir/nir_metadata.c b/src/glsl/nir/nir_metadata.c index 6de981f430f..d5324b35a78 100644 --- a/src/glsl/nir/nir_metadata.c +++ b/src/glsl/nir/nir_metadata.c @@ -52,3 +52,39 @@ nir_metadata_preserve(nir_function_impl *impl, nir_metadata preserved) { impl->valid_metadata &= preserved; } + +#ifdef DEBUG +/** + * Make sure passes properly invalidate metadata (part 1). + * + * Call this before running a pass to set a bogus metadata flag, which will + * only be preserved if the pass forgets to call nir_metadata_preserve(). + */ +void +nir_metadata_set_validation_flag(nir_shader *shader) +{ + nir_foreach_overload(shader, overload) { + if (overload->impl) { + overload->impl->valid_metadata |= nir_metadata_not_properly_reset; + } + } +} + +/** + * Make sure passes properly invalidate metadata (part 2). + * + * Call this after a pass makes progress to verify that the bogus metadata set by + * the earlier function was properly thrown away. Note that passes may not call + * nir_metadata_preserve() if they don't actually make any changes at all. + */ +void +nir_metadata_check_validation_flag(nir_shader *shader) +{ + nir_foreach_overload(shader, overload) { + if (overload->impl) { + assert(!(overload->impl->valid_metadata & + nir_metadata_not_properly_reset)); + } + } +} +#endif diff --git a/src/mesa/drivers/dri/i965/brw_nir.c b/src/mesa/drivers/dri/i965/brw_nir.c index b19f9691956..7826729db85 100644 --- a/src/mesa/drivers/dri/i965/brw_nir.c +++ b/src/mesa/drivers/dri/i965/brw_nir.c @@ -178,9 +178,13 @@ brw_nir_lower_outputs(nir_shader *nir, bool is_scalar) this_progress; \ })) -#define OPT(pass, ...) _OPT( \ - this_progress = pass(nir ,##__VA_ARGS__); \ - progress = progress || this_progress; \ +#define OPT(pass, ...) _OPT( \ + nir_metadata_set_validation_flag(nir); \ + this_progress = pass(nir ,##__VA_ARGS__); \ + if (this_progress) { \ + progress = true; \ + nir_metadata_check_validation_flag(nir); \ + } \ ) #define OPT_V(pass, ...) _OPT( \ |