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:
parent
bf1fe84d35
commit
816148fe32
|
@ -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; },
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue