diff --git a/compiler/optimizer/ecma_pipeline.cpp b/compiler/optimizer/ecma_pipeline.cpp index c82c73ea87aed63d80b5fbc390e7e380dc6d925c..1ea70fc6e5b4ff68b4e09987f7a9418555022402 100644 --- a/compiler/optimizer/ecma_pipeline.cpp +++ b/compiler/optimizer/ecma_pipeline.cpp @@ -37,6 +37,7 @@ #include "optimizer/optimizations/memory_barriers.h" #include "optimizer/optimizations/memory_coalescing.h" #include "optimizer/optimizations/peepholes.h" +#include "optimizer/optimizations/phi_type_resolving.h" #include "optimizer/optimizations/redundant_loop_elimination.h" #include "optimizer/optimizations/regalloc/reg_alloc.h" #include "optimizer/optimizations/scheduler.h" @@ -72,6 +73,7 @@ bool EcmaPipeline::RunOptimizations() graph->RunPass(); } graph->RunPass(); + graph->RunPass(); graph->RunPass(); graph->RunPass(); graph->RunPass(); @@ -81,6 +83,7 @@ bool EcmaPipeline::RunOptimizations() graph->RunPass(); graph->RunPass(); graph->RunPass(); + graph->RunPass(); graph->RunPass(); graph->RunPass(); if (graph->RunPass() && graph->RunPass()) { diff --git a/tests/compiler/CMakeLists.txt b/tests/compiler/CMakeLists.txt index c8c1efa1db5270dd9a97569b4db9eb664a79c6b2..6266712e4efab3d4e94e8345e408972ceb6ed9f3 100644 --- a/tests/compiler/CMakeLists.txt +++ b/tests/compiler/CMakeLists.txt @@ -27,6 +27,7 @@ set(PANDA_COMPILER_ECMA_TESTS_SOURCES lowering_ecma_test.cpp peepholes_ecma_test.cpp types_resolving_ecma_tests.cpp + phi_type_resolving_ecma_test.cpp vn_test_ecma.cpp ) diff --git a/tests/compiler/phi_type_resolving_ecma_test.cpp b/tests/compiler/phi_type_resolving_ecma_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9c568d809713239c7e7f5b755159c4262d3f5eb5 --- /dev/null +++ b/tests/compiler/phi_type_resolving_ecma_test.cpp @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2021-2022 Huawei Device Co., Ltd. + * 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 "unit_ecma_test.h" +#include "optimizer/ir/graph_cloner.h" +#include "optimizer/optimizations/cleanup.h" +#include "optimizer/optimizations/phi_type_resolving.h" + +namespace panda::compiler { +class PhiTypeResolvingTest : public AsmTest { +public: + PhiTypeResolvingTest() = default; +}; + +// NOLINTBEGIN(readability-magic-numbers) +TEST_F(PhiTypeResolvingTest, ResolvePhi) +{ + auto graph = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph) + { + CONSTANT(0, 0).i64(); + CONSTANT(1, 1).i64(); + PARAMETER(2, 0).any(); + + BASIC_BLOCK(2, 3, 4) + { + INST(3, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(1); + INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); + INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); + } + BASIC_BLOCK(3, 4) {} + + BASIC_BLOCK(4, -1) + { + INST(8, Opcode::Phi).any().Inputs(3, 4); + INST(9, Opcode::Return).any().Inputs(8); + } + } + ASSERT_TRUE(graph->RunPass()); + ASSERT_TRUE(graph->RunPass()); + GraphChecker(graph).Check(); + + auto graph_opt = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph_opt) + { + CONSTANT(0, 0).i64(); + CONSTANT(1, 1).i64(); + PARAMETER(2, 0).any(); + + BASIC_BLOCK(2, 3, 4) + { + INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); + INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); + } + BASIC_BLOCK(3, 4) {} + + BASIC_BLOCK(4, -1) + { + INST(8, Opcode::Phi).i32().Inputs(0, 1); + INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(8); + INST(9, Opcode::Return).any().Inputs(10); + } + } + + ASSERT_TRUE(GraphComparator().Compare(graph, graph_opt)); +} + +TEST_F(PhiTypeResolvingTest, Resolve2Phi) +{ + auto graph = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph) + { + CONSTANT(0, 0).i64(); + CONSTANT(1, 1).i64(); + CONSTANT(21, 1).i64(); + PARAMETER(2, 0).any(); + PARAMETER(22, 1).any(); + + BASIC_BLOCK(2, 3, 4) + { + INST(3, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(1); + INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(21); + INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); + INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); + } + BASIC_BLOCK(3, 4) {} + + BASIC_BLOCK(4, 5, 6) + { + INST(13, Opcode::Phi).any().Inputs(3, 4); + INST(11, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(22); + INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11); + } + BASIC_BLOCK(6, 5) {} + + BASIC_BLOCK(5, -1) + { + INST(8, Opcode::Phi).any().Inputs(13, 10); + INST(9, Opcode::Return).any().Inputs(8); + } + } + ASSERT_TRUE(graph->RunPass()); + ASSERT_TRUE(graph->RunPass()); + GraphChecker(graph).Check(); + + auto graph_opt = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph_opt) + { + CONSTANT(0, 0).i64(); + CONSTANT(1, 1).i64(); + CONSTANT(21, 1).i64(); + PARAMETER(2, 0).any(); + PARAMETER(22, 1).any(); + + BASIC_BLOCK(2, 3, 4) + { + INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); + INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); + } + BASIC_BLOCK(3, 4) {} + + BASIC_BLOCK(4, 5, 6) + { + INST(13, Opcode::Phi).i32().Inputs(0, 1); + INST(11, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(22); + INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11); + } + BASIC_BLOCK(6, 5) {} + + BASIC_BLOCK(5, -1) + { + INST(8, Opcode::Phi).i32().Inputs(13, 21); + INST(25, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(8); + INST(9, Opcode::Return).any().Inputs(25); + } + } + + ASSERT_TRUE(GraphComparator().Compare(graph, graph_opt)); +} + +TEST_F(PhiTypeResolvingTest, ResolvePhiNotApply) +{ + auto graph = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph) + { + CONSTANT(0, 0).i64(); + CONSTANT(1, 1.1).f64(); + PARAMETER(2, 0).any(); + + BASIC_BLOCK(2, 3, 4) + { + INST(3, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(1); + INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); + INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); + } + BASIC_BLOCK(3, 4) {} + + BASIC_BLOCK(4, -1) + { + INST(8, Opcode::Phi).any().Inputs(3, 4); + INST(9, Opcode::Return).any().Inputs(8); + } + } + auto graph_opt = GraphCloner(graph, graph->GetAllocator(), graph->GetLocalAllocator()).CloneGraph(); + + ASSERT_FALSE(graph->RunPass()); + ASSERT_FALSE(graph->RunPass()); + GraphChecker(graph).Check(); + + ASSERT_TRUE(GraphComparator().Compare(graph, graph_opt)); +} + +TEST_F(PhiTypeResolvingTest, ResolvePhiUserNotAnyType) +{ + auto graph = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph) + { + CONSTANT(0, 0).f64(); + CONSTANT(1, 1).f64(); + PARAMETER(2, 0).any(); + + BASIC_BLOCK(2, 3, 4) + { + INST(3, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(0); + INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(1); + INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); + INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); + } + BASIC_BLOCK(3, 4) {} + + BASIC_BLOCK(4, -1) + { + INST(8, Opcode::Phi).any().Inputs(3, 4); + INST(9, Opcode::CompareAnyType).AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).b().Inputs(8); + INST(10, Opcode::Return).b().Inputs(9); + } + } + ASSERT_TRUE(graph->RunPass()); + ASSERT_TRUE(graph->RunPass()); + GraphChecker(graph).Check(); + + auto graph_opt = CreateGraphDynWithDefaultRuntime(); + GRAPH(graph_opt) + { + CONSTANT(0, 0).f64(); + CONSTANT(1, 1).f64(); + PARAMETER(2, 0).any(); + + BASIC_BLOCK(2, 3, 4) + { + INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); + INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); + } + BASIC_BLOCK(3, 4) {} + + BASIC_BLOCK(4, -1) + { + INST(8, Opcode::Phi).f64().Inputs(0, 1); + INST(11, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(8); + INST(9, Opcode::CompareAnyType).AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).b().Inputs(11); + INST(10, Opcode::Return).b().Inputs(9); + } + } + + ASSERT_TRUE(GraphComparator().Compare(graph, graph_opt)); +} +// NOLINTEND(readability-magic-numbers) + +} // namespace panda::compiler diff --git a/tests/compiler/types_resolving_ecma_tests.cpp b/tests/compiler/types_resolving_ecma_tests.cpp index 90df3e086e8d74af3dd91c030d1c46f56df824ce..19498349c6dd3f35f1672a0cbe785f1cd05c891e 100644 --- a/tests/compiler/types_resolving_ecma_tests.cpp +++ b/tests/compiler/types_resolving_ecma_tests.cpp @@ -17,6 +17,7 @@ #include "optimizer/ir/datatype.h" #include "optimizer/ir/graph_cloner.h" #include "optimizer/optimizations/cleanup.h" +#include "optimizer/optimizations/phi_type_resolving.h" #include "optimizer/optimizations/types_resolving.h" #include "runtime/include/coretypes/tagged_value.h" @@ -298,221 +299,6 @@ TEST_F(TypeResolvingTest, ToNumber) } } -TEST_F(TypeResolvingTest, ResolvePhi) -{ - auto graph = CreateGraphDynWithDefaultRuntime(); - GRAPH(graph) - { - CONSTANT(0, 0).i64(); - CONSTANT(1, 1).i64(); - PARAMETER(2, 0).any(); - - BASIC_BLOCK(2, 3, 4) - { - INST(3, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); - INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(1); - INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); - INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); - } - BASIC_BLOCK(3, 4) {} - - BASIC_BLOCK(4, -1) - { - INST(8, Opcode::Phi).any().Inputs(3, 4); - INST(9, Opcode::Return).any().Inputs(8); - } - } - ASSERT_TRUE(graph->RunPass()); - ASSERT_TRUE(graph->RunPass()); - GraphChecker(graph).Check(); - - auto graph_opt = CreateGraphDynWithDefaultRuntime(); - GRAPH(graph_opt) - { - CONSTANT(0, 0).i64(); - CONSTANT(1, 1).i64(); - PARAMETER(2, 0).any(); - - BASIC_BLOCK(2, 3, 4) - { - INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); - INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); - } - BASIC_BLOCK(3, 4) {} - - BASIC_BLOCK(4, -1) - { - INST(8, Opcode::Phi).i32().Inputs(0, 1); - INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(8); - INST(9, Opcode::Return).any().Inputs(10); - } - } - - ASSERT_TRUE(GraphComparator().Compare(graph, graph_opt)); -} - -TEST_F(TypeResolvingTest, Resolve2Phi) -{ - auto graph = CreateGraphDynWithDefaultRuntime(); - GRAPH(graph) - { - CONSTANT(0, 0).i64(); - CONSTANT(1, 1).i64(); - CONSTANT(21, 1).i64(); - PARAMETER(2, 0).any(); - PARAMETER(22, 1).any(); - - BASIC_BLOCK(2, 3, 4) - { - INST(3, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); - INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(1); - INST(10, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(21); - INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); - INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); - } - BASIC_BLOCK(3, 4) {} - - BASIC_BLOCK(4, 5, 6) - { - INST(13, Opcode::Phi).any().Inputs(3, 4); - INST(11, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(22); - INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11); - } - BASIC_BLOCK(6, 5) {} - - BASIC_BLOCK(5, -1) - { - INST(8, Opcode::Phi).any().Inputs(13, 10); - INST(9, Opcode::Return).any().Inputs(8); - } - } - ASSERT_TRUE(graph->RunPass()); - ASSERT_TRUE(graph->RunPass()); - GraphChecker(graph).Check(); - - auto graph_opt = CreateGraphDynWithDefaultRuntime(); - GRAPH(graph_opt) - { - CONSTANT(0, 0).i64(); - CONSTANT(1, 1).i64(); - CONSTANT(21, 1).i64(); - PARAMETER(2, 0).any(); - PARAMETER(22, 1).any(); - - BASIC_BLOCK(2, 3, 4) - { - INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); - INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); - } - BASIC_BLOCK(3, 4) {} - - BASIC_BLOCK(4, 5, 6) - { - INST(13, Opcode::Phi).i32().Inputs(0, 1); - INST(11, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(22); - INST(12, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(11); - } - BASIC_BLOCK(6, 5) {} - - BASIC_BLOCK(5, -1) - { - INST(8, Opcode::Phi).i32().Inputs(13, 21); - INST(25, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(8); - INST(9, Opcode::Return).any().Inputs(25); - } - } - - ASSERT_TRUE(GraphComparator().Compare(graph, graph_opt)); -} - -TEST_F(TypeResolvingTest, ResolvePhiNotApply) -{ - auto graph = CreateGraphDynWithDefaultRuntime(); - GRAPH(graph) - { - CONSTANT(0, 0).i64(); - CONSTANT(1, 1.1).f64(); - PARAMETER(2, 0).any(); - - BASIC_BLOCK(2, 3, 4) - { - INST(3, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).Inputs(0); - INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(1); - INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); - INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); - } - BASIC_BLOCK(3, 4) {} - - BASIC_BLOCK(4, -1) - { - INST(8, Opcode::Phi).any().Inputs(3, 4); - INST(9, Opcode::Return).any().Inputs(8); - } - } - auto graph_opt = GraphCloner(graph, graph->GetAllocator(), graph->GetLocalAllocator()).CloneGraph(); - - ASSERT_FALSE(graph->RunPass()); - ASSERT_FALSE(graph->RunPass()); - GraphChecker(graph).Check(); - - ASSERT_TRUE(GraphComparator().Compare(graph, graph_opt)); -} - -TEST_F(TypeResolvingTest, ResolvePhiUserNotAnyType) -{ - auto graph = CreateGraphDynWithDefaultRuntime(); - GRAPH(graph) - { - CONSTANT(0, 0).f64(); - CONSTANT(1, 1).f64(); - PARAMETER(2, 0).any(); - - BASIC_BLOCK(2, 3, 4) - { - INST(3, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(0); - INST(4, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(1); - INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); - INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); - } - BASIC_BLOCK(3, 4) {} - - BASIC_BLOCK(4, -1) - { - INST(8, Opcode::Phi).any().Inputs(3, 4); - INST(9, Opcode::CompareAnyType).AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).b().Inputs(8); - INST(10, Opcode::Return).b().Inputs(9); - } - } - ASSERT_TRUE(graph->RunPass()); - ASSERT_TRUE(graph->RunPass()); - GraphChecker(graph).Check(); - - auto graph_opt = CreateGraphDynWithDefaultRuntime(); - GRAPH(graph_opt) - { - CONSTANT(0, 0).f64(); - CONSTANT(1, 1).f64(); - PARAMETER(2, 0).any(); - - BASIC_BLOCK(2, 3, 4) - { - INST(6, Opcode::CastAnyTypeValue).b().AnyType(AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE).Inputs(2); - INST(7, Opcode::IfImm).SrcType(DataType::BOOL).CC(CC_NE).Imm(0).Inputs(6); - } - BASIC_BLOCK(3, 4) {} - - BASIC_BLOCK(4, -1) - { - INST(8, Opcode::Phi).f64().Inputs(0, 1); - INST(11, Opcode::CastValueToAnyType).any().AnyType(AnyBaseType::ECMASCRIPT_DOUBLE_TYPE).Inputs(8); - INST(9, Opcode::CompareAnyType).AnyType(AnyBaseType::ECMASCRIPT_INT_TYPE).b().Inputs(11); - INST(10, Opcode::Return).b().Inputs(9); - } - } - - ASSERT_TRUE(GraphComparator().Compare(graph, graph_opt)); -} - TEST_F(TypeResolvingTest, ResolveLoopPhi) { auto graph = CreateGraphDynWithDefaultRuntime(); @@ -575,6 +361,7 @@ TEST_F(TypeResolvingTest, ResolveLoopPhi) } } ASSERT_TRUE(graph->RunPass()); + ASSERT_TRUE(graph->RunPass()); ASSERT_TRUE(graph->RunPass(false)); GraphChecker(graph).Check();