diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn index b51e531616..fbbfe5a3b1 100644 --- a/src/tint/BUILD.gn +++ b/src/tint/BUILD.gn @@ -554,8 +554,6 @@ libtint_source_set("libtint_core_all_src") { "transform/transform.h", "transform/unshadow.cc", "transform/unshadow.h", - "transform/unwind_discard_functions.cc", - "transform/unwind_discard_functions.h", "transform/utils/get_insertion_point.cc", "transform/utils/get_insertion_point.h", "transform/utils/hoist_to_decl_before.cc", @@ -1253,7 +1251,6 @@ if (tint_build_unittests) { "transform/test_helper.h", "transform/transform_test.cc", "transform/unshadow_test.cc", - "transform/unwind_discard_functions_test.cc", "transform/utils/get_insertion_point_test.cc", "transform/utils/hoist_to_decl_before_test.cc", "transform/var_for_dynamic_index_test.cc", diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt index a42d58e355..21da5e8dc7 100644 --- a/src/tint/CMakeLists.txt +++ b/src/tint/CMakeLists.txt @@ -479,8 +479,6 @@ list(APPEND TINT_LIB_SRCS transform/transform.h transform/unshadow.cc transform/unshadow.h - transform/unwind_discard_functions.cc - transform/unwind_discard_functions.h transform/utils/get_insertion_point.cc transform/utils/get_insertion_point.h transform/utils/hoist_to_decl_before.cc @@ -1213,7 +1211,6 @@ if(TINT_BUILD_TESTS) transform/substitute_override_test.cc transform/test_helper.h transform/unshadow_test.cc - transform/unwind_discard_functions_test.cc transform/var_for_dynamic_index_test.cc transform/vectorize_matrix_conversions_test.cc transform/vectorize_scalar_matrix_initializers_test.cc diff --git a/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker.cc b/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker.cc index 66bbaf7c85..d77a76299e 100644 --- a/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker.cc +++ b/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker.cc @@ -29,7 +29,7 @@ namespace tint::fuzzers::ast_fuzzer { JumpTracker::JumpTracker(const Program& program) { - // Consider every AST node, looking for break, return and discard statements. + // Consider every AST node, looking for break and return statements. for (auto* node : program.ASTNodes().Objects()) { auto* stmt = node->As(); if (stmt == nullptr) { @@ -63,14 +63,12 @@ JumpTracker::JumpTracker(const Program& program) { } candidate_statements.insert(current); } - } else if (stmt->As() || stmt->As()) { - // Walk up the AST from the return or discard statement, recording that every node - // encountered along the way contains a return/discard. - auto& target_set = stmt->As() ? contains_return_ - : contains_intraprocedural_discard_; + } else if (stmt->As()) { + // Walk up the AST from the return statement, recording that every node encountered + // along the way contains a return. const ast::Statement* current = stmt; while (true) { - target_set.insert(current); + contains_return_.insert(current); auto* parent = program.Sem().Get(current)->Parent(); if (parent == nullptr) { break; diff --git a/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker.h b/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker.h index 614ceb5281..ec40ee8732 100644 --- a/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker.h +++ b/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker.h @@ -22,7 +22,7 @@ namespace tint::fuzzers::ast_fuzzer { -/// This class computes information on which statements contain loop breaks, returns and discards. +/// This class computes information on which statements contain loop breaks and returns. /// It could be extended to handle other jumps, such as switch breaks and loop continues, should /// such information prove useful. class JumpTracker { @@ -47,20 +47,9 @@ class JumpTracker { return contains_return_.count(&statement) > 0; } - /// Indicates whether a statement contains a discard statement. - /// @param statement - the statement of interest. - /// @return true if and only if the statement is, or contains, a discard statement. This is - /// determined in an intraprocedural fashion: the answer will be "false" if no discard occurs - /// inside the statement, even if the statement calls a function that may lead to a discard - /// being performed. - bool ContainsIntraproceduralDiscard(const ast::Statement& statement) const { - return contains_intraprocedural_discard_.count(&statement) > 0; - } - private: std::unordered_set contains_break_for_innermost_loop_; std::unordered_set contains_return_; - std::unordered_set contains_intraprocedural_discard_; }; } // namespace tint::fuzzers::ast_fuzzer diff --git a/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker_test.cc b/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker_test.cc index f83e639a73..2482feefe3 100644 --- a/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker_test.cc +++ b/src/tint/fuzzers/tint_ast_fuzzer/jump_tracker_test.cc @@ -200,93 +200,6 @@ fn main() { } } -TEST(JumpTrackerTest, Discards) { - std::string content = R"( -fn main() { - var x : u32; - for (var i : i32 = 0; i < 100; i++) { - if (i == 40) { - { - discard; - } - } - for (var j : i32 = 0; j < 10; j++) { - loop { - if (i > j) { - discard; - } - continuing { - i++; - j-=2; - } - } - switch (j) { - case 0: { - if (i == j) { - break; - } - i = i + 1; - continue; - } - default: { - discard; - } - } - } - } -} - )"; - Source::File file("test.wgsl", content); - auto program = reader::wgsl::Parse(&file); - ASSERT_TRUE(program.IsValid()) << program.Diagnostics().str(); - - JumpTracker jump_tracker(program); - - const auto* function_body = program.AST().Functions()[0]->body; - const auto* outer_loop = function_body->statements[1]->As(); - const auto* outer_loop_body = outer_loop->body; - const auto* first_if = outer_loop_body->statements[0]->As(); - const auto* first_if_body = first_if->body; - const auto* block_in_first_if = first_if_body->statements[0]->As(); - const auto* discard_in_first_if = block_in_first_if->statements[0]->As(); - const auto* inner_for_loop = outer_loop_body->statements[1]->As(); - const auto* inner_for_loop_body = inner_for_loop->body; - const auto* innermost_loop = inner_for_loop_body->statements[0]->As(); - const auto* innermost_loop_body = innermost_loop->body; - const auto* innermost_loop_if = innermost_loop_body->statements[0]->As(); - const auto* innermost_loop_if_body = innermost_loop_if->body; - const auto* discard_in_innermost_loop = - innermost_loop_if_body->statements[0]->As(); - const auto* switch_statement = inner_for_loop_body->statements[1]->As(); - const auto* default_statement = switch_statement->body[1]; - const auto* default_statement_body = default_statement->body; - const auto* discard_in_default_statement = - default_statement_body->statements[0]->As(); - - std::unordered_set containing_discard = { - function_body, outer_loop, - outer_loop_body, first_if, - first_if_body, block_in_first_if, - discard_in_first_if, inner_for_loop, - inner_for_loop_body, innermost_loop, - innermost_loop_body, innermost_loop_if, - innermost_loop_if_body, discard_in_innermost_loop, - switch_statement, default_statement, - default_statement_body, discard_in_default_statement}; - - for (auto* node : program.ASTNodes().Objects()) { - auto* stmt = node->As(); - if (stmt == nullptr) { - continue; - } - if (containing_discard.count(stmt) > 0) { - ASSERT_TRUE(jump_tracker.ContainsIntraproceduralDiscard(*stmt)); - } else { - ASSERT_FALSE(jump_tracker.ContainsIntraproceduralDiscard(*stmt)); - } - } -} - TEST(JumpTrackerTest, WhileLoop) { std::string content = R"( fn main() { diff --git a/src/tint/fuzzers/tint_ast_fuzzer/mutations/delete_statement.cc b/src/tint/fuzzers/tint_ast_fuzzer/mutations/delete_statement.cc index 1ec3ca414c..89ab66bbf4 100644 --- a/src/tint/fuzzers/tint_ast_fuzzer/mutations/delete_statement.cc +++ b/src/tint/fuzzers/tint_ast_fuzzer/mutations/delete_statement.cc @@ -135,10 +135,9 @@ bool MutationDeleteStatement::CanBeDeleted(const ast::Statement& statement_node, return false; } - if (jump_tracker.ContainsReturn(statement_node) || - jump_tracker.ContainsIntraproceduralDiscard(statement_node)) { - // This is conservative. It would be possible to delete a return/discard statement as long - // as there is still a return/discard on every control flow path. + if (jump_tracker.ContainsReturn(statement_node)) { + // This is conservative. It would be possible to delete a return statement as long as there + // is still a return on every control flow path. return false; } diff --git a/src/tint/fuzzers/tint_ast_fuzzer/mutations/delete_statement_test.cc b/src/tint/fuzzers/tint_ast_fuzzer/mutations/delete_statement_test.cc index 275a19e028..a2ab29cf75 100644 --- a/src/tint/fuzzers/tint_ast_fuzzer/mutations/delete_statement_test.cc +++ b/src/tint/fuzzers/tint_ast_fuzzer/mutations/delete_statement_test.cc @@ -606,48 +606,6 @@ fn foo() -> i32 { CheckStatementDeletionNotAllowed(original, statement_finder); } -TEST(DeleteStatementTest, DoNotRemoveDiscard) { - auto original = R"( -fn main() { - discard; -})"; - auto statement_finder = [](const Program& program) -> const ast::Statement* { - return program.AST().Functions()[0]->body->statements[0]->As(); - }; - CheckStatementDeletionNotAllowed(original, statement_finder); -} - -TEST(DeleteStatementTest, DoNotRemoveStatementContainingDiscard) { - auto original = R"( -fn foo() -> i32 { - if (true) { - discard; - } else { - discard; - } -})"; - auto statement_finder = [](const Program& program) -> const ast::Statement* { - return program.AST().Functions()[0]->body->statements[0]->As(); - }; - CheckStatementDeletionNotAllowed(original, statement_finder); -} - -TEST(DeleteStatementTest, DoNotRemoveLoopBody) { - auto original = R"( -fn foo() { - discard; -} -fn main() { - loop { - foo(); - } -})"; - auto statement_finder = [](const Program& program) -> const ast::Statement* { - return program.AST().Functions()[1]->body->statements[0]->As()->body; - }; - CheckStatementDeletionNotAllowed(original, statement_finder); -} - TEST(DeleteStatementTest, DoNotRemoveForLoopBody) { auto original = R"( fn main() { diff --git a/src/tint/resolver/function_validation_test.cc b/src/tint/resolver/function_validation_test.cc index 49d37a13cb..a4ff9d8e6d 100644 --- a/src/tint/resolver/function_validation_test.cc +++ b/src/tint/resolver/function_validation_test.cc @@ -161,7 +161,7 @@ TEST_F(ResolverFunctionValidationTest, UnreachableCode_return_InBlocks) { EXPECT_FALSE(Sem().Get(assign_a)->IsReachable()); } -TEST_F(ResolverFunctionValidationTest, UnreachableCode_discard) { +TEST_F(ResolverFunctionValidationTest, UnreachableCode_discard_nowarning) { // fn func() -> { // var a : i32; // discard; @@ -175,38 +175,17 @@ TEST_F(ResolverFunctionValidationTest, UnreachableCode_discard) { Func("func", utils::Empty, ty.void_(), utils::Vector{decl_a, discard, assign_a}); ASSERT_TRUE(r()->Resolve()); - EXPECT_EQ(r()->error(), "12:34 warning: code is unreachable"); EXPECT_TRUE(Sem().Get(decl_a)->IsReachable()); EXPECT_TRUE(Sem().Get(discard)->IsReachable()); - EXPECT_FALSE(Sem().Get(assign_a)->IsReachable()); -} - -TEST_F(ResolverFunctionValidationTest, UnreachableCode_discard_InBlocks) { - // fn func() -> { - // var a : i32; - // {{{discard;}}} - // a = 2i; - //} - - auto* decl_a = Decl(Var("a", ty.i32())); - auto* discard = Discard(); - auto* assign_a = Assign(Source{{12, 34}}, "a", 2_i); - - Func("func", utils::Empty, ty.void_(), - utils::Vector{decl_a, Block(Block(Block(discard))), assign_a}); - - ASSERT_TRUE(r()->Resolve()); - EXPECT_EQ(r()->error(), "12:34 warning: code is unreachable"); - EXPECT_TRUE(Sem().Get(decl_a)->IsReachable()); - EXPECT_TRUE(Sem().Get(discard)->IsReachable()); - EXPECT_FALSE(Sem().Get(assign_a)->IsReachable()); + EXPECT_TRUE(Sem().Get(assign_a)->IsReachable()); } TEST_F(ResolverFunctionValidationTest, DiscardCalledDirectlyFromVertexEntryPoint) { - // @vertex() fn func() -> @position(0) vec4 { discard; } + // @vertex() fn func() -> @position(0) vec4 { discard; return; } Func(Source{{1, 2}}, "func", utils::Empty, ty.vec4(), utils::Vector{ Discard(Source{{12, 34}}), + Return(Construct(ty.vec4())), }, utils::Vector{Stage(ast::PipelineStage::kVertex)}, utils::Vector{Builtin(ast::BuiltinValue::kPosition)}); diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc index daec00aeac..d30d671b29 100644 --- a/src/tint/resolver/resolver.cc +++ b/src/tint/resolver/resolver.cc @@ -3295,10 +3295,8 @@ sem::Statement* Resolver::DiscardStatement(const ast::DiscardStatement* stmt) { auto* sem = builder_->create(stmt, current_compound_statement_, current_function_); return StatementScope(stmt, sem, [&] { - sem->Behaviors() = sem::Behavior::kDiscard; current_function_->SetDiscardStatement(sem); - - return validator_.DiscardStatement(sem, current_statement_); + return true; }); } diff --git a/src/tint/resolver/resolver_behavior_test.cc b/src/tint/resolver/resolver_behavior_test.cc index 150512a6f5..01b7890cc4 100644 --- a/src/tint/resolver/resolver_behavior_test.cc +++ b/src/tint/resolver/resolver_behavior_test.cc @@ -30,10 +30,11 @@ namespace { class ResolverBehaviorTest : public ResolverTest { protected: void SetUp() override { - // Create a function called 'DiscardOrNext' which returns an i32, and has - // the behavior of {Discard, Return}, which when called, will have the - // behavior {Discard, Next}. - Func("DiscardOrNext", utils::Empty, ty.i32(), + // Create a function called 'Next' which returns an i32, and has the behavior of {Return}, + // which when called, will have the behavior {Next}. + // It contains a discard statement, which should not affect the behavior analysis or any + // related validation. + Func("Next", utils::Empty, ty.i32(), utils::Vector{ If(true, Block(Discard())), Return(1_i), @@ -42,7 +43,7 @@ class ResolverBehaviorTest : public ResolverTest { }; TEST_F(ResolverBehaviorTest, ExprBinaryOp_LHS) { - auto* stmt = Decl(Var("lhs", ty.i32(), Add(Call("DiscardOrNext"), 1_i))); + auto* stmt = Decl(Var("lhs", ty.i32(), Add(Call("Next"), 1_i))); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -50,11 +51,11 @@ TEST_F(ResolverBehaviorTest, ExprBinaryOp_LHS) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, ExprBinaryOp_RHS) { - auto* stmt = Decl(Var("lhs", ty.i32(), Add(1_i, Call("DiscardOrNext")))); + auto* stmt = Decl(Var("lhs", ty.i32(), Add(1_i, Call("Next")))); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -62,11 +63,11 @@ TEST_F(ResolverBehaviorTest, ExprBinaryOp_RHS) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, ExprBitcastOp) { - auto* stmt = Decl(Var("lhs", ty.u32(), Bitcast(Call("DiscardOrNext")))); + auto* stmt = Decl(Var("lhs", ty.u32(), Bitcast(Call("Next")))); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -74,7 +75,7 @@ TEST_F(ResolverBehaviorTest, ExprBitcastOp) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, ExprIndex_Arr) { @@ -92,11 +93,11 @@ TEST_F(ResolverBehaviorTest, ExprIndex_Arr) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, ExprIndex_Idx) { - auto* stmt = Decl(Var("lhs", ty.i32(), IndexAccessor("arr", Call("DiscardOrNext")))); + auto* stmt = Decl(Var("lhs", ty.i32(), IndexAccessor("arr", Call("Next")))); Func("F", utils::Empty, ty.void_(), utils::Vector{ @@ -108,13 +109,12 @@ TEST_F(ResolverBehaviorTest, ExprIndex_Idx) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, ExprUnaryOp) { - auto* stmt = - Decl(Var("lhs", ty.i32(), - create(ast::UnaryOp::kComplement, Call("DiscardOrNext")))); + auto* stmt = Decl(Var("lhs", ty.i32(), + create(ast::UnaryOp::kComplement, Call("Next")))); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -122,7 +122,7 @@ TEST_F(ResolverBehaviorTest, ExprUnaryOp) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtAssign) { @@ -138,7 +138,7 @@ TEST_F(ResolverBehaviorTest, StmtAssign) { } TEST_F(ResolverBehaviorTest, StmtAssign_LHSDiscardOrNext) { - auto* stmt = Assign(IndexAccessor("lhs", Call("DiscardOrNext")), 1_i); + auto* stmt = Assign(IndexAccessor("lhs", Call("Next")), 1_i); Func("F", utils::Empty, ty.void_(), utils::Vector{ @@ -150,11 +150,11 @@ TEST_F(ResolverBehaviorTest, StmtAssign_LHSDiscardOrNext) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtAssign_RHSDiscardOrNext) { - auto* stmt = Assign("lhs", Call("DiscardOrNext")); + auto* stmt = Assign("lhs", Call("Next")); Func("F", utils::Empty, ty.void_(), utils::Vector{ @@ -166,7 +166,7 @@ TEST_F(ResolverBehaviorTest, StmtAssign_RHSDiscardOrNext) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtBlockEmpty) { @@ -180,7 +180,7 @@ TEST_F(ResolverBehaviorTest, StmtBlockEmpty) { } TEST_F(ResolverBehaviorTest, StmtBlockSingleStmt) { - auto* stmt = Block(Discard()); + auto* stmt = Block(Return()); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -188,7 +188,7 @@ TEST_F(ResolverBehaviorTest, StmtBlockSingleStmt) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behavior::kDiscard); + EXPECT_EQ(sem->Behaviors(), sem::Behavior::kReturn); } TEST_F(ResolverBehaviorTest, StmtCallReturn) { @@ -212,12 +212,11 @@ TEST_F(ResolverBehaviorTest, StmtCallFuncDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behavior::kDiscard); + EXPECT_EQ(sem->Behaviors(), sem::Behavior::kNext); } TEST_F(ResolverBehaviorTest, StmtCallFuncMayDiscard) { - auto* stmt = - For(Decl(Var("v", ty.i32(), Call("DiscardOrNext"))), nullptr, nullptr, Block(Break())); + auto* stmt = For(Decl(Var("v", ty.i32(), Call("Next"))), nullptr, nullptr, Block(Break())); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -225,7 +224,7 @@ TEST_F(ResolverBehaviorTest, StmtCallFuncMayDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtBreak) { @@ -258,7 +257,7 @@ TEST_F(ResolverBehaviorTest, StmtDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behavior::kDiscard); + EXPECT_EQ(sem->Behaviors(), sem::Behavior::kNext); } TEST_F(ResolverBehaviorTest, StmtForLoopEmpty_NoExit) { @@ -288,7 +287,7 @@ TEST_F(ResolverBehaviorTest, StmtForLoopContinue_NoExit) { } TEST_F(ResolverBehaviorTest, StmtForLoopDiscard) { - auto* stmt = For(nullptr, nullptr, nullptr, Block(Discard())); + auto* stmt = For(nullptr, nullptr, nullptr, Block(Discard(), Break())); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -296,7 +295,7 @@ TEST_F(ResolverBehaviorTest, StmtForLoopDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behavior::kDiscard); + EXPECT_EQ(sem->Behaviors(), sem::Behavior::kNext); } TEST_F(ResolverBehaviorTest, StmtForLoopReturn) { @@ -310,8 +309,7 @@ TEST_F(ResolverBehaviorTest, StmtForLoopReturn) { } TEST_F(ResolverBehaviorTest, StmtForLoopBreak_InitCallFuncMayDiscard) { - auto* stmt = - For(Decl(Var("v", ty.i32(), Call("DiscardOrNext"))), nullptr, nullptr, Block(Break())); + auto* stmt = For(Decl(Var("v", ty.i32(), Call("Next"))), nullptr, nullptr, Block(Break())); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -319,11 +317,11 @@ TEST_F(ResolverBehaviorTest, StmtForLoopBreak_InitCallFuncMayDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtForLoopEmpty_InitCallFuncMayDiscard) { - auto* stmt = For(Decl(Var("v", ty.i32(), Call("DiscardOrNext"))), nullptr, nullptr, Block()); + auto* stmt = For(Decl(Var("v", ty.i32(), Call("Next"))), nullptr, nullptr, Block(Break())); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -331,7 +329,7 @@ TEST_F(ResolverBehaviorTest, StmtForLoopEmpty_InitCallFuncMayDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behavior::kDiscard); + EXPECT_EQ(sem->Behaviors(), sem::Behavior::kNext); } TEST_F(ResolverBehaviorTest, StmtForLoopEmpty_CondTrue) { @@ -345,7 +343,7 @@ TEST_F(ResolverBehaviorTest, StmtForLoopEmpty_CondTrue) { } TEST_F(ResolverBehaviorTest, StmtForLoopEmpty_CondCallFuncMayDiscard) { - auto* stmt = For(nullptr, Equal(Call("DiscardOrNext"), 1_i), nullptr, Block()); + auto* stmt = For(nullptr, Equal(Call("Next"), 1_i), nullptr, Block()); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -353,7 +351,7 @@ TEST_F(ResolverBehaviorTest, StmtForLoopEmpty_CondCallFuncMayDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtWhileBreak) { @@ -375,7 +373,7 @@ TEST_F(ResolverBehaviorTest, StmtWhileDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtWhileReturn) { @@ -399,7 +397,7 @@ TEST_F(ResolverBehaviorTest, StmtWhileEmpty_CondTrue) { } TEST_F(ResolverBehaviorTest, StmtWhileEmpty_CondCallFuncMayDiscard) { - auto* stmt = While(Equal(Call("DiscardOrNext"), 1_i), Block()); + auto* stmt = While(Equal(Call("Next"), 1_i), Block()); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -407,7 +405,7 @@ TEST_F(ResolverBehaviorTest, StmtWhileEmpty_CondCallFuncMayDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtIfTrue_ThenEmptyBlock) { @@ -429,7 +427,7 @@ TEST_F(ResolverBehaviorTest, StmtIfTrue_ThenDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtIfTrue_ThenEmptyBlock_ElseDiscard) { @@ -441,7 +439,7 @@ TEST_F(ResolverBehaviorTest, StmtIfTrue_ThenEmptyBlock_ElseDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtIfTrue_ThenDiscard_ElseDiscard) { @@ -453,11 +451,11 @@ TEST_F(ResolverBehaviorTest, StmtIfTrue_ThenDiscard_ElseDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behavior::kDiscard); + EXPECT_EQ(sem->Behaviors(), sem::Behavior::kNext); } TEST_F(ResolverBehaviorTest, StmtIfCallFuncMayDiscard_ThenEmptyBlock) { - auto* stmt = If(Equal(Call("DiscardOrNext"), 1_i), Block()); + auto* stmt = If(Equal(Call("Next"), 1_i), Block()); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -465,12 +463,12 @@ TEST_F(ResolverBehaviorTest, StmtIfCallFuncMayDiscard_ThenEmptyBlock) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtIfTrue_ThenEmptyBlock_ElseCallFuncMayDiscard) { auto* stmt = If(true, Block(), // - Else(If(Equal(Call("DiscardOrNext"), 1_i), Block()))); + Else(If(Equal(Call("Next"), 1_i), Block()))); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -478,7 +476,7 @@ TEST_F(ResolverBehaviorTest, StmtIfTrue_ThenEmptyBlock_ElseCallFuncMayDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtLetDecl) { @@ -492,7 +490,7 @@ TEST_F(ResolverBehaviorTest, StmtLetDecl) { } TEST_F(ResolverBehaviorTest, StmtLetDecl_RHSDiscardOrNext) { - auto* stmt = Decl(Let("lhs", ty.i32(), Call("DiscardOrNext"))); + auto* stmt = Decl(Let("lhs", ty.i32(), Call("Next"))); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -500,7 +498,7 @@ TEST_F(ResolverBehaviorTest, StmtLetDecl_RHSDiscardOrNext) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtLoopEmpty_NoExit) { @@ -530,7 +528,7 @@ TEST_F(ResolverBehaviorTest, StmtLoopContinue_NoExit) { } TEST_F(ResolverBehaviorTest, StmtLoopDiscard) { - auto* stmt = Loop(Block(Discard())); + auto* stmt = Loop(Block(Discard(), Break())); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -538,7 +536,7 @@ TEST_F(ResolverBehaviorTest, StmtLoopDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behavior::kDiscard); + EXPECT_EQ(sem->Behaviors(), sem::Behavior::kNext); } TEST_F(ResolverBehaviorTest, StmtLoopReturn) { @@ -590,14 +588,14 @@ TEST_F(ResolverBehaviorTest, StmtReturn) { } TEST_F(ResolverBehaviorTest, StmtReturn_DiscardOrNext) { - auto* stmt = Return(Call("DiscardOrNext")); + auto* stmt = Return(Call("Next")); Func("F", utils::Empty, ty.i32(), utils::Vector{stmt}); ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kReturn, sem::Behavior::kDiscard)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kReturn)); } TEST_F(ResolverBehaviorTest, StmtSwitch_CondTrue_DefaultEmpty) { @@ -629,7 +627,7 @@ TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_DefaultDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behavior::kDiscard); + EXPECT_EQ(sem->Behaviors(), sem::Behavior::kNext); } TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_DefaultReturn) { @@ -661,7 +659,7 @@ TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_Case0Empty_DefaultDiscard) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext, sem::Behavior::kDiscard)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_Case0Empty_DefaultReturn) { @@ -683,7 +681,7 @@ TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_Case0Discard_DefaultEmpty) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_Case0Discard_DefaultDiscard) { @@ -696,7 +694,7 @@ TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_Case0Discard_DefaultDiscard) ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behavior::kDiscard); + EXPECT_EQ(sem->Behaviors(), sem::Behavior::kNext); } TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_Case0Discard_DefaultReturn) { @@ -709,7 +707,7 @@ TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_Case0Discard_DefaultReturn) ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kReturn)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kReturn, sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_Case0Discard_Case1Return_DefaultEmpty) { @@ -724,12 +722,11 @@ TEST_F(ResolverBehaviorTest, StmtSwitch_CondLiteral_Case0Discard_Case1Return_Def ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext, - sem::Behavior::kReturn)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext, sem::Behavior::kReturn)); } TEST_F(ResolverBehaviorTest, StmtSwitch_CondCallFuncMayDiscard_DefaultEmpty) { - auto* stmt = Switch(Call("DiscardOrNext"), DefaultCase(Block())); + auto* stmt = Switch(Call("Next"), DefaultCase(Block())); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -737,7 +734,7 @@ TEST_F(ResolverBehaviorTest, StmtSwitch_CondCallFuncMayDiscard_DefaultEmpty) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } TEST_F(ResolverBehaviorTest, StmtVarDecl) { @@ -751,7 +748,7 @@ TEST_F(ResolverBehaviorTest, StmtVarDecl) { } TEST_F(ResolverBehaviorTest, StmtVarDecl_RHSDiscardOrNext) { - auto* stmt = Decl(Var("lhs", ty.i32(), Call("DiscardOrNext"))); + auto* stmt = Decl(Var("lhs", ty.i32(), Call("Next"))); Func("F", utils::Empty, ty.void_(), utils::Vector{stmt}, utils::Vector{Stage(ast::PipelineStage::kFragment)}); @@ -759,7 +756,7 @@ TEST_F(ResolverBehaviorTest, StmtVarDecl_RHSDiscardOrNext) { ASSERT_TRUE(r()->Resolve()) << r()->error(); auto* sem = Sem().Get(stmt); - EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kDiscard, sem::Behavior::kNext)); + EXPECT_EQ(sem->Behaviors(), sem::Behaviors(sem::Behavior::kNext)); } } // namespace diff --git a/src/tint/resolver/uniformity_test.cc b/src/tint/resolver/uniformity_test.cc index fbaeff93cf..c7fd1f6d88 100644 --- a/src/tint/resolver/uniformity_test.cc +++ b/src/tint/resolver/uniformity_test.cc @@ -736,7 +736,6 @@ enum ControlFlowInterrupt { kBreak, kContinue, kReturn, - kDiscard, }; enum Condition { kNone, @@ -754,8 +753,6 @@ static std::string ToStr(ControlFlowInterrupt interrupt) { return "continue"; case kReturn: return "return"; - case kDiscard: - return "discard"; } return ""; } @@ -790,7 +787,7 @@ class LoopTest : public UniformityAnalysisTestBase, INSTANTIATE_TEST_SUITE_P(UniformityAnalysisTest, LoopTest, - ::testing::Combine(::testing::Range(0, kDiscard + 1), + ::testing::Combine(::testing::Range(0, kReturn + 1), ::testing::Range(0, kNonUniform + 1)), [](const ::testing::TestParamInfo& p) { ControlFlowInterrupt interrupt = @@ -1025,7 +1022,7 @@ class LoopDeadCodeTest : public UniformityAnalysisTestBase, public ::testing::Te INSTANTIATE_TEST_SUITE_P(UniformityAnalysisTest, LoopDeadCodeTest, - ::testing::Range(0, kDiscard + 1), + ::testing::Range(0, kReturn + 1), [](const ::testing::TestParamInfo& p) { return ToStr(static_cast(p.param)); }); @@ -2890,36 +2887,6 @@ test:5:7 note: reading from read_write storage buffer 'non_uniform' may result i )"); } -TEST_F(UniformityAnalysisTest, IfElse_NonUniformDiscard_NoReconverge) { - // If statements should not reconverge after non-uniform discards. - std::string src = R"( -@group(0) @binding(0) var non_uniform : i32; - -fn foo() { - if (non_uniform == 42) { - discard; - } else { - } - workgroupBarrier(); -} -)"; - - RunTest(src, false); - EXPECT_EQ(error_, - R"(test:9:3 warning: 'workgroupBarrier' must only be called from uniform control flow - workgroupBarrier(); - ^^^^^^^^^^^^^^^^ - -test:5:3 note: control flow depends on non-uniform value - if (non_uniform == 42) { - ^^ - -test:5:7 note: reading from read_write storage buffer 'non_uniform' may result in a non-uniform value - if (non_uniform == 42) { - ^^^^^^^^^^^ -)"); -} - //////////////////////////////////////////////////////////////////////////////// /// Switch statement tests. //////////////////////////////////////////////////////////////////////////////// @@ -6749,6 +6716,22 @@ fn foo() { /// Miscellaneous statement and expression tests. //////////////////////////////////////////////////////////////////////////////// +TEST_F(UniformityAnalysisTest, NonUniformDiscard) { + // Non-uniform discard statements should not cause uniformity issues. + std::string src = R"( +@group(0) @binding(0) var non_uniform : i32; + +fn foo() { + if (non_uniform == 42) { + discard; + } + _ = dpdx(1.0); +} +)"; + + RunTest(src, true); +} + TEST_F(UniformityAnalysisTest, FunctionReconvergesOnExit) { // Call a function that has returns during non-uniform control flow, and test that the analysis // reconverges when returning to the caller. @@ -6775,29 +6758,6 @@ fn main() { RunTest(src, true); } -TEST_F(UniformityAnalysisTest, FunctionRequiresUniformFlowAndCausesNonUniformFlow) { - // Test that a function that requires uniform flow and then causes non-uniform flow can be - // called without error. - std::string src = R"( -@group(0) @binding(0) var non_uniform_global : i32; - -fn foo() { - _ = dpdx(0.5); - - if (non_uniform_global == 0) { - discard; - } -} - -@fragment -fn main() { - foo(); -} -)"; - - RunTest(src, true); -} - TEST_F(UniformityAnalysisTest, TypeInitializer) { std::string src = R"( @group(0) @binding(0) var non_uniform_global : i32; @@ -7031,22 +6991,6 @@ fn foo() { RunTest(src, true); } -TEST_F(UniformityAnalysisTest, DeadCode_AfterDiscard) { - // Dead code after a discard statement shouldn't cause uniformity errors. - std::string src = R"( -@group(0) @binding(0) var non_uniform : i32; - -fn foo() { - discard; - if (non_uniform == 42) { - workgroupBarrier(); - } -} -)"; - - RunTest(src, true); -} - TEST_F(UniformityAnalysisTest, ArrayLength) { std::string src = R"( @group(0) @binding(0) var arr : array; diff --git a/src/tint/resolver/validation_test.cc b/src/tint/resolver/validation_test.cc index 34ddd90798..c3893af1d0 100644 --- a/src/tint/resolver/validation_test.cc +++ b/src/tint/resolver/validation_test.cc @@ -766,69 +766,17 @@ TEST_F(ResolverTest, Stmt_Loop_DiscardInContinuing_Direct) { // loop { // continuing { // discard; + // breakif true; // } // } - WrapInFunction(Loop( // loop - Block(), // loop block - Block( // loop continuing block - Discard(Source{{12, 34}})))); + Func("my_func", utils::Empty, ty.void_(), + utils::Vector{Loop( // loop + Block(), // loop block + Block( // loop continuing block + Discard(Source{{12, 34}}), BreakIf(true)))}); - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - R"(12:34 error: continuing blocks must not contain a discard statement)"); -} - -TEST_F(ResolverTest, Stmt_Loop_DiscardInContinuing_Indirect) { - // loop { - // if (false) { break; } - // continuing { - // loop { discard; } - // } - // } - - WrapInFunction(Loop( // outer loop - Block(If(false, Block(Break()))), // outer loop block - Block(Source{{56, 78}}, // outer loop continuing block - Loop( // inner loop - Block( // inner loop block - Discard(Source{{12, 34}})))))); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - R"(12:34 error: continuing blocks must not contain a discard statement -56:78 note: see continuing block here)"); -} - -TEST_F(ResolverTest, Stmt_Loop_DiscardInContinuing_Indirect_ViaCall) { - // fn MayDiscard() { if (true) { discard; } } - // fn F() { MayDiscard(); } - // loop { - // continuing { - // loop { F(); } - // } - // } - - Func("MayDiscard", utils::Empty, ty.void_(), - utils::Vector{ - If(true, Block(Discard())), - }); - Func("SomeFunc", utils::Empty, ty.void_(), - utils::Vector{ - CallStmt(Call("MayDiscard")), - }); - - WrapInFunction(Loop( // outer loop - Block(), // outer loop block - Block(Source{{56, 78}}, // outer loop continuing block - Loop( // inner loop - Block( // inner loop block - CallStmt(Call(Source{{12, 34}}, "SomeFunc"))))))); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - R"(12:34 error: cannot call a function that may discard inside a continuing block -56:78 note: see continuing block here)"); + EXPECT_TRUE(r()->Resolve()) << r()->error(); } TEST_F(ResolverTest, Stmt_Loop_ContinueInContinuing_Direct) { @@ -973,55 +921,11 @@ TEST_F(ResolverTest, Stmt_ForLoop_DiscardInContinuing_Direct) { // break; // } - WrapInFunction(For(nullptr, nullptr, Discard(Source{{12, 34}}), // - Block(Break()))); + Func("my_func", utils::Empty, ty.void_(), + utils::Vector{For(nullptr, nullptr, Discard(Source{{12, 34}}), // + Block(Break()))}); - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - R"(12:34 error: continuing blocks must not contain a discard statement)"); -} - -TEST_F(ResolverTest, Stmt_ForLoop_DiscardInContinuing_Indirect) { - // for(;; loop { discard }) { - // break; - // } - - WrapInFunction(For(nullptr, nullptr, - Loop(Source{{56, 78}}, // - Block(Discard(Source{{12, 34}}))), // - Block(Break()))); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - R"(12:34 error: continuing blocks must not contain a discard statement -56:78 note: see continuing block here)"); -} - -TEST_F(ResolverTest, Stmt_ForLoop_DiscardInContinuing_Indirect_ViaCall) { - // fn MayDiscard() { if (true) { discard; } } - // fn F() { MayDiscard(); } - // for(;; loop { F() }) { - // break; - // } - - Func("MayDiscard", utils::Empty, ty.void_(), - utils::Vector{ - If(true, Block(Discard())), - }); - Func("F", utils::Empty, ty.void_(), - utils::Vector{ - CallStmt(Call("MayDiscard")), - }); - - WrapInFunction(For(nullptr, nullptr, - Loop(Source{{56, 78}}, // - Block(CallStmt(Call(Source{{12, 34}}, "F")))), // - Block(Break()))); - - EXPECT_FALSE(r()->Resolve()); - EXPECT_EQ(r()->error(), - R"(12:34 error: cannot call a function that may discard inside a continuing block -56:78 note: see continuing block here)"); + EXPECT_TRUE(r()->Resolve()) << r()->error(); } TEST_F(ResolverTest, Stmt_ForLoop_ContinueInContinuing_Direct) { diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc index f285b5f42a..5b38e684c2 100644 --- a/src/tint/resolver/validator.cc +++ b/src/tint/resolver/validator.cc @@ -1076,12 +1076,8 @@ bool Validator::Function(const sem::Function* func, ast::PipelineStage stage) co } // https://www.w3.org/TR/WGSL/#behaviors-rules - // a function behavior is always one of {}, {Next}, {Discard}, or - // {Next, Discard}. - if (func->Behaviors() != sem::Behaviors{} && // NOLINT: bad warning - func->Behaviors() != sem::Behavior::kNext && func->Behaviors() != sem::Behavior::kDiscard && - func->Behaviors() != sem::Behaviors{sem::Behavior::kNext, // - sem::Behavior::kDiscard}) { + // a function behavior is always one of {}, or {Next}. + if (func->Behaviors() != sem::Behaviors{} && func->Behaviors() != sem::Behavior::kNext) { auto name = symbols_.NameFor(decl->symbol); TINT_ICE(Resolver, diagnostics_) << "function '" << name << "' behaviors are: " << func->Behaviors(); @@ -1544,19 +1540,6 @@ bool Validator::Call(const sem::Call* call, sem::Statement* current_statement) c return true; } -bool Validator::DiscardStatement(const sem::Statement* stmt, - sem::Statement* current_statement) const { - if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ false, current_statement)) { - AddError("continuing blocks must not contain a discard statement", - stmt->Declaration()->source); - if (continuing != stmt->Declaration() && continuing != stmt->Parent()->Declaration()) { - AddNote("see continuing block here", continuing->source); - } - return false; - } - return true; -} - bool Validator::FallthroughStatement(const sem::Statement* stmt) const { if (auto* block = As(stmt->Parent())) { if (auto* c = As(block->Parent())) { @@ -1843,18 +1826,6 @@ bool Validator::FunctionCall(const sem::Call* call, sem::Statement* current_stat } } - if (call->Behaviors().Contains(sem::Behavior::kDiscard)) { - if (auto* continuing = ClosestContinuing(/*stop_at_loop*/ false, current_statement)) { - AddError("cannot call a function that may discard inside a continuing block", - call->Declaration()->source); - if (continuing != call->Stmt()->Declaration() && - continuing != call->Stmt()->Parent()->Declaration()) { - AddNote("see continuing block here", continuing->source); - } - return false; - } - } - return true; } diff --git a/src/tint/resolver/validator.h b/src/tint/resolver/validator.h index efc38423ae..082147b0c2 100644 --- a/src/tint/resolver/validator.h +++ b/src/tint/resolver/validator.h @@ -199,12 +199,6 @@ class Validator { /// @returns true on success, false otherwise bool Call(const sem::Call* call, sem::Statement* current_statement) const; - /// Validates a discard statement - /// @param stmt the statement to validate - /// @param current_statement the current statement being resolved - /// @returns true on success, false otherwise - bool DiscardStatement(const sem::Statement* stmt, sem::Statement* current_statement) const; - /// Validates an entry point /// @param func the entry point function to validate /// @param stage the pipeline stage for the entry point diff --git a/src/tint/sem/behavior.cc b/src/tint/sem/behavior.cc index 617794fc1a..4746104370 100644 --- a/src/tint/sem/behavior.cc +++ b/src/tint/sem/behavior.cc @@ -20,8 +20,6 @@ std::ostream& operator<<(std::ostream& out, Behavior behavior) { switch (behavior) { case Behavior::kReturn: return out << "Return"; - case Behavior::kDiscard: - return out << "Discard"; case Behavior::kBreak: return out << "Break"; case Behavior::kContinue: diff --git a/src/tint/sem/behavior.h b/src/tint/sem/behavior.h index 4acb8d5a22..25572523cf 100644 --- a/src/tint/sem/behavior.h +++ b/src/tint/sem/behavior.h @@ -23,7 +23,6 @@ namespace tint::sem { /// @see https://www.w3.org/TR/WGSL/#behaviors enum class Behavior { kReturn, - kDiscard, kBreak, kContinue, kFallthrough, diff --git a/src/tint/transform/demote_to_helper.h b/src/tint/transform/demote_to_helper.h index 8968e78b23..ba87febfd1 100644 --- a/src/tint/transform/demote_to_helper.h +++ b/src/tint/transform/demote_to_helper.h @@ -25,6 +25,10 @@ namespace tint::transform { /// program to ensure that discarding the fragment does not affect uniformity with respect to /// derivative operations. We do this by setting a global flag and masking all writes to storage /// buffers and textures. +/// +/// @note Depends on the following transforms to have been run first: +/// * PromoteSideEffectsToDecl +/// * ExpandCompoundAssignment class DemoteToHelper final : public Castable { public: /// Constructor diff --git a/src/tint/transform/for_loop_to_loop_test.cc b/src/tint/transform/for_loop_to_loop_test.cc index 172e1fc15d..fa34f56f34 100644 --- a/src/tint/transform/for_loop_to_loop_test.cc +++ b/src/tint/transform/for_loop_to_loop_test.cc @@ -76,7 +76,7 @@ TEST_F(ForLoopToLoopTest, Body) { auto* src = R"( fn f() { for (;;) { - discard; + return; } } )"; @@ -84,7 +84,7 @@ fn f() { auto* expect = R"( fn f() { loop { - discard; + return; } } )"; diff --git a/src/tint/transform/remove_unreachable_statements_test.cc b/src/tint/transform/remove_unreachable_statements_test.cc index 4b0a2655dd..3e8c2b6689 100644 --- a/src/tint/transform/remove_unreachable_statements_test.cc +++ b/src/tint/transform/remove_unreachable_statements_test.cc @@ -113,187 +113,23 @@ fn f() { EXPECT_EQ(expect, str(got)); } +// Discard has "demote-to-helper" semantics, and so code following a discard statement is not +// considered unreachable. TEST_F(RemoveUnreachableStatementsTest, Discard) { auto* src = R"( fn f() { discard; - var remove_me = 1; - if (true) { - var remove_me_too = 1; - } -} -)"; - - auto* expect = R"( -fn f() { - discard; -} -)"; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(RemoveUnreachableStatementsTest, NestedDiscard) { - auto* src = R"( -fn f() { - { - { - discard; - } - } - var remove_me = 1; - if (true) { - var remove_me_too = 1; - } -} -)"; - - auto* expect = R"( -fn f() { - { - { - discard; - } - } -} -)"; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(RemoveUnreachableStatementsTest, CallToFuncWithDiscard) { - auto* src = R"( -fn DISCARD() { - discard; -} - -fn f() { - DISCARD(); - var remove_me = 1; - if (true) { - var remove_me_too = 1; - } -} -)"; - - auto* expect = R"( -fn DISCARD() { - discard; -} - -fn f() { - DISCARD(); -} -)"; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(RemoveUnreachableStatementsTest, CallToFuncWithIfDiscard) { - auto* src = R"( -fn DISCARD() { - if (true) { - discard; - } -} - -fn f() { - DISCARD(); var preserve_me = 1; - if (true) { - var preserve_me_too = 1; - } -} -)"; - - auto* expect = src; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(RemoveUnreachableStatementsTest, IfDiscardElseDiscard) { - auto* src = R"( -fn f() { - if (true) { - discard; - } else { - discard; - } - var remove_me = 1; - if (true) { - var remove_me_too = 1; - } } )"; auto* expect = R"( fn f() { - if (true) { - discard; - } else { - discard; - } -} -)"; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(RemoveUnreachableStatementsTest, IfDiscardElseReturn) { - auto* src = R"( -fn f() { - if (true) { - discard; - } else { - return; - } - var remove_me = 1; - if (true) { - var remove_me_too = 1; - } -} -)"; - - auto* expect = R"( -fn f() { - if (true) { - discard; - } else { - return; - } -} -)"; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(RemoveUnreachableStatementsTest, IfDiscard) { - auto* src = R"( -fn f() { - if (true) { - discard; - } + discard; var preserve_me = 1; - if (true) { - var preserve_me_too = 1; - } } )"; - auto* expect = src; - auto got = Run(src); EXPECT_EQ(expect, str(got)); @@ -319,27 +155,6 @@ fn f() { EXPECT_EQ(expect, str(got)); } -TEST_F(RemoveUnreachableStatementsTest, IfElseDiscard) { - auto* src = R"( -fn f() { - if (true) { - } else { - discard; - } - var preserve_me = 1; - if (true) { - var preserve_me_too = 1; - } -} -)"; - - auto* expect = src; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - TEST_F(RemoveUnreachableStatementsTest, IfElseReturn) { auto* src = R"( fn f() { @@ -361,42 +176,6 @@ fn f() { EXPECT_EQ(expect, str(got)); } -TEST_F(RemoveUnreachableStatementsTest, LoopWithDiscard) { - auto* src = R"( -fn f() { - loop { - var a = 1; - discard; - - continuing { - var b = 2; - } - } - var remove_me = 1; - if (true) { - var remove_me_too = 1; - } -} -)"; - - auto* expect = R"( -fn f() { - loop { - var a = 1; - discard; - - continuing { - var b = 2; - } - } -} -)"; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - TEST_F(RemoveUnreachableStatementsTest, LoopWithConditionalBreak) { auto* src = R"( fn f() { @@ -449,97 +228,6 @@ fn f() { EXPECT_EQ(expect, str(got)); } -TEST_F(RemoveUnreachableStatementsTest, SwitchDefaultDiscard) { - auto* src = R"( -fn f() { - switch(1) { - default: { - discard; - } - } - var remove_me = 1; - if (true) { - var remove_me_too = 1; - } -} -)"; - - auto* expect = R"( -fn f() { - switch(1) { - default: { - discard; - } - } -} -)"; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(RemoveUnreachableStatementsTest, SwitchCaseReturnDefaultDiscard) { - auto* src = R"( -fn f() { - switch(1) { - case 0: { - return; - } - default: { - discard; - } - } - var remove_me = 1; - if (true) { - var remove_me_too = 1; - } -} -)"; - - auto* expect = R"( -fn f() { - switch(1) { - case 0: { - return; - } - default: { - discard; - } - } -} -)"; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(RemoveUnreachableStatementsTest, SwitchCaseBreakDefaultDiscard) { - auto* src = R"( -fn f() { - switch(1) { - case 0: { - break; - } - default: { - discard; - } - } - var preserve_me = 1; - if (true) { - var preserve_me_too = 1; - } -} -)"; - - auto* expect = src; - - auto got = Run(src); - - EXPECT_EQ(expect, str(got)); -} - TEST_F(RemoveUnreachableStatementsTest, SwitchCaseReturnDefaultBreak) { auto* src = R"( fn f() { diff --git a/src/tint/transform/unwind_discard_functions.cc b/src/tint/transform/unwind_discard_functions.cc deleted file mode 100644 index 068fe35989..0000000000 --- a/src/tint/transform/unwind_discard_functions.cc +++ /dev/null @@ -1,374 +0,0 @@ -// Copyright 2022 The Tint Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "src/tint/transform/unwind_discard_functions.h" - -#include -#include -#include -#include -#include - -#include "src/tint/ast/discard_statement.h" -#include "src/tint/ast/return_statement.h" -#include "src/tint/ast/traverse_expressions.h" -#include "src/tint/sem/block_statement.h" -#include "src/tint/sem/call.h" -#include "src/tint/sem/for_loop_statement.h" -#include "src/tint/sem/function.h" -#include "src/tint/sem/if_statement.h" -#include "src/tint/transform/utils/get_insertion_point.h" - -TINT_INSTANTIATE_TYPEINFO(tint::transform::UnwindDiscardFunctions); - -namespace tint::transform { -namespace { - -bool ShouldRun(const Program* program) { - auto& sem = program->Sem(); - for (auto* f : program->AST().Functions()) { - if (sem.Get(f)->Behaviors().Contains(sem::Behavior::kDiscard)) { - return true; - } - } - return false; -} - -} // namespace - -/// PIMPL state for the transform -struct UnwindDiscardFunctions::State { - /// Constructor - /// @param ctx_in the context - explicit State(CloneContext& ctx_in) : ctx(ctx_in), b(*ctx_in.dst), sem(ctx_in.src->Sem()) {} - - /// Runs the transform - void Run() { - ctx.ReplaceAll([&](const ast::BlockStatement* block) -> const ast::Statement* { - // Iterate block statements and replace them as needed. - for (auto* stmt : block->statements) { - if (auto* new_stmt = Statement(stmt)) { - ctx.Replace(stmt, new_stmt); - } - - // Handle for loops, as they are the only other AST node that - // contains statements outside of BlockStatements. - if (auto* fl = stmt->As()) { - if (auto* new_stmt = Statement(fl->initializer)) { - ctx.Replace(fl->initializer, new_stmt); - } - if (auto* new_stmt = Statement(fl->continuing)) { - // NOTE: Should never reach here as we cannot discard in a - // continuing block. - ctx.Replace(fl->continuing, new_stmt); - } - } - } - - return nullptr; - }); - } - - private: - CloneContext& ctx; - ProgramBuilder& b; - const sem::Info& sem; - Symbol module_discard_var_name; // Use ModuleDiscardVarName() to read - Symbol module_discard_func_name; // Use ModuleDiscardFuncName() to read - - // Returns true if `sem_expr` contains a call expression that may - // (transitively) execute a discard statement. - bool MayDiscard(const sem::Expression* sem_expr) { - return sem_expr && sem_expr->Behaviors().Contains(sem::Behavior::kDiscard); - } - - // Lazily creates and returns the name of the module bool variable for whether - // to discard: "tint_discard". - Symbol ModuleDiscardVarName() { - if (!module_discard_var_name.IsValid()) { - module_discard_var_name = b.Symbols().New("tint_discard"); - ctx.dst->GlobalVar(module_discard_var_name, b.ty.bool_(), b.Expr(false), - ast::AddressSpace::kPrivate); - } - return module_discard_var_name; - } - - // Lazily creates and returns the name of the function that contains a single - // discard statement: "tint_discard_func". - // We do this to avoid having multiple discard statements in a single program, - // which causes problems in certain backends (see crbug.com/1118). - Symbol ModuleDiscardFuncName() { - if (!module_discard_func_name.IsValid()) { - module_discard_func_name = b.Symbols().New("tint_discard_func"); - b.Func(module_discard_func_name, tint::utils::Empty, b.ty.void_(), - tint::utils::Vector{b.Discard()}); - } - return module_discard_func_name; - } - - // Creates "return ;" based on the return type of - // `stmt`'s owning function. - const ast::ReturnStatement* Return(const ast::Statement* stmt) { - const ast::Expression* ret_val = nullptr; - auto* ret_type = sem.Get(stmt)->Function()->Declaration()->return_type; - if (!ret_type->Is()) { - ret_val = b.Construct(ctx.Clone(ret_type)); - } - return b.Return(ret_val); - } - - // Returns true if the function `stmt` is in is an entry point - bool IsInEntryPointFunc(const ast::Statement* stmt) { - return sem.Get(stmt)->Function()->Declaration()->IsEntryPoint(); - } - - // Creates "tint_discard_func();" - const ast::CallStatement* CallDiscardFunc() { - auto func_name = ModuleDiscardFuncName(); - return b.CallStmt(b.Call(func_name)); - } - - // Creates and returns a new if-statement of the form: - // - // if (tint_discard) { - // return ; - // } - // - // or if `stmt` is in a entry point function: - // - // if (tint_discard) { - // tint_discard_func(); - // return ; - // } - // - const ast::IfStatement* IfDiscardReturn(const ast::Statement* stmt) { - tint::utils::Vector stmts; - - // For entry point functions, also emit the discard statement - if (IsInEntryPointFunc(stmt)) { - stmts.Push(CallDiscardFunc()); - } - - stmts.Push(Return(stmt)); - - auto var_name = ModuleDiscardVarName(); - return b.If(var_name, b.Block(stmts)); - } - - // Hoists `sem_expr` to a let followed by an `IfDiscardReturn` before `stmt`. - // For example, if `stmt` is: - // - // return f(); - // - // This function will transform this to: - // - // let t1 = f(); - // if (tint_discard) { - // return; - // } - // return t1; - // - const ast::Statement* HoistAndInsertBefore(const ast::Statement* stmt, - const sem::Expression* sem_expr) { - auto* expr = sem_expr->Declaration(); - - auto ip = utils::GetInsertionPoint(ctx, stmt); - auto var_name = b.Sym(); - auto* decl = b.Decl(b.Var(var_name, ctx.Clone(expr))); - ctx.InsertBefore(ip.first->Declaration()->statements, ip.second, decl); - - ctx.InsertBefore(ip.first->Declaration()->statements, ip.second, IfDiscardReturn(stmt)); - - auto* var_expr = b.Expr(var_name); - - // Special handling for CallStatement as we can only replace its expression - // with a CallExpression. - if (stmt->Is()) { - // We could replace the call statement with no statement, but we can't do - // that with transforms (yet), so just return a phony assignment. - return b.Assign(b.Phony(), var_expr); - } - - ctx.Replace(expr, var_expr); - return ctx.CloneWithoutTransform(stmt); - } - - // Returns true if `stmt` is a for-loop initializer statement. - bool IsForLoopInitStatement(const ast::Statement* stmt) { - if (auto* sem_stmt = sem.Get(stmt)) { - if (auto* sem_fl = tint::As(sem_stmt->Parent())) { - return sem_fl->Declaration()->initializer == stmt; - } - } - return false; - } - - // Inserts an `IfDiscardReturn` after `stmt` if possible (i.e. `stmt` is not - // in a for-loop init), otherwise falls back to HoistAndInsertBefore, hoisting - // `sem_expr` to a let followed by an `IfDiscardReturn` before `stmt`. - // - // For example, if `stmt` is: - // - // let r = f(); - // - // This function will transform this to: - // - // let r = f(); - // if (tint_discard) { - // return; - // } - const ast::Statement* TryInsertAfter(const ast::Statement* stmt, - const sem::Expression* sem_expr) { - // If `stmt` is the init of a for-loop, hoist and insert before instead. - if (IsForLoopInitStatement(stmt)) { - return HoistAndInsertBefore(stmt, sem_expr); - } - - auto ip = utils::GetInsertionPoint(ctx, stmt); - ctx.InsertAfter(ip.first->Declaration()->statements, ip.second, IfDiscardReturn(stmt)); - return nullptr; // Don't replace current statement - } - - // Replaces the input discard statement with either setting the module level - // discard bool ("tint_discard = true"), or calling the discard function - // ("tint_discard_func()"), followed by a default return statement. - // - // Replaces "discard;" with: - // - // tint_discard = true; - // return; - // - // Or if `stmt` is a entry point function, replaces with: - // - // tint_discard_func(); - // return; - // - const ast::Statement* ReplaceDiscardStatement(const ast::DiscardStatement* stmt) { - const ast::Statement* to_insert = nullptr; - if (IsInEntryPointFunc(stmt)) { - to_insert = CallDiscardFunc(); - } else { - auto var_name = ModuleDiscardVarName(); - to_insert = b.Assign(var_name, true); - } - - auto ip = utils::GetInsertionPoint(ctx, stmt); - ctx.InsertBefore(ip.first->Declaration()->statements, ip.second, to_insert); - return Return(stmt); - } - - // Handle statement - const ast::Statement* Statement(const ast::Statement* stmt) { - return Switch( - stmt, - [&](const ast::DiscardStatement* s) -> const ast::Statement* { - return ReplaceDiscardStatement(s); - }, - [&](const ast::AssignmentStatement* s) -> const ast::Statement* { - auto* sem_lhs = sem.Get(s->lhs); - auto* sem_rhs = sem.Get(s->rhs); - if (MayDiscard(sem_lhs)) { - if (MayDiscard(sem_rhs)) { - TINT_ICE(Transform, b.Diagnostics()) - << "Unexpected: both sides of assignment statement may " - "discard. Make sure transform::PromoteSideEffectsToDecl " - "was run first."; - } - return TryInsertAfter(s, sem_lhs); - } else if (MayDiscard(sem_rhs)) { - return TryInsertAfter(s, sem_rhs); - } - return nullptr; - }, - [&](const ast::CallStatement* s) -> const ast::Statement* { - auto* sem_expr = sem.Get(s->expr); - if (!MayDiscard(sem_expr)) { - return nullptr; - } - return TryInsertAfter(s, sem_expr); - }, - [&](const ast::ForLoopStatement* s) -> const ast::Statement* { - if (MayDiscard(sem.Get(s->condition))) { - TINT_ICE(Transform, b.Diagnostics()) - << "Unexpected ForLoopStatement condition that may discard. " - "Make sure transform::PromoteSideEffectsToDecl was run " - "first."; - } - return nullptr; - }, - [&](const ast::WhileStatement* s) -> const ast::Statement* { - if (MayDiscard(sem.Get(s->condition))) { - TINT_ICE(Transform, b.Diagnostics()) - << "Unexpected WhileStatement condition that may discard. " - "Make sure transform::PromoteSideEffectsToDecl was run " - "first."; - } - return nullptr; - }, - [&](const ast::IfStatement* s) -> const ast::Statement* { - auto* sem_expr = sem.Get(s->condition); - if (!MayDiscard(sem_expr)) { - return nullptr; - } - return HoistAndInsertBefore(s, sem_expr); - }, - [&](const ast::ReturnStatement* s) -> const ast::Statement* { - auto* sem_expr = sem.Get(s->value); - if (!MayDiscard(sem_expr)) { - return nullptr; - } - return HoistAndInsertBefore(s, sem_expr); - }, - [&](const ast::SwitchStatement* s) -> const ast::Statement* { - auto* sem_expr = sem.Get(s->condition); - if (!MayDiscard(sem_expr)) { - return nullptr; - } - return HoistAndInsertBefore(s, sem_expr); - }, - [&](const ast::VariableDeclStatement* s) -> const ast::Statement* { - auto* var = s->variable; - if (!var->initializer) { - return nullptr; - } - auto* sem_expr = sem.Get(var->initializer); - if (!MayDiscard(sem_expr)) { - return nullptr; - } - return TryInsertAfter(s, sem_expr); - }); - } -}; - -UnwindDiscardFunctions::UnwindDiscardFunctions() = default; -UnwindDiscardFunctions::~UnwindDiscardFunctions() = default; - -Transform::ApplyResult UnwindDiscardFunctions::Apply(const Program* src, - const DataMap&, - DataMap&) const { - if (!ShouldRun(src)) { - return SkipTransform; - } - - ProgramBuilder b; - CloneContext ctx{&b, src, /* auto_clone_symbols */ true}; - - State state(ctx); - state.Run(); - - ctx.Clone(); - return Program(std::move(b)); -} - -} // namespace tint::transform diff --git a/src/tint/transform/unwind_discard_functions.h b/src/tint/transform/unwind_discard_functions.h deleted file mode 100644 index 7614c2759b..0000000000 --- a/src/tint/transform/unwind_discard_functions.h +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2022 The Tint Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef SRC_TINT_TRANSFORM_UNWIND_DISCARD_FUNCTIONS_H_ -#define SRC_TINT_TRANSFORM_UNWIND_DISCARD_FUNCTIONS_H_ - -#include "src/tint/transform/transform.h" - -namespace tint::transform { - -/// This transform is responsible for implementing discard semantics as per the -/// WGSL specification: https://gpuweb.github.io/gpuweb/wgsl/#discard-statement -/// -/// Not all backend languages implement discard this way (e.g. HLSL), so this -/// transform does the following: -/// -/// * Replaces discard statements with setting a module-level boolean -/// "tint_discard" to true and returning immediately. -/// * Wherever calls are made to discarding functions (directly or -/// transitively), it inserts a check afterwards for if "tint_discard" is true, -/// to return immediately. -/// * Finally, entry point functions that call discarding functions -/// emit a call to "tint_discard_func()" that contains the sole discard -/// statement. -/// -/// @note Depends on the following transforms to have been run first: -/// * PromoteSideEffectsToDecl -class UnwindDiscardFunctions final : public Castable { - public: - /// Constructor - UnwindDiscardFunctions(); - - /// Destructor - ~UnwindDiscardFunctions() override; - - /// @copydoc Transform::Apply - ApplyResult Apply(const Program* program, - const DataMap& inputs, - DataMap& outputs) const override; - - private: - struct State; -}; - -} // namespace tint::transform - -#endif // SRC_TINT_TRANSFORM_UNWIND_DISCARD_FUNCTIONS_H_ diff --git a/src/tint/transform/unwind_discard_functions_test.cc b/src/tint/transform/unwind_discard_functions_test.cc deleted file mode 100644 index 7d1fa27264..0000000000 --- a/src/tint/transform/unwind_discard_functions_test.cc +++ /dev/null @@ -1,1480 +0,0 @@ -// Copyright 2022 The Tint Authors. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#include "src/tint/transform/unwind_discard_functions.h" -#include "src/tint/transform/promote_side_effects_to_decl.h" -#include "src/tint/transform/test_helper.h" - -namespace tint::transform { -namespace { - -using UnwindDiscardFunctionsTest = TransformTest; - -TEST_F(UnwindDiscardFunctionsTest, EmptyModule) { - auto* src = ""; - auto* expect = src; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, ShouldRun_NoDiscardFunc) { - auto* src = R"( -fn f() { -} -)"; - - EXPECT_FALSE(ShouldRun(src)); -} - -TEST_F(UnwindDiscardFunctionsTest, SingleDiscardFunc_NoCall) { - auto* src = R"( -fn f() { - discard; -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() { - tint_discard = true; - return; -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, MultipleDiscardFuncs_NoCall) { - auto* src = R"( -fn f() { - discard; - let marker1 = 0; -} - -fn g() { - discard; - let marker1 = 0; -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() { - tint_discard = true; - return; - let marker1 = 0; -} - -fn g() { - tint_discard = true; - return; - let marker1 = 0; -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Call_VoidReturn) { - auto* src = R"( -fn f() { - discard; - let marker1 = 0; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - f(); - let marker1 = 0; - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() { - tint_discard = true; - return; - let marker1 = 0; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let marker1 = 0; - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Call_NonVoidReturn) { - auto* src = R"( -struct S { - x : i32, - y : i32, -}; - -fn f() -> S { - if (true) { - discard; - } - let marker1 = 0; - var s : S; - return s; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - f(); - let marker2 = 0; - return vec4(); -} -)"; - auto* expect = R"( -struct S { - x : i32, - y : i32, -} - -var tint_discard : bool = false; - -fn f() -> S { - if (true) { - tint_discard = true; - return S(); - } - let marker1 = 0; - var s : S; - return s; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let marker1 = 0; - f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let marker2 = 0; - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Call_Nested) { - auto* src = R"( -fn f() -> i32 { - let marker1 = 0; - if (true) { - discard; - } - let marker2 = 0; - return 0; -} - -fn g() -> i32 { - let marker1 = 0; - f(); - let marker2 = 0; - return 0; -} - -fn h() -> i32{ - let marker1 = 0; - g(); - let marker2 = 0; - return 0; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - h(); - let marker2 = 0; - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - let marker1 = 0; - if (true) { - tint_discard = true; - return i32(); - } - let marker2 = 0; - return 0; -} - -fn g() -> i32 { - let marker1 = 0; - f(); - if (tint_discard) { - return i32(); - } - let marker2 = 0; - return 0; -} - -fn h() -> i32 { - let marker1 = 0; - g(); - if (tint_discard) { - return i32(); - } - let marker2 = 0; - return 0; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let marker1 = 0; - h(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let marker2 = 0; - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Call_Multiple) { - auto* src = R"( -fn f() { - discard; - let marker1 = 0; -} - -fn g() { - discard; - let marker1 = 0; -} - -fn h() { - discard; - let marker1 = 0; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - f(); - let marker2 = 0; - g(); - let marker3 = 0; - h(); - let marker4 = 0; - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() { - tint_discard = true; - return; - let marker1 = 0; -} - -fn g() { - tint_discard = true; - return; - let marker1 = 0; -} - -fn h() { - tint_discard = true; - return; - let marker1 = 0; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let marker1 = 0; - f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let marker2 = 0; - g(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let marker3 = 0; - h(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let marker4 = 0; - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Call_DiscardFuncDeclaredBelow) { - auto* src = R"( -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - f(); - let marker1 = 0; - return vec4(); -} - -fn f() { - discard; - let marker1 = 0; -} -)"; - auto* expect = R"( -fn tint_discard_func() { - discard; -} - -var tint_discard : bool = false; - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let marker1 = 0; - return vec4(); -} - -fn f() { - tint_discard = true; - return; - let marker1 = 0; -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, If) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - if (f() == 42) { - let marker1 = 0; - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - if ((tint_symbol == 42)) { - let marker1 = 0; - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, ElseIf) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - if (true) { - let marker1 = 0; - } else if (f() == 42) { - let marker2 = 0; - } else if (true) { - let marker3 = 0; - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - if (true) { - let marker1 = 0; - } else { - let tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - if ((tint_symbol == 42)) { - let marker2 = 0; - } else if (true) { - let marker3 = 0; - } - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, ForLoop_Init_Assignment) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - var a = 0; - for (a = f(); ; ) { - let marker2 = 0; - break; - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let marker1 = 0; - var a = 0; - var tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - for(a = tint_symbol; ; ) { - let marker2 = 0; - break; - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, ForLoop_Init_Call) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - for (f(); ; ) { - let marker2 = 0; - break; - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let marker1 = 0; - var tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - for(_ = tint_symbol; ; ) { - let marker2 = 0; - break; - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, ForLoop_Init_VariableDecl) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - for (let i = f(); ; ) { - let marker2 = 0; - break; - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let marker1 = 0; - var tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - for(let i = tint_symbol; ; ) { - let marker2 = 0; - break; - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, ForLoop_Cond) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - for (; f() == 42; ) { - let marker2 = 0; - break; - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let marker1 = 0; - loop { - let tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - if (!((tint_symbol == 42))) { - break; - } - { - let marker2 = 0; - break; - } - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, ForLoop_Cont) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - for (; ; f()) { - let marker2 = 0; - break; - } - return vec4(); -} -)"; - auto* expect = - R"(test:12:12 error: cannot call a function that may discard inside a continuing block - for (; ; f()) { - ^ -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, While_Cond) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - while (f() == 42) { - let marker2 = 0; - break; - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let marker1 = 0; - loop { - let tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - if (!((tint_symbol == 42))) { - break; - } - { - let marker2 = 0; - break; - } - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Switch) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - switch (f()) { - case 0: { - let marker1 = 0; - } - case 1: { - let marker2 = 0; - } - case 42: { - let marker3 = 0; - } - default: { - let marker4 = 0; - } - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - var tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - switch(tint_symbol) { - case 0: { - let marker1 = 0; - } - case 1: { - let marker2 = 0; - } - case 42: { - let marker3 = 0; - } - default: { - let marker4 = 0; - } - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Return) { - auto* src = R"( -struct S { - x : i32, - y : i32, -}; - -fn f() -> S { - if (true) { - discard; - } - var s : S; - return s; -} - -fn g() -> S { - return f(); -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - let marker1 = 0; - g(); - return vec4(); -} -)"; - auto* expect = R"( -struct S { - x : i32, - y : i32, -} - -var tint_discard : bool = false; - -fn f() -> S { - if (true) { - tint_discard = true; - return S(); - } - var s : S; - return s; -} - -fn g() -> S { - var tint_symbol = f(); - if (tint_discard) { - return S(); - } - return tint_symbol; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let marker1 = 0; - g(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, VariableDecl) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - var a = f(); - let marker1 = 0; - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - var a = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let marker1 = 0; - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Assignment_RightDiscard) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 42; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - var a : i32; - a = f(); - let marker1 = 0; - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 42; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - var a : i32; - a = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let marker1 = 0; - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Assignment_LeftDiscard) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 0; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - var b = array(); - b[f()] = 10; - let marker1 = 0; - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 0; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - var b = array(); - let tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - b[tint_symbol] = 10; - let marker1 = 0; - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Assignment_BothDiscard) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 0; -} - -fn g() -> i32 { - if (true) { - discard; - } - return 0; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - var b = array(); - b[f()] = g(); - let marker1 = 0; - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 0; -} - -fn g() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 0; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - var b = array(); - let tint_symbol = g(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let tint_symbol_1 = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - b[tint_symbol_1] = tint_symbol; - let marker1 = 0; - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Binary_Arith_MultipleDiscardFuncs) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 0; -} - -fn g() -> i32 { - if (true) { - discard; - } - return 0; -} - -fn h() -> i32{ - if (true) { - discard; - } - return 0; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - if ((f() + g() + h()) == 0) { - let marker1 = 0; - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 0; -} - -fn g() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 0; -} - -fn h() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 0; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let tint_symbol = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let tint_symbol_1 = g(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - let tint_symbol_2 = h(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - if ((((tint_symbol + tint_symbol_1) + tint_symbol_2) == 0)) { - let marker1 = 0; - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, Binary_Logical_MultipleDiscardFuncs) { - auto* src = R"( -fn f() -> i32 { - if (true) { - discard; - } - return 0; -} - -fn g() -> i32 { - if (true) { - discard; - } - return 0; -} - -fn h() -> i32{ - if (true) { - discard; - } - return 0; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - if (f() == 1 && g() == 2 && h() == 3) { - let marker1 = 0; - } - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard : bool = false; - -fn f() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 0; -} - -fn g() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 0; -} - -fn h() -> i32 { - if (true) { - tint_discard = true; - return i32(); - } - return 0; -} - -fn tint_discard_func() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - let tint_symbol_2 = f(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - var tint_symbol_1 = (tint_symbol_2 == 1); - if (tint_symbol_1) { - let tint_symbol_3 = g(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - tint_symbol_1 = (tint_symbol_3 == 2); - } - var tint_symbol = tint_symbol_1; - if (tint_symbol) { - let tint_symbol_4 = h(); - if (tint_discard) { - tint_discard_func(); - return vec4(); - } - tint_symbol = (tint_symbol_4 == 3); - } - if (tint_symbol) { - let marker1 = 0; - } - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -TEST_F(UnwindDiscardFunctionsTest, EnsureNoSymbolCollision) { - auto* src = R"( -var tint_discard_func : i32; -var tint_discard : i32; - -fn f() { - discard; - let marker1 = 0; -} - -@fragment -fn main(@builtin(position) coord_in: vec4) -> @location(0) vec4 { - f(); - let marker1 = 0; - return vec4(); -} -)"; - auto* expect = R"( -var tint_discard_func : i32; - -var tint_discard : i32; - -var tint_discard_1 : bool = false; - -fn f() { - tint_discard_1 = true; - return; - let marker1 = 0; -} - -fn tint_discard_func_1() { - discard; -} - -@fragment -fn main(@builtin(position) coord_in : vec4) -> @location(0) vec4 { - f(); - if (tint_discard_1) { - tint_discard_func_1(); - return vec4(); - } - let marker1 = 0; - return vec4(); -} -)"; - - DataMap data; - auto got = Run(src, data); - - EXPECT_EQ(expect, str(got)); -} - -} // namespace -} // namespace tint::transform diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc index 50cdbcf716..29136cbe09 100644 --- a/src/tint/writer/glsl/generator_impl.cc +++ b/src/tint/writer/glsl/generator_impl.cc @@ -54,6 +54,7 @@ #include "src/tint/transform/canonicalize_entry_point_io.h" #include "src/tint/transform/combine_samplers.h" #include "src/tint/transform/decompose_memory_access.h" +#include "src/tint/transform/demote_to_helper.h" #include "src/tint/transform/disable_uniformity_analysis.h" #include "src/tint/transform/expand_compound_assignment.h" #include "src/tint/transform/manager.h" @@ -66,7 +67,6 @@ #include "src/tint/transform/single_entry_point.h" #include "src/tint/transform/std140.h" #include "src/tint/transform/unshadow.h" -#include "src/tint/transform/unwind_discard_functions.h" #include "src/tint/transform/zero_init_workgroup_memory.h" #include "src/tint/utils/defer.h" #include "src/tint/utils/map.h" @@ -217,7 +217,9 @@ SanitizedResult Sanitize(const Program* in, manager.Add(); manager.Add(); manager.Add(); - manager.Add(); + + // DemoteToHelper must come after PromoteSideEffectsToDecl and ExpandCompoundAssignment. + manager.Add(); manager.Add(); diff --git a/src/tint/writer/glsl/generator_impl_loop_test.cc b/src/tint/writer/glsl/generator_impl_loop_test.cc index 7aa94be3bc..639107b79d 100644 --- a/src/tint/writer/glsl/generator_impl_loop_test.cc +++ b/src/tint/writer/glsl/generator_impl_loop_test.cc @@ -23,7 +23,7 @@ namespace { using GlslGeneratorImplTest_Loop = TestHelper; TEST_F(GlslGeneratorImplTest_Loop, Emit_Loop) { - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(); auto* l = Loop(body, continuing); @@ -36,7 +36,7 @@ TEST_F(GlslGeneratorImplTest_Loop, Emit_Loop) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { - discard; + break; } )"); } @@ -44,7 +44,7 @@ TEST_F(GlslGeneratorImplTest_Loop, Emit_Loop) { TEST_F(GlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) { Func("a_statement", {}, ty.void_(), {}); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement"))); auto* l = Loop(body, continuing); @@ -57,7 +57,7 @@ TEST_F(GlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { - discard; + break; { a_statement(); } @@ -68,7 +68,7 @@ TEST_F(GlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) { TEST_F(GlslGeneratorImplTest_Loop, Emit_LoopWithContinuing_BreakIf) { Func("a_statement", {}, ty.void_(), {}); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement")), BreakIf(true)); auto* l = Loop(body, continuing); @@ -81,7 +81,7 @@ TEST_F(GlslGeneratorImplTest_Loop, Emit_LoopWithContinuing_BreakIf) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { - discard; + break; { a_statement(); if (true) { break; } @@ -96,7 +96,7 @@ TEST_F(GlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) { GlobalVar("lhs", ty.f32(), ast::AddressSpace::kPrivate); GlobalVar("rhs", ty.f32(), ast::AddressSpace::kPrivate); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement"))); auto* inner = Loop(body, continuing); @@ -105,7 +105,7 @@ TEST_F(GlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) { auto* lhs = Expr("lhs"); auto* rhs = Expr("rhs"); - continuing = Block(Assign(lhs, rhs)); + continuing = Block(Assign(lhs, rhs), BreakIf(true)); auto* outer = Loop(body, continuing); @@ -119,13 +119,14 @@ TEST_F(GlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) { ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { while (true) { - discard; + break; { a_statement(); } } { lhs = rhs; + if (true) { break; } } } )"); diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc index 92e0cc5595..a7c3f00514 100644 --- a/src/tint/writer/hlsl/generator_impl.cc +++ b/src/tint/writer/hlsl/generator_impl.cc @@ -54,6 +54,7 @@ #include "src/tint/transform/calculate_array_length.h" #include "src/tint/transform/canonicalize_entry_point_io.h" #include "src/tint/transform/decompose_memory_access.h" +#include "src/tint/transform/demote_to_helper.h" #include "src/tint/transform/disable_uniformity_analysis.h" #include "src/tint/transform/expand_compound_assignment.h" #include "src/tint/transform/localize_struct_array_assignment.h" @@ -65,7 +66,6 @@ #include "src/tint/transform/remove_phonies.h" #include "src/tint/transform/simplify_pointers.h" #include "src/tint/transform/unshadow.h" -#include "src/tint/transform/unwind_discard_functions.h" #include "src/tint/transform/vectorize_scalar_matrix_initializers.h" #include "src/tint/transform/zero_init_workgroup_memory.h" #include "src/tint/utils/defer.h" @@ -213,10 +213,15 @@ SanitizedResult Sanitize(const Program* in, const Options& options) { manager.Add(); manager.Add(); manager.Add(); - manager.Add(); manager.Add(); manager.Add(); manager.Add(); + + // DemoteToHelper must come after CanonicalizeEntryPointIO, PromoteSideEffectsToDecl, and + // ExpandCompoundAssignment. + // TODO(crbug.com/tint/1752): This is only necessary when FXC is being used. + manager.Add(); + // ArrayLengthFromUniform must come after InlinePointerLets and Simplify, as // it assumes that the form of the array length argument is &var.array. manager.Add(); diff --git a/src/tint/writer/hlsl/generator_impl_loop_test.cc b/src/tint/writer/hlsl/generator_impl_loop_test.cc index 3d8219b064..9d2a4def2e 100644 --- a/src/tint/writer/hlsl/generator_impl_loop_test.cc +++ b/src/tint/writer/hlsl/generator_impl_loop_test.cc @@ -23,7 +23,7 @@ namespace { using HlslGeneratorImplTest_Loop = TestHelper; TEST_F(HlslGeneratorImplTest_Loop, Emit_Loop) { - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(); auto* l = Loop(body, continuing); @@ -36,7 +36,7 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_Loop) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { - discard; + break; } )"); } @@ -44,7 +44,7 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_Loop) { TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) { Func("a_statement", {}, ty.void_(), {}); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement"))); auto* l = Loop(body, continuing); @@ -57,7 +57,7 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { - discard; + break; { a_statement(); } @@ -68,7 +68,7 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) { TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing_BreakIf) { Func("a_statement", {}, ty.void_(), {}); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement")), BreakIf(true)); auto* l = Loop(body, continuing); @@ -81,7 +81,7 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing_BreakIf) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { - discard; + break; { a_statement(); if (true) { break; } @@ -96,7 +96,7 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) { GlobalVar("lhs", ty.f32(), ast::AddressSpace::kPrivate); GlobalVar("rhs", ty.f32(), ast::AddressSpace::kPrivate); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement"))); auto* inner = Loop(body, continuing); @@ -105,7 +105,7 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) { auto* lhs = Expr("lhs"); auto* rhs = Expr("rhs"); - continuing = Block(Assign(lhs, rhs)); + continuing = Block(Assign(lhs, rhs), BreakIf(true)); auto* outer = Loop(body, continuing); @@ -119,13 +119,14 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) { ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { while (true) { - discard; + break; { a_statement(); } } { lhs = rhs; + if (true) { break; } } } )"); diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc index 65b52756e5..88578dff6a 100644 --- a/src/tint/writer/msl/generator_impl.cc +++ b/src/tint/writer/msl/generator_impl.cc @@ -62,6 +62,7 @@ #include "src/tint/transform/array_length_from_uniform.h" #include "src/tint/transform/builtin_polyfill.h" #include "src/tint/transform/canonicalize_entry_point_io.h" +#include "src/tint/transform/demote_to_helper.h" #include "src/tint/transform/disable_uniformity_analysis.h" #include "src/tint/transform/expand_compound_assignment.h" #include "src/tint/transform/manager.h" @@ -72,7 +73,6 @@ #include "src/tint/transform/remove_phonies.h" #include "src/tint/transform/simplify_pointers.h" #include "src/tint/transform/unshadow.h" -#include "src/tint/transform/unwind_discard_functions.h" #include "src/tint/transform/vectorize_scalar_matrix_initializers.h" #include "src/tint/transform/zero_init_workgroup_memory.h" #include "src/tint/utils/defer.h" @@ -226,9 +226,12 @@ SanitizedResult Sanitize(const Program* in, const Options& options) { manager.Add(); manager.Add(); manager.Add(); - manager.Add(); manager.Add(); + // DemoteToHelper must come after PromoteSideEffectsToDecl and ExpandCompoundAssignment. + // TODO(crbug.com/tint/1752): This is only necessary for Metal versions older than 2.3. + manager.Add(); + manager.Add(); manager.Add(); manager.Add(); diff --git a/src/tint/writer/msl/generator_impl_loop_test.cc b/src/tint/writer/msl/generator_impl_loop_test.cc index 1dd5430ab4..89009e0cd0 100644 --- a/src/tint/writer/msl/generator_impl_loop_test.cc +++ b/src/tint/writer/msl/generator_impl_loop_test.cc @@ -23,7 +23,7 @@ namespace { using MslGeneratorImplTest = TestHelper; TEST_F(MslGeneratorImplTest, Emit_Loop) { - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(); auto* l = Loop(body, continuing); @@ -36,7 +36,7 @@ TEST_F(MslGeneratorImplTest, Emit_Loop) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { - discard_fragment(); + break; } )"); } @@ -44,7 +44,7 @@ TEST_F(MslGeneratorImplTest, Emit_Loop) { TEST_F(MslGeneratorImplTest, Emit_LoopWithContinuing) { Func("a_statement", {}, ty.void_(), utils::Empty); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement"))); auto* l = Loop(body, continuing); @@ -57,7 +57,7 @@ TEST_F(MslGeneratorImplTest, Emit_LoopWithContinuing) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { - discard_fragment(); + break; { a_statement(); } @@ -68,7 +68,7 @@ TEST_F(MslGeneratorImplTest, Emit_LoopWithContinuing) { TEST_F(MslGeneratorImplTest, Emit_LoopWithContinuing_BreakIf) { Func("a_statement", {}, ty.void_(), {}); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement")), BreakIf(true)); auto* l = Loop(body, continuing); @@ -81,7 +81,7 @@ TEST_F(MslGeneratorImplTest, Emit_LoopWithContinuing_BreakIf) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { - discard_fragment(); + break; { a_statement(); if (true) { break; } @@ -96,13 +96,13 @@ TEST_F(MslGeneratorImplTest, Emit_LoopNestedWithContinuing) { GlobalVar("lhs", ty.f32(), ast::AddressSpace::kPrivate); GlobalVar("rhs", ty.f32(), ast::AddressSpace::kPrivate); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement"))); auto* inner = Loop(body, continuing); body = Block(inner); - continuing = Block(Assign("lhs", "rhs")); + continuing = Block(Assign("lhs", "rhs"), BreakIf(true)); auto* outer = Loop(body, continuing); @@ -116,13 +116,14 @@ TEST_F(MslGeneratorImplTest, Emit_LoopNestedWithContinuing) { ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error(); EXPECT_EQ(gen.result(), R"( while (true) { while (true) { - discard_fragment(); + break; { a_statement(); } } { lhs = rhs; + if (true) { break; } } } )"); diff --git a/src/tint/writer/spirv/generator_impl.cc b/src/tint/writer/spirv/generator_impl.cc index aa5d4493f8..30dd186001 100644 --- a/src/tint/writer/spirv/generator_impl.cc +++ b/src/tint/writer/spirv/generator_impl.cc @@ -21,6 +21,7 @@ #include "src/tint/transform/add_empty_entry_point.h" #include "src/tint/transform/builtin_polyfill.h" #include "src/tint/transform/canonicalize_entry_point_io.h" +#include "src/tint/transform/demote_to_helper.h" #include "src/tint/transform/disable_uniformity_analysis.h" #include "src/tint/transform/expand_compound_assignment.h" #include "src/tint/transform/for_loop_to_loop.h" @@ -32,7 +33,6 @@ #include "src/tint/transform/simplify_pointers.h" #include "src/tint/transform/std140.h" #include "src/tint/transform/unshadow.h" -#include "src/tint/transform/unwind_discard_functions.h" #include "src/tint/transform/var_for_dynamic_index.h" #include "src/tint/transform/vectorize_matrix_conversions.h" #include "src/tint/transform/vectorize_scalar_matrix_initializers.h" @@ -82,7 +82,6 @@ SanitizedResult Sanitize(const Program* in, const Options& options) { manager.Add(); manager.Add(); manager.Add(); - manager.Add(); manager.Add(); // Required for arrayLength() manager.Add(); manager.Add(); @@ -93,6 +92,11 @@ SanitizedResult Sanitize(const Program* in, const Options& options) { manager.Add(); manager.Add(); + // DemoteToHelper must come after CanonicalizeEntryPointIO, PromoteSideEffectsToDecl, and + // ExpandCompoundAssignment. + // TODO(crbug.com/tint/1752): Use SPV_EXT_demote_to_helper_invocation if available. + manager.Add(); + // Std140 must come after PromoteSideEffectsToDecl. // Std140 must come before VarForDynamicIndex and ForLoopToLoop. manager.Add(); diff --git a/src/tint/writer/wgsl/generator_impl_loop_test.cc b/src/tint/writer/wgsl/generator_impl_loop_test.cc index 48510bbd57..ac3f80849a 100644 --- a/src/tint/writer/wgsl/generator_impl_loop_test.cc +++ b/src/tint/writer/wgsl/generator_impl_loop_test.cc @@ -22,7 +22,7 @@ namespace { using WgslGeneratorImplTest = TestHelper; TEST_F(WgslGeneratorImplTest, Emit_Loop) { - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(); auto* l = Loop(body, continuing); @@ -35,7 +35,7 @@ TEST_F(WgslGeneratorImplTest, Emit_Loop) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( loop { - discard; + break; } )"); } @@ -43,7 +43,7 @@ TEST_F(WgslGeneratorImplTest, Emit_Loop) { TEST_F(WgslGeneratorImplTest, Emit_LoopWithContinuing) { Func("a_statement", {}, ty.void_(), {}); - auto* body = Block(create()); + auto* body = Block(Break()); auto* continuing = Block(CallStmt(Call("a_statement"))); auto* l = Loop(body, continuing); @@ -56,7 +56,7 @@ TEST_F(WgslGeneratorImplTest, Emit_LoopWithContinuing) { ASSERT_TRUE(gen.EmitStatement(l)) << gen.error(); EXPECT_EQ(gen.result(), R"( loop { - discard; + break; continuing { a_statement(); diff --git a/test/tint/bug/dawn/947.wgsl.expected.dxc.hlsl b/test/tint/bug/dawn/947.wgsl.expected.dxc.hlsl index 7557169e12..262a1ca347 100644 --- a/test/tint/bug/dawn/947.wgsl.expected.dxc.hlsl +++ b/test/tint/bug/dawn/947.wgsl.expected.dxc.hlsl @@ -1,3 +1,5 @@ +static bool tint_discarded = false; + cbuffer cbuffer_uniforms : register(b0, space0) { uint4 uniforms[1]; }; @@ -45,30 +47,21 @@ struct tint_symbol_5 { float4 value : SV_Target0; }; -static bool tint_discard = false; - float4 fs_main_inner(float2 texcoord) { float2 clampedTexcoord = clamp(texcoord, (0.0f).xx, (1.0f).xx); if (!(all((clampedTexcoord == texcoord)))) { - tint_discard = true; - return (0.0f).xxxx; + tint_discarded = true; } float4 srcColor = (0.0f).xxxx; return srcColor; } -void tint_discard_func() { - discard; -} - tint_symbol_5 fs_main(tint_symbol_4 tint_symbol_3) { const float4 inner_result_1 = fs_main_inner(tint_symbol_3.texcoord); - if (tint_discard) { - tint_discard_func(); - const tint_symbol_5 tint_symbol_8 = (tint_symbol_5)0; - return tint_symbol_8; - } tint_symbol_5 wrapper_result_1 = (tint_symbol_5)0; wrapper_result_1.value = inner_result_1; + if (tint_discarded) { + discard; + } return wrapper_result_1; } diff --git a/test/tint/bug/dawn/947.wgsl.expected.fxc.hlsl b/test/tint/bug/dawn/947.wgsl.expected.fxc.hlsl index 7557169e12..262a1ca347 100644 --- a/test/tint/bug/dawn/947.wgsl.expected.fxc.hlsl +++ b/test/tint/bug/dawn/947.wgsl.expected.fxc.hlsl @@ -1,3 +1,5 @@ +static bool tint_discarded = false; + cbuffer cbuffer_uniforms : register(b0, space0) { uint4 uniforms[1]; }; @@ -45,30 +47,21 @@ struct tint_symbol_5 { float4 value : SV_Target0; }; -static bool tint_discard = false; - float4 fs_main_inner(float2 texcoord) { float2 clampedTexcoord = clamp(texcoord, (0.0f).xx, (1.0f).xx); if (!(all((clampedTexcoord == texcoord)))) { - tint_discard = true; - return (0.0f).xxxx; + tint_discarded = true; } float4 srcColor = (0.0f).xxxx; return srcColor; } -void tint_discard_func() { - discard; -} - tint_symbol_5 fs_main(tint_symbol_4 tint_symbol_3) { const float4 inner_result_1 = fs_main_inner(tint_symbol_3.texcoord); - if (tint_discard) { - tint_discard_func(); - const tint_symbol_5 tint_symbol_8 = (tint_symbol_5)0; - return tint_symbol_8; - } tint_symbol_5 wrapper_result_1 = (tint_symbol_5)0; wrapper_result_1.value = inner_result_1; + if (tint_discarded) { + discard; + } return wrapper_result_1; } diff --git a/test/tint/bug/dawn/947.wgsl.expected.glsl b/test/tint/bug/dawn/947.wgsl.expected.glsl index 307e7c3cb9..ead3e6bd60 100644 --- a/test/tint/bug/dawn/947.wgsl.expected.glsl +++ b/test/tint/bug/dawn/947.wgsl.expected.glsl @@ -40,6 +40,7 @@ void main() { #version 310 es precision mediump float; +bool tint_discarded = false; layout(location = 0) in vec2 texcoord_1; layout(location = 0) out vec4 value; struct Uniforms { @@ -52,27 +53,20 @@ struct VertexOutputs { vec4 position; }; -bool tint_discard = false; vec4 fs_main(vec2 texcoord) { vec2 clampedTexcoord = clamp(texcoord, vec2(0.0f), vec2(1.0f)); if (!(all(equal(clampedTexcoord, texcoord)))) { - tint_discard = true; - return vec4(0.0f); + tint_discarded = true; } vec4 srcColor = vec4(0.0f); return srcColor; } -void tint_discard_func() { - discard; -} - void main() { vec4 inner_result = fs_main(texcoord_1); - if (tint_discard) { - tint_discard_func(); - return; - } value = inner_result; + if (tint_discarded) { + discard; + } return; } diff --git a/test/tint/bug/dawn/947.wgsl.expected.msl b/test/tint/bug/dawn/947.wgsl.expected.msl index df5dab0a46..02084ce57e 100644 --- a/test/tint/bug/dawn/947.wgsl.expected.msl +++ b/test/tint/bug/dawn/947.wgsl.expected.msl @@ -29,21 +29,21 @@ struct tint_symbol { float4 position [[position]]; }; -VertexOutputs vs_main_inner(uint VertexIndex, const constant Uniforms* const tint_symbol_5) { +VertexOutputs vs_main_inner(uint VertexIndex, const constant Uniforms* const tint_symbol_4) { tint_array texcoord = tint_array{float2(-0.5f, 0.0f), float2(1.5f, 0.0f), float2(0.5f, 2.0f)}; VertexOutputs output = {}; output.position = float4(((texcoord[VertexIndex] * 2.0f) - float2(1.0f)), 0.0f, 1.0f); - bool flipY = ((*(tint_symbol_5)).u_scale[1] < 0.0f); + bool flipY = ((*(tint_symbol_4)).u_scale[1] < 0.0f); if (flipY) { - output.texcoords = ((((texcoord[VertexIndex] * (*(tint_symbol_5)).u_scale) + (*(tint_symbol_5)).u_offset) * float2(1.0f, -1.0f)) + float2(0.0f, 1.0f)); + output.texcoords = ((((texcoord[VertexIndex] * (*(tint_symbol_4)).u_scale) + (*(tint_symbol_4)).u_offset) * float2(1.0f, -1.0f)) + float2(0.0f, 1.0f)); } else { - output.texcoords = ((((texcoord[VertexIndex] * float2(1.0f, -1.0f)) + float2(0.0f, 1.0f)) * (*(tint_symbol_5)).u_scale) + (*(tint_symbol_5)).u_offset); + output.texcoords = ((((texcoord[VertexIndex] * float2(1.0f, -1.0f)) + float2(0.0f, 1.0f)) * (*(tint_symbol_4)).u_scale) + (*(tint_symbol_4)).u_offset); } return output; } -vertex tint_symbol vs_main(const constant Uniforms* tint_symbol_6 [[buffer(0)]], uint VertexIndex [[vertex_id]]) { - VertexOutputs const inner_result = vs_main_inner(VertexIndex, tint_symbol_6); +vertex tint_symbol vs_main(const constant Uniforms* tint_symbol_5 [[buffer(0)]], uint VertexIndex [[vertex_id]]) { + VertexOutputs const inner_result = vs_main_inner(VertexIndex, tint_symbol_5); tint_symbol wrapper_result = {}; wrapper_result.texcoords = inner_result.texcoords; wrapper_result.position = inner_result.position; @@ -58,30 +58,23 @@ struct tint_symbol_3 { float4 value [[color(0)]]; }; -float4 fs_main_inner(float2 texcoord, thread bool* const tint_symbol_7) { +float4 fs_main_inner(float2 texcoord, thread bool* const tint_symbol_6) { float2 clampedTexcoord = clamp(texcoord, float2(0.0f), float2(1.0f)); if (!(all((clampedTexcoord == texcoord)))) { - *(tint_symbol_7) = true; - return float4(0.0f); + *(tint_symbol_6) = true; } float4 srcColor = float4(0.0f); return srcColor; } -void tint_discard_func() { - discard_fragment(); -} - fragment tint_symbol_3 fs_main(tint_symbol_2 tint_symbol_1 [[stage_in]]) { - thread bool tint_symbol_8 = false; - float4 const inner_result_1 = fs_main_inner(tint_symbol_1.texcoord, &(tint_symbol_8)); - if (tint_symbol_8) { - tint_discard_func(); - tint_symbol_3 const tint_symbol_4 = tint_symbol_3{}; - return tint_symbol_4; - } + thread bool tint_symbol_7 = false; + float4 const inner_result_1 = fs_main_inner(tint_symbol_1.texcoord, &(tint_symbol_7)); tint_symbol_3 wrapper_result_1 = {}; wrapper_result_1.value = inner_result_1; + if (tint_symbol_7) { + discard_fragment(); + } return wrapper_result_1; } diff --git a/test/tint/bug/dawn/947.wgsl.expected.spvasm b/test/tint/bug/dawn/947.wgsl.expected.spvasm index 10da7fedc1..c60d142912 100644 --- a/test/tint/bug/dawn/947.wgsl.expected.spvasm +++ b/test/tint/bug/dawn/947.wgsl.expected.spvasm @@ -1,7 +1,7 @@ ; SPIR-V ; Version: 1.3 ; Generator: Google Tint Compiler; 0 -; Bound: 134 +; Bound: 137 ; Schema: 0 OpCapability Shader %118 = OpExtInstImport "GLSL.std.450" @@ -9,6 +9,7 @@ OpEntryPoint Vertex %vs_main "vs_main" %VertexIndex_1 %texcoords_1 %position_1 %vertex_point_size OpEntryPoint Fragment %fs_main "fs_main" %texcoord_1 %value OpExecutionMode %fs_main OriginUpperLeft + OpName %tint_discarded "tint_discarded" OpName %VertexIndex_1 "VertexIndex_1" OpName %texcoords_1 "texcoords_1" OpName %position_1 "position_1" @@ -32,7 +33,6 @@ OpName %output "output" OpName %flipY "flipY" OpName %vs_main "vs_main" - OpName %tint_discard_func "tint_discard_func" OpName %fs_main_inner "fs_main_inner" OpName %texcoord_0 "texcoord" OpName %clampedTexcoord "clampedTexcoord" @@ -58,144 +58,143 @@ OpMemberDecorate %VertexOutputs 0 Offset 0 OpMemberDecorate %VertexOutputs 1 Offset 16 OpDecorate %_arr_v2float_uint_3 ArrayStride 8 + %bool = OpTypeBool + %2 = OpConstantNull %bool +%_ptr_Private_bool = OpTypePointer Private %bool +%tint_discarded = OpVariable %_ptr_Private_bool Private %2 %uint = OpTypeInt 32 0 %_ptr_Input_uint = OpTypePointer Input %uint %VertexIndex_1 = OpVariable %_ptr_Input_uint Input %float = OpTypeFloat 32 %v2float = OpTypeVector %float 2 %_ptr_Output_v2float = OpTypePointer Output %v2float - %8 = OpConstantNull %v2float -%texcoords_1 = OpVariable %_ptr_Output_v2float Output %8 + %12 = OpConstantNull %v2float +%texcoords_1 = OpVariable %_ptr_Output_v2float Output %12 %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float - %12 = OpConstantNull %v4float - %position_1 = OpVariable %_ptr_Output_v4float Output %12 + %16 = OpConstantNull %v4float + %position_1 = OpVariable %_ptr_Output_v4float Output %16 %_ptr_Output_float = OpTypePointer Output %float - %15 = OpConstantNull %float -%vertex_point_size = OpVariable %_ptr_Output_float Output %15 + %19 = OpConstantNull %float +%vertex_point_size = OpVariable %_ptr_Output_float Output %19 %_ptr_Input_v2float = OpTypePointer Input %v2float %texcoord_1 = OpVariable %_ptr_Input_v2float Input - %value = OpVariable %_ptr_Output_v4float Output %12 + %value = OpVariable %_ptr_Output_v4float Output %16 %Uniforms = OpTypeStruct %v2float %v2float %uniforms_block = OpTypeStruct %Uniforms %_ptr_Uniform_uniforms_block = OpTypePointer Uniform %uniforms_block %uniforms = OpVariable %_ptr_Uniform_uniforms_block Uniform - %25 = OpTypeSampler -%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %25 - %mySampler = OpVariable %_ptr_UniformConstant_25 UniformConstant - %28 = OpTypeImage %float 2D 0 0 0 1 Unknown -%_ptr_UniformConstant_28 = OpTypePointer UniformConstant %28 - %myTexture = OpVariable %_ptr_UniformConstant_28 UniformConstant + %29 = OpTypeSampler +%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29 + %mySampler = OpVariable %_ptr_UniformConstant_29 UniformConstant + %32 = OpTypeImage %float 2D 0 0 0 1 Unknown +%_ptr_UniformConstant_32 = OpTypePointer UniformConstant %32 + %myTexture = OpVariable %_ptr_UniformConstant_32 UniformConstant %VertexOutputs = OpTypeStruct %v2float %v4float - %29 = OpTypeFunction %VertexOutputs %uint + %33 = OpTypeFunction %VertexOutputs %uint %uint_3 = OpConstant %uint 3 %_arr_v2float_uint_3 = OpTypeArray %v2float %uint_3 %float_n0_5 = OpConstant %float -0.5 - %37 = OpConstantComposite %v2float %float_n0_5 %15 + %41 = OpConstantComposite %v2float %float_n0_5 %19 %float_1_5 = OpConstant %float 1.5 - %39 = OpConstantComposite %v2float %float_1_5 %15 + %43 = OpConstantComposite %v2float %float_1_5 %19 %float_0_5 = OpConstant %float 0.5 %float_2 = OpConstant %float 2 - %42 = OpConstantComposite %v2float %float_0_5 %float_2 - %43 = OpConstantComposite %_arr_v2float_uint_3 %37 %39 %42 + %46 = OpConstantComposite %v2float %float_0_5 %float_2 + %47 = OpConstantComposite %_arr_v2float_uint_3 %41 %43 %46 %_ptr_Function__arr_v2float_uint_3 = OpTypePointer Function %_arr_v2float_uint_3 - %46 = OpConstantNull %_arr_v2float_uint_3 + %50 = OpConstantNull %_arr_v2float_uint_3 %_ptr_Function_VertexOutputs = OpTypePointer Function %VertexOutputs - %49 = OpConstantNull %VertexOutputs + %53 = OpConstantNull %VertexOutputs %uint_1 = OpConstant %uint 1 %_ptr_Function_v4float = OpTypePointer Function %v4float %_ptr_Function_v2float = OpTypePointer Function %v2float %float_1 = OpConstant %float 1 - %58 = OpConstantComposite %v2float %float_1 %float_1 + %62 = OpConstantComposite %v2float %float_1 %float_1 %uint_0 = OpConstant %uint 0 %_ptr_Uniform_float = OpTypePointer Uniform %float - %bool = OpTypeBool %_ptr_Function_bool = OpTypePointer Function %bool - %71 = OpConstantNull %bool %_ptr_Uniform_v2float = OpTypePointer Uniform %v2float %float_n1 = OpConstant %float -1 - %87 = OpConstantComposite %v2float %float_1 %float_n1 - %89 = OpConstantComposite %v2float %15 %float_1 + %89 = OpConstantComposite %v2float %float_1 %float_n1 + %91 = OpConstantComposite %v2float %19 %float_1 %void = OpTypeVoid - %103 = OpTypeFunction %void + %105 = OpTypeFunction %void %113 = OpTypeFunction %v4float %v2float %v2bool = OpTypeVector %bool 2 -%vs_main_inner = OpFunction %VertexOutputs None %29 + %true = OpConstantTrue %bool +%vs_main_inner = OpFunction %VertexOutputs None %33 %VertexIndex = OpFunctionParameter %uint - %33 = OpLabel - %texcoord = OpVariable %_ptr_Function__arr_v2float_uint_3 Function %46 - %output = OpVariable %_ptr_Function_VertexOutputs Function %49 - %flipY = OpVariable %_ptr_Function_bool Function %71 - OpStore %texcoord %43 - %52 = OpAccessChain %_ptr_Function_v4float %output %uint_1 - %54 = OpAccessChain %_ptr_Function_v2float %texcoord %VertexIndex - %55 = OpLoad %v2float %54 - %56 = OpVectorTimesScalar %v2float %55 %float_2 - %59 = OpFSub %v2float %56 %58 - %60 = OpCompositeExtract %float %59 0 - %61 = OpCompositeExtract %float %59 1 - %62 = OpCompositeConstruct %v4float %60 %61 %15 %float_1 - OpStore %52 %62 - %65 = OpAccessChain %_ptr_Uniform_float %uniforms %uint_0 %uint_0 %uint_1 - %66 = OpLoad %float %65 - %67 = OpFOrdLessThan %bool %66 %15 - OpStore %flipY %67 - %72 = OpLoad %bool %flipY - OpSelectionMerge %73 None - OpBranchConditional %72 %74 %75 - %74 = OpLabel - %76 = OpAccessChain %_ptr_Function_v2float %output %uint_0 - %77 = OpAccessChain %_ptr_Function_v2float %texcoord %VertexIndex - %78 = OpLoad %v2float %77 - %80 = OpAccessChain %_ptr_Uniform_v2float %uniforms %uint_0 %uint_0 - %81 = OpLoad %v2float %80 - %82 = OpFMul %v2float %78 %81 - %83 = OpAccessChain %_ptr_Uniform_v2float %uniforms %uint_0 %uint_1 - %84 = OpLoad %v2float %83 - %85 = OpFAdd %v2float %82 %84 - %88 = OpFMul %v2float %85 %87 - %90 = OpFAdd %v2float %88 %89 - OpStore %76 %90 - OpBranch %73 + %37 = OpLabel + %texcoord = OpVariable %_ptr_Function__arr_v2float_uint_3 Function %50 + %output = OpVariable %_ptr_Function_VertexOutputs Function %53 + %flipY = OpVariable %_ptr_Function_bool Function %2 + OpStore %texcoord %47 + %56 = OpAccessChain %_ptr_Function_v4float %output %uint_1 + %58 = OpAccessChain %_ptr_Function_v2float %texcoord %VertexIndex + %59 = OpLoad %v2float %58 + %60 = OpVectorTimesScalar %v2float %59 %float_2 + %63 = OpFSub %v2float %60 %62 + %64 = OpCompositeExtract %float %63 0 + %65 = OpCompositeExtract %float %63 1 + %66 = OpCompositeConstruct %v4float %64 %65 %19 %float_1 + OpStore %56 %66 + %69 = OpAccessChain %_ptr_Uniform_float %uniforms %uint_0 %uint_0 %uint_1 + %70 = OpLoad %float %69 + %71 = OpFOrdLessThan %bool %70 %19 + OpStore %flipY %71 + %74 = OpLoad %bool %flipY + OpSelectionMerge %75 None + OpBranchConditional %74 %76 %77 + %76 = OpLabel + %78 = OpAccessChain %_ptr_Function_v2float %output %uint_0 + %79 = OpAccessChain %_ptr_Function_v2float %texcoord %VertexIndex + %80 = OpLoad %v2float %79 + %82 = OpAccessChain %_ptr_Uniform_v2float %uniforms %uint_0 %uint_0 + %83 = OpLoad %v2float %82 + %84 = OpFMul %v2float %80 %83 + %85 = OpAccessChain %_ptr_Uniform_v2float %uniforms %uint_0 %uint_1 + %86 = OpLoad %v2float %85 + %87 = OpFAdd %v2float %84 %86 + %90 = OpFMul %v2float %87 %89 + %92 = OpFAdd %v2float %90 %91 + OpStore %78 %92 + OpBranch %75 + %77 = OpLabel + %93 = OpAccessChain %_ptr_Function_v2float %output %uint_0 + %94 = OpAccessChain %_ptr_Function_v2float %texcoord %VertexIndex + %95 = OpLoad %v2float %94 + %96 = OpFMul %v2float %95 %89 + %97 = OpFAdd %v2float %96 %91 + %98 = OpAccessChain %_ptr_Uniform_v2float %uniforms %uint_0 %uint_0 + %99 = OpLoad %v2float %98 + %100 = OpFMul %v2float %97 %99 + %101 = OpAccessChain %_ptr_Uniform_v2float %uniforms %uint_0 %uint_1 + %102 = OpLoad %v2float %101 + %103 = OpFAdd %v2float %100 %102 + OpStore %93 %103 + OpBranch %75 %75 = OpLabel - %91 = OpAccessChain %_ptr_Function_v2float %output %uint_0 - %92 = OpAccessChain %_ptr_Function_v2float %texcoord %VertexIndex - %93 = OpLoad %v2float %92 - %94 = OpFMul %v2float %93 %87 - %95 = OpFAdd %v2float %94 %89 - %96 = OpAccessChain %_ptr_Uniform_v2float %uniforms %uint_0 %uint_0 - %97 = OpLoad %v2float %96 - %98 = OpFMul %v2float %95 %97 - %99 = OpAccessChain %_ptr_Uniform_v2float %uniforms %uint_0 %uint_1 - %100 = OpLoad %v2float %99 - %101 = OpFAdd %v2float %98 %100 - OpStore %91 %101 - OpBranch %73 - %73 = OpLabel - %102 = OpLoad %VertexOutputs %output - OpReturnValue %102 + %104 = OpLoad %VertexOutputs %output + OpReturnValue %104 OpFunctionEnd - %vs_main = OpFunction %void None %103 - %106 = OpLabel - %108 = OpLoad %uint %VertexIndex_1 - %107 = OpFunctionCall %VertexOutputs %vs_main_inner %108 - %109 = OpCompositeExtract %v2float %107 0 - OpStore %texcoords_1 %109 - %110 = OpCompositeExtract %v4float %107 1 - OpStore %position_1 %110 + %vs_main = OpFunction %void None %105 + %108 = OpLabel + %110 = OpLoad %uint %VertexIndex_1 + %109 = OpFunctionCall %VertexOutputs %vs_main_inner %110 + %111 = OpCompositeExtract %v2float %109 0 + OpStore %texcoords_1 %111 + %112 = OpCompositeExtract %v4float %109 1 + OpStore %position_1 %112 OpStore %vertex_point_size %float_1 OpReturn OpFunctionEnd -%tint_discard_func = OpFunction %void None %103 - %112 = OpLabel - OpKill - OpFunctionEnd %fs_main_inner = OpFunction %v4float None %113 %texcoord_0 = OpFunctionParameter %v2float %116 = OpLabel -%clampedTexcoord = OpVariable %_ptr_Function_v2float Function %8 - %srcColor = OpVariable %_ptr_Function_v4float Function %12 - %117 = OpExtInst %v2float %118 NClamp %texcoord_0 %8 %58 +%clampedTexcoord = OpVariable %_ptr_Function_v2float Function %12 + %srcColor = OpVariable %_ptr_Function_v4float Function %16 + %117 = OpExtInst %v2float %118 NClamp %texcoord_0 %12 %62 OpStore %clampedTexcoord %117 %122 = OpLoad %v2float %clampedTexcoord %123 = OpFOrdEqual %v2bool %122 %texcoord_0 @@ -204,17 +203,23 @@ OpSelectionMerge %125 None OpBranchConditional %120 %126 %125 %126 = OpLabel - %127 = OpFunctionCall %void %tint_discard_func - OpReturnValue %12 + OpStore %tint_discarded %true + OpBranch %125 %125 = OpLabel - OpStore %srcColor %12 + OpStore %srcColor %16 %129 = OpLoad %v4float %srcColor OpReturnValue %129 OpFunctionEnd - %fs_main = OpFunction %void None %103 + %fs_main = OpFunction %void None %105 %131 = OpLabel %133 = OpLoad %v2float %texcoord_1 %132 = OpFunctionCall %v4float %fs_main_inner %133 OpStore %value %132 + %134 = OpLoad %bool %tint_discarded + OpSelectionMerge %135 None + OpBranchConditional %134 %136 %135 + %136 = OpLabel + OpKill + %135 = OpLabel OpReturn OpFunctionEnd diff --git a/test/tint/bug/tint/1081.wgsl.expected.dxc.hlsl b/test/tint/bug/tint/1081.wgsl.expected.dxc.hlsl index 55f7d157cf..0f7e2c2b41 100644 --- a/test/tint/bug/tint/1081.wgsl.expected.dxc.hlsl +++ b/test/tint/bug/tint/1081.wgsl.expected.dxc.hlsl @@ -1,9 +1,8 @@ -static bool tint_discard = false; +static bool tint_discarded = false; int f(int x) { if ((x == 10)) { - tint_discard = true; - return 0; + tint_discarded = true; } return x; } @@ -19,9 +18,6 @@ int main_inner(int3 x) { int y = x.x; while (true) { const int r = f(y); - if (tint_discard) { - return 0; - } if ((r == 0)) { break; } @@ -29,18 +25,12 @@ int main_inner(int3 x) { return y; } -void tint_discard_func() { - discard; -} - tint_symbol_2 main(tint_symbol_1 tint_symbol) { const int inner_result = main_inner(tint_symbol.x); - if (tint_discard) { - tint_discard_func(); - const tint_symbol_2 tint_symbol_3 = (tint_symbol_2)0; - return tint_symbol_3; - } tint_symbol_2 wrapper_result = (tint_symbol_2)0; wrapper_result.value = inner_result; + if (tint_discarded) { + discard; + } return wrapper_result; } diff --git a/test/tint/bug/tint/1081.wgsl.expected.fxc.hlsl b/test/tint/bug/tint/1081.wgsl.expected.fxc.hlsl index 55f7d157cf..0f7e2c2b41 100644 --- a/test/tint/bug/tint/1081.wgsl.expected.fxc.hlsl +++ b/test/tint/bug/tint/1081.wgsl.expected.fxc.hlsl @@ -1,9 +1,8 @@ -static bool tint_discard = false; +static bool tint_discarded = false; int f(int x) { if ((x == 10)) { - tint_discard = true; - return 0; + tint_discarded = true; } return x; } @@ -19,9 +18,6 @@ int main_inner(int3 x) { int y = x.x; while (true) { const int r = f(y); - if (tint_discard) { - return 0; - } if ((r == 0)) { break; } @@ -29,18 +25,12 @@ int main_inner(int3 x) { return y; } -void tint_discard_func() { - discard; -} - tint_symbol_2 main(tint_symbol_1 tint_symbol) { const int inner_result = main_inner(tint_symbol.x); - if (tint_discard) { - tint_discard_func(); - const tint_symbol_2 tint_symbol_3 = (tint_symbol_2)0; - return tint_symbol_3; - } tint_symbol_2 wrapper_result = (tint_symbol_2)0; wrapper_result.value = inner_result; + if (tint_discarded) { + discard; + } return wrapper_result; } diff --git a/test/tint/bug/tint/1081.wgsl.expected.glsl b/test/tint/bug/tint/1081.wgsl.expected.glsl index 5bef66033b..cd44545a15 100644 --- a/test/tint/bug/tint/1081.wgsl.expected.glsl +++ b/test/tint/bug/tint/1081.wgsl.expected.glsl @@ -1,13 +1,12 @@ #version 310 es precision mediump float; +bool tint_discarded = false; layout(location = 1) flat in ivec3 x_1; layout(location = 2) out int value; -bool tint_discard = false; int f(int x) { if ((x == 10)) { - tint_discard = true; - return 0; + tint_discarded = true; } return x; } @@ -16,9 +15,6 @@ int tint_symbol(ivec3 x) { int y = x.x; while (true) { int r = f(y); - if (tint_discard) { - return 0; - } if ((r == 0)) { break; } @@ -26,16 +22,11 @@ int tint_symbol(ivec3 x) { return y; } -void tint_discard_func() { - discard; -} - void main() { int inner_result = tint_symbol(x_1); - if (tint_discard) { - tint_discard_func(); - return; - } value = inner_result; + if (tint_discarded) { + discard; + } return; } diff --git a/test/tint/bug/tint/1081.wgsl.expected.msl b/test/tint/bug/tint/1081.wgsl.expected.msl index d60e03286f..1194ebf5ca 100644 --- a/test/tint/bug/tint/1081.wgsl.expected.msl +++ b/test/tint/bug/tint/1081.wgsl.expected.msl @@ -1,10 +1,9 @@ #include using namespace metal; -int f(int x, thread bool* const tint_symbol_5) { +int f(int x, thread bool* const tint_symbol_4) { if ((x == 10)) { - *(tint_symbol_5) = true; - return 0; + *(tint_symbol_4) = true; } return x; } @@ -17,13 +16,10 @@ struct tint_symbol_3 { int value [[color(2)]]; }; -int tint_symbol_inner(int3 x, thread bool* const tint_symbol_6) { +int tint_symbol_inner(int3 x, thread bool* const tint_symbol_5) { int y = x[0]; while (true) { - int const r = f(y, tint_symbol_6); - if (*(tint_symbol_6)) { - return 0; - } + int const r = f(y, tint_symbol_5); if ((r == 0)) { break; } @@ -31,20 +27,14 @@ int tint_symbol_inner(int3 x, thread bool* const tint_symbol_6) { return y; } -void tint_discard_func() { - discard_fragment(); -} - fragment tint_symbol_3 tint_symbol(tint_symbol_2 tint_symbol_1 [[stage_in]]) { - thread bool tint_symbol_7 = false; - int const inner_result = tint_symbol_inner(tint_symbol_1.x, &(tint_symbol_7)); - if (tint_symbol_7) { - tint_discard_func(); - tint_symbol_3 const tint_symbol_4 = tint_symbol_3{}; - return tint_symbol_4; - } + thread bool tint_symbol_6 = false; + int const inner_result = tint_symbol_inner(tint_symbol_1.x, &(tint_symbol_6)); tint_symbol_3 wrapper_result = {}; wrapper_result.value = inner_result; + if (tint_symbol_6) { + discard_fragment(); + } return wrapper_result; } diff --git a/test/tint/bug/tint/1081.wgsl.expected.spvasm b/test/tint/bug/tint/1081.wgsl.expected.spvasm index 16ea294d3f..62aac7b962 100644 --- a/test/tint/bug/tint/1081.wgsl.expected.spvasm +++ b/test/tint/bug/tint/1081.wgsl.expected.spvasm @@ -1,20 +1,17 @@ ; SPIR-V ; Version: 1.3 ; Generator: Google Tint Compiler; 0 -; Bound: 58 +; Bound: 47 ; Schema: 0 OpCapability Shader OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %main "main" %x_1 %value OpExecutionMode %main OriginUpperLeft + OpName %tint_discarded "tint_discarded" OpName %x_1 "x_1" OpName %value "value" - OpName %tint_discard "tint_discard" OpName %f "f" OpName %x "x" - OpName %tint_return_flag "tint_return_flag" - OpName %tint_return_value "tint_return_value" - OpName %tint_discard_func "tint_discard_func" OpName %main_inner "main_inner" OpName %x_0 "x" OpName %y "y" @@ -22,92 +19,72 @@ OpDecorate %x_1 Location 1 OpDecorate %x_1 Flat OpDecorate %value Location 2 + %bool = OpTypeBool + %2 = OpConstantNull %bool +%_ptr_Private_bool = OpTypePointer Private %bool +%tint_discarded = OpVariable %_ptr_Private_bool Private %2 %int = OpTypeInt 32 1 %v3int = OpTypeVector %int 3 %_ptr_Input_v3int = OpTypePointer Input %v3int %x_1 = OpVariable %_ptr_Input_v3int Input %_ptr_Output_int = OpTypePointer Output %int - %7 = OpConstantNull %int - %value = OpVariable %_ptr_Output_int Output %7 - %bool = OpTypeBool - %9 = OpConstantNull %bool -%_ptr_Private_bool = OpTypePointer Private %bool -%tint_discard = OpVariable %_ptr_Private_bool Private %9 + %11 = OpConstantNull %int + %value = OpVariable %_ptr_Output_int Output %11 %12 = OpTypeFunction %int %int -%_ptr_Function_bool = OpTypePointer Function %bool -%_ptr_Function_int = OpTypePointer Function %int %int_10 = OpConstant %int 10 %true = OpConstantTrue %bool + %21 = OpTypeFunction %int %v3int +%_ptr_Function_int = OpTypePointer Function %int %void = OpTypeVoid - %30 = OpTypeFunction %void - %34 = OpTypeFunction %int %v3int + %38 = OpTypeFunction %void %f = OpFunction %int None %12 %x = OpFunctionParameter %int %15 = OpLabel -%tint_return_flag = OpVariable %_ptr_Function_bool Function %9 -%tint_return_value = OpVariable %_ptr_Function_int Function %7 - %21 = OpIEqual %bool %x %int_10 - OpSelectionMerge %22 None - OpBranchConditional %21 %23 %22 - %23 = OpLabel - OpStore %tint_discard %true - OpStore %tint_return_flag %true - OpStore %tint_return_value %7 - OpBranch %22 - %22 = OpLabel - %26 = OpLoad %bool %tint_return_flag - %25 = OpLogicalNot %bool %26 - OpSelectionMerge %27 None - OpBranchConditional %25 %28 %27 - %28 = OpLabel - OpStore %tint_return_flag %true - OpStore %tint_return_value %x - OpBranch %27 - %27 = OpLabel - %29 = OpLoad %int %tint_return_value - OpReturnValue %29 + %17 = OpIEqual %bool %x %int_10 + OpSelectionMerge %18 None + OpBranchConditional %17 %19 %18 + %19 = OpLabel + OpStore %tint_discarded %true + OpBranch %18 + %18 = OpLabel + OpReturnValue %x OpFunctionEnd -%tint_discard_func = OpFunction %void None %30 - %33 = OpLabel - OpKill - OpFunctionEnd - %main_inner = OpFunction %int None %34 + %main_inner = OpFunction %int None %21 %x_0 = OpFunctionParameter %v3int - %37 = OpLabel - %y = OpVariable %_ptr_Function_int Function %7 - %38 = OpCompositeExtract %int %x_0 0 - OpStore %y %38 - OpBranch %40 - %40 = OpLabel - OpLoopMerge %41 %42 None - OpBranch %43 - %43 = OpLabel - %45 = OpLoad %int %y - %44 = OpFunctionCall %int %f %45 - %46 = OpLoad %bool %tint_discard - OpSelectionMerge %47 None - OpBranchConditional %46 %48 %47 - %48 = OpLabel - %49 = OpFunctionCall %void %tint_discard_func - OpReturnValue %7 - %47 = OpLabel - %50 = OpIEqual %bool %44 %7 - OpSelectionMerge %51 None - OpBranchConditional %50 %52 %51 - %52 = OpLabel - OpBranch %41 - %51 = OpLabel - OpBranch %42 - %42 = OpLabel - OpBranch %40 - %41 = OpLabel - %53 = OpLoad %int %y - OpReturnValue %53 + %24 = OpLabel + %y = OpVariable %_ptr_Function_int Function %11 + %25 = OpCompositeExtract %int %x_0 0 + OpStore %y %25 + OpBranch %28 + %28 = OpLabel + OpLoopMerge %29 %30 None + OpBranch %31 + %31 = OpLabel + %33 = OpLoad %int %y + %32 = OpFunctionCall %int %f %33 + %34 = OpIEqual %bool %32 %11 + OpSelectionMerge %35 None + OpBranchConditional %34 %36 %35 + %36 = OpLabel + OpBranch %29 + %35 = OpLabel + OpBranch %30 + %30 = OpLabel + OpBranch %28 + %29 = OpLabel + %37 = OpLoad %int %y + OpReturnValue %37 OpFunctionEnd - %main = OpFunction %void None %30 - %55 = OpLabel - %57 = OpLoad %v3int %x_1 - %56 = OpFunctionCall %int %main_inner %57 - OpStore %value %56 + %main = OpFunction %void None %38 + %41 = OpLabel + %43 = OpLoad %v3int %x_1 + %42 = OpFunctionCall %int %main_inner %43 + OpStore %value %42 + %44 = OpLoad %bool %tint_discarded + OpSelectionMerge %45 None + OpBranchConditional %44 %46 %45 + %46 = OpLabel + OpKill + %45 = OpLabel OpReturn OpFunctionEnd diff --git a/test/tint/bug/tint/1118.wgsl.expected.dxc.hlsl b/test/tint/bug/tint/1118.wgsl.expected.dxc.hlsl index e348eb1d34..9b18484b7c 100644 --- a/test/tint/bug/tint/1118.wgsl.expected.dxc.hlsl +++ b/test/tint/bug/tint/1118.wgsl.expected.dxc.hlsl @@ -1,3 +1,5 @@ +static bool tint_discarded = false; + static float fClipDistance3 = 0.0f; static float fClipDistance4 = 0.0f; cbuffer cbuffer_x_29 : register(b0, space0) { @@ -10,7 +12,6 @@ cbuffer cbuffer_x_137 : register(b2, space0) { uint4 x_137[1]; }; static float4 glFragColor = float4(0.0f, 0.0f, 0.0f, 0.0f); -static bool tint_discard = false; void main_1() { float3 viewDirectionW = float3(0.0f, 0.0f, 0.0f); @@ -31,13 +32,11 @@ void main_1() { float4 color = float4(0.0f, 0.0f, 0.0f, 0.0f); const float x_9 = fClipDistance3; if ((x_9 > 0.0f)) { - tint_discard = true; - return; + tint_discarded = true; } const float x_17 = fClipDistance4; if ((x_17 > 0.0f)) { - tint_discard = true; - return; + tint_discarded = true; } const float4 x_34 = asfloat(x_29[0]); const float3 x_38 = (0.0f).xxx; @@ -105,26 +104,16 @@ main_out main_inner(float fClipDistance3_param, float fClipDistance4_param) { fClipDistance3 = fClipDistance3_param; fClipDistance4 = fClipDistance4_param; main_1(); - if (tint_discard) { - const main_out tint_symbol_8 = (main_out)0; - return tint_symbol_8; - } - const main_out tint_symbol_9 = {glFragColor}; - return tint_symbol_9; -} - -void tint_discard_func() { - discard; + const main_out tint_symbol_8 = {glFragColor}; + return tint_symbol_8; } tint_symbol_2 main(tint_symbol_1 tint_symbol) { const main_out inner_result = main_inner(tint_symbol.fClipDistance3_param, tint_symbol.fClipDistance4_param); - if (tint_discard) { - tint_discard_func(); - const tint_symbol_2 tint_symbol_10 = (tint_symbol_2)0; - return tint_symbol_10; - } tint_symbol_2 wrapper_result = (tint_symbol_2)0; wrapper_result.glFragColor_1 = inner_result.glFragColor_1; + if (tint_discarded) { + discard; + } return wrapper_result; } diff --git a/test/tint/bug/tint/1118.wgsl.expected.fxc.hlsl b/test/tint/bug/tint/1118.wgsl.expected.fxc.hlsl index e348eb1d34..9b18484b7c 100644 --- a/test/tint/bug/tint/1118.wgsl.expected.fxc.hlsl +++ b/test/tint/bug/tint/1118.wgsl.expected.fxc.hlsl @@ -1,3 +1,5 @@ +static bool tint_discarded = false; + static float fClipDistance3 = 0.0f; static float fClipDistance4 = 0.0f; cbuffer cbuffer_x_29 : register(b0, space0) { @@ -10,7 +12,6 @@ cbuffer cbuffer_x_137 : register(b2, space0) { uint4 x_137[1]; }; static float4 glFragColor = float4(0.0f, 0.0f, 0.0f, 0.0f); -static bool tint_discard = false; void main_1() { float3 viewDirectionW = float3(0.0f, 0.0f, 0.0f); @@ -31,13 +32,11 @@ void main_1() { float4 color = float4(0.0f, 0.0f, 0.0f, 0.0f); const float x_9 = fClipDistance3; if ((x_9 > 0.0f)) { - tint_discard = true; - return; + tint_discarded = true; } const float x_17 = fClipDistance4; if ((x_17 > 0.0f)) { - tint_discard = true; - return; + tint_discarded = true; } const float4 x_34 = asfloat(x_29[0]); const float3 x_38 = (0.0f).xxx; @@ -105,26 +104,16 @@ main_out main_inner(float fClipDistance3_param, float fClipDistance4_param) { fClipDistance3 = fClipDistance3_param; fClipDistance4 = fClipDistance4_param; main_1(); - if (tint_discard) { - const main_out tint_symbol_8 = (main_out)0; - return tint_symbol_8; - } - const main_out tint_symbol_9 = {glFragColor}; - return tint_symbol_9; -} - -void tint_discard_func() { - discard; + const main_out tint_symbol_8 = {glFragColor}; + return tint_symbol_8; } tint_symbol_2 main(tint_symbol_1 tint_symbol) { const main_out inner_result = main_inner(tint_symbol.fClipDistance3_param, tint_symbol.fClipDistance4_param); - if (tint_discard) { - tint_discard_func(); - const tint_symbol_2 tint_symbol_10 = (tint_symbol_2)0; - return tint_symbol_10; - } tint_symbol_2 wrapper_result = (tint_symbol_2)0; wrapper_result.glFragColor_1 = inner_result.glFragColor_1; + if (tint_discarded) { + discard; + } return wrapper_result; } diff --git a/test/tint/bug/tint/1118.wgsl.expected.glsl b/test/tint/bug/tint/1118.wgsl.expected.glsl index 7b0565ab1d..671c8699f7 100644 --- a/test/tint/bug/tint/1118.wgsl.expected.glsl +++ b/test/tint/bug/tint/1118.wgsl.expected.glsl @@ -1,6 +1,7 @@ #version 310 es precision mediump float; +bool tint_discarded = false; layout(location = 2) in float fClipDistance3_param_1; layout(location = 3) in float fClipDistance4_param_1; layout(location = 0) out vec4 glFragColor_1_1; @@ -38,7 +39,6 @@ layout(binding = 2, std140) uniform x_137_block_ubo { } x_137; vec4 glFragColor = vec4(0.0f, 0.0f, 0.0f, 0.0f); -bool tint_discard = false; void main_1() { vec3 viewDirectionW = vec3(0.0f, 0.0f, 0.0f); vec4 baseColor = vec4(0.0f, 0.0f, 0.0f, 0.0f); @@ -58,13 +58,11 @@ void main_1() { vec4 color = vec4(0.0f, 0.0f, 0.0f, 0.0f); float x_9 = fClipDistance3; if ((x_9 > 0.0f)) { - tint_discard = true; - return; + tint_discarded = true; } float x_17 = fClipDistance4; if ((x_17 > 0.0f)) { - tint_discard = true; - return; + tint_discarded = true; } vec4 x_34 = x_29.inner.vEyePosition; vec3 x_38 = vec3(0.0f); @@ -125,24 +123,15 @@ main_out tint_symbol(float fClipDistance3_param, float fClipDistance4_param) { fClipDistance3 = fClipDistance3_param; fClipDistance4 = fClipDistance4_param; main_1(); - if (tint_discard) { - main_out tint_symbol_1 = main_out(vec4(0.0f)); - return tint_symbol_1; - } - main_out tint_symbol_2 = main_out(glFragColor); - return tint_symbol_2; -} - -void tint_discard_func() { - discard; + main_out tint_symbol_1 = main_out(glFragColor); + return tint_symbol_1; } void main() { main_out inner_result = tint_symbol(fClipDistance3_param_1, fClipDistance4_param_1); - if (tint_discard) { - tint_discard_func(); - return; - } glFragColor_1_1 = inner_result.glFragColor_1; + if (tint_discarded) { + discard; + } return; } diff --git a/test/tint/bug/tint/1118.wgsl.expected.msl b/test/tint/bug/tint/1118.wgsl.expected.msl index 5539c67f1a..9dc50df119 100644 --- a/test/tint/bug/tint/1118.wgsl.expected.msl +++ b/test/tint/bug/tint/1118.wgsl.expected.msl @@ -17,7 +17,7 @@ struct Mesh { /* 0x0000 */ float visibility; }; -void main_1(thread float* const tint_symbol_7, thread bool* const tint_symbol_8, thread float* const tint_symbol_9, const constant Scene* const tint_symbol_10, const constant Material* const tint_symbol_11, const constant Mesh* const tint_symbol_12, thread float4* const tint_symbol_13) { +void main_1(thread float* const tint_symbol_5, thread bool* const tint_symbol_6, thread float* const tint_symbol_7, const constant Scene* const tint_symbol_8, const constant Material* const tint_symbol_9, const constant Mesh* const tint_symbol_10, thread float4* const tint_symbol_11) { float3 viewDirectionW = 0.0f; float4 baseColor = 0.0f; float3 diffuseColor = 0.0f; @@ -34,23 +34,21 @@ void main_1(thread float* const tint_symbol_7, thread bool* const tint_symbol_8, float3 finalDiffuse = 0.0f; float3 finalSpecular = 0.0f; float4 color = 0.0f; - float const x_9 = *(tint_symbol_7); + float const x_9 = *(tint_symbol_5); if ((x_9 > 0.0f)) { - *(tint_symbol_8) = true; - return; + *(tint_symbol_6) = true; } - float const x_17 = *(tint_symbol_9); + float const x_17 = *(tint_symbol_7); if ((x_17 > 0.0f)) { - *(tint_symbol_8) = true; - return; + *(tint_symbol_6) = true; } - float4 const x_34 = (*(tint_symbol_10)).vEyePosition; + float4 const x_34 = (*(tint_symbol_8)).vEyePosition; float3 const x_38 = float3(0.0f); viewDirectionW = normalize((float3(x_34[0], x_34[1], x_34[2]) - x_38)); baseColor = float4(1.0f); - float4 const x_52 = (*(tint_symbol_11)).vDiffuseColor; + float4 const x_52 = (*(tint_symbol_9)).vDiffuseColor; diffuseColor = float3(x_52[0], x_52[1], x_52[2]); - float const x_60 = (*(tint_symbol_11)).vDiffuseColor[3]; + float const x_60 = (*(tint_symbol_9)).vDiffuseColor[3]; alpha = x_60; float3 const x_62 = float3(0.0f); float3 const x_64 = float3(0.0f); @@ -66,12 +64,12 @@ void main_1(thread float* const tint_symbol_7, thread bool* const tint_symbol_8, shadow = 1.0f; refractionColor = float4(0.0f, 0.0f, 0.0f, 1.0f); reflectionColor = float4(0.0f, 0.0f, 0.0f, 1.0f); - float3 const x_94 = float3((*(tint_symbol_11)).vEmissiveColor); + float3 const x_94 = float3((*(tint_symbol_9)).vEmissiveColor); emissiveColor = x_94; float3 const x_96 = diffuseBase; float3 const x_97 = diffuseColor; float3 const x_99 = emissiveColor; - float3 const x_103 = float3((*(tint_symbol_11)).vAmbientColor); + float3 const x_103 = float3((*(tint_symbol_9)).vAmbientColor); float4 const x_108 = baseColor; finalDiffuse = (clamp((((x_96 * x_97) + x_99) + x_103), float3(0.0f), float3(1.0f)) * float3(x_108[0], x_108[1], x_108[2])); finalSpecular = float3(0.0f); @@ -87,11 +85,11 @@ void main_1(thread float* const tint_symbol_7, thread bool* const tint_symbol_8, float3 const x_132 = fmax(float3(x_129[0], x_129[1], x_129[2]), float3(0.0f)); float4 const x_133 = color; color = float4(x_132[0], x_132[1], x_132[2], x_133[3]); - float const x_140 = (*(tint_symbol_12)).visibility; + float const x_140 = (*(tint_symbol_10)).visibility; float const x_142 = color[3]; color[3] = (x_142 * x_140); float4 const x_147 = color; - *(tint_symbol_13) = x_147; + *(tint_symbol_11) = x_147; return; } @@ -108,35 +106,25 @@ struct tint_symbol_3 { float4 glFragColor_1 [[color(0)]]; }; -main_out tint_symbol_inner(float fClipDistance3_param, float fClipDistance4_param, thread float* const tint_symbol_14, thread float* const tint_symbol_15, thread bool* const tint_symbol_16, const constant Scene* const tint_symbol_17, const constant Material* const tint_symbol_18, const constant Mesh* const tint_symbol_19, thread float4* const tint_symbol_20) { - *(tint_symbol_14) = fClipDistance3_param; - *(tint_symbol_15) = fClipDistance4_param; - main_1(tint_symbol_14, tint_symbol_16, tint_symbol_15, tint_symbol_17, tint_symbol_18, tint_symbol_19, tint_symbol_20); - if (*(tint_symbol_16)) { - main_out const tint_symbol_4 = main_out{}; - return tint_symbol_4; - } - main_out const tint_symbol_5 = {.glFragColor_1=*(tint_symbol_20)}; - return tint_symbol_5; +main_out tint_symbol_inner(float fClipDistance3_param, float fClipDistance4_param, thread float* const tint_symbol_12, thread float* const tint_symbol_13, thread bool* const tint_symbol_14, const constant Scene* const tint_symbol_15, const constant Material* const tint_symbol_16, const constant Mesh* const tint_symbol_17, thread float4* const tint_symbol_18) { + *(tint_symbol_12) = fClipDistance3_param; + *(tint_symbol_13) = fClipDistance4_param; + main_1(tint_symbol_12, tint_symbol_14, tint_symbol_13, tint_symbol_15, tint_symbol_16, tint_symbol_17, tint_symbol_18); + main_out const tint_symbol_4 = {.glFragColor_1=*(tint_symbol_18)}; + return tint_symbol_4; } -void tint_discard_func() { - discard_fragment(); -} - -fragment tint_symbol_3 tint_symbol(const constant Scene* tint_symbol_24 [[buffer(0)]], const constant Material* tint_symbol_25 [[buffer(1)]], const constant Mesh* tint_symbol_26 [[buffer(2)]], tint_symbol_2 tint_symbol_1 [[stage_in]]) { - thread float tint_symbol_21 = 0.0f; - thread float tint_symbol_22 = 0.0f; - thread bool tint_symbol_23 = false; - thread float4 tint_symbol_27 = 0.0f; - main_out const inner_result = tint_symbol_inner(tint_symbol_1.fClipDistance3_param, tint_symbol_1.fClipDistance4_param, &(tint_symbol_21), &(tint_symbol_22), &(tint_symbol_23), tint_symbol_24, tint_symbol_25, tint_symbol_26, &(tint_symbol_27)); - if (tint_symbol_23) { - tint_discard_func(); - tint_symbol_3 const tint_symbol_6 = tint_symbol_3{}; - return tint_symbol_6; - } +fragment tint_symbol_3 tint_symbol(const constant Scene* tint_symbol_22 [[buffer(0)]], const constant Material* tint_symbol_23 [[buffer(1)]], const constant Mesh* tint_symbol_24 [[buffer(2)]], tint_symbol_2 tint_symbol_1 [[stage_in]]) { + thread float tint_symbol_19 = 0.0f; + thread float tint_symbol_20 = 0.0f; + thread bool tint_symbol_21 = false; + thread float4 tint_symbol_25 = 0.0f; + main_out const inner_result = tint_symbol_inner(tint_symbol_1.fClipDistance3_param, tint_symbol_1.fClipDistance4_param, &(tint_symbol_19), &(tint_symbol_20), &(tint_symbol_21), tint_symbol_22, tint_symbol_23, tint_symbol_24, &(tint_symbol_25)); tint_symbol_3 wrapper_result = {}; wrapper_result.glFragColor_1 = inner_result.glFragColor_1; + if (tint_symbol_21) { + discard_fragment(); + } return wrapper_result; } diff --git a/test/tint/bug/tint/1118.wgsl.expected.spvasm b/test/tint/bug/tint/1118.wgsl.expected.spvasm index bde22d6f9f..5fb873a7f2 100644 --- a/test/tint/bug/tint/1118.wgsl.expected.spvasm +++ b/test/tint/bug/tint/1118.wgsl.expected.spvasm @@ -1,13 +1,14 @@ ; SPIR-V ; Version: 1.3 ; Generator: Google Tint Compiler; 0 -; Bound: 202 +; Bound: 188 ; Schema: 0 OpCapability Shader - %84 = OpExtInstImport "GLSL.std.450" + %74 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %main "main" %fClipDistance3_param_1 %fClipDistance4_param_1 %glFragColor_1_1 OpExecutionMode %main OriginUpperLeft + OpName %tint_discarded "tint_discarded" OpName %fClipDistance3_param_1 "fClipDistance3_param_1" OpName %fClipDistance4_param_1 "fClipDistance4_param_1" OpName %glFragColor_1_1 "glFragColor_1_1" @@ -33,9 +34,7 @@ OpMemberName %Mesh 0 "visibility" OpName %x_137 "x_137" OpName %glFragColor "glFragColor" - OpName %tint_discard "tint_discard" OpName %main_1 "main_1" - OpName %tint_return_flag "tint_return_flag" OpName %viewDirectionW "viewDirectionW" OpName %baseColor "baseColor" OpName %diffuseColor "diffuseColor" @@ -52,7 +51,6 @@ OpName %finalDiffuse "finalDiffuse" OpName %finalSpecular "finalSpecular" OpName %color "color" - OpName %tint_discard_func "tint_discard_func" OpName %main_out "main_out" OpMemberName %main_out 0 "glFragColor_1" OpName %main_inner "main_inner" @@ -85,18 +83,22 @@ OpDecorate %x_137 DescriptorSet 0 OpDecorate %x_137 Binding 2 OpMemberDecorate %main_out 0 Offset 0 + %bool = OpTypeBool + %2 = OpConstantNull %bool +%_ptr_Private_bool = OpTypePointer Private %bool +%tint_discarded = OpVariable %_ptr_Private_bool Private %2 %float = OpTypeFloat 32 %_ptr_Input_float = OpTypePointer Input %float %fClipDistance3_param_1 = OpVariable %_ptr_Input_float Input %fClipDistance4_param_1 = OpVariable %_ptr_Input_float Input %v4float = OpTypeVector %float 4 %_ptr_Output_v4float = OpTypePointer Output %v4float - %8 = OpConstantNull %v4float -%glFragColor_1_1 = OpVariable %_ptr_Output_v4float Output %8 + %12 = OpConstantNull %v4float +%glFragColor_1_1 = OpVariable %_ptr_Output_v4float Output %12 %_ptr_Private_float = OpTypePointer Private %float - %11 = OpConstantNull %float -%fClipDistance3 = OpVariable %_ptr_Private_float Private %11 -%fClipDistance4 = OpVariable %_ptr_Private_float Private %11 + %15 = OpConstantNull %float +%fClipDistance3 = OpVariable %_ptr_Private_float Private %15 +%fClipDistance4 = OpVariable %_ptr_Private_float Private %15 %Scene = OpTypeStruct %v4float %x_29_block = OpTypeStruct %Scene %_ptr_Uniform_x_29_block = OpTypePointer Uniform %x_29_block @@ -111,227 +113,198 @@ %_ptr_Uniform_x_137_block = OpTypePointer Uniform %x_137_block %x_137 = OpVariable %_ptr_Uniform_x_137_block Uniform %_ptr_Private_v4float = OpTypePointer Private %v4float -%glFragColor = OpVariable %_ptr_Private_v4float Private %8 - %bool = OpTypeBool - %29 = OpConstantNull %bool -%_ptr_Private_bool = OpTypePointer Private %bool -%tint_discard = OpVariable %_ptr_Private_bool Private %29 +%glFragColor = OpVariable %_ptr_Private_v4float Private %12 %void = OpTypeVoid %32 = OpTypeFunction %void -%_ptr_Function_bool = OpTypePointer Function %bool %_ptr_Function_v3float = OpTypePointer Function %v3float - %40 = OpConstantNull %v3float + %38 = OpConstantNull %v3float %_ptr_Function_v4float = OpTypePointer Function %v4float %_ptr_Function_float = OpTypePointer Function %float %v2float = OpTypeVector %float 2 %_ptr_Function_v2float = OpTypePointer Function %v2float - %50 = OpConstantNull %v2float + %48 = OpConstantNull %v2float %true = OpConstantTrue %bool %uint = OpTypeInt 32 0 %uint_0 = OpConstant %uint 0 %_ptr_Uniform_v4float = OpTypePointer Uniform %v4float %float_1 = OpConstant %float 1 - %91 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 + %81 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 %uint_3 = OpConstant %uint 3 %_ptr_Uniform_float = OpTypePointer Uniform %float - %118 = OpConstantComposite %v3float %float_1 %float_1 %float_1 - %119 = OpConstantComposite %v4float %11 %11 %11 %float_1 + %108 = OpConstantComposite %v3float %float_1 %float_1 %float_1 + %109 = OpConstantComposite %v4float %15 %15 %15 %float_1 %_ptr_Uniform_v3float = OpTypePointer Uniform %v3float %uint_1 = OpConstant %uint 1 %main_out = OpTypeStruct %v4float - %182 = OpTypeFunction %main_out %float %float - %193 = OpConstantNull %main_out + %170 = OpTypeFunction %main_out %float %float %main_1 = OpFunction %void None %32 %35 = OpLabel -%tint_return_flag = OpVariable %_ptr_Function_bool Function %29 -%viewDirectionW = OpVariable %_ptr_Function_v3float Function %40 - %baseColor = OpVariable %_ptr_Function_v4float Function %8 -%diffuseColor = OpVariable %_ptr_Function_v3float Function %40 - %alpha = OpVariable %_ptr_Function_float Function %11 - %normalW = OpVariable %_ptr_Function_v3float Function %40 - %uvOffset = OpVariable %_ptr_Function_v2float Function %50 -%baseAmbientColor = OpVariable %_ptr_Function_v3float Function %40 - %glossiness = OpVariable %_ptr_Function_float Function %11 -%diffuseBase = OpVariable %_ptr_Function_v3float Function %40 - %shadow = OpVariable %_ptr_Function_float Function %11 -%refractionColor = OpVariable %_ptr_Function_v4float Function %8 -%reflectionColor = OpVariable %_ptr_Function_v4float Function %8 -%emissiveColor = OpVariable %_ptr_Function_v3float Function %40 -%finalDiffuse = OpVariable %_ptr_Function_v3float Function %40 -%finalSpecular = OpVariable %_ptr_Function_v3float Function %40 - %color = OpVariable %_ptr_Function_v4float Function %8 - %61 = OpLoad %float %fClipDistance3 - %62 = OpFOrdGreaterThan %bool %61 %11 - OpSelectionMerge %63 None - OpBranchConditional %62 %64 %63 - %64 = OpLabel - OpStore %tint_discard %true - OpStore %tint_return_flag %true - OpBranch %63 - %63 = OpLabel - %67 = OpLoad %bool %tint_return_flag - %66 = OpLogicalNot %bool %67 - OpSelectionMerge %68 None - OpBranchConditional %66 %69 %68 - %69 = OpLabel - %70 = OpLoad %float %fClipDistance4 - %71 = OpFOrdGreaterThan %bool %70 %11 - OpSelectionMerge %72 None - OpBranchConditional %71 %73 %72 - %73 = OpLabel - OpStore %tint_discard %true - OpStore %tint_return_flag %true - OpBranch %72 - %72 = OpLabel - %75 = OpLoad %bool %tint_return_flag - %74 = OpLogicalNot %bool %75 - OpSelectionMerge %76 None - OpBranchConditional %74 %77 %76 - %77 = OpLabel - %81 = OpAccessChain %_ptr_Uniform_v4float %x_29 %uint_0 %uint_0 - %82 = OpLoad %v4float %81 - %85 = OpCompositeExtract %float %82 0 - %86 = OpCompositeExtract %float %82 1 - %87 = OpCompositeExtract %float %82 2 - %88 = OpCompositeConstruct %v3float %85 %86 %87 - %89 = OpFSub %v3float %88 %40 - %83 = OpExtInst %v3float %84 Normalize %89 - OpStore %viewDirectionW %83 - OpStore %baseColor %91 - %92 = OpAccessChain %_ptr_Uniform_v4float %x_49 %uint_0 %uint_0 - %93 = OpLoad %v4float %92 - %94 = OpCompositeExtract %float %93 0 - %95 = OpCompositeExtract %float %93 1 - %96 = OpCompositeExtract %float %93 2 - %97 = OpCompositeConstruct %v3float %94 %95 %96 - OpStore %diffuseColor %97 - %100 = OpAccessChain %_ptr_Uniform_float %x_49 %uint_0 %uint_0 %uint_3 - %101 = OpLoad %float %100 - OpStore %alpha %101 - OpStore %uvOffset %50 +%viewDirectionW = OpVariable %_ptr_Function_v3float Function %38 + %baseColor = OpVariable %_ptr_Function_v4float Function %12 +%diffuseColor = OpVariable %_ptr_Function_v3float Function %38 + %alpha = OpVariable %_ptr_Function_float Function %15 + %normalW = OpVariable %_ptr_Function_v3float Function %38 + %uvOffset = OpVariable %_ptr_Function_v2float Function %48 +%baseAmbientColor = OpVariable %_ptr_Function_v3float Function %38 + %glossiness = OpVariable %_ptr_Function_float Function %15 +%diffuseBase = OpVariable %_ptr_Function_v3float Function %38 + %shadow = OpVariable %_ptr_Function_float Function %15 +%refractionColor = OpVariable %_ptr_Function_v4float Function %12 +%reflectionColor = OpVariable %_ptr_Function_v4float Function %12 +%emissiveColor = OpVariable %_ptr_Function_v3float Function %38 +%finalDiffuse = OpVariable %_ptr_Function_v3float Function %38 +%finalSpecular = OpVariable %_ptr_Function_v3float Function %38 + %color = OpVariable %_ptr_Function_v4float Function %12 + %59 = OpLoad %float %fClipDistance3 + %60 = OpFOrdGreaterThan %bool %59 %15 + OpSelectionMerge %61 None + OpBranchConditional %60 %62 %61 + %62 = OpLabel + OpStore %tint_discarded %true + OpBranch %61 + %61 = OpLabel + %64 = OpLoad %float %fClipDistance4 + %65 = OpFOrdGreaterThan %bool %64 %15 + OpSelectionMerge %66 None + OpBranchConditional %65 %67 %66 + %67 = OpLabel + OpStore %tint_discarded %true + OpBranch %66 + %66 = OpLabel + %71 = OpAccessChain %_ptr_Uniform_v4float %x_29 %uint_0 %uint_0 + %72 = OpLoad %v4float %71 + %75 = OpCompositeExtract %float %72 0 + %76 = OpCompositeExtract %float %72 1 + %77 = OpCompositeExtract %float %72 2 + %78 = OpCompositeConstruct %v3float %75 %76 %77 + %79 = OpFSub %v3float %78 %38 + %73 = OpExtInst %v3float %74 Normalize %79 + OpStore %viewDirectionW %73 + OpStore %baseColor %81 + %82 = OpAccessChain %_ptr_Uniform_v4float %x_49 %uint_0 %uint_0 + %83 = OpLoad %v4float %82 + %84 = OpCompositeExtract %float %83 0 + %85 = OpCompositeExtract %float %83 1 + %86 = OpCompositeExtract %float %83 2 + %87 = OpCompositeConstruct %v3float %84 %85 %86 + OpStore %diffuseColor %87 + %90 = OpAccessChain %_ptr_Uniform_float %x_49 %uint_0 %uint_0 %uint_3 + %91 = OpLoad %float %90 + OpStore %alpha %91 + OpStore %uvOffset %48 + %92 = OpLoad %v4float %baseColor + %93 = OpCompositeExtract %float %92 0 + %94 = OpCompositeExtract %float %92 1 + %95 = OpCompositeExtract %float %92 2 + %96 = OpCompositeConstruct %v3float %93 %94 %95 + %97 = OpCompositeExtract %float %12 0 + %98 = OpCompositeExtract %float %12 1 + %99 = OpCompositeExtract %float %12 2 + %100 = OpCompositeConstruct %v3float %97 %98 %99 + %101 = OpFMul %v3float %96 %100 %102 = OpLoad %v4float %baseColor - %103 = OpCompositeExtract %float %102 0 - %104 = OpCompositeExtract %float %102 1 - %105 = OpCompositeExtract %float %102 2 - %106 = OpCompositeConstruct %v3float %103 %104 %105 - %107 = OpCompositeExtract %float %8 0 - %108 = OpCompositeExtract %float %8 1 - %109 = OpCompositeExtract %float %8 2 - %110 = OpCompositeConstruct %v3float %107 %108 %109 - %111 = OpFMul %v3float %106 %110 - %112 = OpLoad %v4float %baseColor - %113 = OpCompositeExtract %float %111 0 - %114 = OpCompositeExtract %float %111 1 - %115 = OpCompositeExtract %float %111 2 - %116 = OpCompositeExtract %float %112 3 - %117 = OpCompositeConstruct %v4float %113 %114 %115 %116 - OpStore %baseColor %117 - OpStore %baseAmbientColor %118 - OpStore %glossiness %11 - OpStore %diffuseBase %40 + %103 = OpCompositeExtract %float %101 0 + %104 = OpCompositeExtract %float %101 1 + %105 = OpCompositeExtract %float %101 2 + %106 = OpCompositeExtract %float %102 3 + %107 = OpCompositeConstruct %v4float %103 %104 %105 %106 + OpStore %baseColor %107 + OpStore %baseAmbientColor %108 + OpStore %glossiness %15 + OpStore %diffuseBase %38 OpStore %shadow %float_1 - OpStore %refractionColor %119 - OpStore %reflectionColor %119 - %121 = OpAccessChain %_ptr_Uniform_v3float %x_49 %uint_0 %uint_3 - %122 = OpLoad %v3float %121 - OpStore %emissiveColor %122 - %123 = OpLoad %v3float %diffuseBase - %124 = OpLoad %v3float %diffuseColor - %125 = OpLoad %v3float %emissiveColor - %127 = OpAccessChain %_ptr_Uniform_v3float %x_49 %uint_0 %uint_1 - %128 = OpLoad %v3float %127 - %129 = OpLoad %v4float %baseColor - %131 = OpFMul %v3float %123 %124 - %132 = OpFAdd %v3float %131 %125 - %133 = OpFAdd %v3float %132 %128 - %130 = OpExtInst %v3float %84 NClamp %133 %40 %118 - %134 = OpCompositeExtract %float %129 0 - %135 = OpCompositeExtract %float %129 1 - %136 = OpCompositeExtract %float %129 2 - %137 = OpCompositeConstruct %v3float %134 %135 %136 - %138 = OpFMul %v3float %130 %137 - OpStore %finalDiffuse %138 - OpStore %finalSpecular %40 - %139 = OpLoad %v3float %finalDiffuse - %140 = OpLoad %v3float %baseAmbientColor - %141 = OpLoad %v3float %finalSpecular - %142 = OpLoad %v4float %reflectionColor - %143 = OpLoad %v4float %refractionColor - %144 = OpFMul %v3float %139 %140 - %145 = OpFAdd %v3float %144 %141 - %146 = OpCompositeExtract %float %142 0 - %147 = OpCompositeExtract %float %142 1 - %148 = OpCompositeExtract %float %142 2 - %149 = OpCompositeConstruct %v3float %146 %147 %148 - %150 = OpFAdd %v3float %145 %149 - %151 = OpCompositeExtract %float %143 0 - %152 = OpCompositeExtract %float %143 1 - %153 = OpCompositeExtract %float %143 2 - %154 = OpCompositeConstruct %v3float %151 %152 %153 - %155 = OpFAdd %v3float %150 %154 - %156 = OpLoad %float %alpha - %157 = OpCompositeExtract %float %155 0 - %158 = OpCompositeExtract %float %155 1 - %159 = OpCompositeExtract %float %155 2 - %160 = OpCompositeConstruct %v4float %157 %158 %159 %156 - OpStore %color %160 - %161 = OpLoad %v4float %color - %163 = OpCompositeExtract %float %161 0 - %164 = OpCompositeExtract %float %161 1 - %165 = OpCompositeExtract %float %161 2 - %166 = OpCompositeConstruct %v3float %163 %164 %165 - %162 = OpExtInst %v3float %84 NMax %166 %40 - %167 = OpLoad %v4float %color - %168 = OpCompositeExtract %float %162 0 - %169 = OpCompositeExtract %float %162 1 - %170 = OpCompositeExtract %float %162 2 - %171 = OpCompositeExtract %float %167 3 - %172 = OpCompositeConstruct %v4float %168 %169 %170 %171 - OpStore %color %172 - %173 = OpAccessChain %_ptr_Uniform_float %x_137 %uint_0 %uint_0 - %174 = OpLoad %float %173 - %175 = OpAccessChain %_ptr_Function_float %color %uint_3 - %176 = OpLoad %float %175 - %177 = OpAccessChain %_ptr_Function_float %color %uint_3 - %178 = OpFMul %float %176 %174 - OpStore %177 %178 - %179 = OpLoad %v4float %color - OpStore %glFragColor %179 - OpStore %tint_return_flag %true - OpBranch %76 - %76 = OpLabel - OpBranch %68 - %68 = OpLabel + OpStore %refractionColor %109 + OpStore %reflectionColor %109 + %111 = OpAccessChain %_ptr_Uniform_v3float %x_49 %uint_0 %uint_3 + %112 = OpLoad %v3float %111 + OpStore %emissiveColor %112 + %113 = OpLoad %v3float %diffuseBase + %114 = OpLoad %v3float %diffuseColor + %115 = OpLoad %v3float %emissiveColor + %117 = OpAccessChain %_ptr_Uniform_v3float %x_49 %uint_0 %uint_1 + %118 = OpLoad %v3float %117 + %119 = OpLoad %v4float %baseColor + %121 = OpFMul %v3float %113 %114 + %122 = OpFAdd %v3float %121 %115 + %123 = OpFAdd %v3float %122 %118 + %120 = OpExtInst %v3float %74 NClamp %123 %38 %108 + %124 = OpCompositeExtract %float %119 0 + %125 = OpCompositeExtract %float %119 1 + %126 = OpCompositeExtract %float %119 2 + %127 = OpCompositeConstruct %v3float %124 %125 %126 + %128 = OpFMul %v3float %120 %127 + OpStore %finalDiffuse %128 + OpStore %finalSpecular %38 + %129 = OpLoad %v3float %finalDiffuse + %130 = OpLoad %v3float %baseAmbientColor + %131 = OpLoad %v3float %finalSpecular + %132 = OpLoad %v4float %reflectionColor + %133 = OpLoad %v4float %refractionColor + %134 = OpFMul %v3float %129 %130 + %135 = OpFAdd %v3float %134 %131 + %136 = OpCompositeExtract %float %132 0 + %137 = OpCompositeExtract %float %132 1 + %138 = OpCompositeExtract %float %132 2 + %139 = OpCompositeConstruct %v3float %136 %137 %138 + %140 = OpFAdd %v3float %135 %139 + %141 = OpCompositeExtract %float %133 0 + %142 = OpCompositeExtract %float %133 1 + %143 = OpCompositeExtract %float %133 2 + %144 = OpCompositeConstruct %v3float %141 %142 %143 + %145 = OpFAdd %v3float %140 %144 + %146 = OpLoad %float %alpha + %147 = OpCompositeExtract %float %145 0 + %148 = OpCompositeExtract %float %145 1 + %149 = OpCompositeExtract %float %145 2 + %150 = OpCompositeConstruct %v4float %147 %148 %149 %146 + OpStore %color %150 + %151 = OpLoad %v4float %color + %153 = OpCompositeExtract %float %151 0 + %154 = OpCompositeExtract %float %151 1 + %155 = OpCompositeExtract %float %151 2 + %156 = OpCompositeConstruct %v3float %153 %154 %155 + %152 = OpExtInst %v3float %74 NMax %156 %38 + %157 = OpLoad %v4float %color + %158 = OpCompositeExtract %float %152 0 + %159 = OpCompositeExtract %float %152 1 + %160 = OpCompositeExtract %float %152 2 + %161 = OpCompositeExtract %float %157 3 + %162 = OpCompositeConstruct %v4float %158 %159 %160 %161 + OpStore %color %162 + %163 = OpAccessChain %_ptr_Uniform_float %x_137 %uint_0 %uint_0 + %164 = OpLoad %float %163 + %165 = OpAccessChain %_ptr_Function_float %color %uint_3 + %166 = OpLoad %float %165 + %167 = OpAccessChain %_ptr_Function_float %color %uint_3 + %168 = OpFMul %float %166 %164 + OpStore %167 %168 + %169 = OpLoad %v4float %color + OpStore %glFragColor %169 OpReturn OpFunctionEnd -%tint_discard_func = OpFunction %void None %32 - %181 = OpLabel - OpKill - OpFunctionEnd - %main_inner = OpFunction %main_out None %182 + %main_inner = OpFunction %main_out None %170 %fClipDistance3_param = OpFunctionParameter %float %fClipDistance4_param = OpFunctionParameter %float - %187 = OpLabel + %175 = OpLabel OpStore %fClipDistance3 %fClipDistance3_param OpStore %fClipDistance4 %fClipDistance4_param - %188 = OpFunctionCall %void %main_1 - %189 = OpLoad %bool %tint_discard - OpSelectionMerge %190 None - OpBranchConditional %189 %191 %190 - %191 = OpLabel - %192 = OpFunctionCall %void %tint_discard_func - OpReturnValue %193 - %190 = OpLabel - %194 = OpLoad %v4float %glFragColor - %195 = OpCompositeConstruct %main_out %194 - OpReturnValue %195 + %176 = OpFunctionCall %void %main_1 + %177 = OpLoad %v4float %glFragColor + %178 = OpCompositeConstruct %main_out %177 + OpReturnValue %178 OpFunctionEnd %main = OpFunction %void None %32 - %197 = OpLabel - %199 = OpLoad %float %fClipDistance3_param_1 - %200 = OpLoad %float %fClipDistance4_param_1 - %198 = OpFunctionCall %main_out %main_inner %199 %200 - %201 = OpCompositeExtract %v4float %198 0 - OpStore %glFragColor_1_1 %201 + %180 = OpLabel + %182 = OpLoad %float %fClipDistance3_param_1 + %183 = OpLoad %float %fClipDistance4_param_1 + %181 = OpFunctionCall %main_out %main_inner %182 %183 + %184 = OpCompositeExtract %v4float %181 0 + OpStore %glFragColor_1_1 %184 + %185 = OpLoad %bool %tint_discarded + OpSelectionMerge %186 None + OpBranchConditional %185 %187 %186 + %187 = OpLabel + OpKill + %186 = OpLabel OpReturn OpFunctionEnd diff --git a/test/tint/bug/tint/1369.wgsl.expected.dxc.hlsl b/test/tint/bug/tint/1369.wgsl.expected.dxc.hlsl index 0981f3857f..dde30f92cc 100644 --- a/test/tint/bug/tint/1369.wgsl.expected.dxc.hlsl +++ b/test/tint/bug/tint/1369.wgsl.expected.dxc.hlsl @@ -1,29 +1,15 @@ -bug/tint/1369.wgsl:3:3 warning: code is unreachable - return true; - ^^^^^^ - -bug/tint/1369.wgsl:9:5 warning: code is unreachable - var also_unreachable : bool; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -static bool tint_discard = false; +static bool tint_discarded = false; bool call_discard() { - tint_discard = true; - return false; + tint_discarded = true; return true; } -void tint_discard_func() { - discard; -} - void f() { bool v = call_discard(); - if (tint_discard) { - tint_discard_func(); - return; - } bool also_unreachable = false; + if (tint_discarded) { + discard; + } return; } diff --git a/test/tint/bug/tint/1369.wgsl.expected.fxc.hlsl b/test/tint/bug/tint/1369.wgsl.expected.fxc.hlsl index 0981f3857f..dde30f92cc 100644 --- a/test/tint/bug/tint/1369.wgsl.expected.fxc.hlsl +++ b/test/tint/bug/tint/1369.wgsl.expected.fxc.hlsl @@ -1,29 +1,15 @@ -bug/tint/1369.wgsl:3:3 warning: code is unreachable - return true; - ^^^^^^ - -bug/tint/1369.wgsl:9:5 warning: code is unreachable - var also_unreachable : bool; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -static bool tint_discard = false; +static bool tint_discarded = false; bool call_discard() { - tint_discard = true; - return false; + tint_discarded = true; return true; } -void tint_discard_func() { - discard; -} - void f() { bool v = call_discard(); - if (tint_discard) { - tint_discard_func(); - return; - } bool also_unreachable = false; + if (tint_discarded) { + discard; + } return; } diff --git a/test/tint/bug/tint/1369.wgsl.expected.glsl b/test/tint/bug/tint/1369.wgsl.expected.glsl index 82b1904238..e288349961 100644 --- a/test/tint/bug/tint/1369.wgsl.expected.glsl +++ b/test/tint/bug/tint/1369.wgsl.expected.glsl @@ -1,38 +1,21 @@ -bug/tint/1369.wgsl:3:3 warning: code is unreachable - return true; - ^^^^^^ - -bug/tint/1369.wgsl:9:5 warning: code is unreachable - var also_unreachable : bool; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - #version 310 es precision mediump float; -bool tint_discard = false; +bool tint_discarded = false; bool call_discard() { - tint_discard = true; - return false; + tint_discarded = true; return true; } void f() { bool v = call_discard(); - if (tint_discard) { - return; - } bool also_unreachable = false; } -void tint_discard_func() { - discard; -} - void main() { f(); - if (tint_discard) { - tint_discard_func(); - return; + if (tint_discarded) { + discard; } return; } diff --git a/test/tint/bug/tint/1369.wgsl.expected.msl b/test/tint/bug/tint/1369.wgsl.expected.msl index 32624c3edd..87932206da 100644 --- a/test/tint/bug/tint/1369.wgsl.expected.msl +++ b/test/tint/bug/tint/1369.wgsl.expected.msl @@ -1,32 +1,18 @@ -bug/tint/1369.wgsl:3:3 warning: code is unreachable - return true; - ^^^^^^ - -bug/tint/1369.wgsl:9:5 warning: code is unreachable - var also_unreachable : bool; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - #include using namespace metal; bool call_discard(thread bool* const tint_symbol) { *(tint_symbol) = true; - return false; return true; } -void tint_discard_func() { - discard_fragment(); -} - fragment void f() { thread bool tint_symbol_1 = false; bool v = call_discard(&(tint_symbol_1)); - if (tint_symbol_1) { - tint_discard_func(); - return; - } bool also_unreachable = false; + if (tint_symbol_1) { + discard_fragment(); + } return; } diff --git a/test/tint/bug/tint/1369.wgsl.expected.spvasm b/test/tint/bug/tint/1369.wgsl.expected.spvasm index 803df82849..6d26689931 100644 --- a/test/tint/bug/tint/1369.wgsl.expected.spvasm +++ b/test/tint/bug/tint/1369.wgsl.expected.spvasm @@ -1,29 +1,21 @@ -bug/tint/1369.wgsl:3:3 warning: code is unreachable - return true; - ^^^^^^ - -bug/tint/1369.wgsl:9:5 warning: code is unreachable - var also_unreachable : bool; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - ; SPIR-V ; Version: 1.3 ; Generator: Google Tint Compiler; 0 -; Bound: 22 +; Bound: 20 ; Schema: 0 OpCapability Shader OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %f "f" OpExecutionMode %f OriginUpperLeft - OpName %tint_discard "tint_discard" + OpName %tint_discarded "tint_discarded" OpName %call_discard "call_discard" - OpName %tint_discard_func "tint_discard_func" OpName %f "f" OpName %v "v" + OpName %also_unreachable "also_unreachable" %bool = OpTypeBool %2 = OpConstantNull %bool %_ptr_Private_bool = OpTypePointer Private %bool -%tint_discard = OpVariable %_ptr_Private_bool Private %2 +%tint_discarded = OpVariable %_ptr_Private_bool Private %2 %5 = OpTypeFunction %bool %true = OpConstantTrue %bool %void = OpTypeVoid @@ -31,24 +23,20 @@ bug/tint/1369.wgsl:9:5 warning: code is unreachable %_ptr_Function_bool = OpTypePointer Function %bool %call_discard = OpFunction %bool None %5 %7 = OpLabel - OpStore %tint_discard %true - OpReturnValue %2 - OpFunctionEnd -%tint_discard_func = OpFunction %void None %9 - %12 = OpLabel - OpKill + OpStore %tint_discarded %true + OpReturnValue %true OpFunctionEnd %f = OpFunction %void None %9 - %14 = OpLabel + %12 = OpLabel %v = OpVariable %_ptr_Function_bool Function %2 - %15 = OpFunctionCall %bool %call_discard - OpStore %v %15 - %18 = OpLoad %bool %tint_discard - OpSelectionMerge %19 None - OpBranchConditional %18 %20 %19 - %20 = OpLabel - %21 = OpFunctionCall %void %tint_discard_func - OpReturn +%also_unreachable = OpVariable %_ptr_Function_bool Function %2 + %13 = OpFunctionCall %bool %call_discard + OpStore %v %13 + %17 = OpLoad %bool %tint_discarded + OpSelectionMerge %18 None + OpBranchConditional %17 %19 %18 %19 = OpLabel + OpKill + %18 = OpLabel OpReturn OpFunctionEnd diff --git a/test/tint/bug/tint/1369.wgsl.expected.wgsl b/test/tint/bug/tint/1369.wgsl.expected.wgsl index 5b3ca83259..c3275102d2 100644 --- a/test/tint/bug/tint/1369.wgsl.expected.wgsl +++ b/test/tint/bug/tint/1369.wgsl.expected.wgsl @@ -1,11 +1,3 @@ -bug/tint/1369.wgsl:3:3 warning: code is unreachable - return true; - ^^^^^^ - -bug/tint/1369.wgsl:9:5 warning: code is unreachable - var also_unreachable : bool; - ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - fn call_discard() -> bool { discard; return true; diff --git a/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl new file mode 100644 index 0000000000..325a0199e2 --- /dev/null +++ b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl @@ -0,0 +1,17 @@ +@group(0) @binding(0) var t : texture_2d; + +@group(0) @binding(1) var s : sampler; + +@group(0) @binding(2) var a : atomic; + +@fragment +fn foo(@location(0) in : f32, @location(1) coord : vec2) -> @location(0) i32 { + if (in == 0.0) { + discard; + } + var result = i32(textureSample(t, s, coord).x); + for (var i = 0; i < 10; i = atomicAdd(&a, 1)) { + result += i; + } + return result; +} diff --git a/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.dxc.hlsl b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.dxc.hlsl new file mode 100644 index 0000000000..44d8b38244 --- /dev/null +++ b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.dxc.hlsl @@ -0,0 +1,55 @@ +static bool tint_discarded = false; +Texture2D t : register(t0, space0); +SamplerState s : register(s1, space0); +RWByteAddressBuffer a : register(u2, space0); + +struct tint_symbol_2 { + float tint_symbol : TEXCOORD0; + float2 coord : TEXCOORD1; +}; +struct tint_symbol_3 { + int value : SV_Target0; +}; + +int tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, int value) { + int original_value = 0; + buffer.InterlockedAdd(offset, value, original_value); + return original_value; +} + + +int foo_inner(float tint_symbol, float2 coord) { + if ((tint_symbol == 0.0f)) { + tint_discarded = true; + } + int result = int(t.Sample(s, coord).x); + { + int i = 0; + while (true) { + if (!((i < 10))) { + break; + } + { + result = (result + i); + } + { + int tint_symbol_4 = 0; + if (!(tint_discarded)) { + tint_symbol_4 = tint_atomicAdd(a, 0u, 1); + } + i = tint_symbol_4; + } + } + } + return result; +} + +tint_symbol_3 foo(tint_symbol_2 tint_symbol_1) { + const int inner_result = foo_inner(tint_symbol_1.tint_symbol, tint_symbol_1.coord); + tint_symbol_3 wrapper_result = (tint_symbol_3)0; + wrapper_result.value = inner_result; + if (tint_discarded) { + discard; + } + return wrapper_result; +} diff --git a/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.fxc.hlsl b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.fxc.hlsl new file mode 100644 index 0000000000..44d8b38244 --- /dev/null +++ b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.fxc.hlsl @@ -0,0 +1,55 @@ +static bool tint_discarded = false; +Texture2D t : register(t0, space0); +SamplerState s : register(s1, space0); +RWByteAddressBuffer a : register(u2, space0); + +struct tint_symbol_2 { + float tint_symbol : TEXCOORD0; + float2 coord : TEXCOORD1; +}; +struct tint_symbol_3 { + int value : SV_Target0; +}; + +int tint_atomicAdd(RWByteAddressBuffer buffer, uint offset, int value) { + int original_value = 0; + buffer.InterlockedAdd(offset, value, original_value); + return original_value; +} + + +int foo_inner(float tint_symbol, float2 coord) { + if ((tint_symbol == 0.0f)) { + tint_discarded = true; + } + int result = int(t.Sample(s, coord).x); + { + int i = 0; + while (true) { + if (!((i < 10))) { + break; + } + { + result = (result + i); + } + { + int tint_symbol_4 = 0; + if (!(tint_discarded)) { + tint_symbol_4 = tint_atomicAdd(a, 0u, 1); + } + i = tint_symbol_4; + } + } + } + return result; +} + +tint_symbol_3 foo(tint_symbol_2 tint_symbol_1) { + const int inner_result = foo_inner(tint_symbol_1.tint_symbol, tint_symbol_1.coord); + tint_symbol_3 wrapper_result = (tint_symbol_3)0; + wrapper_result.value = inner_result; + if (tint_discarded) { + discard; + } + return wrapper_result; +} diff --git a/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.glsl b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.glsl new file mode 100644 index 0000000000..3af238a9a6 --- /dev/null +++ b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.glsl @@ -0,0 +1,47 @@ +#version 310 es +precision mediump float; + +bool tint_discarded = false; +layout(location = 0) in float tint_symbol_1; +layout(location = 1) in vec2 coord_1; +layout(location = 0) out int value; +layout(binding = 2, std430) buffer a_block_ssbo { + int inner; +} a; + +uniform highp sampler2D t_s; + +int foo(float tint_symbol, vec2 coord) { + if ((tint_symbol == 0.0f)) { + tint_discarded = true; + } + int result = int(texture(t_s, coord).x); + { + int i = 0; + while (true) { + if (!((i < 10))) { + break; + } + { + result = (result + i); + } + { + int tint_symbol_2 = 0; + if (!(tint_discarded)) { + tint_symbol_2 = atomicAdd(a.inner, 1); + } + i = tint_symbol_2; + } + } + } + return result; +} + +void main() { + int inner_result = foo(tint_symbol_1, coord_1); + value = inner_result; + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.msl b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.msl new file mode 100644 index 0000000000..1da2b9095f --- /dev/null +++ b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.msl @@ -0,0 +1,49 @@ +#include + +using namespace metal; +struct tint_symbol_1 { + float in [[user(locn0)]]; + float2 coord [[user(locn1)]]; +}; + +struct tint_symbol_2 { + int value [[color(0)]]; +}; + +int foo_inner(float in, float2 coord, thread bool* const tint_symbol_4, texture2d tint_symbol_5, sampler tint_symbol_6, device atomic_int* const tint_symbol_7) { + if ((in == 0.0f)) { + *(tint_symbol_4) = true; + } + int result = int(tint_symbol_5.sample(tint_symbol_6, coord)[0]); + { + int i = 0; + while (true) { + if (!((i < 10))) { + break; + } + { + result = as_type((as_type(result) + as_type(i))); + } + { + int tint_symbol_3 = 0; + if (!(*(tint_symbol_4))) { + tint_symbol_3 = atomic_fetch_add_explicit(tint_symbol_7, 1, memory_order_relaxed); + } + i = tint_symbol_3; + } + } + } + return result; +} + +fragment tint_symbol_2 foo(texture2d tint_symbol_9 [[texture(0)]], sampler tint_symbol_10 [[sampler(0)]], device atomic_int* tint_symbol_11 [[buffer(0)]], tint_symbol_1 tint_symbol [[stage_in]]) { + thread bool tint_symbol_8 = false; + int const inner_result = foo_inner(tint_symbol.in, tint_symbol.coord, &(tint_symbol_8), tint_symbol_9, tint_symbol_10, tint_symbol_11); + tint_symbol_2 wrapper_result = {}; + wrapper_result.value = inner_result; + if (tint_symbol_8) { + discard_fragment(); + } + return wrapper_result; +} + diff --git a/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.spvasm b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.spvasm new file mode 100644 index 0000000000..c482728296 --- /dev/null +++ b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.spvasm @@ -0,0 +1,145 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 83 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %foo "foo" %in_1 %coord_1 %value + OpExecutionMode %foo OriginUpperLeft + OpName %tint_discarded "tint_discarded" + OpName %in_1 "in_1" + OpName %coord_1 "coord_1" + OpName %value "value" + OpName %t "t" + OpName %s "s" + OpName %a_block "a_block" + OpMemberName %a_block 0 "inner" + OpName %a "a" + OpName %foo_inner "foo_inner" + OpName %in "in" + OpName %coord "coord" + OpName %result "result" + OpName %i "i" + OpName %tint_symbol "tint_symbol" + OpName %foo "foo" + OpDecorate %in_1 Location 0 + OpDecorate %coord_1 Location 1 + OpDecorate %value Location 0 + OpDecorate %t DescriptorSet 0 + OpDecorate %t Binding 0 + OpDecorate %s DescriptorSet 0 + OpDecorate %s Binding 1 + OpDecorate %a_block Block + OpMemberDecorate %a_block 0 Offset 0 + OpDecorate %a DescriptorSet 0 + OpDecorate %a Binding 2 + %bool = OpTypeBool + %2 = OpConstantNull %bool +%_ptr_Private_bool = OpTypePointer Private %bool +%tint_discarded = OpVariable %_ptr_Private_bool Private %2 + %float = OpTypeFloat 32 +%_ptr_Input_float = OpTypePointer Input %float + %in_1 = OpVariable %_ptr_Input_float Input + %v2float = OpTypeVector %float 2 +%_ptr_Input_v2float = OpTypePointer Input %v2float + %coord_1 = OpVariable %_ptr_Input_v2float Input + %int = OpTypeInt 32 1 +%_ptr_Output_int = OpTypePointer Output %int + %14 = OpConstantNull %int + %value = OpVariable %_ptr_Output_int Output %14 + %17 = OpTypeImage %float 2D 0 0 0 1 Unknown +%_ptr_UniformConstant_17 = OpTypePointer UniformConstant %17 + %t = OpVariable %_ptr_UniformConstant_17 UniformConstant + %20 = OpTypeSampler +%_ptr_UniformConstant_20 = OpTypePointer UniformConstant %20 + %s = OpVariable %_ptr_UniformConstant_20 UniformConstant + %a_block = OpTypeStruct %int +%_ptr_StorageBuffer_a_block = OpTypePointer StorageBuffer %a_block + %a = OpVariable %_ptr_StorageBuffer_a_block StorageBuffer + %24 = OpTypeFunction %int %float %v2float + %29 = OpConstantNull %float + %true = OpConstantTrue %bool + %v4float = OpTypeVector %float 4 + %39 = OpTypeSampledImage %17 +%_ptr_Function_int = OpTypePointer Function %int + %int_10 = OpConstant %int 10 + %uint = OpTypeInt 32 0 + %uint_1 = OpConstant %uint 1 + %uint_0 = OpConstant %uint 0 +%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int + %int_1 = OpConstant %int 1 + %void = OpTypeVoid + %73 = OpTypeFunction %void + %foo_inner = OpFunction %int None %24 + %in = OpFunctionParameter %float + %coord = OpFunctionParameter %v2float + %28 = OpLabel + %result = OpVariable %_ptr_Function_int Function %14 + %i = OpVariable %_ptr_Function_int Function %14 +%tint_symbol = OpVariable %_ptr_Function_int Function %14 + %30 = OpFOrdEqual %bool %in %29 + OpSelectionMerge %31 None + OpBranchConditional %30 %32 %31 + %32 = OpLabel + OpStore %tint_discarded %true + OpBranch %31 + %31 = OpLabel + %37 = OpLoad %20 %s + %38 = OpLoad %17 %t + %40 = OpSampledImage %39 %38 %37 + %35 = OpImageSampleImplicitLod %v4float %40 %coord + %41 = OpCompositeExtract %float %35 0 + %34 = OpConvertFToS %int %41 + OpStore %result %34 + OpStore %i %14 + OpBranch %45 + %45 = OpLabel + OpLoopMerge %46 %47 None + OpBranch %48 + %48 = OpLabel + %50 = OpLoad %int %i + %52 = OpSLessThan %bool %50 %int_10 + %49 = OpLogicalNot %bool %52 + OpSelectionMerge %53 None + OpBranchConditional %49 %54 %53 + %54 = OpLabel + OpBranch %46 + %53 = OpLabel + %55 = OpLoad %int %result + %56 = OpLoad %int %i + %57 = OpIAdd %int %55 %56 + OpStore %result %57 + OpBranch %47 + %47 = OpLabel + %60 = OpLoad %bool %tint_discarded + %59 = OpLogicalNot %bool %60 + OpSelectionMerge %61 None + OpBranchConditional %59 %62 %61 + %62 = OpLabel + %69 = OpAccessChain %_ptr_StorageBuffer_int %a %uint_0 + %63 = OpAtomicIAdd %int %69 %uint_1 %uint_0 %int_1 + OpStore %tint_symbol %63 + OpBranch %61 + %61 = OpLabel + %71 = OpLoad %int %tint_symbol + OpStore %i %71 + OpBranch %45 + %46 = OpLabel + %72 = OpLoad %int %result + OpReturnValue %72 + OpFunctionEnd + %foo = OpFunction %void None %73 + %76 = OpLabel + %78 = OpLoad %float %in_1 + %79 = OpLoad %v2float %coord_1 + %77 = OpFunctionCall %int %foo_inner %78 %79 + OpStore %value %77 + %80 = OpLoad %bool %tint_discarded + OpSelectionMerge %81 None + OpBranchConditional %80 %82 %81 + %82 = OpLabel + OpKill + %81 = OpLabel + OpReturn + OpFunctionEnd diff --git a/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.wgsl b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.wgsl new file mode 100644 index 0000000000..7d8d3fa021 --- /dev/null +++ b/test/tint/statements/discard/atomic_in_for_loop_continuing.wgsl.expected.wgsl @@ -0,0 +1,17 @@ +@group(0) @binding(0) var t : texture_2d; + +@group(0) @binding(1) var s : sampler; + +@group(0) @binding(2) var a : atomic; + +@fragment +fn foo(@location(0) in : f32, @location(1) coord : vec2) -> @location(0) i32 { + if ((in == 0.0)) { + discard; + } + var result = i32(textureSample(t, s, coord).x); + for(var i = 0; (i < 10); i = atomicAdd(&(a), 1)) { + result += i; + } + return result; +} diff --git a/test/tint/statements/discard/helper_functions.wgsl b/test/tint/statements/discard/helper_functions.wgsl new file mode 100644 index 0000000000..9dc24452ca --- /dev/null +++ b/test/tint/statements/discard/helper_functions.wgsl @@ -0,0 +1,19 @@ +@group(0) @binding(0) var non_uniform_global : i32; + +@group(0) @binding(1) var output : f32; + +fn foo() { + if (non_uniform_global < 0) { + discard; + } +} + +fn bar() { + output = dpdx(1.0); +} + +@fragment +fn main() { + foo(); + bar(); +} diff --git a/test/tint/statements/discard/helper_functions.wgsl.expected.dxc.hlsl b/test/tint/statements/discard/helper_functions.wgsl.expected.dxc.hlsl new file mode 100644 index 0000000000..8b015e8f4b --- /dev/null +++ b/test/tint/statements/discard/helper_functions.wgsl.expected.dxc.hlsl @@ -0,0 +1,24 @@ +static bool tint_discarded = false; +RWByteAddressBuffer non_uniform_global : register(u0, space0); +RWByteAddressBuffer output : register(u1, space0); + +void foo() { + if ((asint(non_uniform_global.Load(0u)) < 0)) { + tint_discarded = true; + } +} + +void bar() { + if (!(tint_discarded)) { + output.Store(0u, asuint(ddx(1.0f))); + } +} + +void main() { + foo(); + bar(); + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/helper_functions.wgsl.expected.fxc.hlsl b/test/tint/statements/discard/helper_functions.wgsl.expected.fxc.hlsl new file mode 100644 index 0000000000..8b015e8f4b --- /dev/null +++ b/test/tint/statements/discard/helper_functions.wgsl.expected.fxc.hlsl @@ -0,0 +1,24 @@ +static bool tint_discarded = false; +RWByteAddressBuffer non_uniform_global : register(u0, space0); +RWByteAddressBuffer output : register(u1, space0); + +void foo() { + if ((asint(non_uniform_global.Load(0u)) < 0)) { + tint_discarded = true; + } +} + +void bar() { + if (!(tint_discarded)) { + output.Store(0u, asuint(ddx(1.0f))); + } +} + +void main() { + foo(); + bar(); + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/helper_functions.wgsl.expected.glsl b/test/tint/statements/discard/helper_functions.wgsl.expected.glsl new file mode 100644 index 0000000000..a17e8f5e8a --- /dev/null +++ b/test/tint/statements/discard/helper_functions.wgsl.expected.glsl @@ -0,0 +1,36 @@ +#version 310 es +precision mediump float; + +bool tint_discarded = false; +layout(binding = 0, std430) buffer non_uniform_global_block_ssbo { + int inner; +} non_uniform_global; + +layout(binding = 1, std430) buffer tint_symbol_block_ssbo { + float inner; +} tint_symbol; + +void foo() { + if ((non_uniform_global.inner < 0)) { + tint_discarded = true; + } +} + +void bar() { + if (!(tint_discarded)) { + tint_symbol.inner = dFdx(1.0f); + } +} + +void tint_symbol_1() { + foo(); + bar(); +} + +void main() { + tint_symbol_1(); + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/helper_functions.wgsl.expected.msl b/test/tint/statements/discard/helper_functions.wgsl.expected.msl new file mode 100644 index 0000000000..57e769ef27 --- /dev/null +++ b/test/tint/statements/discard/helper_functions.wgsl.expected.msl @@ -0,0 +1,25 @@ +#include + +using namespace metal; +void foo(device int* const tint_symbol_1, thread bool* const tint_symbol_2) { + if ((*(tint_symbol_1) < 0)) { + *(tint_symbol_2) = true; + } +} + +void bar(thread bool* const tint_symbol_3, device float* const tint_symbol_4) { + if (!(*(tint_symbol_3))) { + *(tint_symbol_4) = dfdx(1.0f); + } +} + +fragment void tint_symbol(device int* tint_symbol_5 [[buffer(0)]], device float* tint_symbol_7 [[buffer(1)]]) { + thread bool tint_symbol_6 = false; + foo(tint_symbol_5, &(tint_symbol_6)); + bar(&(tint_symbol_6), tint_symbol_7); + if (tint_symbol_6) { + discard_fragment(); + } + return; +} + diff --git a/test/tint/statements/discard/helper_functions.wgsl.expected.spvasm b/test/tint/statements/discard/helper_functions.wgsl.expected.spvasm new file mode 100644 index 0000000000..9758c2549b --- /dev/null +++ b/test/tint/statements/discard/helper_functions.wgsl.expected.spvasm @@ -0,0 +1,87 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 44 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" + OpExecutionMode %main OriginUpperLeft + OpName %tint_discarded "tint_discarded" + OpName %non_uniform_global_block "non_uniform_global_block" + OpMemberName %non_uniform_global_block 0 "inner" + OpName %non_uniform_global "non_uniform_global" + OpName %output_block "output_block" + OpMemberName %output_block 0 "inner" + OpName %output "output" + OpName %foo "foo" + OpName %bar "bar" + OpName %main "main" + OpDecorate %non_uniform_global_block Block + OpMemberDecorate %non_uniform_global_block 0 Offset 0 + OpDecorate %non_uniform_global DescriptorSet 0 + OpDecorate %non_uniform_global Binding 0 + OpDecorate %output_block Block + OpMemberDecorate %output_block 0 Offset 0 + OpDecorate %output DescriptorSet 0 + OpDecorate %output Binding 1 + %bool = OpTypeBool + %2 = OpConstantNull %bool +%_ptr_Private_bool = OpTypePointer Private %bool +%tint_discarded = OpVariable %_ptr_Private_bool Private %2 + %int = OpTypeInt 32 1 +%non_uniform_global_block = OpTypeStruct %int +%_ptr_StorageBuffer_non_uniform_global_block = OpTypePointer StorageBuffer %non_uniform_global_block +%non_uniform_global = OpVariable %_ptr_StorageBuffer_non_uniform_global_block StorageBuffer + %float = OpTypeFloat 32 +%output_block = OpTypeStruct %float +%_ptr_StorageBuffer_output_block = OpTypePointer StorageBuffer %output_block + %output = OpVariable %_ptr_StorageBuffer_output_block StorageBuffer + %void = OpTypeVoid + %13 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int + %22 = OpConstantNull %int + %true = OpConstantTrue %bool +%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float + %float_1 = OpConstant %float 1 + %foo = OpFunction %void None %13 + %16 = OpLabel + %20 = OpAccessChain %_ptr_StorageBuffer_int %non_uniform_global %uint_0 + %21 = OpLoad %int %20 + %23 = OpSLessThan %bool %21 %22 + OpSelectionMerge %24 None + OpBranchConditional %23 %25 %24 + %25 = OpLabel + OpStore %tint_discarded %true + OpBranch %24 + %24 = OpLabel + OpReturn + OpFunctionEnd + %bar = OpFunction %void None %13 + %28 = OpLabel + %30 = OpLoad %bool %tint_discarded + %29 = OpLogicalNot %bool %30 + OpSelectionMerge %31 None + OpBranchConditional %29 %32 %31 + %32 = OpLabel + %34 = OpAccessChain %_ptr_StorageBuffer_float %output %uint_0 + %35 = OpDPdx %float %float_1 + OpStore %34 %35 + OpBranch %31 + %31 = OpLabel + OpReturn + OpFunctionEnd + %main = OpFunction %void None %13 + %38 = OpLabel + %39 = OpFunctionCall %void %foo + %40 = OpFunctionCall %void %bar + %41 = OpLoad %bool %tint_discarded + OpSelectionMerge %42 None + OpBranchConditional %41 %43 %42 + %43 = OpLabel + OpKill + %42 = OpLabel + OpReturn + OpFunctionEnd diff --git a/test/tint/statements/discard/helper_functions.wgsl.expected.wgsl b/test/tint/statements/discard/helper_functions.wgsl.expected.wgsl new file mode 100644 index 0000000000..a900752786 --- /dev/null +++ b/test/tint/statements/discard/helper_functions.wgsl.expected.wgsl @@ -0,0 +1,19 @@ +@group(0) @binding(0) var non_uniform_global : i32; + +@group(0) @binding(1) var output : f32; + +fn foo() { + if ((non_uniform_global < 0)) { + discard; + } +} + +fn bar() { + output = dpdx(1.0); +} + +@fragment +fn main() { + foo(); + bar(); +} diff --git a/test/tint/statements/discard/multiple_returns.wgsl b/test/tint/statements/discard/multiple_returns.wgsl new file mode 100644 index 0000000000..2464f3f221 --- /dev/null +++ b/test/tint/statements/discard/multiple_returns.wgsl @@ -0,0 +1,26 @@ +@group(0) @binding(0) var non_uniform_global : i32; + +@group(0) @binding(1) var output : f32; + +@fragment +fn main() { + if (non_uniform_global < 0) { + discard; + } + output = dpdx(1.0); + if (output < 0) { + var i = 0; + loop { + if (output > f32(i)) { + output = f32(i); + return; + } + continuing { + i++; + break if i == 5; + } + } + return; + } + return; +} diff --git a/test/tint/statements/discard/multiple_returns.wgsl.expected.dxc.hlsl b/test/tint/statements/discard/multiple_returns.wgsl.expected.dxc.hlsl new file mode 100644 index 0000000000..f7b1a2685e --- /dev/null +++ b/test/tint/statements/discard/multiple_returns.wgsl.expected.dxc.hlsl @@ -0,0 +1,38 @@ +static bool tint_discarded = false; +RWByteAddressBuffer non_uniform_global : register(u0, space0); +RWByteAddressBuffer output : register(u1, space0); + +void main() { + if ((asint(non_uniform_global.Load(0u)) < 0)) { + tint_discarded = true; + } + if (!(tint_discarded)) { + output.Store(0u, asuint(ddx(1.0f))); + } + if ((asfloat(output.Load(0u)) < 0.0f)) { + int i = 0; + while (true) { + if ((asfloat(output.Load(0u)) > float(i))) { + if (!(tint_discarded)) { + output.Store(0u, asuint(float(i))); + } + if (tint_discarded) { + discard; + } + return; + } + { + i = (i + 1); + if ((i == 5)) { break; } + } + } + if (tint_discarded) { + discard; + } + return; + } + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/multiple_returns.wgsl.expected.fxc.hlsl b/test/tint/statements/discard/multiple_returns.wgsl.expected.fxc.hlsl new file mode 100644 index 0000000000..f7b1a2685e --- /dev/null +++ b/test/tint/statements/discard/multiple_returns.wgsl.expected.fxc.hlsl @@ -0,0 +1,38 @@ +static bool tint_discarded = false; +RWByteAddressBuffer non_uniform_global : register(u0, space0); +RWByteAddressBuffer output : register(u1, space0); + +void main() { + if ((asint(non_uniform_global.Load(0u)) < 0)) { + tint_discarded = true; + } + if (!(tint_discarded)) { + output.Store(0u, asuint(ddx(1.0f))); + } + if ((asfloat(output.Load(0u)) < 0.0f)) { + int i = 0; + while (true) { + if ((asfloat(output.Load(0u)) > float(i))) { + if (!(tint_discarded)) { + output.Store(0u, asuint(float(i))); + } + if (tint_discarded) { + discard; + } + return; + } + { + i = (i + 1); + if ((i == 5)) { break; } + } + } + if (tint_discarded) { + discard; + } + return; + } + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/multiple_returns.wgsl.expected.glsl b/test/tint/statements/discard/multiple_returns.wgsl.expected.glsl new file mode 100644 index 0000000000..8cd3e9976a --- /dev/null +++ b/test/tint/statements/discard/multiple_returns.wgsl.expected.glsl @@ -0,0 +1,45 @@ +#version 310 es +precision mediump float; + +bool tint_discarded = false; +layout(binding = 0, std430) buffer non_uniform_global_block_ssbo { + int inner; +} non_uniform_global; + +layout(binding = 1, std430) buffer tint_symbol_block_ssbo { + float inner; +} tint_symbol; + +void tint_symbol_1() { + if ((non_uniform_global.inner < 0)) { + tint_discarded = true; + } + if (!(tint_discarded)) { + tint_symbol.inner = dFdx(1.0f); + } + if ((tint_symbol.inner < 0.0f)) { + int i = 0; + while (true) { + if ((tint_symbol.inner > float(i))) { + if (!(tint_discarded)) { + tint_symbol.inner = float(i); + } + return; + } + { + i = (i + 1); + if ((i == 5)) { break; } + } + } + return; + } + return; +} + +void main() { + tint_symbol_1(); + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/multiple_returns.wgsl.expected.msl b/test/tint/statements/discard/multiple_returns.wgsl.expected.msl new file mode 100644 index 0000000000..751016ed51 --- /dev/null +++ b/test/tint/statements/discard/multiple_returns.wgsl.expected.msl @@ -0,0 +1,39 @@ +#include + +using namespace metal; +fragment void tint_symbol(device int* tint_symbol_1 [[buffer(0)]], device float* tint_symbol_3 [[buffer(1)]]) { + thread bool tint_symbol_2 = false; + if ((*(tint_symbol_1) < 0)) { + tint_symbol_2 = true; + } + if (!(tint_symbol_2)) { + *(tint_symbol_3) = dfdx(1.0f); + } + if ((*(tint_symbol_3) < 0.0f)) { + int i = 0; + while (true) { + if ((*(tint_symbol_3) > float(i))) { + if (!(tint_symbol_2)) { + *(tint_symbol_3) = float(i); + } + if (tint_symbol_2) { + discard_fragment(); + } + return; + } + { + i = as_type((as_type(i) + as_type(1))); + if ((i == 5)) { break; } + } + } + if (tint_symbol_2) { + discard_fragment(); + } + return; + } + if (tint_symbol_2) { + discard_fragment(); + } + return; +} + diff --git a/test/tint/statements/discard/multiple_returns.wgsl.expected.spvasm b/test/tint/statements/discard/multiple_returns.wgsl.expected.spvasm new file mode 100644 index 0000000000..6e8336711a --- /dev/null +++ b/test/tint/statements/discard/multiple_returns.wgsl.expected.spvasm @@ -0,0 +1,137 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 76 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" + OpExecutionMode %main OriginUpperLeft + OpName %tint_discarded "tint_discarded" + OpName %non_uniform_global_block "non_uniform_global_block" + OpMemberName %non_uniform_global_block 0 "inner" + OpName %non_uniform_global "non_uniform_global" + OpName %output_block "output_block" + OpMemberName %output_block 0 "inner" + OpName %output "output" + OpName %main "main" + OpName %i "i" + OpDecorate %non_uniform_global_block Block + OpMemberDecorate %non_uniform_global_block 0 Offset 0 + OpDecorate %non_uniform_global DescriptorSet 0 + OpDecorate %non_uniform_global Binding 0 + OpDecorate %output_block Block + OpMemberDecorate %output_block 0 Offset 0 + OpDecorate %output DescriptorSet 0 + OpDecorate %output Binding 1 + %bool = OpTypeBool + %2 = OpConstantNull %bool +%_ptr_Private_bool = OpTypePointer Private %bool +%tint_discarded = OpVariable %_ptr_Private_bool Private %2 + %int = OpTypeInt 32 1 +%non_uniform_global_block = OpTypeStruct %int +%_ptr_StorageBuffer_non_uniform_global_block = OpTypePointer StorageBuffer %non_uniform_global_block +%non_uniform_global = OpVariable %_ptr_StorageBuffer_non_uniform_global_block StorageBuffer + %float = OpTypeFloat 32 +%output_block = OpTypeStruct %float +%_ptr_StorageBuffer_output_block = OpTypePointer StorageBuffer %output_block + %output = OpVariable %_ptr_StorageBuffer_output_block StorageBuffer + %void = OpTypeVoid + %13 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int + %22 = OpConstantNull %int + %true = OpConstantTrue %bool +%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float + %float_1 = OpConstant %float 1 + %37 = OpConstantNull %float +%_ptr_Function_int = OpTypePointer Function %int + %int_1 = OpConstant %int 1 + %int_5 = OpConstant %int 5 + %main = OpFunction %void None %13 + %16 = OpLabel + %i = OpVariable %_ptr_Function_int Function %22 + %20 = OpAccessChain %_ptr_StorageBuffer_int %non_uniform_global %uint_0 + %21 = OpLoad %int %20 + %23 = OpSLessThan %bool %21 %22 + OpSelectionMerge %24 None + OpBranchConditional %23 %25 %24 + %25 = OpLabel + OpStore %tint_discarded %true + OpBranch %24 + %24 = OpLabel + %28 = OpLoad %bool %tint_discarded + %27 = OpLogicalNot %bool %28 + OpSelectionMerge %29 None + OpBranchConditional %27 %30 %29 + %30 = OpLabel + %32 = OpAccessChain %_ptr_StorageBuffer_float %output %uint_0 + %33 = OpDPdx %float %float_1 + OpStore %32 %33 + OpBranch %29 + %29 = OpLabel + %35 = OpAccessChain %_ptr_StorageBuffer_float %output %uint_0 + %36 = OpLoad %float %35 + %38 = OpFOrdLessThan %bool %36 %37 + OpSelectionMerge %39 None + OpBranchConditional %38 %40 %39 + %40 = OpLabel + OpStore %i %22 + OpBranch %43 + %43 = OpLabel + OpLoopMerge %44 %45 None + OpBranch %46 + %46 = OpLabel + %47 = OpAccessChain %_ptr_StorageBuffer_float %output %uint_0 + %48 = OpLoad %float %47 + %50 = OpLoad %int %i + %49 = OpConvertSToF %float %50 + %51 = OpFOrdGreaterThan %bool %48 %49 + OpSelectionMerge %52 None + OpBranchConditional %51 %53 %52 + %53 = OpLabel + %55 = OpLoad %bool %tint_discarded + %54 = OpLogicalNot %bool %55 + OpSelectionMerge %56 None + OpBranchConditional %54 %57 %56 + %57 = OpLabel + %58 = OpAccessChain %_ptr_StorageBuffer_float %output %uint_0 + %60 = OpLoad %int %i + %59 = OpConvertSToF %float %60 + OpStore %58 %59 + OpBranch %56 + %56 = OpLabel + %61 = OpLoad %bool %tint_discarded + OpSelectionMerge %62 None + OpBranchConditional %61 %63 %62 + %63 = OpLabel + OpKill + %62 = OpLabel + OpReturn + %52 = OpLabel + OpBranch %45 + %45 = OpLabel + %64 = OpLoad %int %i + %66 = OpIAdd %int %64 %int_1 + OpStore %i %66 + %67 = OpLoad %int %i + %69 = OpIEqual %bool %67 %int_5 + OpBranchConditional %69 %44 %43 + %44 = OpLabel + %70 = OpLoad %bool %tint_discarded + OpSelectionMerge %71 None + OpBranchConditional %70 %72 %71 + %72 = OpLabel + OpKill + %71 = OpLabel + OpReturn + %39 = OpLabel + %73 = OpLoad %bool %tint_discarded + OpSelectionMerge %74 None + OpBranchConditional %73 %75 %74 + %75 = OpLabel + OpKill + %74 = OpLabel + OpReturn + OpFunctionEnd diff --git a/test/tint/statements/discard/multiple_returns.wgsl.expected.wgsl b/test/tint/statements/discard/multiple_returns.wgsl.expected.wgsl new file mode 100644 index 0000000000..4d52f05c25 --- /dev/null +++ b/test/tint/statements/discard/multiple_returns.wgsl.expected.wgsl @@ -0,0 +1,27 @@ +@group(0) @binding(0) var non_uniform_global : i32; + +@group(0) @binding(1) var output : f32; + +@fragment +fn main() { + if ((non_uniform_global < 0)) { + discard; + } + output = dpdx(1.0); + if ((output < 0)) { + var i = 0; + loop { + if ((output > f32(i))) { + output = f32(i); + return; + } + + continuing { + i++; + break if (i == 5); + } + } + return; + } + return; +} diff --git a/test/tint/statements/discard/nested_return.wgsl b/test/tint/statements/discard/nested_return.wgsl new file mode 100644 index 0000000000..75bcdb03ab --- /dev/null +++ b/test/tint/statements/discard/nested_return.wgsl @@ -0,0 +1,13 @@ +@group(0) @binding(0) var non_uniform_global : i32; + +@fragment +fn main() { + if (non_uniform_global < 0) { + discard; + } + { + { + return; + } + } +} diff --git a/test/tint/statements/discard/nested_return.wgsl.expected.dxc.hlsl b/test/tint/statements/discard/nested_return.wgsl.expected.dxc.hlsl new file mode 100644 index 0000000000..c8e4eda9c2 --- /dev/null +++ b/test/tint/statements/discard/nested_return.wgsl.expected.dxc.hlsl @@ -0,0 +1,17 @@ +static bool tint_discarded = false; +RWByteAddressBuffer non_uniform_global : register(u0, space0); + +void main() { + if ((asint(non_uniform_global.Load(0u)) < 0)) { + tint_discarded = true; + } + { + { + if (tint_discarded) { + discard; + } + return; + } + } + return; +} diff --git a/test/tint/statements/discard/nested_return.wgsl.expected.fxc.hlsl b/test/tint/statements/discard/nested_return.wgsl.expected.fxc.hlsl new file mode 100644 index 0000000000..c8e4eda9c2 --- /dev/null +++ b/test/tint/statements/discard/nested_return.wgsl.expected.fxc.hlsl @@ -0,0 +1,17 @@ +static bool tint_discarded = false; +RWByteAddressBuffer non_uniform_global : register(u0, space0); + +void main() { + if ((asint(non_uniform_global.Load(0u)) < 0)) { + tint_discarded = true; + } + { + { + if (tint_discarded) { + discard; + } + return; + } + } + return; +} diff --git a/test/tint/statements/discard/nested_return.wgsl.expected.glsl b/test/tint/statements/discard/nested_return.wgsl.expected.glsl new file mode 100644 index 0000000000..601c6697ec --- /dev/null +++ b/test/tint/statements/discard/nested_return.wgsl.expected.glsl @@ -0,0 +1,26 @@ +#version 310 es +precision mediump float; + +bool tint_discarded = false; +layout(binding = 0, std430) buffer non_uniform_global_block_ssbo { + int inner; +} non_uniform_global; + +void tint_symbol() { + if ((non_uniform_global.inner < 0)) { + tint_discarded = true; + } + { + { + return; + } + } +} + +void main() { + tint_symbol(); + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/nested_return.wgsl.expected.msl b/test/tint/statements/discard/nested_return.wgsl.expected.msl new file mode 100644 index 0000000000..eac069dba8 --- /dev/null +++ b/test/tint/statements/discard/nested_return.wgsl.expected.msl @@ -0,0 +1,19 @@ +#include + +using namespace metal; +fragment void tint_symbol(device int* tint_symbol_1 [[buffer(0)]]) { + thread bool tint_symbol_2 = false; + if ((*(tint_symbol_1) < 0)) { + tint_symbol_2 = true; + } + { + { + if (tint_symbol_2) { + discard_fragment(); + } + return; + } + } + return; +} + diff --git a/test/tint/statements/discard/nested_return.wgsl.expected.spvasm b/test/tint/statements/discard/nested_return.wgsl.expected.spvasm new file mode 100644 index 0000000000..c1c59a301e --- /dev/null +++ b/test/tint/statements/discard/nested_return.wgsl.expected.spvasm @@ -0,0 +1,52 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 26 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" + OpExecutionMode %main OriginUpperLeft + OpName %tint_discarded "tint_discarded" + OpName %non_uniform_global_block "non_uniform_global_block" + OpMemberName %non_uniform_global_block 0 "inner" + OpName %non_uniform_global "non_uniform_global" + OpName %main "main" + OpDecorate %non_uniform_global_block Block + OpMemberDecorate %non_uniform_global_block 0 Offset 0 + OpDecorate %non_uniform_global DescriptorSet 0 + OpDecorate %non_uniform_global Binding 0 + %bool = OpTypeBool + %2 = OpConstantNull %bool +%_ptr_Private_bool = OpTypePointer Private %bool +%tint_discarded = OpVariable %_ptr_Private_bool Private %2 + %int = OpTypeInt 32 1 +%non_uniform_global_block = OpTypeStruct %int +%_ptr_StorageBuffer_non_uniform_global_block = OpTypePointer StorageBuffer %non_uniform_global_block +%non_uniform_global = OpVariable %_ptr_StorageBuffer_non_uniform_global_block StorageBuffer + %void = OpTypeVoid + %9 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int + %18 = OpConstantNull %int + %true = OpConstantTrue %bool + %main = OpFunction %void None %9 + %12 = OpLabel + %16 = OpAccessChain %_ptr_StorageBuffer_int %non_uniform_global %uint_0 + %17 = OpLoad %int %16 + %19 = OpSLessThan %bool %17 %18 + OpSelectionMerge %20 None + OpBranchConditional %19 %21 %20 + %21 = OpLabel + OpStore %tint_discarded %true + OpBranch %20 + %20 = OpLabel + %23 = OpLoad %bool %tint_discarded + OpSelectionMerge %24 None + OpBranchConditional %23 %25 %24 + %25 = OpLabel + OpKill + %24 = OpLabel + OpReturn + OpFunctionEnd diff --git a/test/tint/statements/discard/nested_return.wgsl.expected.wgsl b/test/tint/statements/discard/nested_return.wgsl.expected.wgsl new file mode 100644 index 0000000000..a33d2733c8 --- /dev/null +++ b/test/tint/statements/discard/nested_return.wgsl.expected.wgsl @@ -0,0 +1,13 @@ +@group(0) @binding(0) var non_uniform_global : i32; + +@fragment +fn main() { + if ((non_uniform_global < 0)) { + discard; + } + { + { + return; + } + } +} diff --git a/test/tint/statements/discard/non_uniform.wgsl b/test/tint/statements/discard/non_uniform.wgsl new file mode 100644 index 0000000000..06c9927876 --- /dev/null +++ b/test/tint/statements/discard/non_uniform.wgsl @@ -0,0 +1,11 @@ +@group(0) @binding(0) var non_uniform_global : i32; + +@group(0) @binding(1) var output : f32; + +@fragment +fn main() { + if (non_uniform_global < 0) { + discard; + } + output = dpdx(1.0); +} diff --git a/test/tint/statements/discard/non_uniform.wgsl.expected.dxc.hlsl b/test/tint/statements/discard/non_uniform.wgsl.expected.dxc.hlsl new file mode 100644 index 0000000000..88ce6fa389 --- /dev/null +++ b/test/tint/statements/discard/non_uniform.wgsl.expected.dxc.hlsl @@ -0,0 +1,16 @@ +static bool tint_discarded = false; +RWByteAddressBuffer non_uniform_global : register(u0, space0); +RWByteAddressBuffer output : register(u1, space0); + +void main() { + if ((asint(non_uniform_global.Load(0u)) < 0)) { + tint_discarded = true; + } + if (!(tint_discarded)) { + output.Store(0u, asuint(ddx(1.0f))); + } + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/non_uniform.wgsl.expected.fxc.hlsl b/test/tint/statements/discard/non_uniform.wgsl.expected.fxc.hlsl new file mode 100644 index 0000000000..88ce6fa389 --- /dev/null +++ b/test/tint/statements/discard/non_uniform.wgsl.expected.fxc.hlsl @@ -0,0 +1,16 @@ +static bool tint_discarded = false; +RWByteAddressBuffer non_uniform_global : register(u0, space0); +RWByteAddressBuffer output : register(u1, space0); + +void main() { + if ((asint(non_uniform_global.Load(0u)) < 0)) { + tint_discarded = true; + } + if (!(tint_discarded)) { + output.Store(0u, asuint(ddx(1.0f))); + } + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/non_uniform.wgsl.expected.glsl b/test/tint/statements/discard/non_uniform.wgsl.expected.glsl new file mode 100644 index 0000000000..b6be83af24 --- /dev/null +++ b/test/tint/statements/discard/non_uniform.wgsl.expected.glsl @@ -0,0 +1,28 @@ +#version 310 es +precision mediump float; + +bool tint_discarded = false; +layout(binding = 0, std430) buffer non_uniform_global_block_ssbo { + int inner; +} non_uniform_global; + +layout(binding = 1, std430) buffer tint_symbol_block_ssbo { + float inner; +} tint_symbol; + +void tint_symbol_1() { + if ((non_uniform_global.inner < 0)) { + tint_discarded = true; + } + if (!(tint_discarded)) { + tint_symbol.inner = dFdx(1.0f); + } +} + +void main() { + tint_symbol_1(); + if (tint_discarded) { + discard; + } + return; +} diff --git a/test/tint/statements/discard/non_uniform.wgsl.expected.msl b/test/tint/statements/discard/non_uniform.wgsl.expected.msl new file mode 100644 index 0000000000..2ada21da9e --- /dev/null +++ b/test/tint/statements/discard/non_uniform.wgsl.expected.msl @@ -0,0 +1,17 @@ +#include + +using namespace metal; +fragment void tint_symbol(device int* tint_symbol_1 [[buffer(0)]], device float* tint_symbol_3 [[buffer(1)]]) { + thread bool tint_symbol_2 = false; + if ((*(tint_symbol_1) < 0)) { + tint_symbol_2 = true; + } + if (!(tint_symbol_2)) { + *(tint_symbol_3) = dfdx(1.0f); + } + if (tint_symbol_2) { + discard_fragment(); + } + return; +} + diff --git a/test/tint/statements/discard/non_uniform.wgsl.expected.spvasm b/test/tint/statements/discard/non_uniform.wgsl.expected.spvasm new file mode 100644 index 0000000000..a023542b3e --- /dev/null +++ b/test/tint/statements/discard/non_uniform.wgsl.expected.spvasm @@ -0,0 +1,75 @@ +; SPIR-V +; Version: 1.3 +; Generator: Google Tint Compiler; 0 +; Bound: 38 +; Schema: 0 + OpCapability Shader + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" + OpExecutionMode %main OriginUpperLeft + OpName %tint_discarded "tint_discarded" + OpName %non_uniform_global_block "non_uniform_global_block" + OpMemberName %non_uniform_global_block 0 "inner" + OpName %non_uniform_global "non_uniform_global" + OpName %output_block "output_block" + OpMemberName %output_block 0 "inner" + OpName %output "output" + OpName %main "main" + OpDecorate %non_uniform_global_block Block + OpMemberDecorate %non_uniform_global_block 0 Offset 0 + OpDecorate %non_uniform_global DescriptorSet 0 + OpDecorate %non_uniform_global Binding 0 + OpDecorate %output_block Block + OpMemberDecorate %output_block 0 Offset 0 + OpDecorate %output DescriptorSet 0 + OpDecorate %output Binding 1 + %bool = OpTypeBool + %2 = OpConstantNull %bool +%_ptr_Private_bool = OpTypePointer Private %bool +%tint_discarded = OpVariable %_ptr_Private_bool Private %2 + %int = OpTypeInt 32 1 +%non_uniform_global_block = OpTypeStruct %int +%_ptr_StorageBuffer_non_uniform_global_block = OpTypePointer StorageBuffer %non_uniform_global_block +%non_uniform_global = OpVariable %_ptr_StorageBuffer_non_uniform_global_block StorageBuffer + %float = OpTypeFloat 32 +%output_block = OpTypeStruct %float +%_ptr_StorageBuffer_output_block = OpTypePointer StorageBuffer %output_block + %output = OpVariable %_ptr_StorageBuffer_output_block StorageBuffer + %void = OpTypeVoid + %13 = OpTypeFunction %void + %uint = OpTypeInt 32 0 + %uint_0 = OpConstant %uint 0 +%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int + %22 = OpConstantNull %int + %true = OpConstantTrue %bool +%_ptr_StorageBuffer_float = OpTypePointer StorageBuffer %float + %float_1 = OpConstant %float 1 + %main = OpFunction %void None %13 + %16 = OpLabel + %20 = OpAccessChain %_ptr_StorageBuffer_int %non_uniform_global %uint_0 + %21 = OpLoad %int %20 + %23 = OpSLessThan %bool %21 %22 + OpSelectionMerge %24 None + OpBranchConditional %23 %25 %24 + %25 = OpLabel + OpStore %tint_discarded %true + OpBranch %24 + %24 = OpLabel + %28 = OpLoad %bool %tint_discarded + %27 = OpLogicalNot %bool %28 + OpSelectionMerge %29 None + OpBranchConditional %27 %30 %29 + %30 = OpLabel + %32 = OpAccessChain %_ptr_StorageBuffer_float %output %uint_0 + %33 = OpDPdx %float %float_1 + OpStore %32 %33 + OpBranch %29 + %29 = OpLabel + %35 = OpLoad %bool %tint_discarded + OpSelectionMerge %36 None + OpBranchConditional %35 %37 %36 + %37 = OpLabel + OpKill + %36 = OpLabel + OpReturn + OpFunctionEnd diff --git a/test/tint/statements/discard/non_uniform.wgsl.expected.wgsl b/test/tint/statements/discard/non_uniform.wgsl.expected.wgsl new file mode 100644 index 0000000000..5d697d4d59 --- /dev/null +++ b/test/tint/statements/discard/non_uniform.wgsl.expected.wgsl @@ -0,0 +1,11 @@ +@group(0) @binding(0) var non_uniform_global : i32; + +@group(0) @binding(1) var output : f32; + +@fragment +fn main() { + if ((non_uniform_global < 0)) { + discard; + } + output = dpdx(1.0); +} diff --git a/test/tint/unittest/reader/spirv/SpvParserCFGTest_EmitBody_Kill_InsideLoop.spvasm b/test/tint/unittest/reader/spirv/SpvParserCFGTest_EmitBody_Kill_InsideLoop.spvasm deleted file mode 100644 index 85a2d5bc05..0000000000 --- a/test/tint/unittest/reader/spirv/SpvParserCFGTest_EmitBody_Kill_InsideLoop.spvasm +++ /dev/null @@ -1,55 +0,0 @@ -; Test: SpvParserCFGTest_EmitBody_Kill_InsideLoop.spvasm -; SPIR-V -; Version: 1.0 -; Generator: Khronos SPIR-V Tools Assembler; 0 -; Bound: 1000 -; Schema: 0 -OpCapability Shader -OpMemoryModel Logical Simple -OpEntryPoint Fragment %100 "main" -OpExecutionMode %100 OriginUpperLeft -OpName %var "var" -%void = OpTypeVoid -%3 = OpTypeFunction %void -%bool = OpTypeBool -%5 = OpConstantNull %bool -%true = OpConstantTrue %bool -%false = OpConstantFalse %bool -%uint = OpTypeInt 32 0 -%int = OpTypeInt 32 1 -%uint_42 = OpConstant %uint 42 -%int_42 = OpConstant %int 42 -%13 = OpTypeFunction %uint -%uint_0 = OpConstant %uint 0 -%uint_1 = OpConstant %uint 1 -%uint_2 = OpConstant %uint 2 -%uint_3 = OpConstant %uint 3 -%uint_4 = OpConstant %uint 4 -%uint_5 = OpConstant %uint 5 -%uint_6 = OpConstant %uint 6 -%uint_7 = OpConstant %uint 7 -%uint_8 = OpConstant %uint 8 -%uint_10 = OpConstant %uint 10 -%uint_20 = OpConstant %uint 20 -%uint_30 = OpConstant %uint 30 -%uint_40 = OpConstant %uint 40 -%uint_50 = OpConstant %uint 50 -%uint_90 = OpConstant %uint 90 -%uint_99 = OpConstant %uint 99 -%_ptr_Private_uint = OpTypePointer Private %uint -%var = OpVariable %_ptr_Private_uint Private -%uint_999 = OpConstant %uint 999 -%100 = OpFunction %void None %3 -%10 = OpLabel -OpBranch %20 -%20 = OpLabel -OpLoopMerge %99 %80 None -OpBranchConditional %5 %30 %30 -%30 = OpLabel -OpKill -%80 = OpLabel -OpBranch %20 -%99 = OpLabel -OpKill -OpFunctionEnd - diff --git a/test/tint/vk-gl-cts/graphicsfuzz/stable-binarysearch-tree-false-if-discard-loop/1.spvasm b/test/tint/vk-gl-cts/graphicsfuzz/stable-binarysearch-tree-false-if-discard-loop/1.spvasm deleted file mode 100644 index 235ec037e3..0000000000 --- a/test/tint/vk-gl-cts/graphicsfuzz/stable-binarysearch-tree-false-if-discard-loop/1.spvasm +++ /dev/null @@ -1,1053 +0,0 @@ - OpCapability Shader - %1 = OpExtInstImport "GLSL.std.450" - OpMemoryModel Logical GLSL450 - OpEntryPoint Fragment %main "main" %gl_FragCoord %_GLF_color - OpExecutionMode %main OriginUpperLeft - OpSource ESSL 320 - OpName %main "main" - OpName %BST "BST" - OpMemberName %BST 0 "data" - OpMemberName %BST 1 "leftIndex" - OpMemberName %BST 2 "rightIndex" - OpName %tree "tree" - OpName %buf0 "buf0" - OpMemberName %buf0 0 "injectionSwitch" - OpName %_ "" - OpName %gl_FragCoord "gl_FragCoord" - OpName %_GLF_color "_GLF_color" - OpMemberDecorate %buf0 0 Offset 0 - OpDecorate %buf0 Block - OpDecorate %_ DescriptorSet 0 - OpDecorate %_ Binding 0 - OpDecorate %gl_FragCoord BuiltIn FragCoord - OpDecorate %_GLF_color Location 0 - %void = OpTypeVoid - %10 = OpTypeFunction %void - %int = OpTypeInt 32 1 - %BST = OpTypeStruct %int %int %int -%_ptr_Function_BST = OpTypePointer Function %BST -%_ptr_Function_int = OpTypePointer Function %int - %int_0 = OpConstant %int 0 - %int_1 = OpConstant %int 1 - %int_n1 = OpConstant %int -1 - %int_2 = OpConstant %int 2 - %bool = OpTypeBool - %uint = OpTypeInt 32 0 - %uint_10 = OpConstant %uint 10 -%_arr_BST_uint_10 = OpTypeArray %BST %uint_10 - %float = OpTypeFloat 32 - %v2float = OpTypeVector %float 2 - %buf0 = OpTypeStruct %v2float -%_ptr_Uniform_buf0 = OpTypePointer Uniform %buf0 - %_ = OpVariable %_ptr_Uniform_buf0 Uniform - %uint_1 = OpConstant %uint 1 -%_ptr_Uniform_float = OpTypePointer Uniform %float - %uint_0 = OpConstant %uint 0 - %int_9 = OpConstant %int 9 - %int_5 = OpConstant %int 5 - %v4float = OpTypeVector %float 4 -%_ptr_Input_v4float = OpTypePointer Input %v4float -%gl_FragCoord = OpVariable %_ptr_Input_v4float Input -%_ptr_Input_float = OpTypePointer Input %float - %float_0 = OpConstant %float 0 - %int_12 = OpConstant %int 12 - %int_15 = OpConstant %int 15 - %int_7 = OpConstant %int 7 - %int_8 = OpConstant %int 8 - %int_6 = OpConstant %int 6 - %int_17 = OpConstant %int 17 - %int_13 = OpConstant %int 13 - %int_20 = OpConstant %int 20 -%_ptr_Output_v4float = OpTypePointer Output %v4float - %_GLF_color = OpVariable %_ptr_Output_v4float Output - %float_1 = OpConstant %float 1 - %44 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_1 - %45 = OpConstantComposite %v4float %float_0 %float_0 %float_1 %float_1 - %false = OpConstantFalse %bool - %true = OpConstantTrue %bool -%_ptr_Function__arr_BST_uint_10 = OpTypePointer Function %_arr_BST_uint_10 - %49 = OpUndef %int - %50 = OpConstantComposite %BST %int_9 %int_n1 %int_n1 - %51 = OpConstantComposite %BST %int_5 %int_n1 %int_n1 - %int_3 = OpConstant %int 3 - %53 = OpConstantComposite %BST %int_12 %int_n1 %int_n1 - %54 = OpConstantComposite %BST %int_15 %int_n1 %int_n1 - %int_4 = OpConstant %int 4 - %56 = OpConstantComposite %BST %int_7 %int_n1 %int_n1 - %57 = OpConstantComposite %BST %int_8 %int_n1 %int_n1 - %58 = OpConstantComposite %BST %int_2 %int_n1 %int_n1 - %59 = OpConstantComposite %BST %int_6 %int_n1 %int_n1 - %60 = OpConstantComposite %BST %int_17 %int_n1 %int_n1 - %61 = OpConstantComposite %BST %int_13 %int_n1 %int_n1 - %main = OpFunction %void None %10 - %62 = OpLabel - %tree = OpVariable %_ptr_Function__arr_BST_uint_10 Function - %63 = OpAccessChain %_ptr_Function_BST %tree %int_0 - OpStore %63 %50 - OpSelectionMerge %64 None - OpSwitch %uint_0 %65 - %65 = OpLabel - OpBranch %66 - %66 = OpLabel - %67 = OpPhi %bool %false %65 %68 %69 - %70 = OpPhi %int %int_0 %65 %71 %69 - %72 = OpSLessThanEqual %bool %70 %int_1 - OpLoopMerge %73 %69 None - OpBranchConditional %72 %74 %73 - %74 = OpLabel - %75 = OpAccessChain %_ptr_Function_int %tree %70 %int_0 - %76 = OpLoad %int %75 - %77 = OpSLessThanEqual %bool %int_5 %76 - OpSelectionMerge %78 None - OpBranchConditional %77 %79 %80 - %80 = OpLabel - %81 = OpAccessChain %_ptr_Function_int %tree %70 %int_2 - %82 = OpLoad %int %81 - %83 = OpIEqual %bool %82 %int_n1 - OpSelectionMerge %84 None - OpBranchConditional %83 %85 %86 - %86 = OpLabel - %87 = OpLoad %int %81 - OpBranch %69 - %85 = OpLabel - OpStore %81 %int_1 - %88 = OpAccessChain %_ptr_Function_BST %tree %int_1 - OpStore %88 %51 - OpBranch %73 - %84 = OpLabel - OpUnreachable - %79 = OpLabel - %89 = OpAccessChain %_ptr_Function_int %tree %70 %int_1 - %90 = OpLoad %int %89 - %91 = OpIEqual %bool %90 %int_n1 - OpSelectionMerge %92 None - OpBranchConditional %91 %93 %94 - %94 = OpLabel - %95 = OpLoad %int %89 - OpBranch %69 - %93 = OpLabel - %96 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %97 = OpLoad %float %96 - %98 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_0 - %99 = OpLoad %float %98 - %100 = OpFOrdLessThan %bool %97 %99 - OpSelectionMerge %101 None - OpBranchConditional %100 %102 %101 - %102 = OpLabel - OpBranch %103 - %103 = OpLabel - OpLoopMerge %104 %105 None - OpBranch %106 - %106 = OpLabel - OpKill - %105 = OpLabel - OpBranch %103 - %104 = OpLabel - OpUnreachable - %101 = OpLabel - OpStore %89 %int_1 - %107 = OpAccessChain %_ptr_Function_BST %tree %int_1 - OpStore %107 %51 - OpBranch %108 - %108 = OpLabel - %109 = OpConvertFToS %int %97 - %110 = OpSLessThan %bool %int_0 %109 - OpLoopMerge %111 %112 None - OpBranchConditional %110 %113 %111 - %113 = OpLabel - OpBranch %111 - %112 = OpLabel - OpBranch %108 - %111 = OpLabel - %114 = OpPhi %bool %67 %108 %true %113 - OpSelectionMerge %115 None - OpBranchConditional %114 %73 %115 - %115 = OpLabel - OpBranch %92 - %92 = OpLabel - OpBranch %78 - %78 = OpLabel - OpBranch %69 - %69 = OpLabel - %68 = OpPhi %bool %67 %94 %67 %86 %114 %78 - %71 = OpPhi %int %95 %94 %87 %86 %70 %78 - OpBranch %66 - %73 = OpLabel - %116 = OpPhi %bool %67 %66 %114 %111 %true %85 - OpSelectionMerge %117 None - OpBranchConditional %116 %64 %117 - %117 = OpLabel - OpBranch %64 - %64 = OpLabel - OpBranch %118 - %118 = OpLabel - %119 = OpPhi %int %int_0 %64 %120 %121 - OpLoopMerge %122 %121 None - OpBranch %123 - %123 = OpLabel - %124 = OpAccessChain %_ptr_Input_float %gl_FragCoord %uint_1 - %125 = OpLoad %float %124 - %126 = OpFOrdLessThan %bool %125 %float_0 - %127 = OpLogicalNot %bool %126 - OpSelectionMerge %128 None - OpBranchConditional %127 %129 %128 - %129 = OpLabel - %130 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %131 = OpLoad %float %130 - %132 = OpConvertFToS %int %131 - %133 = OpINotEqual %bool %119 %132 - OpBranch %128 - %128 = OpLabel - %134 = OpPhi %bool %126 %123 %133 %129 - OpBranchConditional %134 %135 %122 - %135 = OpLabel - OpSelectionMerge %136 None - OpSwitch %uint_0 %137 - %137 = OpLabel - OpBranch %138 - %138 = OpLabel - %139 = OpPhi %bool %false %137 %140 %141 - %142 = OpPhi %int %int_0 %137 %143 %141 - %144 = OpSLessThanEqual %bool %142 %int_2 - OpLoopMerge %145 %141 None - OpBranchConditional %144 %146 %145 - %146 = OpLabel - %147 = OpAccessChain %_ptr_Function_int %tree %142 %int_0 - %148 = OpLoad %int %147 - %149 = OpSLessThanEqual %bool %int_12 %148 - OpSelectionMerge %150 None - OpBranchConditional %149 %151 %152 - %152 = OpLabel - %153 = OpAccessChain %_ptr_Function_int %tree %142 %int_2 - %154 = OpLoad %int %153 - %155 = OpIEqual %bool %154 %int_n1 - OpSelectionMerge %156 None - OpBranchConditional %155 %157 %158 - %158 = OpLabel - %159 = OpLoad %int %153 - OpBranch %141 - %157 = OpLabel - OpStore %153 %int_2 - %160 = OpAccessChain %_ptr_Function_BST %tree %int_2 - OpStore %160 %53 - OpBranch %145 - %156 = OpLabel - OpUnreachable - %151 = OpLabel - %161 = OpAccessChain %_ptr_Function_int %tree %142 %int_1 - %162 = OpLoad %int %161 - %163 = OpIEqual %bool %162 %int_n1 - OpSelectionMerge %164 None - OpBranchConditional %163 %165 %166 - %166 = OpLabel - %167 = OpLoad %int %161 - OpBranch %141 - %165 = OpLabel - %168 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %169 = OpLoad %float %168 - %170 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_0 - %171 = OpLoad %float %170 - %172 = OpFOrdLessThan %bool %169 %171 - OpSelectionMerge %173 None - OpBranchConditional %172 %174 %173 - %174 = OpLabel - OpBranch %175 - %175 = OpLabel - OpLoopMerge %176 %177 None - OpBranch %178 - %178 = OpLabel - OpKill - %177 = OpLabel - OpBranch %175 - %176 = OpLabel - OpUnreachable - %173 = OpLabel - OpStore %161 %int_2 - %179 = OpAccessChain %_ptr_Function_BST %tree %int_2 - OpStore %179 %53 - OpBranch %180 - %180 = OpLabel - %181 = OpConvertFToS %int %169 - %182 = OpSLessThan %bool %int_0 %181 - OpLoopMerge %183 %184 None - OpBranchConditional %182 %185 %183 - %185 = OpLabel - OpBranch %183 - %184 = OpLabel - OpBranch %180 - %183 = OpLabel - %186 = OpPhi %bool %139 %180 %true %185 - OpSelectionMerge %187 None - OpBranchConditional %186 %145 %187 - %187 = OpLabel - OpBranch %164 - %164 = OpLabel - OpBranch %150 - %150 = OpLabel - OpBranch %141 - %141 = OpLabel - %140 = OpPhi %bool %139 %166 %139 %158 %186 %150 - %143 = OpPhi %int %167 %166 %159 %158 %142 %150 - OpBranch %138 - %145 = OpLabel - %188 = OpPhi %bool %139 %138 %186 %183 %true %157 - OpSelectionMerge %189 None - OpBranchConditional %188 %136 %189 - %189 = OpLabel - OpBranch %136 - %136 = OpLabel - OpBranch %121 - %121 = OpLabel - %120 = OpIAdd %int %119 %int_1 - OpBranch %118 - %122 = OpLabel - OpSelectionMerge %190 None - OpSwitch %uint_0 %191 - %191 = OpLabel - OpBranch %192 - %192 = OpLabel - %193 = OpPhi %bool %false %191 %194 %195 - %196 = OpPhi %int %int_0 %191 %197 %195 - %198 = OpSLessThanEqual %bool %196 %int_3 - OpLoopMerge %199 %195 None - OpBranchConditional %198 %200 %199 - %200 = OpLabel - %201 = OpAccessChain %_ptr_Function_int %tree %196 %int_0 - %202 = OpLoad %int %201 - %203 = OpSLessThanEqual %bool %int_15 %202 - OpSelectionMerge %204 None - OpBranchConditional %203 %205 %206 - %206 = OpLabel - %207 = OpAccessChain %_ptr_Function_int %tree %196 %int_2 - %208 = OpLoad %int %207 - %209 = OpIEqual %bool %208 %int_n1 - OpSelectionMerge %210 None - OpBranchConditional %209 %211 %212 - %212 = OpLabel - %213 = OpLoad %int %207 - OpBranch %195 - %211 = OpLabel - OpStore %207 %int_3 - %214 = OpAccessChain %_ptr_Function_BST %tree %int_3 - OpStore %214 %54 - OpBranch %199 - %210 = OpLabel - OpUnreachable - %205 = OpLabel - %215 = OpAccessChain %_ptr_Function_int %tree %196 %int_1 - %216 = OpLoad %int %215 - %217 = OpIEqual %bool %216 %int_n1 - OpSelectionMerge %218 None - OpBranchConditional %217 %219 %220 - %220 = OpLabel - %221 = OpLoad %int %215 - OpBranch %195 - %219 = OpLabel - %222 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %223 = OpLoad %float %222 - %224 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_0 - %225 = OpLoad %float %224 - %226 = OpFOrdLessThan %bool %223 %225 - OpSelectionMerge %227 None - OpBranchConditional %226 %228 %227 - %228 = OpLabel - OpBranch %229 - %229 = OpLabel - OpLoopMerge %230 %231 None - OpBranch %232 - %232 = OpLabel - OpKill - %231 = OpLabel - OpBranch %229 - %230 = OpLabel - OpUnreachable - %227 = OpLabel - OpStore %215 %int_3 - %233 = OpAccessChain %_ptr_Function_BST %tree %int_3 - OpStore %233 %54 - OpBranch %234 - %234 = OpLabel - %235 = OpConvertFToS %int %223 - %236 = OpSLessThan %bool %int_0 %235 - OpLoopMerge %237 %238 None - OpBranchConditional %236 %239 %237 - %239 = OpLabel - OpBranch %237 - %238 = OpLabel - OpBranch %234 - %237 = OpLabel - %240 = OpPhi %bool %193 %234 %true %239 - OpSelectionMerge %241 None - OpBranchConditional %240 %199 %241 - %241 = OpLabel - OpBranch %218 - %218 = OpLabel - OpBranch %204 - %204 = OpLabel - OpBranch %195 - %195 = OpLabel - %194 = OpPhi %bool %193 %220 %193 %212 %240 %204 - %197 = OpPhi %int %221 %220 %213 %212 %196 %204 - OpBranch %192 - %199 = OpLabel - %242 = OpPhi %bool %193 %192 %240 %237 %true %211 - OpSelectionMerge %243 None - OpBranchConditional %242 %190 %243 - %243 = OpLabel - OpBranch %190 - %190 = OpLabel - OpSelectionMerge %244 None - OpSwitch %uint_0 %245 - %245 = OpLabel - OpBranch %246 - %246 = OpLabel - %247 = OpPhi %bool %false %245 %248 %249 - %250 = OpPhi %int %int_0 %245 %251 %249 - %252 = OpSLessThanEqual %bool %250 %int_4 - OpLoopMerge %253 %249 None - OpBranchConditional %252 %254 %253 - %254 = OpLabel - %255 = OpAccessChain %_ptr_Function_int %tree %250 %int_0 - %256 = OpLoad %int %255 - %257 = OpSLessThanEqual %bool %int_7 %256 - OpSelectionMerge %258 None - OpBranchConditional %257 %259 %260 - %260 = OpLabel - %261 = OpAccessChain %_ptr_Function_int %tree %250 %int_2 - %262 = OpLoad %int %261 - %263 = OpIEqual %bool %262 %int_n1 - OpSelectionMerge %264 None - OpBranchConditional %263 %265 %266 - %266 = OpLabel - %267 = OpLoad %int %261 - OpBranch %249 - %265 = OpLabel - OpStore %261 %int_4 - %268 = OpAccessChain %_ptr_Function_BST %tree %int_4 - OpStore %268 %56 - OpBranch %253 - %264 = OpLabel - OpUnreachable - %259 = OpLabel - %269 = OpAccessChain %_ptr_Function_int %tree %250 %int_1 - %270 = OpLoad %int %269 - %271 = OpIEqual %bool %270 %int_n1 - OpSelectionMerge %272 None - OpBranchConditional %271 %273 %274 - %274 = OpLabel - %275 = OpLoad %int %269 - OpBranch %249 - %273 = OpLabel - %276 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %277 = OpLoad %float %276 - %278 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_0 - %279 = OpLoad %float %278 - %280 = OpFOrdLessThan %bool %277 %279 - OpSelectionMerge %281 None - OpBranchConditional %280 %282 %281 - %282 = OpLabel - OpBranch %283 - %283 = OpLabel - OpLoopMerge %284 %285 None - OpBranch %286 - %286 = OpLabel - OpKill - %285 = OpLabel - OpBranch %283 - %284 = OpLabel - OpUnreachable - %281 = OpLabel - OpStore %269 %int_4 - %287 = OpAccessChain %_ptr_Function_BST %tree %int_4 - OpStore %287 %56 - OpBranch %288 - %288 = OpLabel - %289 = OpConvertFToS %int %277 - %290 = OpSLessThan %bool %int_0 %289 - OpLoopMerge %291 %292 None - OpBranchConditional %290 %293 %291 - %293 = OpLabel - OpBranch %291 - %292 = OpLabel - OpBranch %288 - %291 = OpLabel - %294 = OpPhi %bool %247 %288 %true %293 - OpSelectionMerge %295 None - OpBranchConditional %294 %253 %295 - %295 = OpLabel - OpBranch %272 - %272 = OpLabel - OpBranch %258 - %258 = OpLabel - OpBranch %249 - %249 = OpLabel - %248 = OpPhi %bool %247 %274 %247 %266 %294 %258 - %251 = OpPhi %int %275 %274 %267 %266 %250 %258 - OpBranch %246 - %253 = OpLabel - %296 = OpPhi %bool %247 %246 %294 %291 %true %265 - OpSelectionMerge %297 None - OpBranchConditional %296 %244 %297 - %297 = OpLabel - OpBranch %244 - %244 = OpLabel - OpSelectionMerge %298 None - OpSwitch %uint_0 %299 - %299 = OpLabel - OpBranch %300 - %300 = OpLabel - %301 = OpPhi %bool %false %299 %302 %303 - %304 = OpPhi %int %int_0 %299 %305 %303 - %306 = OpSLessThanEqual %bool %304 %int_5 - OpLoopMerge %307 %303 None - OpBranchConditional %306 %308 %307 - %308 = OpLabel - %309 = OpAccessChain %_ptr_Function_int %tree %304 %int_0 - %310 = OpLoad %int %309 - %311 = OpSLessThanEqual %bool %int_8 %310 - OpSelectionMerge %312 None - OpBranchConditional %311 %313 %314 - %314 = OpLabel - %315 = OpAccessChain %_ptr_Function_int %tree %304 %int_2 - %316 = OpLoad %int %315 - %317 = OpIEqual %bool %316 %int_n1 - OpSelectionMerge %318 None - OpBranchConditional %317 %319 %320 - %320 = OpLabel - %321 = OpLoad %int %315 - OpBranch %303 - %319 = OpLabel - OpStore %315 %int_5 - %322 = OpAccessChain %_ptr_Function_BST %tree %int_5 - OpStore %322 %57 - OpBranch %307 - %318 = OpLabel - OpUnreachable - %313 = OpLabel - %323 = OpAccessChain %_ptr_Function_int %tree %304 %int_1 - %324 = OpLoad %int %323 - %325 = OpIEqual %bool %324 %int_n1 - OpSelectionMerge %326 None - OpBranchConditional %325 %327 %328 - %328 = OpLabel - %329 = OpLoad %int %323 - OpBranch %303 - %327 = OpLabel - %330 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %331 = OpLoad %float %330 - %332 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_0 - %333 = OpLoad %float %332 - %334 = OpFOrdLessThan %bool %331 %333 - OpSelectionMerge %335 None - OpBranchConditional %334 %336 %335 - %336 = OpLabel - OpBranch %337 - %337 = OpLabel - OpLoopMerge %338 %339 None - OpBranch %340 - %340 = OpLabel - OpKill - %339 = OpLabel - OpBranch %337 - %338 = OpLabel - OpUnreachable - %335 = OpLabel - OpStore %323 %int_5 - %341 = OpAccessChain %_ptr_Function_BST %tree %int_5 - OpStore %341 %57 - OpBranch %342 - %342 = OpLabel - %343 = OpConvertFToS %int %331 - %344 = OpSLessThan %bool %int_0 %343 - OpLoopMerge %345 %346 None - OpBranchConditional %344 %347 %345 - %347 = OpLabel - OpBranch %345 - %346 = OpLabel - OpBranch %342 - %345 = OpLabel - %348 = OpPhi %bool %301 %342 %true %347 - OpSelectionMerge %349 None - OpBranchConditional %348 %307 %349 - %349 = OpLabel - OpBranch %326 - %326 = OpLabel - OpBranch %312 - %312 = OpLabel - OpBranch %303 - %303 = OpLabel - %302 = OpPhi %bool %301 %328 %301 %320 %348 %312 - %305 = OpPhi %int %329 %328 %321 %320 %304 %312 - OpBranch %300 - %307 = OpLabel - %350 = OpPhi %bool %301 %300 %348 %345 %true %319 - OpSelectionMerge %351 None - OpBranchConditional %350 %298 %351 - %351 = OpLabel - OpBranch %298 - %298 = OpLabel - OpSelectionMerge %352 None - OpSwitch %uint_0 %353 - %353 = OpLabel - OpBranch %354 - %354 = OpLabel - %355 = OpPhi %bool %false %353 %356 %357 - %358 = OpPhi %int %int_0 %353 %359 %357 - %360 = OpSLessThanEqual %bool %358 %int_6 - OpLoopMerge %361 %357 None - OpBranchConditional %360 %362 %361 - %362 = OpLabel - %363 = OpAccessChain %_ptr_Function_int %tree %358 %int_0 - %364 = OpLoad %int %363 - %365 = OpSLessThanEqual %bool %int_2 %364 - OpSelectionMerge %366 None - OpBranchConditional %365 %367 %368 - %368 = OpLabel - %369 = OpAccessChain %_ptr_Function_int %tree %358 %int_2 - %370 = OpLoad %int %369 - %371 = OpIEqual %bool %370 %int_n1 - OpSelectionMerge %372 None - OpBranchConditional %371 %373 %374 - %374 = OpLabel - %375 = OpLoad %int %369 - OpBranch %357 - %373 = OpLabel - OpStore %369 %int_6 - %376 = OpAccessChain %_ptr_Function_BST %tree %int_6 - OpStore %376 %58 - OpBranch %361 - %372 = OpLabel - OpUnreachable - %367 = OpLabel - %377 = OpAccessChain %_ptr_Function_int %tree %358 %int_1 - %378 = OpLoad %int %377 - %379 = OpIEqual %bool %378 %int_n1 - OpSelectionMerge %380 None - OpBranchConditional %379 %381 %382 - %382 = OpLabel - %383 = OpLoad %int %377 - OpBranch %357 - %381 = OpLabel - %384 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %385 = OpLoad %float %384 - %386 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_0 - %387 = OpLoad %float %386 - %388 = OpFOrdLessThan %bool %385 %387 - OpSelectionMerge %389 None - OpBranchConditional %388 %390 %389 - %390 = OpLabel - OpBranch %391 - %391 = OpLabel - OpLoopMerge %392 %393 None - OpBranch %394 - %394 = OpLabel - OpKill - %393 = OpLabel - OpBranch %391 - %392 = OpLabel - OpUnreachable - %389 = OpLabel - OpStore %377 %int_6 - %395 = OpAccessChain %_ptr_Function_BST %tree %int_6 - OpStore %395 %58 - OpBranch %396 - %396 = OpLabel - %397 = OpConvertFToS %int %385 - %398 = OpSLessThan %bool %int_0 %397 - OpLoopMerge %399 %400 None - OpBranchConditional %398 %401 %399 - %401 = OpLabel - OpBranch %399 - %400 = OpLabel - OpBranch %396 - %399 = OpLabel - %402 = OpPhi %bool %355 %396 %true %401 - OpSelectionMerge %403 None - OpBranchConditional %402 %361 %403 - %403 = OpLabel - OpBranch %380 - %380 = OpLabel - OpBranch %366 - %366 = OpLabel - OpBranch %357 - %357 = OpLabel - %356 = OpPhi %bool %355 %382 %355 %374 %402 %366 - %359 = OpPhi %int %383 %382 %375 %374 %358 %366 - OpBranch %354 - %361 = OpLabel - %404 = OpPhi %bool %355 %354 %402 %399 %true %373 - OpSelectionMerge %405 None - OpBranchConditional %404 %352 %405 - %405 = OpLabel - OpBranch %352 - %352 = OpLabel - OpSelectionMerge %406 None - OpSwitch %uint_0 %407 - %407 = OpLabel - OpBranch %408 - %408 = OpLabel - %409 = OpPhi %bool %false %407 %410 %411 - %412 = OpPhi %int %int_0 %407 %413 %411 - %414 = OpSLessThanEqual %bool %412 %int_7 - OpLoopMerge %415 %411 None - OpBranchConditional %414 %416 %415 - %416 = OpLabel - %417 = OpAccessChain %_ptr_Function_int %tree %412 %int_0 - %418 = OpLoad %int %417 - %419 = OpSLessThanEqual %bool %int_6 %418 - OpSelectionMerge %420 None - OpBranchConditional %419 %421 %422 - %422 = OpLabel - %423 = OpAccessChain %_ptr_Function_int %tree %412 %int_2 - %424 = OpLoad %int %423 - %425 = OpIEqual %bool %424 %int_n1 - OpSelectionMerge %426 None - OpBranchConditional %425 %427 %428 - %428 = OpLabel - %429 = OpLoad %int %423 - OpBranch %411 - %427 = OpLabel - OpStore %423 %int_7 - %430 = OpAccessChain %_ptr_Function_BST %tree %int_7 - OpStore %430 %59 - OpBranch %415 - %426 = OpLabel - OpUnreachable - %421 = OpLabel - %431 = OpAccessChain %_ptr_Function_int %tree %412 %int_1 - %432 = OpLoad %int %431 - %433 = OpIEqual %bool %432 %int_n1 - OpSelectionMerge %434 None - OpBranchConditional %433 %435 %436 - %436 = OpLabel - %437 = OpLoad %int %431 - OpBranch %411 - %435 = OpLabel - %438 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %439 = OpLoad %float %438 - %440 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_0 - %441 = OpLoad %float %440 - %442 = OpFOrdLessThan %bool %439 %441 - OpSelectionMerge %443 None - OpBranchConditional %442 %444 %443 - %444 = OpLabel - OpBranch %445 - %445 = OpLabel - OpLoopMerge %446 %447 None - OpBranch %448 - %448 = OpLabel - OpKill - %447 = OpLabel - OpBranch %445 - %446 = OpLabel - OpUnreachable - %443 = OpLabel - OpStore %431 %int_7 - %449 = OpAccessChain %_ptr_Function_BST %tree %int_7 - OpStore %449 %59 - OpBranch %450 - %450 = OpLabel - %451 = OpConvertFToS %int %439 - %452 = OpSLessThan %bool %int_0 %451 - OpLoopMerge %453 %454 None - OpBranchConditional %452 %455 %453 - %455 = OpLabel - OpBranch %453 - %454 = OpLabel - OpBranch %450 - %453 = OpLabel - %456 = OpPhi %bool %409 %450 %true %455 - OpSelectionMerge %457 None - OpBranchConditional %456 %415 %457 - %457 = OpLabel - OpBranch %434 - %434 = OpLabel - OpBranch %420 - %420 = OpLabel - OpBranch %411 - %411 = OpLabel - %410 = OpPhi %bool %409 %436 %409 %428 %456 %420 - %413 = OpPhi %int %437 %436 %429 %428 %412 %420 - OpBranch %408 - %415 = OpLabel - %458 = OpPhi %bool %409 %408 %456 %453 %true %427 - OpSelectionMerge %459 None - OpBranchConditional %458 %406 %459 - %459 = OpLabel - OpBranch %406 - %406 = OpLabel - OpSelectionMerge %460 None - OpSwitch %uint_0 %461 - %461 = OpLabel - OpBranch %462 - %462 = OpLabel - %463 = OpPhi %bool %false %461 %464 %465 - %466 = OpPhi %int %int_0 %461 %467 %465 - %468 = OpSLessThanEqual %bool %466 %int_8 - OpLoopMerge %469 %465 None - OpBranchConditional %468 %470 %469 - %470 = OpLabel - %471 = OpAccessChain %_ptr_Function_int %tree %466 %int_0 - %472 = OpLoad %int %471 - %473 = OpSLessThanEqual %bool %int_17 %472 - OpSelectionMerge %474 None - OpBranchConditional %473 %475 %476 - %476 = OpLabel - %477 = OpAccessChain %_ptr_Function_int %tree %466 %int_2 - %478 = OpLoad %int %477 - %479 = OpIEqual %bool %478 %int_n1 - OpSelectionMerge %480 None - OpBranchConditional %479 %481 %482 - %482 = OpLabel - %483 = OpLoad %int %477 - OpBranch %465 - %481 = OpLabel - OpStore %477 %int_8 - %484 = OpAccessChain %_ptr_Function_BST %tree %int_8 - OpStore %484 %60 - OpBranch %469 - %480 = OpLabel - OpUnreachable - %475 = OpLabel - %485 = OpAccessChain %_ptr_Function_int %tree %466 %int_1 - %486 = OpLoad %int %485 - %487 = OpIEqual %bool %486 %int_n1 - OpSelectionMerge %488 None - OpBranchConditional %487 %489 %490 - %490 = OpLabel - %491 = OpLoad %int %485 - OpBranch %465 - %489 = OpLabel - %492 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %493 = OpLoad %float %492 - %494 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_0 - %495 = OpLoad %float %494 - %496 = OpFOrdLessThan %bool %493 %495 - OpSelectionMerge %497 None - OpBranchConditional %496 %498 %497 - %498 = OpLabel - OpBranch %499 - %499 = OpLabel - OpLoopMerge %500 %501 None - OpBranch %502 - %502 = OpLabel - OpKill - %501 = OpLabel - OpBranch %499 - %500 = OpLabel - OpUnreachable - %497 = OpLabel - OpStore %485 %int_8 - %503 = OpAccessChain %_ptr_Function_BST %tree %int_8 - OpStore %503 %60 - OpBranch %504 - %504 = OpLabel - %505 = OpConvertFToS %int %493 - %506 = OpSLessThan %bool %int_0 %505 - OpLoopMerge %507 %508 None - OpBranchConditional %506 %509 %507 - %509 = OpLabel - OpBranch %507 - %508 = OpLabel - OpBranch %504 - %507 = OpLabel - %510 = OpPhi %bool %463 %504 %true %509 - OpSelectionMerge %511 None - OpBranchConditional %510 %469 %511 - %511 = OpLabel - OpBranch %488 - %488 = OpLabel - OpBranch %474 - %474 = OpLabel - OpBranch %465 - %465 = OpLabel - %464 = OpPhi %bool %463 %490 %463 %482 %510 %474 - %467 = OpPhi %int %491 %490 %483 %482 %466 %474 - OpBranch %462 - %469 = OpLabel - %512 = OpPhi %bool %463 %462 %510 %507 %true %481 - OpSelectionMerge %513 None - OpBranchConditional %512 %460 %513 - %513 = OpLabel - OpBranch %460 - %460 = OpLabel - OpSelectionMerge %514 None - OpSwitch %uint_0 %515 - %515 = OpLabel - OpBranch %516 - %516 = OpLabel - %517 = OpPhi %bool %false %515 %518 %519 - %520 = OpPhi %int %int_0 %515 %521 %519 - %522 = OpSLessThanEqual %bool %520 %int_9 - OpLoopMerge %523 %519 None - OpBranchConditional %522 %524 %523 - %524 = OpLabel - %525 = OpAccessChain %_ptr_Function_int %tree %520 %int_0 - %526 = OpLoad %int %525 - %527 = OpSLessThanEqual %bool %int_13 %526 - OpSelectionMerge %528 None - OpBranchConditional %527 %529 %530 - %530 = OpLabel - %531 = OpAccessChain %_ptr_Function_int %tree %520 %int_2 - %532 = OpLoad %int %531 - %533 = OpIEqual %bool %532 %int_n1 - OpSelectionMerge %534 None - OpBranchConditional %533 %535 %536 - %536 = OpLabel - %537 = OpLoad %int %531 - OpBranch %519 - %535 = OpLabel - OpStore %531 %int_9 - %538 = OpAccessChain %_ptr_Function_BST %tree %int_9 - OpStore %538 %61 - OpBranch %523 - %534 = OpLabel - OpUnreachable - %529 = OpLabel - %539 = OpAccessChain %_ptr_Function_int %tree %520 %int_1 - %540 = OpLoad %int %539 - %541 = OpIEqual %bool %540 %int_n1 - OpSelectionMerge %542 None - OpBranchConditional %541 %543 %544 - %544 = OpLabel - %545 = OpLoad %int %539 - OpBranch %519 - %543 = OpLabel - %546 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_1 - %547 = OpLoad %float %546 - %548 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %uint_0 - %549 = OpLoad %float %548 - %550 = OpFOrdLessThan %bool %547 %549 - OpSelectionMerge %551 None - OpBranchConditional %550 %552 %551 - %552 = OpLabel - OpBranch %553 - %553 = OpLabel - OpLoopMerge %554 %555 None - OpBranch %556 - %556 = OpLabel - OpKill - %555 = OpLabel - OpBranch %553 - %554 = OpLabel - OpUnreachable - %551 = OpLabel - OpStore %539 %int_9 - %557 = OpAccessChain %_ptr_Function_BST %tree %int_9 - OpStore %557 %61 - OpBranch %558 - %558 = OpLabel - %559 = OpConvertFToS %int %547 - %560 = OpSLessThan %bool %int_0 %559 - OpLoopMerge %561 %562 None - OpBranchConditional %560 %563 %561 - %563 = OpLabel - OpBranch %561 - %562 = OpLabel - OpBranch %558 - %561 = OpLabel - %564 = OpPhi %bool %517 %558 %true %563 - OpSelectionMerge %565 None - OpBranchConditional %564 %523 %565 - %565 = OpLabel - OpBranch %542 - %542 = OpLabel - OpBranch %528 - %528 = OpLabel - OpBranch %519 - %519 = OpLabel - %518 = OpPhi %bool %517 %544 %517 %536 %564 %528 - %521 = OpPhi %int %545 %544 %537 %536 %520 %528 - OpBranch %516 - %523 = OpLabel - %566 = OpPhi %bool %517 %516 %564 %561 %true %535 - OpSelectionMerge %567 None - OpBranchConditional %566 %514 %567 - %567 = OpLabel - OpBranch %514 - %514 = OpLabel - OpBranch %568 - %568 = OpLabel - %569 = OpPhi %int %49 %514 %570 %571 - %572 = OpPhi %int %int_0 %514 %573 %571 - %574 = OpPhi %int %int_0 %514 %575 %571 - %576 = OpSLessThan %bool %574 %int_20 - OpLoopMerge %577 %571 None - OpBranchConditional %576 %578 %577 - %578 = OpLabel - OpSelectionMerge %579 None - OpSwitch %uint_0 %580 - %580 = OpLabel - OpBranch %581 - %581 = OpLabel - %582 = OpPhi %int %int_0 %580 %583 %584 - %585 = OpINotEqual %bool %582 %int_n1 - OpLoopMerge %586 %584 None - OpBranchConditional %585 %587 %586 - %587 = OpLabel - %588 = OpAccessChain %_ptr_Function_BST %tree %582 - %589 = OpLoad %BST %588 - %590 = OpCompositeExtract %int %589 0 - %591 = OpCompositeExtract %int %589 1 - %592 = OpCompositeExtract %int %589 2 - %593 = OpIEqual %bool %590 %574 - OpSelectionMerge %594 None - OpBranchConditional %593 %595 %594 - %595 = OpLabel - OpBranch %586 - %594 = OpLabel - %596 = OpSGreaterThan %bool %574 %590 - %583 = OpSelect %int %596 %592 %591 - OpBranch %584 - %584 = OpLabel - OpBranch %581 - %586 = OpLabel - %597 = OpPhi %int %569 %581 %574 %595 - %598 = OpPhi %bool %false %581 %true %595 - OpSelectionMerge %599 None - OpBranchConditional %598 %579 %599 - %599 = OpLabel - OpBranch %579 - %579 = OpLabel - %570 = OpPhi %int %597 %586 %int_n1 %599 - OpSelectionMerge %600 None - OpSwitch %574 %601 9 %602 5 %602 12 %602 15 %602 7 %602 8 %602 2 %602 6 %602 17 %602 13 %602 - %602 = OpLabel - %603 = OpIEqual %bool %570 %574 - OpSelectionMerge %604 None - OpBranchConditional %603 %605 %604 - %605 = OpLabel - %606 = OpIAdd %int %572 %int_1 - OpBranch %604 - %604 = OpLabel - %607 = OpPhi %int %572 %602 %606 %605 - OpBranch %600 - %601 = OpLabel - %608 = OpIEqual %bool %570 %int_n1 - OpSelectionMerge %609 None - OpBranchConditional %608 %610 %609 - %610 = OpLabel - %611 = OpIAdd %int %572 %int_1 - OpBranch %609 - %609 = OpLabel - %612 = OpPhi %int %572 %601 %611 %610 - OpBranch %600 - %600 = OpLabel - %573 = OpPhi %int %612 %609 %607 %604 - OpBranch %571 - %571 = OpLabel - %575 = OpIAdd %int %574 %int_1 - OpBranch %568 - %577 = OpLabel - %613 = OpIEqual %bool %572 %int_20 - OpSelectionMerge %614 None - OpBranchConditional %613 %615 %616 - %616 = OpLabel - OpStore %_GLF_color %45 - OpBranch %614 - %615 = OpLabel - OpStore %_GLF_color %44 - OpBranch %614 - %614 = OpLabel - OpReturn - OpFunctionEnd diff --git a/test/tint/vk-gl-cts/graphicsfuzz/stable-binarysearch-tree-false-if-discard-loop/1.wgsl b/test/tint/vk-gl-cts/graphicsfuzz/stable-binarysearch-tree-false-if-discard-loop/1.wgsl deleted file mode 100644 index 8fe63eff80..0000000000 --- a/test/tint/vk-gl-cts/graphicsfuzz/stable-binarysearch-tree-false-if-discard-loop/1.wgsl +++ /dev/null @@ -1,958 +0,0 @@ -struct BST { - data : i32, - leftIndex : i32, - rightIndex : i32, -} - -struct buf0 { - injectionSwitch : vec2, -} - -@group(0) @binding(0) var x_8 : buf0; - -var gl_FragCoord : vec4; - -var x_GLF_color : vec4; - -fn main_1() { - var tree : array; - var x_67 : bool; - var x_114 : bool; - var x_572 : i32; - var x_67_phi : bool; - var x_70_phi : i32; - var x_116_phi : bool; - var x_119_phi : i32; - var x_569_phi : i32; - var x_572_phi : i32; - var x_574_phi : i32; - tree[0] = BST(9, -1, -1); - switch(0u) { - default: { - x_67_phi = false; - x_70_phi = 0; - loop { - var x_95 : i32; - var x_87 : i32; - var x_68 : bool; - var x_71 : i32; - var x_68_phi : bool; - var x_71_phi : i32; - x_67 = x_67_phi; - let x_70 : i32 = x_70_phi; - x_116_phi = x_67; - if ((x_70 <= 1)) { - } else { - break; - } - let x_76 : i32 = tree[x_70].data; - if ((5 <= x_76)) { - var x_114_phi : bool; - let x_89_save = x_70; - let x_90 : i32 = tree[x_89_save].leftIndex; - if ((x_90 == -1)) { - let x_97 : f32 = x_8.injectionSwitch.y; - let x_99 : f32 = x_8.injectionSwitch.x; - if ((x_97 < x_99)) { - loop { - discard; - } - } - tree[x_89_save].leftIndex = 1; - tree[1] = BST(5, -1, -1); - loop { - x_114_phi = x_67; - if ((0 < i32(x_97))) { - } else { - break; - } - x_114_phi = true; - break; - } - x_114 = x_114_phi; - x_116_phi = x_114; - if (x_114) { - break; - } - } else { - x_95 = tree[x_89_save].leftIndex; - x_68_phi = x_67; - x_71_phi = x_95; - continue; - } - } else { - let x_81_save = x_70; - let x_82 : i32 = tree[x_81_save].rightIndex; - if ((x_82 == -1)) { - tree[x_81_save].rightIndex = 1; - tree[1] = BST(5, -1, -1); - x_116_phi = true; - break; - } else { - x_87 = tree[x_81_save].rightIndex; - x_68_phi = x_67; - x_71_phi = x_87; - continue; - } - } - x_68_phi = x_114; - x_71_phi = x_70; - - continuing { - x_68 = x_68_phi; - x_71 = x_71_phi; - x_67_phi = x_68; - x_70_phi = x_71; - } - } - let x_116 : bool = x_116_phi; - if (x_116) { - break; - } - } - } - x_119_phi = 0; - loop { - var x_133 : bool; - var x_120 : i32; - var x_134_phi : bool; - let x_119 : i32 = x_119_phi; - let x_125 : f32 = gl_FragCoord.y; - let x_126 : bool = (x_125 < 0.0); - x_134_phi = x_126; - if (!(x_126)) { - let x_131 : f32 = x_8.injectionSwitch.y; - x_133 = (x_119 != i32(x_131)); - x_134_phi = x_133; - } - let x_134 : bool = x_134_phi; - if (x_134) { - } else { - break; - } - var x_139 : bool; - var x_186 : bool; - var x_139_phi : bool; - var x_142_phi : i32; - var x_188_phi : bool; - switch(0u) { - default: { - x_139_phi = false; - x_142_phi = 0; - loop { - var x_167 : i32; - var x_159 : i32; - var x_140 : bool; - var x_143 : i32; - var x_140_phi : bool; - var x_143_phi : i32; - x_139 = x_139_phi; - let x_142 : i32 = x_142_phi; - x_188_phi = x_139; - if ((x_142 <= 2)) { - } else { - break; - } - let x_148 : i32 = tree[x_142].data; - if ((12 <= x_148)) { - var x_186_phi : bool; - let x_161_save = x_142; - let x_162 : i32 = tree[x_161_save].leftIndex; - if ((x_162 == -1)) { - let x_169 : f32 = x_8.injectionSwitch.y; - let x_171 : f32 = x_8.injectionSwitch.x; - if ((x_169 < x_171)) { - loop { - discard; - } - } - tree[x_161_save].leftIndex = 2; - tree[2] = BST(12, -1, -1); - loop { - x_186_phi = x_139; - if ((0 < i32(x_169))) { - } else { - break; - } - x_186_phi = true; - break; - } - x_186 = x_186_phi; - x_188_phi = x_186; - if (x_186) { - break; - } - } else { - x_167 = tree[x_161_save].leftIndex; - x_140_phi = x_139; - x_143_phi = x_167; - continue; - } - } else { - let x_153_save = x_142; - let x_154 : i32 = tree[x_153_save].rightIndex; - if ((x_154 == -1)) { - tree[x_153_save].rightIndex = 2; - tree[2] = BST(12, -1, -1); - x_188_phi = true; - break; - } else { - x_159 = tree[x_153_save].rightIndex; - x_140_phi = x_139; - x_143_phi = x_159; - continue; - } - } - x_140_phi = x_186; - x_143_phi = x_142; - - continuing { - x_140 = x_140_phi; - x_143 = x_143_phi; - x_139_phi = x_140; - x_142_phi = x_143; - } - } - let x_188 : bool = x_188_phi; - if (x_188) { - break; - } - } - } - - continuing { - x_120 = (x_119 + 1); - x_119_phi = x_120; - } - } - var x_193 : bool; - var x_240 : bool; - var x_193_phi : bool; - var x_196_phi : i32; - var x_242_phi : bool; - switch(0u) { - default: { - x_193_phi = false; - x_196_phi = 0; - loop { - var x_221 : i32; - var x_213 : i32; - var x_194 : bool; - var x_197 : i32; - var x_194_phi : bool; - var x_197_phi : i32; - x_193 = x_193_phi; - let x_196 : i32 = x_196_phi; - x_242_phi = x_193; - if ((x_196 <= 3)) { - } else { - break; - } - let x_202 : i32 = tree[x_196].data; - if ((15 <= x_202)) { - var x_240_phi : bool; - let x_215_save = x_196; - let x_216 : i32 = tree[x_215_save].leftIndex; - if ((x_216 == -1)) { - let x_223 : f32 = x_8.injectionSwitch.y; - let x_225 : f32 = x_8.injectionSwitch.x; - if ((x_223 < x_225)) { - loop { - discard; - } - } - tree[x_215_save].leftIndex = 3; - tree[3] = BST(15, -1, -1); - loop { - x_240_phi = x_193; - if ((0 < i32(x_223))) { - } else { - break; - } - x_240_phi = true; - break; - } - x_240 = x_240_phi; - x_242_phi = x_240; - if (x_240) { - break; - } - } else { - x_221 = tree[x_215_save].leftIndex; - x_194_phi = x_193; - x_197_phi = x_221; - continue; - } - } else { - let x_207_save = x_196; - let x_208 : i32 = tree[x_207_save].rightIndex; - if ((x_208 == -1)) { - tree[x_207_save].rightIndex = 3; - tree[3] = BST(15, -1, -1); - x_242_phi = true; - break; - } else { - x_213 = tree[x_207_save].rightIndex; - x_194_phi = x_193; - x_197_phi = x_213; - continue; - } - } - x_194_phi = x_240; - x_197_phi = x_196; - - continuing { - x_194 = x_194_phi; - x_197 = x_197_phi; - x_193_phi = x_194; - x_196_phi = x_197; - } - } - let x_242 : bool = x_242_phi; - if (x_242) { - break; - } - } - } - var x_247 : bool; - var x_294 : bool; - var x_247_phi : bool; - var x_250_phi : i32; - var x_296_phi : bool; - switch(0u) { - default: { - x_247_phi = false; - x_250_phi = 0; - loop { - var x_275 : i32; - var x_267 : i32; - var x_248 : bool; - var x_251 : i32; - var x_248_phi : bool; - var x_251_phi : i32; - x_247 = x_247_phi; - let x_250 : i32 = x_250_phi; - x_296_phi = x_247; - if ((x_250 <= 4)) { - } else { - break; - } - let x_256 : i32 = tree[x_250].data; - if ((7 <= x_256)) { - var x_294_phi : bool; - let x_269_save = x_250; - let x_270 : i32 = tree[x_269_save].leftIndex; - if ((x_270 == -1)) { - let x_277 : f32 = x_8.injectionSwitch.y; - let x_279 : f32 = x_8.injectionSwitch.x; - if ((x_277 < x_279)) { - loop { - discard; - } - } - tree[x_269_save].leftIndex = 4; - tree[4] = BST(7, -1, -1); - loop { - x_294_phi = x_247; - if ((0 < i32(x_277))) { - } else { - break; - } - x_294_phi = true; - break; - } - x_294 = x_294_phi; - x_296_phi = x_294; - if (x_294) { - break; - } - } else { - x_275 = tree[x_269_save].leftIndex; - x_248_phi = x_247; - x_251_phi = x_275; - continue; - } - } else { - let x_261_save = x_250; - let x_262 : i32 = tree[x_261_save].rightIndex; - if ((x_262 == -1)) { - tree[x_261_save].rightIndex = 4; - tree[4] = BST(7, -1, -1); - x_296_phi = true; - break; - } else { - x_267 = tree[x_261_save].rightIndex; - x_248_phi = x_247; - x_251_phi = x_267; - continue; - } - } - x_248_phi = x_294; - x_251_phi = x_250; - - continuing { - x_248 = x_248_phi; - x_251 = x_251_phi; - x_247_phi = x_248; - x_250_phi = x_251; - } - } - let x_296 : bool = x_296_phi; - if (x_296) { - break; - } - } - } - var x_301 : bool; - var x_348 : bool; - var x_301_phi : bool; - var x_304_phi : i32; - var x_350_phi : bool; - switch(0u) { - default: { - x_301_phi = false; - x_304_phi = 0; - loop { - var x_329 : i32; - var x_321 : i32; - var x_302 : bool; - var x_305 : i32; - var x_302_phi : bool; - var x_305_phi : i32; - x_301 = x_301_phi; - let x_304 : i32 = x_304_phi; - x_350_phi = x_301; - if ((x_304 <= 5)) { - } else { - break; - } - let x_310 : i32 = tree[x_304].data; - if ((8 <= x_310)) { - var x_348_phi : bool; - let x_323_save = x_304; - let x_324 : i32 = tree[x_323_save].leftIndex; - if ((x_324 == -1)) { - let x_331 : f32 = x_8.injectionSwitch.y; - let x_333 : f32 = x_8.injectionSwitch.x; - if ((x_331 < x_333)) { - loop { - discard; - } - } - tree[x_323_save].leftIndex = 5; - tree[5] = BST(8, -1, -1); - loop { - x_348_phi = x_301; - if ((0 < i32(x_331))) { - } else { - break; - } - x_348_phi = true; - break; - } - x_348 = x_348_phi; - x_350_phi = x_348; - if (x_348) { - break; - } - } else { - x_329 = tree[x_323_save].leftIndex; - x_302_phi = x_301; - x_305_phi = x_329; - continue; - } - } else { - let x_315_save = x_304; - let x_316 : i32 = tree[x_315_save].rightIndex; - if ((x_316 == -1)) { - tree[x_315_save].rightIndex = 5; - tree[5] = BST(8, -1, -1); - x_350_phi = true; - break; - } else { - x_321 = tree[x_315_save].rightIndex; - x_302_phi = x_301; - x_305_phi = x_321; - continue; - } - } - x_302_phi = x_348; - x_305_phi = x_304; - - continuing { - x_302 = x_302_phi; - x_305 = x_305_phi; - x_301_phi = x_302; - x_304_phi = x_305; - } - } - let x_350 : bool = x_350_phi; - if (x_350) { - break; - } - } - } - var x_355 : bool; - var x_402 : bool; - var x_355_phi : bool; - var x_358_phi : i32; - var x_404_phi : bool; - switch(0u) { - default: { - x_355_phi = false; - x_358_phi = 0; - loop { - var x_383 : i32; - var x_375 : i32; - var x_356 : bool; - var x_359 : i32; - var x_356_phi : bool; - var x_359_phi : i32; - x_355 = x_355_phi; - let x_358 : i32 = x_358_phi; - x_404_phi = x_355; - if ((x_358 <= 6)) { - } else { - break; - } - let x_364 : i32 = tree[x_358].data; - if ((2 <= x_364)) { - var x_402_phi : bool; - let x_377_save = x_358; - let x_378 : i32 = tree[x_377_save].leftIndex; - if ((x_378 == -1)) { - let x_385 : f32 = x_8.injectionSwitch.y; - let x_387 : f32 = x_8.injectionSwitch.x; - if ((x_385 < x_387)) { - loop { - discard; - } - } - tree[x_377_save].leftIndex = 6; - tree[6] = BST(2, -1, -1); - loop { - x_402_phi = x_355; - if ((0 < i32(x_385))) { - } else { - break; - } - x_402_phi = true; - break; - } - x_402 = x_402_phi; - x_404_phi = x_402; - if (x_402) { - break; - } - } else { - x_383 = tree[x_377_save].leftIndex; - x_356_phi = x_355; - x_359_phi = x_383; - continue; - } - } else { - let x_369_save = x_358; - let x_370 : i32 = tree[x_369_save].rightIndex; - if ((x_370 == -1)) { - tree[x_369_save].rightIndex = 6; - tree[6] = BST(2, -1, -1); - x_404_phi = true; - break; - } else { - x_375 = tree[x_369_save].rightIndex; - x_356_phi = x_355; - x_359_phi = x_375; - continue; - } - } - x_356_phi = x_402; - x_359_phi = x_358; - - continuing { - x_356 = x_356_phi; - x_359 = x_359_phi; - x_355_phi = x_356; - x_358_phi = x_359; - } - } - let x_404 : bool = x_404_phi; - if (x_404) { - break; - } - } - } - var x_409 : bool; - var x_456 : bool; - var x_409_phi : bool; - var x_412_phi : i32; - var x_458_phi : bool; - switch(0u) { - default: { - x_409_phi = false; - x_412_phi = 0; - loop { - var x_437 : i32; - var x_429 : i32; - var x_410 : bool; - var x_413 : i32; - var x_410_phi : bool; - var x_413_phi : i32; - x_409 = x_409_phi; - let x_412 : i32 = x_412_phi; - x_458_phi = x_409; - if ((x_412 <= 7)) { - } else { - break; - } - let x_418 : i32 = tree[x_412].data; - if ((6 <= x_418)) { - var x_456_phi : bool; - let x_431_save = x_412; - let x_432 : i32 = tree[x_431_save].leftIndex; - if ((x_432 == -1)) { - let x_439 : f32 = x_8.injectionSwitch.y; - let x_441 : f32 = x_8.injectionSwitch.x; - if ((x_439 < x_441)) { - loop { - discard; - } - } - tree[x_431_save].leftIndex = 7; - tree[7] = BST(6, -1, -1); - loop { - x_456_phi = x_409; - if ((0 < i32(x_439))) { - } else { - break; - } - x_456_phi = true; - break; - } - x_456 = x_456_phi; - x_458_phi = x_456; - if (x_456) { - break; - } - } else { - x_437 = tree[x_431_save].leftIndex; - x_410_phi = x_409; - x_413_phi = x_437; - continue; - } - } else { - let x_423_save = x_412; - let x_424 : i32 = tree[x_423_save].rightIndex; - if ((x_424 == -1)) { - tree[x_423_save].rightIndex = 7; - tree[7] = BST(6, -1, -1); - x_458_phi = true; - break; - } else { - x_429 = tree[x_423_save].rightIndex; - x_410_phi = x_409; - x_413_phi = x_429; - continue; - } - } - x_410_phi = x_456; - x_413_phi = x_412; - - continuing { - x_410 = x_410_phi; - x_413 = x_413_phi; - x_409_phi = x_410; - x_412_phi = x_413; - } - } - let x_458 : bool = x_458_phi; - if (x_458) { - break; - } - } - } - var x_463 : bool; - var x_510 : bool; - var x_463_phi : bool; - var x_466_phi : i32; - var x_512_phi : bool; - switch(0u) { - default: { - x_463_phi = false; - x_466_phi = 0; - loop { - var x_491 : i32; - var x_483 : i32; - var x_464 : bool; - var x_467 : i32; - var x_464_phi : bool; - var x_467_phi : i32; - x_463 = x_463_phi; - let x_466 : i32 = x_466_phi; - x_512_phi = x_463; - if ((x_466 <= 8)) { - } else { - break; - } - let x_472 : i32 = tree[x_466].data; - if ((17 <= x_472)) { - var x_510_phi : bool; - let x_485_save = x_466; - let x_486 : i32 = tree[x_485_save].leftIndex; - if ((x_486 == -1)) { - let x_493 : f32 = x_8.injectionSwitch.y; - let x_495 : f32 = x_8.injectionSwitch.x; - if ((x_493 < x_495)) { - loop { - discard; - } - } - tree[x_485_save].leftIndex = 8; - tree[8] = BST(17, -1, -1); - loop { - x_510_phi = x_463; - if ((0 < i32(x_493))) { - } else { - break; - } - x_510_phi = true; - break; - } - x_510 = x_510_phi; - x_512_phi = x_510; - if (x_510) { - break; - } - } else { - x_491 = tree[x_485_save].leftIndex; - x_464_phi = x_463; - x_467_phi = x_491; - continue; - } - } else { - let x_477_save = x_466; - let x_478 : i32 = tree[x_477_save].rightIndex; - if ((x_478 == -1)) { - tree[x_477_save].rightIndex = 8; - tree[8] = BST(17, -1, -1); - x_512_phi = true; - break; - } else { - x_483 = tree[x_477_save].rightIndex; - x_464_phi = x_463; - x_467_phi = x_483; - continue; - } - } - x_464_phi = x_510; - x_467_phi = x_466; - - continuing { - x_464 = x_464_phi; - x_467 = x_467_phi; - x_463_phi = x_464; - x_466_phi = x_467; - } - } - let x_512 : bool = x_512_phi; - if (x_512) { - break; - } - } - } - var x_517 : bool; - var x_564 : bool; - var x_517_phi : bool; - var x_520_phi : i32; - var x_566_phi : bool; - switch(0u) { - default: { - x_517_phi = false; - x_520_phi = 0; - loop { - var x_545 : i32; - var x_537 : i32; - var x_518 : bool; - var x_521 : i32; - var x_518_phi : bool; - var x_521_phi : i32; - x_517 = x_517_phi; - let x_520 : i32 = x_520_phi; - x_566_phi = x_517; - if ((x_520 <= 9)) { - } else { - break; - } - let x_526 : i32 = tree[x_520].data; - if ((13 <= x_526)) { - var x_564_phi : bool; - let x_539_save = x_520; - let x_540 : i32 = tree[x_539_save].leftIndex; - if ((x_540 == -1)) { - let x_547 : f32 = x_8.injectionSwitch.y; - let x_549 : f32 = x_8.injectionSwitch.x; - if ((x_547 < x_549)) { - loop { - discard; - } - } - tree[x_539_save].leftIndex = 9; - tree[9] = BST(13, -1, -1); - loop { - x_564_phi = x_517; - if ((0 < i32(x_547))) { - } else { - break; - } - x_564_phi = true; - break; - } - x_564 = x_564_phi; - x_566_phi = x_564; - if (x_564) { - break; - } - } else { - x_545 = tree[x_539_save].leftIndex; - x_518_phi = x_517; - x_521_phi = x_545; - continue; - } - } else { - let x_531_save = x_520; - let x_532 : i32 = tree[x_531_save].rightIndex; - if ((x_532 == -1)) { - tree[x_531_save].rightIndex = 9; - tree[9] = BST(13, -1, -1); - x_566_phi = true; - break; - } else { - x_537 = tree[x_531_save].rightIndex; - x_518_phi = x_517; - x_521_phi = x_537; - continue; - } - } - x_518_phi = x_564; - x_521_phi = x_520; - - continuing { - x_518 = x_518_phi; - x_521 = x_521_phi; - x_517_phi = x_518; - x_520_phi = x_521; - } - } - let x_566 : bool = x_566_phi; - if (x_566) { - break; - } - } - } - x_569_phi = 0; - x_572_phi = 0; - x_574_phi = 0; - loop { - var x_597 : i32; - var x_607 : i32; - var x_612 : i32; - var x_575 : i32; - var x_570_phi : i32; - var x_573_phi : i32; - let x_569 : i32 = x_569_phi; - x_572 = x_572_phi; - let x_574 : i32 = x_574_phi; - if ((x_574 < 20)) { - } else { - break; - } - var x_582_phi : i32; - var x_597_phi : i32; - var x_598_phi : bool; - switch(0u) { - default: { - x_582_phi = 0; - loop { - let x_582 : i32 = x_582_phi; - x_597_phi = x_569; - x_598_phi = false; - if ((x_582 != -1)) { - } else { - break; - } - let x_589 : BST = tree[x_582]; - let x_590 : i32 = x_589.data; - let x_591 : i32 = x_589.leftIndex; - let x_592 : i32 = x_589.rightIndex; - if ((x_590 == x_574)) { - x_597_phi = x_574; - x_598_phi = true; - break; - } - - continuing { - x_582_phi = select(x_591, x_592, (x_574 > x_590)); - } - } - x_597 = x_597_phi; - let x_598 : bool = x_598_phi; - x_570_phi = x_597; - if (x_598) { - break; - } - x_570_phi = -1; - } - } - var x_570 : i32; - var x_606 : i32; - var x_611 : i32; - var x_607_phi : i32; - var x_612_phi : i32; - x_570 = x_570_phi; - switch(x_574) { - case 2, 5, 6, 7, 8, 9, 12, 13, 15, 17: { - x_607_phi = x_572; - if ((x_570 == bitcast(x_574))) { - x_606 = bitcast((x_572 + bitcast(1))); - x_607_phi = x_606; - } - x_607 = x_607_phi; - x_573_phi = x_607; - } - default: { - x_612_phi = x_572; - if ((x_570 == bitcast(-1))) { - x_611 = bitcast((x_572 + bitcast(1))); - x_612_phi = x_611; - } - x_612 = x_612_phi; - x_573_phi = x_612; - } - } - let x_573 : i32 = x_573_phi; - - continuing { - x_575 = (x_574 + 1); - x_569_phi = x_570; - x_572_phi = x_573; - x_574_phi = x_575; - } - } - if ((x_572 == bitcast(20))) { - x_GLF_color = vec4(1.0, 0.0, 0.0, 1.0); - } else { - x_GLF_color = vec4(0.0, 0.0, 1.0, 1.0); - } - return; -} - -struct main_out { - @location(0) - x_GLF_color_1 : vec4, -} - -@fragment -fn main(@builtin(position) gl_FragCoord_param : vec4) -> main_out { - gl_FragCoord = gl_FragCoord_param; - main_1(); - return main_out(x_GLF_color); -}