| // Copyright 2021 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/promote_side_effects_to_decl.h" |
| |
| #include "src/tint/transform/test_helper.h" |
| |
| namespace tint::transform { |
| namespace { |
| |
| using PromoteSideEffectsToDeclTest = TransformTest; |
| |
| TEST_F(PromoteSideEffectsToDeclTest, EmptyModule) { |
| auto* src = ""; |
| auto* expect = ""; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Unary_Arith_SE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| let r = -(a(0)); |
| } |
| )"; |
| |
| auto* expect = src; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_BothSE) { |
| auto* src = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn b() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| let r = a() + b(); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn b() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| let tint_symbol = a(); |
| let tint_symbol_1 = b(); |
| let r = (tint_symbol + tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_LeftSE) { |
| auto* src = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = a() + b; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(); |
| let r = (tint_symbol + b); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_RightSE) { |
| auto* src = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = b + a(); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = b; |
| let tint_symbol_1 = a(); |
| let r = (tint_symbol + tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_LeftmostSE) { |
| auto* src = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| var c = 1; |
| var d = 1; |
| let r = a() + b + c + d; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| var c = 1; |
| var d = 1; |
| let tint_symbol = a(); |
| let r = (((tint_symbol + b) + c) + d); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_RightmostSE) { |
| auto* src = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| var c = 1; |
| var d = 1; |
| let r = b + c + d + a(); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| var c = 1; |
| var d = 1; |
| let tint_symbol = ((b + c) + d); |
| let tint_symbol_1 = a(); |
| let r = (tint_symbol + tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_MiddleSE) { |
| auto* src = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| var c = 1; |
| var d = 1; |
| var e = 1; |
| let r = b + c + a() + d + e; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| var c = 1; |
| var d = 1; |
| var e = 1; |
| let tint_symbol = (b + c); |
| let tint_symbol_1 = a(); |
| let r = (((tint_symbol + tint_symbol_1) + d) + e); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_ThreeSE) { |
| auto* src = R"( |
| fn a(v : i32) -> i32 { |
| return v; |
| } |
| |
| fn f() { |
| let r = a(0) + a(1) + a(2); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(v : i32) -> i32 { |
| return v; |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a(1); |
| let tint_symbol_2 = a(2); |
| let r = ((tint_symbol + tint_symbol_1) + tint_symbol_2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_Constants_NoRecvSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| let r = ((((1 + a(0)) - 2) + 3) - 4); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| let r = ((((1 + tint_symbol) - 2) + 3) - 4); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_Constants_RecvSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = a(0) + 1 + b + a(1) + 2; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = b; |
| let tint_symbol_2 = a(1); |
| let r = ((((tint_symbol + 1) + tint_symbol_1) + tint_symbol_2) + 2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_Constants_ConstAndSEAndVar) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn main() { |
| var b = 1; |
| var c = 1; |
| let r = 1 + a(0) + b; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn main() { |
| var b = 1; |
| var c = 1; |
| let tint_symbol = a(0); |
| let r = ((1 + tint_symbol) + b); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_Constants_VarAndSEAndConst) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn main() { |
| var b = 1; |
| let r = b + a(0) + 1; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn main() { |
| var b = 1; |
| let tint_symbol = b; |
| let tint_symbol_1 = a(0); |
| let r = ((tint_symbol + tint_symbol_1) + 1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_Constants_SEAndVarAndConstAndVar) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn main() { |
| var b = 1; |
| var c = 1; |
| let r = a(0) + b + 1 + c; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn main() { |
| var b = 1; |
| var c = 1; |
| let tint_symbol = a(0); |
| let r = (((tint_symbol + b) + 1) + c); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_Builtins_WithSE) { |
| auto* src = R"( |
| struct SB { |
| a : atomic<i32>, |
| } |
| |
| @group(0) @binding(0) var<storage, read_write> sb : SB; |
| |
| fn f() { |
| var b = 0; |
| let r = atomicAdd(&sb.a, 123) + b; |
| } |
| )"; |
| |
| auto* expect = R"( |
| struct SB { |
| a : atomic<i32>, |
| } |
| |
| @group(0) @binding(0) var<storage, read_write> sb : SB; |
| |
| fn f() { |
| var b = 0; |
| let tint_symbol = atomicAdd(&(sb.a), 123); |
| let r = (tint_symbol + b); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_Builtins_NoSEAndVar) { |
| auto* src = R"( |
| struct SB { |
| a : atomic<i32>, |
| } |
| |
| @group(0) @binding(0) var<storage, read_write> sb : SB; |
| |
| fn f() { |
| var b = 0; |
| let r = (atomicLoad(&(sb.a)) + b); |
| } |
| )"; |
| |
| auto* expect = src; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_Builtins_NoSEAndSE) { |
| auto* src = R"( |
| struct SB { |
| a : atomic<i32>, |
| } |
| |
| @group(0) @binding(0) var<storage, read_write> sb : SB; |
| |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 0; |
| let r = (atomicLoad(&(sb.a)) + a(0)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| struct SB { |
| a : atomic<i32>, |
| } |
| |
| @group(0) @binding(0) var<storage, read_write> sb : SB; |
| |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 0; |
| let tint_symbol = atomicLoad(&(sb.a)); |
| let tint_symbol_1 = a(0); |
| let r = (tint_symbol + tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_Vector_RightSE) { |
| auto* src = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b : vec3<i32>; |
| var c : i32; |
| let r = b[c] + a(); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a() -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b : vec3<i32>; |
| var c : i32; |
| let tint_symbol = c; |
| let tint_symbol_1 = b[tint_symbol]; |
| let tint_symbol_2 = a(); |
| let r = (tint_symbol_1 + tint_symbol_2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InCall) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn g(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = g(a(0)) - g(b + a(1)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn g(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = g(tint_symbol); |
| let tint_symbol_2 = b; |
| let tint_symbol_3 = a(1); |
| let tint_symbol_4 = g((tint_symbol_2 + tint_symbol_3)); |
| let r = (tint_symbol_1 - tint_symbol_4); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InTypeInit) { |
| auto* src = R"( |
| |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = i32(a(0)) + i32(a(1) + b) - i32(a(2) - a(3)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = i32(tint_symbol); |
| let tint_symbol_2 = a(1); |
| let tint_symbol_3 = i32((tint_symbol_2 + b)); |
| let tint_symbol_4 = a(2); |
| let tint_symbol_5 = a(3); |
| let tint_symbol_6 = i32((tint_symbol_4 - tint_symbol_5)); |
| let r = ((tint_symbol_1 + tint_symbol_3) - tint_symbol_6); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InTypeConversion) { |
| auto* src = R"( |
| |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1u; |
| let r = u32(a(0)) + u32(a(1)) - b; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1u; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = u32(tint_symbol); |
| let tint_symbol_2 = a(1); |
| let tint_symbol_3 = u32(tint_symbol_2); |
| let r = ((tint_symbol_1 + tint_symbol_3) - b); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InIntrinsic) { |
| auto* src = R"( |
| |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = abs(a(0)) + abs(a(1) + b) - abs(a(2) + a(3)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = abs(tint_symbol); |
| let tint_symbol_2 = a(1); |
| let tint_symbol_3 = abs((tint_symbol_2 + b)); |
| let tint_symbol_4 = a(2); |
| let tint_symbol_5 = a(3); |
| let tint_symbol_6 = abs((tint_symbol_4 + tint_symbol_5)); |
| let r = ((tint_symbol_1 + tint_symbol_3) - tint_symbol_6); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InMemberAccessor) { |
| auto* src = R"( |
| |
| struct S { |
| v : i32, |
| } |
| |
| fn a(i : i32) -> S { |
| return S(); |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = a(0).v + b + a(1).v; |
| } |
| )"; |
| |
| auto* expect = R"( |
| struct S { |
| v : i32, |
| } |
| |
| fn a(i : i32) -> S { |
| return S(); |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = b; |
| let tint_symbol_2 = a(1); |
| let r = ((tint_symbol.v + tint_symbol_1) + tint_symbol_2.v); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InUnary) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = -a(0) + -(b + a(1)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = -(a(0)); |
| let tint_symbol_1 = b; |
| let tint_symbol_2 = a(1); |
| let r = (tint_symbol + -((tint_symbol_1 + tint_symbol_2))); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InBitcast) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = bitcast<u32>(a(0) + a(1)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a(1); |
| let r = bitcast<u32>((tint_symbol + tint_symbol_1)); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InForLoopInit) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| for(var r = a(0) + b; ; ) { |
| var marker = 0; |
| break; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(0); |
| for(var r = (tint_symbol + b); ; ) { |
| var marker = 0; |
| break; |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InForLoopCond) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| for(; a(0) + b > 0;) { |
| var marker = 0; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| loop { |
| let tint_symbol = a(0); |
| if (!(((tint_symbol + b) > 0))) { |
| break; |
| } |
| { |
| var marker = 0; |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InForLoopCont) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| var r = 0; |
| for(; ; r = a(0) + b) { |
| var marker = 0; |
| break; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| var r = 0; |
| loop { |
| { |
| var marker = 0; |
| break; |
| } |
| |
| continuing { |
| let tint_symbol = a(0); |
| r = (tint_symbol + b); |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InForLoopInitCondCont) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| var c = 2; |
| var d = 3; |
| var r = 0; |
| for(var r = a(0) + b; a(1) + c > 0; r = a(2) + d) { |
| var marker = 0; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| var c = 2; |
| var d = 3; |
| var r = 0; |
| { |
| let tint_symbol = a(0); |
| var r = (tint_symbol + b); |
| loop { |
| let tint_symbol_1 = a(1); |
| if (!(((tint_symbol_1 + c) > 0))) { |
| break; |
| } |
| { |
| var marker = 0; |
| } |
| |
| continuing { |
| let tint_symbol_2 = a(2); |
| r = (tint_symbol_2 + d); |
| } |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InWhileCond) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| while(a(0) + b > 0) { |
| var marker = 0; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| loop { |
| let tint_symbol = a(0); |
| if (!(((tint_symbol + b) > 0))) { |
| break; |
| } |
| { |
| var marker = 0; |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InElseIf) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| if (true) { |
| var marker = 0; |
| } else if (a(0) + b > 0) { |
| var marker = 1; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| if (true) { |
| var marker = 0; |
| } else { |
| let tint_symbol = a(0); |
| if (((tint_symbol + b) > 0)) { |
| var marker = 1; |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InElseIfChain) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| if (true) { |
| var marker = 0; |
| } else if (true) { |
| var marker = 1; |
| } else if (a(0) + b > 0) { |
| var marker = 2; |
| } else if (a(1) + a(2) > 0) { |
| var marker = 3; |
| } else if (true) { |
| var marker = 4; |
| } else { |
| var marker = 5; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| if (true) { |
| var marker = 0; |
| } else if (true) { |
| var marker = 1; |
| } else { |
| let tint_symbol = a(0); |
| if (((tint_symbol + b) > 0)) { |
| var marker = 2; |
| } else { |
| let tint_symbol_1 = a(1); |
| let tint_symbol_2 = a(2); |
| if (((tint_symbol_1 + tint_symbol_2) > 0)) { |
| var marker = 3; |
| } else if (true) { |
| var marker = 4; |
| } else { |
| var marker = 5; |
| } |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InReturn) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() -> i32 { |
| var b = 1; |
| return b + a(0); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() -> i32 { |
| var b = 1; |
| let tint_symbol = b; |
| let tint_symbol_1 = a(0); |
| return (tint_symbol + tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Arith_InSwitch) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| switch (b + a(0)) { |
| default: { |
| } |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = b; |
| let tint_symbol_1 = a(0); |
| switch((tint_symbol + tint_symbol_1)) { |
| default: { |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_LeftSE) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let r = a(0) && b; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = b; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_RightSE) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let r = b && a(0); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var tint_symbol = b; |
| if (tint_symbol) { |
| tint_symbol = a(0); |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_BothSE) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| let r = a(0) && a(1); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = a(1); |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_LeftmostSE) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| let r = a(0) && b && c && d; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| var tint_symbol_2 = a(0); |
| if (tint_symbol_2) { |
| tint_symbol_2 = b; |
| } |
| var tint_symbol_1 = tint_symbol_2; |
| if (tint_symbol_1) { |
| tint_symbol_1 = c; |
| } |
| var tint_symbol = tint_symbol_1; |
| if (tint_symbol) { |
| tint_symbol = d; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_RightmostSE) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| let r = b && c && d && a(0); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| var tint_symbol = ((b && c) && d); |
| if (tint_symbol) { |
| tint_symbol = a(0); |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_MiddleSE) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| let r = b && c && a(0) && c && d; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| var tint_symbol_2 = (b && c); |
| if (tint_symbol_2) { |
| tint_symbol_2 = a(0); |
| } |
| var tint_symbol_1 = tint_symbol_2; |
| if (tint_symbol_1) { |
| tint_symbol_1 = c; |
| } |
| var tint_symbol = tint_symbol_1; |
| if (tint_symbol) { |
| tint_symbol = d; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_Constants_NoRecvSE) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| let r = true && a(0) && false && a(1); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var tint_symbol_2 = true; |
| if (tint_symbol_2) { |
| tint_symbol_2 = a(0); |
| } |
| var tint_symbol_1 = tint_symbol_2; |
| if (tint_symbol_1) { |
| tint_symbol_1 = false; |
| } |
| var tint_symbol = tint_symbol_1; |
| if (tint_symbol) { |
| tint_symbol = a(1); |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_Constants_RecvSE) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let r = b && true && a(0) && false && a(1); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var tint_symbol_2 = (b && true); |
| if (tint_symbol_2) { |
| tint_symbol_2 = a(0); |
| } |
| var tint_symbol_1 = tint_symbol_2; |
| if (tint_symbol_1) { |
| tint_symbol_1 = false; |
| } |
| var tint_symbol = tint_symbol_1; |
| if (tint_symbol) { |
| tint_symbol = a(1); |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_Constants_ConstAndSEAndVar) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn main() { |
| var b = true; |
| var c = true; |
| let r = true && a(0) && b; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn main() { |
| var b = true; |
| var c = true; |
| var tint_symbol_1 = true; |
| if (tint_symbol_1) { |
| tint_symbol_1 = a(0); |
| } |
| var tint_symbol = tint_symbol_1; |
| if (tint_symbol) { |
| tint_symbol = b; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_Constants_VarAndSEAndConst) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn main() { |
| var b = true; |
| let r = b && a(0) && true; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn main() { |
| var b = true; |
| var tint_symbol_1 = b; |
| if (tint_symbol_1) { |
| tint_symbol_1 = a(0); |
| } |
| var tint_symbol = tint_symbol_1; |
| if (tint_symbol) { |
| tint_symbol = true; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_Constants_SEAndVarAndConstAndVar) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn main() { |
| var b = true; |
| var c = true; |
| let r = a(0) && b && true && c; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn main() { |
| var b = true; |
| var c = true; |
| var tint_symbol_2 = a(0); |
| if (tint_symbol_2) { |
| tint_symbol_2 = b; |
| } |
| var tint_symbol_1 = tint_symbol_2; |
| if (tint_symbol_1) { |
| tint_symbol_1 = true; |
| } |
| var tint_symbol = tint_symbol_1; |
| if (tint_symbol) { |
| tint_symbol = c; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_MixedSE) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| let r = (b && a(0)) || (c && a(1) && c && d) || a(2); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| var tint_symbol_2 = b; |
| if (tint_symbol_2) { |
| tint_symbol_2 = a(0); |
| } |
| var tint_symbol_1 = tint_symbol_2; |
| if (!(tint_symbol_1)) { |
| var tint_symbol_5 = c; |
| if (tint_symbol_5) { |
| tint_symbol_5 = a(1); |
| } |
| var tint_symbol_4 = tint_symbol_5; |
| if (tint_symbol_4) { |
| tint_symbol_4 = c; |
| } |
| var tint_symbol_3 = tint_symbol_4; |
| if (tint_symbol_3) { |
| tint_symbol_3 = d; |
| } |
| tint_symbol_1 = tint_symbol_3; |
| } |
| var tint_symbol = tint_symbol_1; |
| if (!(tint_symbol)) { |
| tint_symbol = a(2); |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_NestedAnds) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| let r = a(0) && (a(1) && (a(2) && (a(3) && (a(4) && a(5))))); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| var tint_symbol_1 = a(1); |
| if (tint_symbol_1) { |
| var tint_symbol_2 = a(2); |
| if (tint_symbol_2) { |
| var tint_symbol_3 = a(3); |
| if (tint_symbol_3) { |
| var tint_symbol_4 = a(4); |
| if (tint_symbol_4) { |
| tint_symbol_4 = a(5); |
| } |
| tint_symbol_3 = tint_symbol_4; |
| } |
| tint_symbol_2 = tint_symbol_3; |
| } |
| tint_symbol_1 = tint_symbol_2; |
| } |
| tint_symbol = tint_symbol_1; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_NestedOrs) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| let r = a(0) || (a(1) || (a(2) || (a(3) || (a(4) || a(5))))); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var tint_symbol = a(0); |
| if (!(tint_symbol)) { |
| var tint_symbol_1 = a(1); |
| if (!(tint_symbol_1)) { |
| var tint_symbol_2 = a(2); |
| if (!(tint_symbol_2)) { |
| var tint_symbol_3 = a(3); |
| if (!(tint_symbol_3)) { |
| var tint_symbol_4 = a(4); |
| if (!(tint_symbol_4)) { |
| tint_symbol_4 = a(5); |
| } |
| tint_symbol_3 = tint_symbol_4; |
| } |
| tint_symbol_2 = tint_symbol_3; |
| } |
| tint_symbol_1 = tint_symbol_2; |
| } |
| tint_symbol = tint_symbol_1; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_MultipleStatements) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let r1 = b && a(0); |
| let r2 = a(1) || b; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var tint_symbol = b; |
| if (tint_symbol) { |
| tint_symbol = a(0); |
| } |
| let r1 = tint_symbol; |
| var tint_symbol_1 = a(1); |
| if (!(tint_symbol_1)) { |
| tint_symbol_1 = b; |
| } |
| let r2 = tint_symbol_1; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InCall) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(v : bool) -> bool { |
| return v; |
| } |
| |
| fn f() { |
| var b = true; |
| g(b && a(1)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(v : bool) -> bool { |
| return v; |
| } |
| |
| fn f() { |
| var b = true; |
| var tint_symbol = b; |
| if (tint_symbol) { |
| tint_symbol = a(1); |
| } |
| g(tint_symbol); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InTypeInit) { |
| auto* src = R"( |
| |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let r = (bool(a(0)) && bool(a(1) && b)) || bool(a(2) && a(3)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let tint_symbol_2 = a(0); |
| var tint_symbol_1 = bool(tint_symbol_2); |
| if (tint_symbol_1) { |
| var tint_symbol_3 = a(1); |
| if (tint_symbol_3) { |
| tint_symbol_3 = b; |
| } |
| tint_symbol_1 = bool(tint_symbol_3); |
| } |
| var tint_symbol = tint_symbol_1; |
| if (!(tint_symbol)) { |
| var tint_symbol_4 = a(2); |
| if (tint_symbol_4) { |
| tint_symbol_4 = a(3); |
| } |
| tint_symbol = bool(tint_symbol_4); |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InTypeConversion) { |
| auto* src = R"( |
| |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = true; |
| let r = (bool(a(0)) && bool(a(1))) || b; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = true; |
| let tint_symbol_2 = a(0); |
| var tint_symbol_1 = bool(tint_symbol_2); |
| if (tint_symbol_1) { |
| let tint_symbol_3 = a(1); |
| tint_symbol_1 = bool(tint_symbol_3); |
| } |
| var tint_symbol = tint_symbol_1; |
| if (!(tint_symbol)) { |
| tint_symbol = b; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| // Make sure we process logical binary expressions of non-logical binary |
| // expressions. |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_OfNonLogical) { |
| auto* src = R"( |
| |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = bool(a(0) == b) && bool(a(1) == b); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol_1 = a(0); |
| var tint_symbol = bool((tint_symbol_1 == b)); |
| if (tint_symbol) { |
| let tint_symbol_2 = a(1); |
| tint_symbol = bool((tint_symbol_2 == b)); |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InIntrinsic) { |
| auto* src = R"( |
| |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let r = (all(a(0)) && all(a(1) && b)) || all(a(2) && a(3)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let tint_symbol_2 = a(0); |
| var tint_symbol_1 = all(tint_symbol_2); |
| if (tint_symbol_1) { |
| var tint_symbol_3 = a(1); |
| if (tint_symbol_3) { |
| tint_symbol_3 = b; |
| } |
| tint_symbol_1 = all(tint_symbol_3); |
| } |
| var tint_symbol = tint_symbol_1; |
| if (!(tint_symbol)) { |
| var tint_symbol_4 = a(2); |
| if (tint_symbol_4) { |
| tint_symbol_4 = a(3); |
| } |
| tint_symbol = all(tint_symbol_4); |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InMemberAccessor) { |
| auto* src = R"( |
| |
| struct S { |
| v : bool, |
| } |
| |
| fn a(i : i32) -> S { |
| return S(); |
| } |
| |
| fn f() { |
| var b = true; |
| let r = a(0).v && b && a(1).v; |
| } |
| )"; |
| |
| auto* expect = R"( |
| struct S { |
| v : bool, |
| } |
| |
| fn a(i : i32) -> S { |
| return S(); |
| } |
| |
| fn f() { |
| var b = true; |
| let tint_symbol_2 = a(0); |
| var tint_symbol_1 = tint_symbol_2.v; |
| if (tint_symbol_1) { |
| tint_symbol_1 = b; |
| } |
| var tint_symbol = tint_symbol_1; |
| if (tint_symbol) { |
| let tint_symbol_3 = a(1); |
| tint_symbol = tint_symbol_3.v; |
| } |
| let r = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InUnary) { |
| auto* src = R"( |
| |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let r = !(b || a(1)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var tint_symbol = b; |
| if (!(tint_symbol)) { |
| tint_symbol = a(1); |
| } |
| let r = !(tint_symbol); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InBitcast) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| let r = bitcast<u32>(i32(a(0) && a(1))); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = a(1); |
| } |
| let r = bitcast<u32>(i32(tint_symbol)); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InForLoopInit) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| for(var r = a(0) && b; ; ) { |
| var marker = 0; |
| break; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = b; |
| } |
| for(var r = tint_symbol; ; ) { |
| var marker = 0; |
| break; |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InForLoopCond) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| for(; a(0) && b;) { |
| var marker = 0; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| loop { |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = b; |
| } |
| if (!(tint_symbol)) { |
| break; |
| } |
| { |
| var marker = 0; |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InForLoopCont) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var r = true; |
| for(; ; r = a(0) && b) { |
| var marker = 0; |
| break; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var r = true; |
| loop { |
| { |
| var marker = 0; |
| break; |
| } |
| |
| continuing { |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = b; |
| } |
| r = tint_symbol; |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InForLoopInitCondCont) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| var r = true; |
| for(var r = a(0) && b; a(1) && c; r = a(2) && d) { |
| var marker = 0; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| var c = true; |
| var d = true; |
| var r = true; |
| { |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = b; |
| } |
| var r = tint_symbol; |
| loop { |
| var tint_symbol_1 = a(1); |
| if (tint_symbol_1) { |
| tint_symbol_1 = c; |
| } |
| if (!(tint_symbol_1)) { |
| break; |
| } |
| { |
| var marker = 0; |
| } |
| |
| continuing { |
| var tint_symbol_2 = a(2); |
| if (tint_symbol_2) { |
| tint_symbol_2 = d; |
| } |
| r = tint_symbol_2; |
| } |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InWhileCond) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| while(a(0) && b) { |
| var marker = 0; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| loop { |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = b; |
| } |
| if (!(tint_symbol)) { |
| break; |
| } |
| { |
| var marker = 0; |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InElseIf) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| if (true) { |
| var marker = 0; |
| } else if (a(0) && b) { |
| var marker = 1; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| if (true) { |
| var marker = 0; |
| } else { |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = b; |
| } |
| if (tint_symbol) { |
| var marker = 1; |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Logical_InElseIfChain) { |
| auto* src = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| if (true) { |
| var marker = 0; |
| } else if (true) { |
| var marker = 1; |
| } else if (a(0) && b) { |
| var marker = 2; |
| } else if (a(1) && a(2)) { |
| var marker = 3; |
| } else if (true) { |
| var marker = 4; |
| } else { |
| var marker = 5; |
| } |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> bool { |
| return true; |
| } |
| |
| fn f() { |
| var b = true; |
| if (true) { |
| var marker = 0; |
| } else if (true) { |
| var marker = 1; |
| } else { |
| var tint_symbol = a(0); |
| if (tint_symbol) { |
| tint_symbol = b; |
| } |
| if (tint_symbol) { |
| var marker = 2; |
| } else { |
| var tint_symbol_1 = a(1); |
| if (tint_symbol_1) { |
| tint_symbol_1 = a(2); |
| } |
| if (tint_symbol_1) { |
| var marker = 3; |
| } else if (true) { |
| var marker = 4; |
| } else { |
| var marker = 5; |
| } |
| } |
| } |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Call_NoSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn g(a : i32, b : i32, c : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| var c = 1; |
| let r = g(b, c, 3); |
| } |
| )"; |
| |
| auto* expect = src; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Call_OneSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn g(a : i32, b : i32, c : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let r = g(a(0), b, 3); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn g(a : i32, b : i32, c : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(0); |
| let r = g(tint_symbol, b, 3); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Call_AllSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn g(a : i32, b : i32, c : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| let r = g(a(0), a(1), a(2)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn g(a : i32, b : i32, c : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a(1); |
| let tint_symbol_2 = a(2); |
| let r = g(tint_symbol, tint_symbol_1, tint_symbol_2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Call_MiddleNotSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn g(a : i32, b : i32, c : i32) -> i32 { |
| return 1; |
| } |
| |
| |
| fn f() { |
| var b = 1; |
| let r = g(a(0), b, a(1)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn g(a : i32, b : i32, c : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 1; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = b; |
| let tint_symbol_2 = a(1); |
| let r = g(tint_symbol, tint_symbol_1, tint_symbol_2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Call_InBinary) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn g(i : i32, j : i32, k : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 0; |
| var c = 0; |
| var d = 0; |
| let r = b + g(c, a(0), d) + a(1); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn g(i : i32, j : i32, k : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = 0; |
| var c = 0; |
| var d = 0; |
| let tint_symbol = b; |
| let tint_symbol_1 = c; |
| let tint_symbol_2 = a(0); |
| let tint_symbol_3 = g(tint_symbol_1, tint_symbol_2, d); |
| let tint_symbol_4 = a(1); |
| let r = ((tint_symbol + tint_symbol_3) + tint_symbol_4); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor_2D_LeftSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<i32, 10>, 10>(); |
| var c = 1; |
| var r = b[a(0)][c]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<i32, 10>, 10>(); |
| var c = 1; |
| let tint_symbol = a(0); |
| var r = b[tint_symbol][c]; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor_2D_RightSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<i32, 10>, 10>(); |
| var c = 1; |
| let tint_symbol = c; |
| let tint_symbol_1 = a(0); |
| var r = b[tint_symbol][tint_symbol_1]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<i32, 10>, 10>(); |
| var c = 1; |
| let tint_symbol = c; |
| let tint_symbol_1 = a(0); |
| var r = b[tint_symbol][tint_symbol_1]; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor_2D_BothSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<i32, 10>, 10>(); |
| var r = b[a(0)][a(1)]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<i32, 10>, 10>(); |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a(1); |
| var r = b[tint_symbol][tint_symbol_1]; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Assignment_ToPhony) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| _ = a(0); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| _ = a(0); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Assignment_ToArray1D) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<i32, 10>(); |
| b[a(0)] = a(1); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<i32, 10>(); |
| let tint_symbol = a(1); |
| let tint_symbol_1 = a(0); |
| b[tint_symbol_1] = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Assignment_ToArray2D) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<i32, 10>, 10>(); |
| b[a(0)][a(1)] = a(2); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<i32, 10>, 10>(); |
| let tint_symbol = a(2); |
| let tint_symbol_1 = a(0); |
| let tint_symbol_2 = a(1); |
| b[tint_symbol_1][tint_symbol_2] = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Assignment_ToArray3D) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<array<i32, 10>, 10>, 10>(); |
| b[a(0)][a(1)][a(2)] = a(3); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<array<array<i32, 10>, 10>, 10>(); |
| let tint_symbol = a(3); |
| let tint_symbol_1 = a(0); |
| let tint_symbol_2 = a(1); |
| let tint_symbol_3 = a(2); |
| b[tint_symbol_1][tint_symbol_2][tint_symbol_3] = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Assignment_ToArray_FromArray) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<i32, 3>(); |
| var d = array<array<i32, 3>, 3>(); |
| var a_1 = 0; |
| b[a(2)] = d[a(0)][a_1]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = array<i32, 3>(); |
| var d = array<array<i32, 3>, 3>(); |
| var a_1 = 0; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a_1; |
| let tint_symbol_2 = d[tint_symbol][tint_symbol_1]; |
| let tint_symbol_3 = a(2); |
| b[tint_symbol_3] = tint_symbol_2; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Assignment_ToVec_BothSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = vec3<i32>(); |
| b[a(0)] = a(1); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = vec3<i32>(); |
| let tint_symbol = a(1); |
| let tint_symbol_1 = a(0); |
| b[tint_symbol_1] = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Assignment_ToVec_LeftSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = vec3<i32>(); |
| var c = 0; |
| b[a(0)] = c; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = vec3<i32>(); |
| var c = 0; |
| let tint_symbol = c; |
| let tint_symbol_1 = a(0); |
| b[tint_symbol_1] = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Assignment_ToVec_RightSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = vec3<i32>(); |
| var c = 0; |
| b[c] = a(0); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var b = vec3<i32>(); |
| var c = 0; |
| let tint_symbol = a(0); |
| b[c] = tint_symbol; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, TypeInitializer_Struct) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| struct S { |
| x : i32, |
| y : i32, |
| z : i32, |
| } |
| |
| fn f() { |
| var r = S(a(0), a(1), a(2)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| struct S { |
| x : i32, |
| y : i32, |
| z : i32, |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a(1); |
| let tint_symbol_2 = a(2); |
| var r = S(tint_symbol, tint_symbol_1, tint_symbol_2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, TypeInitializer_Array1D) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var r = array<i32, 3>(a(0), a(1), a(2)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a(1); |
| let tint_symbol_2 = a(2); |
| var r = array<i32, 3>(tint_symbol, tint_symbol_1, tint_symbol_2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, TypeInitializer_Array2D) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| var r = array<array<i32, 2>, 2>(array<i32, 2>(a(0), a(1)), array<i32, 2>(a(2), a(3))); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 1; |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a(1); |
| let tint_symbol_2 = array<i32, 2>(tint_symbol, tint_symbol_1); |
| let tint_symbol_3 = a(2); |
| let tint_symbol_4 = a(3); |
| let tint_symbol_5 = array<i32, 2>(tint_symbol_3, tint_symbol_4); |
| var r = array<array<i32, 2>, 2>(tint_symbol_2, tint_symbol_5); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, MemberAccessor_Vec) { |
| auto* src = R"( |
| fn a(i : i32) -> vec3<i32> { |
| return vec3<i32>(); |
| } |
| |
| fn f() { |
| var r = a(0).x + a(1).y; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> vec3<i32> { |
| return vec3<i32>(); |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a(1); |
| var r = (tint_symbol.x + tint_symbol_1.y); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, MemberAccessor_Struct) { |
| auto* src = R"( |
| struct S { |
| x : i32, |
| y : i32, |
| } |
| |
| fn a(i : i32) -> S { |
| return S(); |
| } |
| |
| fn f() { |
| var r = a(0).x + a(1).y; |
| } |
| )"; |
| |
| auto* expect = R"( |
| struct S { |
| x : i32, |
| y : i32, |
| } |
| |
| fn a(i : i32) -> S { |
| return S(); |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| let tint_symbol_1 = a(1); |
| var r = (tint_symbol.x + tint_symbol_1.y); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, MemberAccessor_Struct_Mixed) { |
| auto* src = R"( |
| struct S { |
| x : i32, |
| y : i32, |
| arr : array<i32, 10>, |
| } |
| |
| fn a(i : i32) -> S { |
| return S(); |
| } |
| |
| fn b(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| var i = 0; |
| var j = 0; |
| var k = 0; |
| var l = 0; |
| var m = 0; |
| var r = a(0).x + i + a(1).y + j + a(2).arr[k + b(3) + l] + m; |
| } |
| )"; |
| |
| auto* expect = R"( |
| struct S { |
| x : i32, |
| y : i32, |
| arr : array<i32, 10>, |
| } |
| |
| fn a(i : i32) -> S { |
| return S(); |
| } |
| |
| fn b(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| var i = 0; |
| var j = 0; |
| var k = 0; |
| var l = 0; |
| var m = 0; |
| let tint_symbol = a(0); |
| let tint_symbol_1 = i; |
| let tint_symbol_2 = a(1); |
| let tint_symbol_3 = j; |
| let tint_symbol_4 = a(2); |
| let tint_symbol_5 = k; |
| let tint_symbol_6 = b(3); |
| var r = (((((tint_symbol.x + tint_symbol_1) + tint_symbol_2.y) + tint_symbol_3) + tint_symbol_4.arr[((tint_symbol_5 + tint_symbol_6) + l)]) + m); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor_Plus_SE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| let r = v[0] + a(0); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| let tint_symbol = v[0]; |
| let tint_symbol_1 = a(0); |
| let r = (tint_symbol + tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor_Of_SE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| let r = v[a(0)]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| let tint_symbol = a(0); |
| let r = v[tint_symbol]; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor2_Of_LeftSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<array<i32, 10>, 10>(); |
| let r = v[a(0)][0]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<array<i32, 10>, 10>(); |
| let tint_symbol = a(0); |
| let r = v[tint_symbol][0]; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor2_Of_RightSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<array<i32, 10>, 10>(); |
| let r = v[0][a(0)]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<array<i32, 10>, 10>(); |
| let tint_symbol = a(0); |
| let r = v[0][tint_symbol]; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor2_Of_SEAndVar) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<array<i32, 10>, 10>(); |
| var b : i32; |
| let r = v[a(0)][b]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<array<i32, 10>, 10>(); |
| var b : i32; |
| let tint_symbol = a(0); |
| let r = v[tint_symbol][b]; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor2_Of_VarAndSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<array<i32, 10>, 10>(); |
| var b : i32; |
| let r = v[b][a(0)]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<array<i32, 10>, 10>(); |
| var b : i32; |
| let tint_symbol = b; |
| let tint_symbol_1 = a(0); |
| let r = v[tint_symbol][tint_symbol_1]; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessorOfVar_Plus_SE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| var b = 0; |
| let r = v[b] + a(0); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| var b = 0; |
| let tint_symbol = b; |
| let tint_symbol_1 = v[tint_symbol]; |
| let tint_symbol_2 = a(0); |
| let r = (tint_symbol_1 + tint_symbol_2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessor_Plus_IndexAccessorOfSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| let r = v[0] + v[a(0)]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| let tint_symbol = v[0]; |
| let tint_symbol_1 = a(0); |
| let r = (tint_symbol + v[tint_symbol_1]); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, AssignTo_IndexAccessorOfIndexAccessorOfSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| var w = array<i32, 10>(); |
| v[w[a(0)]] = 1; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| var w = array<i32, 10>(); |
| let tint_symbol = a(0); |
| v[w[tint_symbol]] = 1; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, AssignTo_IndexAccessorOfIndexAccessorOfLiteralPlusSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| var w = array<i32, 10>(); |
| v[w[0] + a(0)] = 1; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| var w = array<i32, 10>(); |
| let tint_symbol = w[0]; |
| let tint_symbol_1 = a(0); |
| v[(tint_symbol + tint_symbol_1)] = 1; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, |
| AssignTo_IndexAccessorOfIndexAccessorOfLiteralPlusIndexAccessorOfSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| var w = array<i32, 10>(); |
| v[w[0] + w[a(0)]] = 1; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn f() { |
| var v = array<i32, 10>(); |
| var w = array<i32, 10>(); |
| let tint_symbol = w[0]; |
| let tint_symbol_1 = a(0); |
| v[(tint_symbol + w[tint_symbol_1])] = 1; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, IndexAccessorOfLhsSERhsSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn b() -> array<i32, 10> { |
| return array<i32, 10>(); |
| } |
| |
| fn f() { |
| let r = b()[a(0)]; |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn b() -> array<i32, 10> { |
| return array<i32, 10>(); |
| } |
| |
| fn f() { |
| let tint_symbol = b(); |
| let tint_symbol_1 = a(0); |
| let r = tint_symbol[tint_symbol_1]; |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, BinaryIndexAccessorOfLhsSERhsSE) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn b() -> array<i32, 10> { |
| return array<i32, 10>(); |
| } |
| |
| fn f() { |
| let r = b()[0] + a(0); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return i; |
| } |
| |
| fn b() -> array<i32, 10> { |
| return array<i32, 10>(); |
| } |
| |
| fn f() { |
| let tint_symbol = b(); |
| let tint_symbol_1 = a(0); |
| let r = (tint_symbol[0] + tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, BinaryMemberAccessorPlusSE) { |
| // bclayton@'s example: |
| // https://dawn-review.googlesource.com/c/tint/+/78620/6..8/src/transform/promote_side_effects_to_decl.cc#b490 |
| auto* src = R"( |
| fn modify_vec(p : ptr<function, vec4<i32>>) -> i32 { |
| (*p).x = 42; |
| return 0; |
| } |
| |
| fn f() { |
| var v = vec4<i32>(); |
| let l = v.x + modify_vec(&v); |
| // l should be 0, not 42 |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn modify_vec(p : ptr<function, vec4<i32>>) -> i32 { |
| (*(p)).x = 42; |
| return 0; |
| } |
| |
| fn f() { |
| var v = vec4<i32>(); |
| let tint_symbol = v.x; |
| let tint_symbol_1 = modify_vec(&(v)); |
| let l = (tint_symbol + tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Call_ReadOnlyArgAndSE) { |
| // Make sure that read-only args don't get hoisted (tex and samp) |
| auto* src = R"( |
| @group(1) @binding(1) var tex: texture_2d_array<u32>; |
| @group(1) @binding(2) var samp: sampler; |
| |
| fn get_uv() -> vec2<f32> { |
| return vec2<f32>(1.0, 2.0); |
| } |
| |
| fn f() { |
| let r = textureGather(1, tex, samp, get_uv(), 1); |
| } |
| )"; |
| |
| auto* expect = R"( |
| @group(1) @binding(1) var tex : texture_2d_array<u32>; |
| |
| @group(1) @binding(2) var samp : sampler; |
| |
| fn get_uv() -> vec2<f32> { |
| return vec2<f32>(1.0, 2.0); |
| } |
| |
| fn f() { |
| let tint_symbol = get_uv(); |
| let r = textureGather(1, tex, samp, tint_symbol, 1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Call_PtrArgAndSE) { |
| // Make sure that read-only args don't get hoisted (tex and samp) |
| auto* src = R"( |
| |
| var<private> b : i32 = 0; |
| |
| fn a(i : i32) -> i32 { |
| b = 42; |
| return 0; |
| } |
| |
| fn g(i : ptr<private, i32>, j : i32) -> i32 { |
| return *i; |
| } |
| |
| fn f() { |
| // a(0) should be hoisted, but not &b |
| let r = g(&b, a(0)); |
| // r should be 42 |
| } |
| )"; |
| |
| auto* expect = R"( |
| var<private> b : i32 = 0; |
| |
| fn a(i : i32) -> i32 { |
| b = 42; |
| return 0; |
| } |
| |
| fn g(i : ptr<private, i32>, j : i32) -> i32 { |
| return *(i); |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| let r = g(&(b), tint_symbol); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, TypeInit_VarPlusI32InitPlusVar) { |
| auto* src = R"( |
| fn f() { |
| var b = 0; |
| var c = 0; |
| var d = 0; |
| let r = ((b + i32(c)) + d); |
| } |
| )"; |
| |
| auto* expect = src; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Mixed_ArithPlusLogical) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(i : bool) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| let r = a(0) + g(b(1) && b(2)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(i : bool) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| var tint_symbol_1 = b(1); |
| if (tint_symbol_1) { |
| tint_symbol_1 = b(2); |
| } |
| let tint_symbol_2 = g(tint_symbol_1); |
| let r = (tint_symbol + tint_symbol_2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Mixed_LogicalPlusArith) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(i : bool) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| let r = g(b(0) && b(1)) + a(2); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(i : bool) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| var tint_symbol = b(0); |
| if (tint_symbol) { |
| tint_symbol = b(1); |
| } |
| let tint_symbol_1 = g(tint_symbol); |
| let tint_symbol_2 = a(2); |
| let r = (tint_symbol_1 + tint_symbol_2); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Mixed_ArithAndLogicalArgs) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(i : i32, j : bool) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| let r = g(a(0), b(1) && b(2)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(i : i32, j : bool) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| var tint_symbol_1 = b(1); |
| if (tint_symbol_1) { |
| tint_symbol_1 = b(2); |
| } |
| let r = g(tint_symbol, tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Mixed_LogicalAndArithArgs) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(i : bool, j : i32) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| let r = g(b(0) && b(1), a(2)); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn g(i : bool, j : i32) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| var tint_symbol = b(0); |
| if (tint_symbol) { |
| tint_symbol = b(1); |
| } |
| let tint_symbol_1 = a(2); |
| let r = g(tint_symbol, tint_symbol_1); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, Binary_Mixed_Complex) { |
| auto* src = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn c(i : bool) -> i32 { |
| return 0; |
| } |
| |
| fn g(i : bool, j : i32) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| let r = a(0) + g(b(1) && b(a(2) + a(3)), a(4)) + a(5); |
| } |
| )"; |
| |
| auto* expect = R"( |
| fn a(i : i32) -> i32 { |
| return 0; |
| } |
| |
| fn b(i : i32) -> bool { |
| return true; |
| } |
| |
| fn c(i : bool) -> i32 { |
| return 0; |
| } |
| |
| fn g(i : bool, j : i32) -> i32 { |
| return 0; |
| } |
| |
| fn f() { |
| let tint_symbol = a(0); |
| var tint_symbol_1 = b(1); |
| if (tint_symbol_1) { |
| let tint_symbol_2 = a(2); |
| let tint_symbol_3 = a(3); |
| tint_symbol_1 = b((tint_symbol_2 + tint_symbol_3)); |
| } |
| let tint_symbol_4 = a(4); |
| let tint_symbol_5 = g(tint_symbol_1, tint_symbol_4); |
| let tint_symbol_6 = a(5); |
| let r = ((tint_symbol + tint_symbol_5) + tint_symbol_6); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| TEST_F(PromoteSideEffectsToDeclTest, TextureSamplerParameter) { |
| auto* src = R"( |
| @group(0) @binding(0) var T : texture_2d<f32>; |
| @group(0) @binding(1) var S : sampler; |
| |
| var<private> P : vec2<f32>; |
| fn side_effects() -> vec2<f32> { |
| P += vec2(1.0); |
| return P; |
| } |
| |
| fn f(t : texture_2d<f32>, s : sampler) -> vec4<f32> { |
| return textureSample(t, s, side_effects()); |
| } |
| |
| fn m() -> vec4<f32>{ |
| return f(T, S); |
| } |
| )"; |
| |
| auto* expect = R"( |
| @group(0) @binding(0) var T : texture_2d<f32>; |
| |
| @group(0) @binding(1) var S : sampler; |
| |
| var<private> P : vec2<f32>; |
| |
| fn side_effects() -> vec2<f32> { |
| P += vec2(1.0); |
| return P; |
| } |
| |
| fn f(t : texture_2d<f32>, s : sampler) -> vec4<f32> { |
| let tint_symbol = side_effects(); |
| return textureSample(t, s, tint_symbol); |
| } |
| |
| fn m() -> vec4<f32> { |
| return f(T, S); |
| } |
| )"; |
| |
| DataMap data; |
| auto got = Run<PromoteSideEffectsToDecl>(src, data); |
| |
| EXPECT_EQ(expect, str(got)); |
| } |
| |
| } // namespace |
| } // namespace tint::transform |