tint: Add implicit CF_return->{last cf} edge

If the function has no return statements, we need to do this to
capture the potential non-uniformity coming from nested function
calls.

This also removes the need to add explicit edges for discard
statements, so remove them.

Bug: tint:880
Change-Id: I88b1132faf35a6d36460ef353912f77a15f8abaa
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/89861
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2022-05-12 11:43:37 +00:00
parent bf1fe84d35
commit 816148fe32
2 changed files with 44 additions and 5 deletions

View File

@ -314,7 +314,8 @@ class UniformityGraph {
// Process function body.
if (func->body) {
ProcessStatement(current_function_->cf_start, func->body);
auto* cf = ProcessStatement(current_function_->cf_start, func->body);
current_function_->cf_return->AddEdge(cf);
}
#if TINT_DUMP_UNIFORMITY_GRAPH
@ -556,10 +557,7 @@ class UniformityGraph {
return cf;
},
[&](const ast::DiscardStatement*) {
current_function_->cf_return->AddEdge(cf);
return cf;
},
[&](const ast::DiscardStatement*) { return cf; },
[&](const ast::FallthroughStatement*) { return cf; },

View File

@ -401,6 +401,47 @@ test:16:3 note: calling 'foo' may cause subsequent control flow to be non-unifor
)");
}
TEST_F(UniformityAnalysisTest, SubsequentControlFlowMayBeNonUniform_Nested_Fail) {
// Indirectly call a function that causes subsequent control flow to be non-uniform, and then
// call another function that requires uniformity.
// The lack of return statement in `foo()` requires that we implicitly add an edge from
// CF_return to that last control flow node of the function.
auto src = R"(
@group(0) @binding(0) var<storage, read_write> rw : i32;
var<private> p : i32;
fn bar() {
if (rw == 0) {
p = 42;
return;
}
p = 5;
return;
}
fn foo() {
bar();
}
fn main() {
foo();
workgroupBarrier();
}
)";
RunTest(src, false);
EXPECT_EQ(error_,
R"(test:21:3 warning: 'workgroupBarrier' must only be called from uniform control flow
workgroupBarrier();
^^^^^^^^^^^^^^^^
test:20:3 note: calling 'foo' may cause subsequent control flow to be non-uniform
foo();
^^^
)");
}
TEST_F(UniformityAnalysisTest, ParameterNoRestriction_Pass) {
// Pass a non-uniform value as an argument, and then try to use the return value for
// control-flow guarding a barrier.