Module: Mesa Branch: main Commit: 0158075b22dc40d157719a65a434e1e07fe6fdec URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=0158075b22dc40d157719a65a434e1e07fe6fdec
Author: Christian Gmeiner <cgmei...@igalia.com> Date: Sun Jan 3 09:29:20 2021 +0100 nir/opt_peephole_select: handle speculative ubo loads Some platforms may be able to speculate ubo loads safely. Signed-off-by: Christian Gmeiner <cgmei...@igalia.com> Reviewed-by: Alyssa Rosenzweig <aly...@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8299> --- src/compiler/nir/meson.build | 1 + src/compiler/nir/nir_opt_peephole_select.c | 8 ++ src/compiler/nir/tests/opt_peephole_select.cpp | 153 +++++++++++++++++++++++++ 3 files changed, 162 insertions(+) diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build index 7cd73f4082a..66011a67126 100644 --- a/src/compiler/nir/meson.build +++ b/src/compiler/nir/meson.build @@ -358,6 +358,7 @@ if with_tests 'tests/mod_analysis_tests.cpp', 'tests/negative_equal_tests.cpp', 'tests/opt_if_tests.cpp', + 'tests/opt_peephole_select.cpp', 'tests/opt_shrink_vectors_tests.cpp', 'tests/serialize_tests.cpp', 'tests/range_analysis_tests.cpp', diff --git a/src/compiler/nir/nir_opt_peephole_select.c b/src/compiler/nir/nir_opt_peephole_select.c index 043e1bad041..8ec072ab4ac 100644 --- a/src/compiler/nir/nir_opt_peephole_select.c +++ b/src/compiler/nir/nir_opt_peephole_select.c @@ -128,6 +128,14 @@ block_check_for_allowed_instrs(nir_block *block, unsigned *count, break; } + case nir_intrinsic_load_ubo: + case nir_intrinsic_load_ubo_vec4: + if (!indirect_load_ok && !nir_src_is_const(intrin->src[1])) + return false; + if (!(nir_intrinsic_access(intrin) & ACCESS_CAN_SPECULATE)) + return false; + break; + case nir_intrinsic_load_uniform: case nir_intrinsic_load_preamble: case nir_intrinsic_load_helper_invocation: diff --git a/src/compiler/nir/tests/opt_peephole_select.cpp b/src/compiler/nir/tests/opt_peephole_select.cpp new file mode 100644 index 00000000000..bc4864afd7c --- /dev/null +++ b/src/compiler/nir/tests/opt_peephole_select.cpp @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2020 Etnaviv Project + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sub license, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Christian Gmeiner <christian.gmei...@gmail.com> + */ + +#include <gtest/gtest.h> +#include "nir.h" +#include "nir_builder.h" + +class nir_opt_peephole_select_test : public ::testing::Test { +protected: + nir_opt_peephole_select_test(); + ~nir_opt_peephole_select_test(); + + nir_builder bld; +}; + +nir_opt_peephole_select_test::nir_opt_peephole_select_test() +{ + glsl_type_singleton_init_or_ref(); + + static const nir_shader_compiler_options options = { }; + bld = nir_builder_init_simple_shader(MESA_SHADER_VERTEX, &options, "peephole test"); +} + +nir_opt_peephole_select_test::~nir_opt_peephole_select_test() +{ + ralloc_free(bld.shader); + glsl_type_singleton_decref(); +} + +TEST_F(nir_opt_peephole_select_test, opt_load_ubo_no_speculate) +{ + /* Tests that opt_peephole_select does not optimize ubo loads: + * + * impl main { + * block b0: // preds: + * 32 %0 = load_const (0x00000001) + * 32 %1 = load_const (0x00000002) + * 32 %2 = load_const (0x0000000a = 10) + * 1 %3 = ieq %0 (0x1), %1 (0x2) + * // succs: b1 b2 + * if %3 { + * block b1: // preds: b0 + * 32 %4 = @load_ubo (%0 (0x1), %2 (0xa)) (access=0, align_mul=16, align_offset=0, range_base=16, range=16) + * // succs: b3 + * } else { + * block b2: // preds: b0 + * 32 %5 = @load_ubo (%0 (0x1), %2 (0xa)) (access=0, align_mul=16, align_offset=0, range_base=16, range=16) + * // succs: b3 + * } + * block b3: // preds: b1 b2, succs: b4 + * block b4: + * } + */ + nir_function *main = nir_shader_get_function_for_name(bld.shader, "main"); + + nir_def *one = nir_imm_int(&bld, 1); + nir_def *two = nir_imm_int(&bld, 2); + nir_def *ten = nir_imm_int(&bld, 10); + + nir_def *cmp_result = nir_ieq(&bld, one, two); + nir_push_if(&bld, cmp_result); + + nir_load_ubo(&bld, 1, 32, one, ten, (gl_access_qualifier)0, 16, 0, 16, 16); + + nir_push_else(&bld, NULL); + + nir_load_ubo(&bld, 1, 32, one, ten, (gl_access_qualifier)0, 16, 0, 16, 16); + + nir_pop_if(&bld, NULL); + + nir_index_blocks(main->impl); + EXPECT_EQ(main->impl->num_blocks, 4); + + ASSERT_FALSE(nir_opt_peephole_select(bld.shader, 16, true, true)); + nir_validate_shader(bld.shader, NULL); + + nir_index_blocks(main->impl); + EXPECT_EQ(main->impl->num_blocks, 4); +} + +TEST_F(nir_opt_peephole_select_test, opt_load_ubo_speculate) +{ + /* Tests that opt_peephole_select correctly optimizes speculative ubo loads: + * + * impl main { + * block b0: // preds: + * 32 %0 = load_const (0x00000001) + * 32 %1 = load_const (0x00000002) + * 32 %2 = load_const (0x0000000a = 10) + * 1 %3 = ieq %0 (0x1), %1 (0x2) + * // succs: b1 b2 + * if %3 { + * block b1: // preds: b0 + * 32 %4 = @load_ubo (%0 (0x1), %2 (0xa)) (access=4096, align_mul=16, align_offset=0, range_base=16, range=16) + * // succs: b3 + * } else { + * block b2: // preds: b0 + * 32 %5 = @load_ubo (%0 (0x1), %2 (0xa)) (access=4096, align_mul=16, align_offset=0, range_base=16, range=16) + * // succs: b3 + * } + * block b3: // preds: b1 b2, succs: b4 + * block b4: + *} + */ + nir_function *main = nir_shader_get_function_for_name(bld.shader, "main"); + + nir_def *one = nir_imm_int(&bld, 1); + nir_def *two = nir_imm_int(&bld, 2); + nir_def *ten = nir_imm_int(&bld, 10); + + nir_def *cmp_result = nir_ieq(&bld, one, two); + nir_push_if(&bld, cmp_result); + + nir_load_ubo(&bld, 1, 32, one, ten, (gl_access_qualifier)ACCESS_CAN_SPECULATE, 16, 0, 16, 16); + + nir_push_else(&bld, NULL); + + nir_load_ubo(&bld, 1, 32, one, ten, (gl_access_qualifier)ACCESS_CAN_SPECULATE, 16, 0, 16, 16); + + nir_pop_if(&bld, NULL); + + nir_index_blocks(main->impl); + EXPECT_EQ(main->impl->num_blocks, 4); + + ASSERT_TRUE(nir_opt_peephole_select(bld.shader, 16, true, true)); + nir_validate_shader(bld.shader, NULL); + + nir_index_blocks(main->impl); + EXPECT_EQ(main->impl->num_blocks, 1); +}