(nir_variable_mode)(nir_var_mem_ssbo | nir_var_mem_ubo |
nir_var_mem_push_const | nir_var_mem_shared |
nir_var_mem_global),
- mem_vectorize_callback)) {
+ mem_vectorize_callback,
+ (nir_variable_mode)0)) {
lower_to_scalar = true;
lower_pack = true;
}
nir_intrinsic_instr *low, nir_intrinsic_instr *high);
bool nir_opt_load_store_vectorize(nir_shader *shader, nir_variable_mode modes,
- nir_should_vectorize_mem_func callback);
+ nir_should_vectorize_mem_func callback,
+ nir_variable_mode robust_modes);
void nir_schedule(nir_shader *shader, int threshold);
struct vectorize_ctx {
nir_variable_mode modes;
nir_should_vectorize_mem_func callback;
+ nir_variable_mode robust_modes;
struct list_head entries[nir_num_variable_modes];
struct hash_table *loads[nir_num_variable_modes];
struct hash_table *stores[nir_num_variable_modes];
return false;
}
+static bool
+check_for_robustness(struct vectorize_ctx *ctx, struct entry *low)
+{
+ nir_variable_mode mode = get_variable_mode(low);
+ if (mode & ctx->robust_modes) {
+ unsigned low_bit_size = get_bit_size(low);
+ unsigned low_size = low->intrin->num_components * low_bit_size;
+
+ /* don't attempt to vectorize accesses if the offset can overflow. */
+ /* TODO: handle indirect accesses. */
+ return low->offset_signed < 0 && low->offset_signed + low_size >= 0;
+ }
+
+ return false;
+}
+
static bool
is_strided_vector(const struct glsl_type *type)
{
if (check_for_aliasing(ctx, first, second))
return false;
+ if (check_for_robustness(ctx, low))
+ return false;
+
/* we can only vectorize non-volatile loads/stores of the same type and with
* the same access */
if (first->info != second->info || first->access != second->access ||
bool
nir_opt_load_store_vectorize(nir_shader *shader, nir_variable_mode modes,
- nir_should_vectorize_mem_func callback)
+ nir_should_vectorize_mem_func callback,
+ nir_variable_mode robust_modes)
{
bool progress = false;
struct vectorize_ctx *ctx = rzalloc(NULL, struct vectorize_ctx);
ctx->modes = modes;
ctx->callback = callback;
+ ctx->robust_modes = robust_modes;
nir_index_vars(shader, NULL, modes);
nir_intrinsic_instr *get_intrinsic(nir_intrinsic_op intrinsic,
unsigned index);
- bool run_vectorizer(nir_variable_mode modes, bool cse=false);
+ bool run_vectorizer(nir_variable_mode modes, bool cse=false,
+ nir_variable_mode robust_modes = (nir_variable_mode)0);
nir_ssa_def *get_resource(uint32_t binding, bool ssbo);
}
bool
-nir_load_store_vectorize_test::run_vectorizer(nir_variable_mode modes, bool cse)
+nir_load_store_vectorize_test::run_vectorizer(nir_variable_mode modes,
+ bool cse,
+ nir_variable_mode robust_modes)
{
if (modes & nir_var_mem_shared)
nir_lower_vars_to_explicit_types(b->shader, nir_var_mem_shared, shared_type_info);
- bool progress = nir_opt_load_store_vectorize(b->shader, modes, mem_vectorize_callback);
+ bool progress = nir_opt_load_store_vectorize(b->shader, modes, mem_vectorize_callback, robust_modes);
if (progress) {
nir_validate_shader(b->shader, NULL);
if (cse)
ASSERT_EQ(count_intrinsics(nir_intrinsic_load_ssbo), 2);
}
+
+TEST_F(nir_load_store_vectorize_test, ssbo_offset_overflow_robust)
+{
+ create_load(nir_var_mem_ssbo, 0, 0xfffffffc, 0x1);
+ create_load(nir_var_mem_ssbo, 0, 0x0, 0x2);
+
+ nir_validate_shader(b->shader, NULL);
+ ASSERT_EQ(count_intrinsics(nir_intrinsic_load_ssbo), 2);
+
+ EXPECT_FALSE(run_vectorizer(nir_var_mem_ssbo, false, nir_var_mem_ssbo));
+
+ ASSERT_EQ(count_intrinsics(nir_intrinsic_load_ssbo), 2);
+}
OPT(nir_opt_load_store_vectorize,
nir_var_mem_ubo | nir_var_mem_ssbo |
nir_var_mem_global | nir_var_mem_shared,
- brw_nir_should_vectorize_mem);
+ brw_nir_should_vectorize_mem,
+ (nir_variable_mode)0);
}
OPT(brw_nir_lower_mem_access_bit_sizes, devinfo);