tint: uniformity: detect pointers assigned to in non-uniform control flow
Bug: tint:1558 Change-Id: Ia92258f1fb40b008a6052ce2ea5a20ec29351ce5 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/93264 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: James Price <jrprice@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
parent
737ff5b482
commit
856d6af57e
|
@ -305,7 +305,7 @@ class UniformityGraph {
|
||||||
/// @param ast the optional AST node that this node corresponds to
|
/// @param ast the optional AST node that this node corresponds to
|
||||||
/// @returns the new node
|
/// @returns the new node
|
||||||
Node* CreateNode(std::string tag, const ast::Node* ast = nullptr) {
|
Node* CreateNode(std::string tag, const ast::Node* ast = nullptr) {
|
||||||
return current_function_->CreateNode(tag, ast);
|
return current_function_->CreateNode(std::move(tag), ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Process a function.
|
/// Process a function.
|
||||||
|
@ -1248,6 +1248,10 @@ class UniformityGraph {
|
||||||
if (func_info->parameters[i].pointer_may_become_non_uniform) {
|
if (func_info->parameters[i].pointer_may_become_non_uniform) {
|
||||||
ptr_result->AddEdge(current_function_->may_be_non_uniform);
|
ptr_result->AddEdge(current_function_->may_be_non_uniform);
|
||||||
} else {
|
} else {
|
||||||
|
// Add edge to the call to catch when it's called in non-uniform control
|
||||||
|
// flow.
|
||||||
|
ptr_result->AddEdge(call_node);
|
||||||
|
|
||||||
// Add edges from the resulting pointer value to any other arguments that
|
// Add edges from the resulting pointer value to any other arguments that
|
||||||
// feed it.
|
// feed it.
|
||||||
for (auto* source : func_info->parameters[i].pointer_param_output_sources) {
|
for (auto* source : func_info->parameters[i].pointer_param_output_sources) {
|
||||||
|
|
|
@ -4624,6 +4624,145 @@ test:12:11 note: reading from read_write storage buffer 'non_uniform' may result
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(UniformityAnalysisTest, PointerParamModifiedInNonUniformControlFlow) {
|
||||||
|
std::string src = R"(
|
||||||
|
@binding(0) @group(0) var<storage, read_write> non_uniform_global : i32;
|
||||||
|
|
||||||
|
fn foo(p : ptr<function, i32>) {
|
||||||
|
*p = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
@compute @workgroup_size(64)
|
||||||
|
fn main() {
|
||||||
|
var a : i32;
|
||||||
|
if (non_uniform_global == 0) {
|
||||||
|
foo(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == 0) {
|
||||||
|
workgroupBarrier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
RunTest(src, false);
|
||||||
|
EXPECT_EQ(error_,
|
||||||
|
R"(test:16:5 warning: 'workgroupBarrier' must only be called from uniform control flow
|
||||||
|
workgroupBarrier();
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
test:11:3 note: control flow depends on non-uniform value
|
||||||
|
if (non_uniform_global == 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
test:11:7 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
|
||||||
|
if (non_uniform_global == 0) {
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UniformityAnalysisTest, PointerParamAssumedModifiedInNonUniformControlFlow) {
|
||||||
|
std::string src = R"(
|
||||||
|
@binding(0) @group(0) var<storage, read_write> non_uniform_global : i32;
|
||||||
|
|
||||||
|
fn foo(p : ptr<function, i32>) {
|
||||||
|
// Do not modify 'p', uniformity analysis presently assumes it will be.
|
||||||
|
}
|
||||||
|
|
||||||
|
@compute @workgroup_size(64)
|
||||||
|
fn main() {
|
||||||
|
var a : i32;
|
||||||
|
if (non_uniform_global == 0) {
|
||||||
|
foo(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == 0) {
|
||||||
|
workgroupBarrier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
RunTest(src, false);
|
||||||
|
EXPECT_EQ(error_,
|
||||||
|
R"(test:16:5 warning: 'workgroupBarrier' must only be called from uniform control flow
|
||||||
|
workgroupBarrier();
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
test:11:3 note: control flow depends on non-uniform value
|
||||||
|
if (non_uniform_global == 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
test:11:7 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
|
||||||
|
if (non_uniform_global == 0) {
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UniformityAnalysisTest, PointerParamModifiedInNonUniformControlFlow_NestedCall) {
|
||||||
|
std::string src = R"(
|
||||||
|
@binding(0) @group(0) var<storage, read_write> non_uniform_global : i32;
|
||||||
|
|
||||||
|
fn foo2(p : ptr<function, i32>) {
|
||||||
|
*p = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn foo(p : ptr<function, i32>) {
|
||||||
|
foo2(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
@compute @workgroup_size(64)
|
||||||
|
fn main() {
|
||||||
|
var a : i32;
|
||||||
|
if (non_uniform_global == 0) {
|
||||||
|
foo(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == 0) {
|
||||||
|
workgroupBarrier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
RunTest(src, false);
|
||||||
|
EXPECT_EQ(error_,
|
||||||
|
R"(test:20:5 warning: 'workgroupBarrier' must only be called from uniform control flow
|
||||||
|
workgroupBarrier();
|
||||||
|
^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
test:15:3 note: control flow depends on non-uniform value
|
||||||
|
if (non_uniform_global == 0) {
|
||||||
|
^^
|
||||||
|
|
||||||
|
test:15:7 note: reading from read_write storage buffer 'non_uniform_global' may result in a non-uniform value
|
||||||
|
if (non_uniform_global == 0) {
|
||||||
|
^^^^^^^^^^^^^^^^^^
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(UniformityAnalysisTest, PointerParamModifiedInUniformControlFlow) {
|
||||||
|
std::string src = R"(
|
||||||
|
@binding(0) @group(0) var<uniform> uniform_global : i32;
|
||||||
|
|
||||||
|
fn foo(p : ptr<function, i32>) {
|
||||||
|
*p = 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
@compute @workgroup_size(64)
|
||||||
|
fn main() {
|
||||||
|
var a : i32;
|
||||||
|
if (uniform_global == 0) {
|
||||||
|
foo(&a);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a == 0) {
|
||||||
|
workgroupBarrier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
RunTest(src, true);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(UniformityAnalysisTest, NonUniformPointerParameterBecomesUniform_AfterUse) {
|
TEST_F(UniformityAnalysisTest, NonUniformPointerParameterBecomesUniform_AfterUse) {
|
||||||
std::string src = R"(
|
std::string src = R"(
|
||||||
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
|
||||||
|
|
Loading…
Reference in New Issue