tint/uniformity: Use non-recursive graph traversal

Fixes a stack overflow when traversing particularly deep graphs.

This changes the iteration order which changes some of the diagnostic
notes, but the diagnostics are still correct and deterministic so it
does not matter.

Fixed: chromium:47418
Change-Id: I2def633b6d96d1525027f7929b0fa0a6fba0efeb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/90140
Auto-Submit: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2022-05-16 11:53:25 +00:00
parent a89ff5981b
commit 35f0fcaac0
17 changed files with 113 additions and 71 deletions

View File

@ -1269,18 +1269,25 @@ class UniformityGraph {
return {cf_after, result}; return {cf_after, result};
} }
/// Recursively traverse a graph starting at `node`, inserting all nodes that are reached into /// Traverse a graph starting at `source`, inserting all visited nodes into `reachable` and
/// `reachable`. /// recording which node they were reached from.
/// @param node the starting node /// @param source the starting node
/// @param reachable the set of reachable nodes to populate, if required /// @param reachable the set of reachable nodes to populate, if required
void Traverse(Node* node, utils::UniqueVector<Node*>* reachable = nullptr) { void Traverse(Node* source, utils::UniqueVector<Node*>* reachable = nullptr) {
std::vector<Node*> to_visit{source};
while (!to_visit.empty()) {
auto* node = to_visit.back();
to_visit.pop_back();
if (reachable) { if (reachable) {
reachable->add(node); reachable->add(node);
} }
for (auto* to : node->edges) { for (auto* to : node->edges) {
if (to->visited_from == nullptr) { if (to->visited_from == nullptr) {
to->visited_from = node; to->visited_from = node;
Traverse(to, reachable); to_visit.push_back(to);
}
} }
} }
} }

View File

@ -5907,6 +5907,41 @@ fn foo() {
RunTest(src, true); RunTest(src, true);
} }
TEST_F(UniformityAnalysisTest, StressGraphTraversalDepth) {
// Create a function with a very long sequence of variable declarations and assignments to
// test traversals of very deep graphs. This requires a non-recursive traversal algorithm.
ProgramBuilder b;
auto& ty = b.ty;
// var<private> v0 : i32 = 0i;
// fn foo() {
// let v1 = v0;
// let v2 = v1;
// ...
// let v{N} = v{N-1};
// if (v{N} == 0) {
// workgroupBarrier();
// }
// }
b.Global("v0", ty.i32(), ast::StorageClass::kPrivate, b.Expr(0_i));
ast::StatementList foo_body;
std::string v_last = "v0";
for (int i = 1; i < 100000; i++) {
auto v = "v" + std::to_string(i);
foo_body.push_back(b.Decl(b.Var(v, nullptr, b.Expr(v_last))));
v_last = v;
}
foo_body.push_back(b.If(b.Equal(v_last, 0_i), b.Block(b.CallStmt(b.Call("workgroupBarrier")))));
b.Func("foo", {}, ty.void_(), foo_body);
// TODO(jrprice): Expect false when uniformity issues become errors.
EXPECT_TRUE(RunTest(std::move(b))) << error_;
EXPECT_EQ(error_,
R"(warning: 'workgroupBarrier' must only be called from uniform control flow
note: control flow depends on non-uniform value
note: reading from module-scope private variable 'v0' may result in a non-uniform value)");
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
/// Tests for the quality of the error messages produced by the analysis. /// Tests for the quality of the error messages produced by the analysis.
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@ -6,8 +6,8 @@ bug/dawn/947.wgsl:55:5 note: control flow depends on non-uniform value
if (!all(clampedTexcoord == texcoord)) { if (!all(clampedTexcoord == texcoord)) {
^^ ^^
bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value bug/dawn/947.wgsl:55:33 note: reading from user-defined input 'texcoord' may result in a non-uniform value
clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0)); if (!all(clampedTexcoord == texcoord)) {
^^^^^^^^ ^^^^^^^^
#version 310 es #version 310 es

View File

@ -6,8 +6,8 @@ bug/dawn/947.wgsl:55:5 note: control flow depends on non-uniform value
if (!all(clampedTexcoord == texcoord)) { if (!all(clampedTexcoord == texcoord)) {
^^ ^^
bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value bug/dawn/947.wgsl:55:33 note: reading from user-defined input 'texcoord' may result in a non-uniform value
clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0)); if (!all(clampedTexcoord == texcoord)) {
^^^^^^^^ ^^^^^^^^
cbuffer cbuffer_uniforms : register(b0, space0) { cbuffer cbuffer_uniforms : register(b0, space0) {

View File

@ -6,8 +6,8 @@ bug/dawn/947.wgsl:55:5 note: control flow depends on non-uniform value
if (!all(clampedTexcoord == texcoord)) { if (!all(clampedTexcoord == texcoord)) {
^^ ^^
bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value bug/dawn/947.wgsl:55:33 note: reading from user-defined input 'texcoord' may result in a non-uniform value
clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0)); if (!all(clampedTexcoord == texcoord)) {
^^^^^^^^ ^^^^^^^^
#include <metal_stdlib> #include <metal_stdlib>

View File

@ -6,8 +6,8 @@ bug/dawn/947.wgsl:55:5 note: control flow depends on non-uniform value
if (!all(clampedTexcoord == texcoord)) { if (!all(clampedTexcoord == texcoord)) {
^^ ^^
bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value bug/dawn/947.wgsl:55:33 note: reading from user-defined input 'texcoord' may result in a non-uniform value
clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0)); if (!all(clampedTexcoord == texcoord)) {
^^^^^^^^ ^^^^^^^^
; SPIR-V ; SPIR-V

View File

@ -6,8 +6,8 @@ bug/dawn/947.wgsl:55:5 note: control flow depends on non-uniform value
if (!all(clampedTexcoord == texcoord)) { if (!all(clampedTexcoord == texcoord)) {
^^ ^^
bug/dawn/947.wgsl:54:15 note: reading from user-defined input 'texcoord' may result in a non-uniform value bug/dawn/947.wgsl:55:33 note: reading from user-defined input 'texcoord' may result in a non-uniform value
clamp(texcoord, vec2<f32>(0.0, 0.0), vec2<f32>(1.0, 1.0)); if (!all(clampedTexcoord == texcoord)) {
^^^^^^^^ ^^^^^^^^
struct Uniforms { struct Uniforms {

View File

@ -2,13 +2,13 @@ bug/tint/948.wgsl:146:33 warning: 'textureSampleBias' must only be called from u
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
bug/tint/948.wgsl:125:5 note: control flow depends on non-uniform value bug/tint/948.wgsl:138:9 note: control flow depends on non-uniform value
if ((x_174 > 0.0)) { if ((x_197 > x_198)) {
^^ ^^
bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform bug/tint/948.wgsl:137:27 note: reading from module-scope private variable 'mt' may result in a non-uniform value
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_198 : f32 = mt;
^^^^^^^^^^^^^^^^^ ^^
#version 310 es #version 310 es
precision mediump float; precision mediump float;

View File

@ -2,13 +2,13 @@ bug/tint/948.wgsl:146:33 warning: 'textureSampleBias' must only be called from u
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
bug/tint/948.wgsl:125:5 note: control flow depends on non-uniform value bug/tint/948.wgsl:138:9 note: control flow depends on non-uniform value
if ((x_174 > 0.0)) { if ((x_197 > x_198)) {
^^ ^^
bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform bug/tint/948.wgsl:137:27 note: reading from module-scope private variable 'mt' may result in a non-uniform value
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_198 : f32 = mt;
^^^^^^^^^^^^^^^^^ ^^
cbuffer cbuffer_x_20 : register(b9, space2) { cbuffer cbuffer_x_20 : register(b9, space2) {
uint4 x_20[8]; uint4 x_20[8];

View File

@ -2,13 +2,13 @@ bug/tint/948.wgsl:146:33 warning: 'textureSampleBias' must only be called from u
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
bug/tint/948.wgsl:125:5 note: control flow depends on non-uniform value bug/tint/948.wgsl:138:9 note: control flow depends on non-uniform value
if ((x_174 > 0.0)) { if ((x_197 > x_198)) {
^^ ^^
bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform bug/tint/948.wgsl:137:27 note: reading from module-scope private variable 'mt' may result in a non-uniform value
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_198 : f32 = mt;
^^^^^^^^^^^^^^^^^ ^^
#include <metal_stdlib> #include <metal_stdlib>

View File

@ -2,13 +2,13 @@ bug/tint/948.wgsl:146:33 warning: 'textureSampleBias' must only be called from u
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
bug/tint/948.wgsl:125:5 note: control flow depends on non-uniform value bug/tint/948.wgsl:138:9 note: control flow depends on non-uniform value
if ((x_174 > 0.0)) { if ((x_197 > x_198)) {
^^ ^^
bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform bug/tint/948.wgsl:137:27 note: reading from module-scope private variable 'mt' may result in a non-uniform value
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_198 : f32 = mt;
^^^^^^^^^^^^^^^^^ ^^
; SPIR-V ; SPIR-V
; Version: 1.3 ; Version: 1.3

View File

@ -2,13 +2,13 @@ bug/tint/948.wgsl:146:33 warning: 'textureSampleBias' must only be called from u
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0);
^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
bug/tint/948.wgsl:125:5 note: control flow depends on non-uniform value bug/tint/948.wgsl:138:9 note: control flow depends on non-uniform value
if ((x_174 > 0.0)) { if ((x_197 > x_198)) {
^^ ^^
bug/tint/948.wgsl:146:33 note: return value of 'textureSampleBias' may be non-uniform bug/tint/948.wgsl:137:27 note: reading from module-scope private variable 'mt' may result in a non-uniform value
let x_217 : vec4<f32> = textureSampleBias(animationMapTexture, animationMapSampler, vec2<f32>(((x_208 + 0.5) / x_211), (0.125 * x_214)), 0.0); let x_198 : f32 = mt;
^^^^^^^^^^^^^^^^^ ^^
struct LeftOver { struct LeftOver {
time : f32, time : f32,

View File

@ -6,9 +6,9 @@ bug/tint/949.wgsl:330:5 note: control flow depends on non-uniform value
if ((x_400 > x_401)) { if ((x_400 > x_401)) {
^^ ^^
bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform bug/tint/949.wgsl:308:27 note: reading from module-scope private variable 'v_output2' may result in a non-uniform value
let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395)); let x_366 : vec4<f32> = v_output2;
^^^^^^^^^^^^^ ^^^^^^^^^
#version 310 es #version 310 es
precision mediump float; precision mediump float;

View File

@ -6,9 +6,9 @@ bug/tint/949.wgsl:330:5 note: control flow depends on non-uniform value
if ((x_400 > x_401)) { if ((x_400 > x_401)) {
^^ ^^
bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform bug/tint/949.wgsl:308:27 note: reading from module-scope private variable 'v_output2' may result in a non-uniform value
let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395)); let x_366 : vec4<f32> = v_output2;
^^^^^^^^^^^^^ ^^^^^^^^^
struct lightingInfo { struct lightingInfo {
float3 diffuse; float3 diffuse;

View File

@ -6,9 +6,9 @@ bug/tint/949.wgsl:330:5 note: control flow depends on non-uniform value
if ((x_400 > x_401)) { if ((x_400 > x_401)) {
^^ ^^
bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform bug/tint/949.wgsl:308:27 note: reading from module-scope private variable 'v_output2' may result in a non-uniform value
let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395)); let x_366 : vec4<f32> = v_output2;
^^^^^^^^^^^^^ ^^^^^^^^^
#include <metal_stdlib> #include <metal_stdlib>

View File

@ -6,9 +6,9 @@ bug/tint/949.wgsl:330:5 note: control flow depends on non-uniform value
if ((x_400 > x_401)) { if ((x_400 > x_401)) {
^^ ^^
bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform bug/tint/949.wgsl:308:27 note: reading from module-scope private variable 'v_output2' may result in a non-uniform value
let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395)); let x_366 : vec4<f32> = v_output2;
^^^^^^^^^^^^^ ^^^^^^^^^
; SPIR-V ; SPIR-V
; Version: 1.3 ; Version: 1.3

View File

@ -6,9 +6,9 @@ bug/tint/949.wgsl:330:5 note: control flow depends on non-uniform value
if ((x_400 > x_401)) { if ((x_400 > x_401)) {
^^ ^^
bug/tint/949.wgsl:326:29 note: return value of 'textureSample' may be non-uniform bug/tint/949.wgsl:308:27 note: reading from module-scope private variable 'v_output2' may result in a non-uniform value
let x_397 : vec4<f32> = textureSample(TextureSamplerTexture, TextureSamplerSampler, (x_394 + x_395)); let x_366 : vec4<f32> = v_output2;
^^^^^^^^^^^^^ ^^^^^^^^^
struct lightingInfo { struct lightingInfo {
diffuse : vec3<f32>, diffuse : vec3<f32>,