[ir] Fix loop condition matching in IR->WGSL
When there were two consecutive if instruction blocks that match the
loop condition pattern, the first was being dropped, leading to
unvisited nodes in the Resolver.
Bug: 351700183
Change-Id: I63e30f72cb648515198a8072b12b92b58bb6527b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/197355
Commit-Queue: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Auto-Submit: James Price <jrprice@google.com>
diff --git a/src/tint/lang/wgsl/ir_roundtrip_test.cc b/src/tint/lang/wgsl/ir_roundtrip_test.cc
index 7afcb96..278e8a6 100644
--- a/src/tint/lang/wgsl/ir_roundtrip_test.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_test.cc
@@ -2813,6 +2813,20 @@
)");
}
+// Test case for crbug.com/351700183.
+TEST_F(IRToProgramRoundtripTest, While_ConditionAndBreak) {
+ RUN_TEST(R"(
+fn f() {
+ while(true) {
+ if (false) {
+ } else {
+ break;
+ }
+ }
+}
+)");
+}
+
////////////////////////////////////////////////////////////////////////////////
// Loop
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 12afe90..265b787 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -432,7 +432,7 @@
{
TINT_SCOPED_ASSIGNMENT(statements_, &body_stmts);
for (auto* inst : *l->Body()) {
- if (body_stmts.IsEmpty()) {
+ if (body_stmts.IsEmpty() && !cond) {
if (auto* if_ = inst->As<core::ir::If>()) {
if (if_->Results().IsEmpty() && //
if_->True()->Length() == 1 && //
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
index d9d55fc..2a5bed4 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program_test.cc
@@ -2398,6 +2398,75 @@
)");
}
+TEST_F(IRToProgramTest, While_BreakAfterStatement) {
+ auto* fn = b.Function("f", ty.void_());
+
+ b.Append(fn->Block(), [&] {
+ auto* loop = b.Loop();
+
+ b.Append(loop->Body(), [&] {
+ auto* let = b.Let("cond", true);
+ auto* cond = b.If(let);
+ b.Append(cond->True(), [&] { b.ExitIf(cond); });
+ b.Append(cond->False(), [&] { b.ExitLoop(loop); });
+
+ b.ExitLoop(loop);
+ });
+
+ b.Return(fn);
+ });
+
+ EXPECT_WGSL(R"(
+fn f() {
+ loop {
+ let cond = true;
+ if (cond) {
+ } else {
+ break;
+ }
+ break;
+ }
+}
+)");
+}
+
+// Test that only the first "if continue then break" instruction is treated as the loop condition.
+// See crbug.com/351700183.
+TEST_F(IRToProgramTest, While_IfBreakInFalse) {
+ auto* fn = b.Function("f", ty.void_());
+ auto* cond = b.FunctionParam("cond", ty.bool_());
+ fn->SetParams({cond});
+
+ b.Append(fn->Block(), [&] {
+ auto* loop = b.Loop();
+
+ b.Append(loop->Body(), [&] {
+ auto* if1 = b.If(true);
+ b.Append(if1->True(), [&] { b.ExitIf(if1); });
+ b.Append(if1->False(), [&] { b.ExitLoop(loop); });
+
+ auto* if2 = b.If(cond);
+ b.Append(if2->True(), [&] { b.ExitIf(if2); });
+ b.Append(if2->False(), [&] { b.ExitLoop(loop); });
+
+ b.Continue(loop);
+ });
+
+ b.Return(fn);
+ });
+
+ EXPECT_WGSL(R"(
+fn f(cond : bool) {
+ while(true) {
+ if (cond) {
+ } else {
+ break;
+ }
+ }
+}
+)");
+}
+
TEST_F(IRToProgramTest, While_IfReturn) {
auto* fn = b.Function("f", ty.void_());
auto* cond = b.FunctionParam("cond", ty.bool_());