mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-06-05 22:23:29 +00:00
This prepares for the addition of IR transforms. Subsequent patches will introduce an ast::transform namespace and refactor the Transform class into a common base class for the two types of transform. Bug: tint:1718 Change-Id: I0088d8356341e861df68df1f4f755ee82757dd2d Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/132423 Commit-Queue: James Price <jrprice@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Kokoro: Kokoro <noreply+kokoro@google.com>
488 lines
7.7 KiB
C++
488 lines
7.7 KiB
C++
// 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/ast/transform/remove_phonies.h"
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "src/tint/ast/transform/test_helper.h"
|
|
|
|
namespace tint::transform {
|
|
namespace {
|
|
|
|
using RemovePhoniesTest = TransformTest;
|
|
|
|
TEST_F(RemovePhoniesTest, ShouldRunEmptyModule) {
|
|
auto* src = R"()";
|
|
|
|
EXPECT_FALSE(ShouldRun<RemovePhonies>(src));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, ShouldRunHasPhony) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
_ = 1;
|
|
}
|
|
)";
|
|
|
|
EXPECT_TRUE(ShouldRun<RemovePhonies>(src));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, EmptyModule) {
|
|
auto* src = "";
|
|
auto* expect = "";
|
|
|
|
auto got = Run<RemovePhonies>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, NoSideEffects) {
|
|
auto* src = R"(
|
|
@group(0) @binding(0) var t : texture_2d<f32>;
|
|
|
|
fn f() {
|
|
var v : i32;
|
|
_ = &v;
|
|
_ = 1;
|
|
_ = 1 + 2;
|
|
_ = t;
|
|
_ = u32(3.0);
|
|
_ = f32(i32(4u));
|
|
_ = vec2<f32>(5.0);
|
|
_ = vec3<i32>(6, 7, 8);
|
|
_ = mat2x2<f32>(9.0, 10.0, 11.0, 12.0);
|
|
_ = atan2(1.0, 2.0);
|
|
_ = clamp(1.0, 2.0, 3.0);
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
@group(0) @binding(0) var t : texture_2d<f32>;
|
|
|
|
fn f() {
|
|
var v : i32;
|
|
}
|
|
)";
|
|
|
|
auto got = Run<RemovePhonies>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, SingleSideEffects) {
|
|
auto* src = R"(
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn f() {
|
|
_ = neg(1);
|
|
_ = add(2, 3);
|
|
_ = add(neg(4), neg(5));
|
|
_ = u32(neg(6));
|
|
_ = f32(add(7, 8));
|
|
_ = vec2<f32>(f32(neg(9)));
|
|
_ = vec3<i32>(1, neg(10), 3);
|
|
_ = mat2x2<f32>(1.0, f32(add(11, 12)), 3.0, 4.0);
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn f() {
|
|
neg(1);
|
|
add(2, 3);
|
|
add(neg(4), neg(5));
|
|
neg(6);
|
|
add(7, 8);
|
|
neg(9);
|
|
neg(10);
|
|
add(11, 12);
|
|
}
|
|
)";
|
|
|
|
auto got = Run<RemovePhonies>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, SingleSideEffectsMustUse) {
|
|
auto* src = R"(
|
|
@must_use
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
|
|
@must_use
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn f() {
|
|
let tint_phony = 42;
|
|
_ = neg(1);
|
|
_ = 100 + add(2, 3) + 200;
|
|
_ = add(neg(4), neg(5)) + 6;
|
|
_ = u32(neg(6));
|
|
_ = f32(add(7, 8));
|
|
_ = vec2<f32>(f32(neg(9)));
|
|
_ = vec3<i32>(1, neg(10), 3);
|
|
_ = mat2x2<f32>(1.0, f32(add(11, 12)), 3.0, 4.0);
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
@must_use
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
|
|
@must_use
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn f() {
|
|
let tint_phony = 42;
|
|
let tint_phony_1 = neg(1);
|
|
let tint_phony_2 = add(2, 3);
|
|
let tint_phony_3 = add(neg(4), neg(5));
|
|
let tint_phony_4 = neg(6);
|
|
let tint_phony_5 = add(7, 8);
|
|
let tint_phony_6 = neg(9);
|
|
let tint_phony_7 = neg(10);
|
|
let tint_phony_8 = add(11, 12);
|
|
}
|
|
)";
|
|
|
|
auto got = Run<RemovePhonies>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, SingleSideEffects_OutOfOrder) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
_ = neg(1);
|
|
_ = add(2, 3);
|
|
_ = add(neg(4), neg(5));
|
|
_ = u32(neg(6));
|
|
_ = f32(add(7, 8));
|
|
_ = vec2<f32>(f32(neg(9)));
|
|
_ = vec3<i32>(1, neg(10), 3);
|
|
_ = mat2x2<f32>(1.0, f32(add(11, 12)), 3.0, 4.0);
|
|
}
|
|
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn f() {
|
|
neg(1);
|
|
add(2, 3);
|
|
add(neg(4), neg(5));
|
|
neg(6);
|
|
add(7, 8);
|
|
neg(9);
|
|
neg(10);
|
|
add(11, 12);
|
|
}
|
|
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
)";
|
|
|
|
auto got = Run<RemovePhonies>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, MultipleSideEffects) {
|
|
auto* src = R"(
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
|
|
@must_use
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn xor(a : u32, b : u32) -> u32 {
|
|
return (a ^ b);
|
|
}
|
|
|
|
fn f() {
|
|
_ = (1 + add(2 + add(3, 4), 5)) * add(6, 7) * neg(8);
|
|
_ = add(9, neg(10)) + neg(11);
|
|
_ = xor(12u, 13u) + xor(14u, 15u);
|
|
_ = neg(16) / neg(17) + add(18, 19);
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
|
|
@must_use
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn xor(a : u32, b : u32) -> u32 {
|
|
return (a ^ b);
|
|
}
|
|
|
|
fn phony_sink(p0 : i32, p1 : i32, p2 : i32) {
|
|
}
|
|
|
|
fn phony_sink_1(p0 : i32, p1 : i32) {
|
|
}
|
|
|
|
fn phony_sink_2(p0 : u32, p1 : u32) {
|
|
}
|
|
|
|
fn f() {
|
|
phony_sink(add((2 + add(3, 4)), 5), add(6, 7), neg(8));
|
|
phony_sink_1(add(9, neg(10)), neg(11));
|
|
phony_sink_2(xor(12u, 13u), xor(14u, 15u));
|
|
phony_sink(neg(16), neg(17), add(18, 19));
|
|
}
|
|
)";
|
|
|
|
auto got = Run<RemovePhonies>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, MultipleSideEffects_OutOfOrder) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
_ = (1 + add(2 + add(3, 4), 5)) * add(6, 7) * neg(8);
|
|
_ = add(9, neg(10)) + neg(11);
|
|
_ = xor(12u, 13u) + xor(14u, 15u);
|
|
_ = neg(16) / neg(17) + add(18, 19);
|
|
}
|
|
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn xor(a : u32, b : u32) -> u32 {
|
|
return (a ^ b);
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn phony_sink(p0 : i32, p1 : i32, p2 : i32) {
|
|
}
|
|
|
|
fn phony_sink_1(p0 : i32, p1 : i32) {
|
|
}
|
|
|
|
fn phony_sink_2(p0 : u32, p1 : u32) {
|
|
}
|
|
|
|
fn f() {
|
|
phony_sink(add((2 + add(3, 4)), 5), add(6, 7), neg(8));
|
|
phony_sink_1(add(9, neg(10)), neg(11));
|
|
phony_sink_2(xor(12u, 13u), xor(14u, 15u));
|
|
phony_sink(neg(16), neg(17), add(18, 19));
|
|
}
|
|
|
|
fn neg(a : i32) -> i32 {
|
|
return -(a);
|
|
}
|
|
|
|
fn add(a : i32, b : i32) -> i32 {
|
|
return (a + b);
|
|
}
|
|
|
|
fn xor(a : u32, b : u32) -> u32 {
|
|
return (a ^ b);
|
|
}
|
|
)";
|
|
|
|
auto got = Run<RemovePhonies>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, ForLoop) {
|
|
auto* src = R"(
|
|
struct S {
|
|
arr : array<i32>,
|
|
};
|
|
|
|
@group(0) @binding(0) var<storage, read_write> s : S;
|
|
|
|
fn x() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn y() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn z() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn f() {
|
|
for (_ = &s.arr; ;_ = &s.arr) {
|
|
break;
|
|
}
|
|
for (_ = x(); ;_ = y() + z()) {
|
|
break;
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
struct S {
|
|
arr : array<i32>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<storage, read_write> s : S;
|
|
|
|
fn x() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn y() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn z() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn phony_sink(p0 : i32, p1 : i32) {
|
|
}
|
|
|
|
fn f() {
|
|
for(; ; ) {
|
|
break;
|
|
}
|
|
for(x(); ; phony_sink(y(), z())) {
|
|
break;
|
|
}
|
|
}
|
|
)";
|
|
|
|
auto got = Run<RemovePhonies>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
TEST_F(RemovePhoniesTest, ForLoop_OutOfOrder) {
|
|
auto* src = R"(
|
|
fn f() {
|
|
for (_ = &s.arr; ;_ = &s.arr) {
|
|
break;
|
|
}
|
|
for (_ = x(); ;_ = y() + z()) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
fn x() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn y() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn z() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
struct S {
|
|
arr : array<i32>,
|
|
};
|
|
|
|
@group(0) @binding(0) var<storage, read_write> s : S;
|
|
)";
|
|
|
|
auto* expect = R"(
|
|
fn phony_sink(p0 : i32, p1 : i32) {
|
|
}
|
|
|
|
fn f() {
|
|
for(; ; ) {
|
|
break;
|
|
}
|
|
for(x(); ; phony_sink(y(), z())) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
fn x() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn y() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
fn z() -> i32 {
|
|
return 0;
|
|
}
|
|
|
|
struct S {
|
|
arr : array<i32>,
|
|
}
|
|
|
|
@group(0) @binding(0) var<storage, read_write> s : S;
|
|
)";
|
|
|
|
auto got = Run<RemovePhonies>(src);
|
|
|
|
EXPECT_EQ(expect, str(got));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace tint::transform
|