summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author David Brazdil <dbrazdil@google.com> 2016-02-02 16:28:56 +0000
committer David Brazdil <dbrazdil@google.com> 2016-02-15 10:21:07 +0000
commitbadd826664896d4a9628a5a89b78016894aa414b (patch)
treea30e8b3e62126ae1e1df1152ac643cfc5f2b074a
parent47a2a45a6673ddf3322115ff5058763f82a9368f (diff)
ART: Run SsaBuilder from HGraphBuilder
First step towards merging the two passes, which will later result in HGraphBuilder directly producing SSA form. This CL mostly just updates tests broken by not being able to inspect the pre-SSA form. Using HLocals outside the HGraphBuilder is now deprecated. Bug: 27150508 Change-Id: I00fb6050580f409dcc5aa5b5aa3a536d6e8d759e
-rw-r--r--compiler/optimizing/builder.cc20
-rw-r--r--compiler/optimizing/builder.h3
-rw-r--r--compiler/optimizing/codegen_test.cc32
-rw-r--r--compiler/optimizing/constant_folding_test.cc78
-rw-r--r--compiler/optimizing/dead_code_elimination_test.cc8
-rw-r--r--compiler/optimizing/dominator_test.cc31
-rw-r--r--compiler/optimizing/find_loops_test.cc65
-rw-r--r--compiler/optimizing/graph_checker.cc390
-rw-r--r--compiler/optimizing/graph_checker.h80
-rw-r--r--compiler/optimizing/graph_checker_test.cc32
-rw-r--r--compiler/optimizing/graph_visualizer.cc8
-rw-r--r--compiler/optimizing/gvn_test.cc8
-rw-r--r--compiler/optimizing/induction_var_analysis_test.cc240
-rw-r--r--compiler/optimizing/induction_var_range_test.cc23
-rw-r--r--compiler/optimizing/inliner.cc8
-rw-r--r--compiler/optimizing/licm_test.cc2
-rw-r--r--compiler/optimizing/linearize_test.cc9
-rw-r--r--compiler/optimizing/live_ranges_test.cc25
-rw-r--r--compiler/optimizing/liveness_test.cc7
-rw-r--r--compiler/optimizing/nodes.cc36
-rw-r--r--compiler/optimizing/nodes.h10
-rw-r--r--compiler/optimizing/optimizing_compiler.cc133
-rw-r--r--compiler/optimizing/optimizing_unit_test.h29
-rw-r--r--compiler/optimizing/pretty_printer_test.cc80
-rw-r--r--compiler/optimizing/register_allocator_test.cc23
-rw-r--r--compiler/optimizing/ssa_builder.cc3
-rw-r--r--compiler/optimizing/ssa_builder.h2
-rw-r--r--compiler/optimizing/ssa_liveness_analysis.cc2
-rw-r--r--compiler/optimizing/ssa_test.cc8
-rw-r--r--compiler/optimizing/suspend_check_test.cc32
-rw-r--r--test/127-checker-secondarydex/src/Test.java2
-rw-r--r--test/444-checker-nce/src/Main.java8
-rw-r--r--test/450-checker-types/src/Main.java24
-rw-r--r--test/458-checker-instruction-simplification/src/Main.java4
-rw-r--r--test/464-checker-inline-sharpen-calls/src/Main.java2
-rw-r--r--test/477-checker-bound-type/src/Main.java8
-rw-r--r--test/492-checker-inline-invoke-interface/src/Main.java2
-rw-r--r--test/510-checker-try-catch/smali/Builder.smali377
-rw-r--r--test/510-checker-try-catch/smali/SsaBuilder.smali17
-rw-r--r--test/517-checker-builder-fallthrough/smali/TestCase.smali4
-rw-r--r--test/523-checker-can-throw-regression/smali/Test.smali6
-rw-r--r--test/537-checker-debuggable/smali/TestCase.smali4
-rw-r--r--test/540-checker-rtp-bug/src/Main.java6
-rw-r--r--test/549-checker-types-merge/src/Main.java22
-rw-r--r--test/550-checker-regression-wide-store/smali/TestCase.smali6
-rw-r--r--test/552-checker-primitive-typeprop/smali/ArrayGet.smali28
-rw-r--r--test/552-checker-primitive-typeprop/smali/ArraySet.smali2
-rw-r--r--test/552-checker-primitive-typeprop/smali/SsaBuilder.smali2
-rw-r--r--test/552-checker-primitive-typeprop/smali/TypePropagation.smali16
-rw-r--r--test/554-checker-rtp-checkcast/src/Main.java6
-rw-r--r--test/557-checker-ref-equivalent/smali/TestCase.smali2
-rw-r--r--test/557-checker-ref-equivalent/src/Main.java4
-rw-r--r--test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali10
-rw-r--r--test/559-checker-rtp-ifnotnull/src/Main.java2
54 files changed, 1005 insertions, 986 deletions
diff --git a/compiler/optimizing/builder.cc b/compiler/optimizing/builder.cc
index a1d62760a1..05e1356ed8 100644
--- a/compiler/optimizing/builder.cc
+++ b/compiler/optimizing/builder.cc
@@ -32,6 +32,7 @@
#include "nodes.h"
#include "primitive.h"
#include "scoped_thread_state_change.h"
+#include "ssa_builder.h"
#include "thread.h"
#include "utils/dex_cache_arrays_layout-inl.h"
@@ -248,7 +249,7 @@ void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item)
// loop for synchronized blocks.
if (block->HasThrowingInstructions()) {
// Try to find a TryItem covering the block.
- DCHECK_NE(block->GetDexPc(), kNoDexPc) << "Block must have a dec_pc to find its TryItem.";
+ DCHECK_NE(block->GetDexPc(), kNoDexPc) << "Block must have a dex_pc to find its TryItem.";
const int32_t try_item_idx = DexFile::FindTryItem(code_item, block->GetDexPc());
if (try_item_idx != -1) {
// Block throwing and in a TryItem. Store the try block information.
@@ -322,7 +323,8 @@ void HGraphBuilder::InsertTryBoundaryBlocks(const DexFile::CodeItem& code_item)
}
}
-bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
+GraphAnalysisResult HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item,
+ StackHandleScopeCollection* handles) {
DCHECK(graph_->GetBlocks().empty());
const uint16_t* code_ptr = code_item.insns_;
@@ -349,12 +351,12 @@ bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
// start a new block, and create these blocks.
if (!ComputeBranchTargets(code_ptr, code_end, &number_of_branches)) {
MaybeRecordStat(MethodCompilationStat::kNotCompiledBranchOutsideMethodCode);
- return false;
+ return kAnalysisInvalidBytecode;
}
// Note that the compiler driver is null when unit testing.
if ((compiler_driver_ != nullptr) && SkipCompilation(code_item, number_of_branches)) {
- return false;
+ return kAnalysisInvalidBytecode;
}
// Find locations where we want to generate extra stackmaps for native debugging.
@@ -385,7 +387,7 @@ bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
}
}
if (!AnalyzeDexInstruction(instruction, dex_pc)) {
- return false;
+ return kAnalysisInvalidBytecode;
}
dex_pc += instruction.SizeInCodeUnits();
code_ptr += instruction.SizeInCodeUnits();
@@ -404,7 +406,13 @@ bool HGraphBuilder::BuildGraph(const DexFile::CodeItem& code_item) {
// non-exceptional edges to have been created.
InsertTryBoundaryBlocks(code_item);
- return true;
+ GraphAnalysisResult result = graph_->BuildDominatorTree();
+ if (result != kAnalysisSuccess) {
+ return result;
+ }
+
+ graph_->InitializeInexactObjectRTI(handles);
+ return SsaBuilder(graph_, handles).BuildSsa();
}
void HGraphBuilder::MaybeUpdateCurrentBlock(size_t dex_pc) {
diff --git a/compiler/optimizing/builder.h b/compiler/optimizing/builder.h
index 93e17d6422..e3dd0e8216 100644
--- a/compiler/optimizing/builder.h
+++ b/compiler/optimizing/builder.h
@@ -80,7 +80,8 @@ class HGraphBuilder : public ValueObject {
null_dex_cache_(),
dex_cache_(null_dex_cache_) {}
- bool BuildGraph(const DexFile::CodeItem& code);
+ GraphAnalysisResult BuildGraph(const DexFile::CodeItem& code,
+ StackHandleScopeCollection* handles);
static constexpr const char* kBuilderPassName = "builder";
diff --git a/compiler/optimizing/codegen_test.cc b/compiler/optimizing/codegen_test.cc
index 4f37c37e39..6be79fa75c 100644
--- a/compiler/optimizing/codegen_test.cc
+++ b/compiler/optimizing/codegen_test.cc
@@ -206,10 +206,13 @@ static void RunCode(CodeGenerator* codegen,
std::function<void(HGraph*)> hook_before_codegen,
bool has_result,
Expected expected) {
- ASSERT_TRUE(graph->IsInSsaForm());
-
- SSAChecker graph_checker(graph);
+ GraphChecker graph_checker(graph);
graph_checker.Run();
+ if (!graph_checker.IsValid()) {
+ for (auto error : graph_checker.GetErrors()) {
+ std::cout << error << std::endl;
+ }
+ }
ASSERT_TRUE(graph_checker.IsValid());
SsaLivenessAnalysis liveness(graph, codegen);
@@ -292,14 +295,9 @@ static void TestCode(const uint16_t* data,
for (InstructionSet target_isa : GetTargetISAs()) {
ArenaPool pool;
ArenaAllocator arena(&pool);
- HGraph* graph = CreateGraph(&arena);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- bool graph_built = builder.BuildGraph(*item);
- ASSERT_TRUE(graph_built);
+ HGraph* graph = CreateCFG(&arena, data);
// Remove suspend checks, they cannot be executed in this context.
RemoveSuspendChecks(graph);
- TransformToSsa(graph);
RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
}
}
@@ -310,14 +308,9 @@ static void TestCodeLong(const uint16_t* data,
for (InstructionSet target_isa : GetTargetISAs()) {
ArenaPool pool;
ArenaAllocator arena(&pool);
- HGraph* graph = CreateGraph(&arena);
- HGraphBuilder builder(graph, Primitive::kPrimLong);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- bool graph_built = builder.BuildGraph(*item);
- ASSERT_TRUE(graph_built);
+ HGraph* graph = CreateCFG(&arena, data, Primitive::kPrimLong);
// Remove suspend checks, they cannot be executed in this context.
RemoveSuspendChecks(graph);
- TransformToSsa(graph);
RunCode(target_isa, graph, [](HGraph*) {}, has_result, expected);
}
}
@@ -640,6 +633,7 @@ TEST_F(CodegenTest, NonMaterializedCondition) {
ArenaAllocator allocator(&pool);
HGraph* graph = CreateGraph(&allocator);
+
HBasicBlock* entry = new (&allocator) HBasicBlock(graph);
graph->AddBlock(entry);
graph->SetEntryBlock(entry);
@@ -672,7 +666,7 @@ TEST_F(CodegenTest, NonMaterializedCondition) {
else_block->AddInstruction(new (&allocator) HReturn(constant1));
ASSERT_FALSE(equal->IsEmittedAtUseSite());
- TransformToSsa(graph);
+ graph->BuildDominatorTree();
PrepareForRegisterAllocation(graph).Run();
ASSERT_TRUE(equal->IsEmittedAtUseSite());
@@ -723,7 +717,7 @@ TEST_F(CodegenTest, MaterializedCondition1) {
HReturn ret(&cmp_lt);
code_block->AddInstruction(&ret);
- TransformToSsa(graph);
+ graph->BuildDominatorTree();
auto hook_before_codegen = [](HGraph* graph_in) {
HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
@@ -791,7 +785,7 @@ TEST_F(CodegenTest, MaterializedCondition2) {
HReturn ret_ge(cst_ge);
if_false_block->AddInstruction(&ret_ge);
- TransformToSsa(graph);
+ graph->BuildDominatorTree();
auto hook_before_codegen = [](HGraph* graph_in) {
HBasicBlock* block = graph_in->GetEntryBlock()->GetSuccessors()[0];
HParallelMove* move = new (graph_in->GetArena()) HParallelMove(graph_in->GetArena());
@@ -907,7 +901,7 @@ static void TestComparison(IfCondition condition,
block->AddInstruction(comparison);
block->AddInstruction(new (&allocator) HReturn(comparison));
- TransformToSsa(graph);
+ graph->BuildDominatorTree();
RunCode(target_isa, graph, [](HGraph*) {}, true, expected_result);
}
diff --git a/compiler/optimizing/constant_folding_test.cc b/compiler/optimizing/constant_folding_test.cc
index a8f65bf516..9c69f8c75b 100644
--- a/compiler/optimizing/constant_folding_test.cc
+++ b/compiler/optimizing/constant_folding_test.cc
@@ -56,7 +56,6 @@ class ConstantFoldingTest : public CommonCompilerTest {
const std::string& expected_after_dce,
std::function<void(HGraph*)> check_after_cf) {
ASSERT_NE(graph_, nullptr);
- TransformToSsa(graph_);
StringPrettyPrinter printer_before(graph_);
printer_before.VisitInsertionOrder();
@@ -67,9 +66,9 @@ class ConstantFoldingTest : public CommonCompilerTest {
X86InstructionSetFeatures::FromCppDefines());
x86::CodeGeneratorX86 codegenX86(graph_, *features_x86.get(), CompilerOptions());
HConstantFolding(graph_).Run();
- SSAChecker ssa_checker_cf(graph_);
- ssa_checker_cf.Run();
- ASSERT_TRUE(ssa_checker_cf.IsValid());
+ GraphChecker graph_checker_cf(graph_);
+ graph_checker_cf.Run();
+ ASSERT_TRUE(graph_checker_cf.IsValid());
StringPrettyPrinter printer_after_cf(graph_);
printer_after_cf.VisitInsertionOrder();
@@ -79,9 +78,9 @@ class ConstantFoldingTest : public CommonCompilerTest {
check_after_cf(graph_);
HDeadCodeElimination(graph_).Run();
- SSAChecker ssa_checker_dce(graph_);
- ssa_checker_dce.Run();
- ASSERT_TRUE(ssa_checker_dce.IsValid());
+ GraphChecker graph_checker_dce(graph_);
+ graph_checker_dce.Run();
+ ASSERT_TRUE(graph_checker_dce.IsValid());
StringPrettyPrinter printer_after_dce(graph_);
printer_after_dce.VisitInsertionOrder();
@@ -775,76 +774,87 @@ TEST_F(ConstantFoldingTest, UnsignedComparisonsWithZero) {
HInstruction* zero = graph_->GetIntConstant(0);
HInstruction* last;
block->AddInstruction(last = new (&allocator_) HAbove(zero, parameter));
- block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
+ block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
block->AddInstruction(last = new (&allocator_) HAbove(parameter, zero));
- block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
+ block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
block->AddInstruction(last = new (&allocator_) HAboveOrEqual(zero, parameter));
- block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
+ block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
block->AddInstruction(last = new (&allocator_) HAboveOrEqual(parameter, zero));
- block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
+ block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
block->AddInstruction(last = new (&allocator_) HBelow(zero, parameter));
- block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
+ block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
block->AddInstruction(last = new (&allocator_) HBelow(parameter, zero));
- block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
+ block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
block->AddInstruction(last = new (&allocator_) HBelowOrEqual(zero, parameter));
- block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
+ block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
block->AddInstruction(last = new (&allocator_) HBelowOrEqual(parameter, zero));
- block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
+ block->AddInstruction(new (&allocator_) HSelect(last, parameter, parameter, 0));
entry_block->AddInstruction(new (&allocator_) HGoto());
block->AddInstruction(new (&allocator_) HReturn(zero));
exit_block->AddInstruction(new (&allocator_) HExit());
+ graph_->BuildDominatorTree();
+
const std::string expected_before =
"BasicBlock 0, succ: 1\n"
- " 0: ParameterValue [16, 14, 12, 10, 8, 6, 4, 2]\n"
+ " 0: ParameterValue [17, 17, 16, 15, 15, 14, 13, 13, 12, 11, 11, 10, 9, 9, "
+ "8, 7, 7, 6, 5, 5, 4, 3, 3, 2]\n"
" 1: IntConstant [19, 16, 14, 12, 10, 8, 6, 4, 2]\n"
" 18: Goto 1\n"
"BasicBlock 1, pred: 0, succ: 2\n"
" 2: Above(1, 0) [3]\n"
- " 3: Deoptimize(2)\n"
+ " 3: Select(0, 0, 2)\n"
" 4: Above(0, 1) [5]\n"
- " 5: Deoptimize(4)\n"
+ " 5: Select(0, 0, 4)\n"
" 6: AboveOrEqual(1, 0) [7]\n"
- " 7: Deoptimize(6)\n"
+ " 7: Select(0, 0, 6)\n"
" 8: AboveOrEqual(0, 1) [9]\n"
- " 9: Deoptimize(8)\n"
+ " 9: Select(0, 0, 8)\n"
" 10: Below(1, 0) [11]\n"
- " 11: Deoptimize(10)\n"
+ " 11: Select(0, 0, 10)\n"
" 12: Below(0, 1) [13]\n"
- " 13: Deoptimize(12)\n"
+ " 13: Select(0, 0, 12)\n"
" 14: BelowOrEqual(1, 0) [15]\n"
- " 15: Deoptimize(14)\n"
+ " 15: Select(0, 0, 14)\n"
" 16: BelowOrEqual(0, 1) [17]\n"
- " 17: Deoptimize(16)\n"
+ " 17: Select(0, 0, 16)\n"
" 19: Return(1)\n"
"BasicBlock 2, pred: 1\n"
" 20: Exit\n";
const std::string expected_after_cf =
"BasicBlock 0, succ: 1\n"
- " 0: ParameterValue [16, 10, 6, 4]\n"
+ " 0: ParameterValue [17, 17, 16, 15, 15, 13, 13, 11, 11, 10, 9, 9, 7, 7, 6, 5, 5, 4, 3, 3]\n"
" 1: IntConstant [13, 3, 19, 16, 10, 6, 4]\n"
" 21: IntConstant [15, 9]\n"
" 18: Goto 1\n"
"BasicBlock 1, pred: 0, succ: 2\n"
- " 3: Deoptimize(1)\n"
+ " 3: Select(0, 0, 1)\n"
" 4: Above(0, 1) [5]\n"
- " 5: Deoptimize(4)\n"
+ " 5: Select(0, 0, 4)\n"
" 6: AboveOrEqual(1, 0) [7]\n"
- " 7: Deoptimize(6)\n"
- " 9: Deoptimize(21)\n"
+ " 7: Select(0, 0, 6)\n"
+ " 9: Select(0, 0, 21)\n"
" 10: Below(1, 0) [11]\n"
- " 11: Deoptimize(10)\n"
- " 13: Deoptimize(1)\n"
- " 15: Deoptimize(21)\n"
+ " 11: Select(0, 0, 10)\n"
+ " 13: Select(0, 0, 1)\n"
+ " 15: Select(0, 0, 21)\n"
" 16: BelowOrEqual(0, 1) [17]\n"
- " 17: Deoptimize(16)\n"
+ " 17: Select(0, 0, 16)\n"
" 19: Return(1)\n"
"BasicBlock 2, pred: 1\n"
" 20: Exit\n";
- const std::string expected_after_dce = expected_after_cf;
+ const std::string expected_after_dce =
+ "BasicBlock 0, succ: 1\n"
+ " 0: ParameterValue\n"
+ " 1: IntConstant [19]\n"
+ " 18: Goto 1\n"
+ "BasicBlock 1, pred: 0, succ: 2\n"
+ " 19: Return(1)\n"
+ "BasicBlock 2, pred: 1\n"
+ " 20: Exit\n";
auto check_after_cf = [](HGraph* graph) {
CHECK(graph != nullptr);
diff --git a/compiler/optimizing/dead_code_elimination_test.cc b/compiler/optimizing/dead_code_elimination_test.cc
index f0f98efadb..930795b4f6 100644
--- a/compiler/optimizing/dead_code_elimination_test.cc
+++ b/compiler/optimizing/dead_code_elimination_test.cc
@@ -36,8 +36,6 @@ static void TestCode(const uint16_t* data,
HGraph* graph = CreateCFG(&allocator, data);
ASSERT_NE(graph, nullptr);
- TransformToSsa(graph);
-
StringPrettyPrinter printer_before(graph);
printer_before.VisitInsertionOrder();
std::string actual_before = printer_before.str();
@@ -47,9 +45,9 @@ static void TestCode(const uint16_t* data,
X86InstructionSetFeatures::FromCppDefines());
x86::CodeGeneratorX86 codegenX86(graph, *features_x86.get(), CompilerOptions());
HDeadCodeElimination(graph).Run();
- SSAChecker ssa_checker(graph);
- ssa_checker.Run();
- ASSERT_TRUE(ssa_checker.IsValid());
+ GraphChecker graph_checker(graph);
+ graph_checker.Run();
+ ASSERT_TRUE(graph_checker.IsValid());
StringPrettyPrinter printer_after(graph);
printer_after.VisitInsertionOrder();
diff --git a/compiler/optimizing/dominator_test.cc b/compiler/optimizing/dominator_test.cc
index feb8b2092a..50c677adf5 100644
--- a/compiler/optimizing/dominator_test.cc
+++ b/compiler/optimizing/dominator_test.cc
@@ -24,15 +24,12 @@
namespace art {
+class OptimizerTest : public CommonCompilerTest {};
+
static void TestCode(const uint16_t* data, const uint32_t* blocks, size_t blocks_length) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = CreateGraph(&allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- bool graph_built = builder.BuildGraph(*item);
- ASSERT_TRUE(graph_built);
- graph->BuildDominatorTree();
+ HGraph* graph = CreateCFG(&allocator, data);
ASSERT_EQ(graph->GetBlocks().size(), blocks_length);
for (size_t i = 0, e = blocks_length; i < e; ++i) {
if (blocks[i] == kInvalidBlockId) {
@@ -50,7 +47,7 @@ static void TestCode(const uint16_t* data, const uint32_t* blocks, size_t blocks
}
}
-TEST(OptimizerTest, ReturnVoid) {
+TEST_F(OptimizerTest, ReturnVoid) {
const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Instruction::RETURN_VOID); // Block number 1
@@ -63,7 +60,7 @@ TEST(OptimizerTest, ReturnVoid) {
TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG1) {
+TEST_F(OptimizerTest, CFG1) {
const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Instruction::GOTO | 0x100, // Block number 1
Instruction::RETURN_VOID); // Block number 2
@@ -78,7 +75,7 @@ TEST(OptimizerTest, CFG1) {
TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG2) {
+TEST_F(OptimizerTest, CFG2) {
const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Instruction::GOTO | 0x100, // Block number 1
Instruction::GOTO | 0x100, // Block number 2
@@ -95,7 +92,7 @@ TEST(OptimizerTest, CFG2) {
TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG3) {
+TEST_F(OptimizerTest, CFG3) {
const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Instruction::GOTO | 0x200, // Block number 1
Instruction::RETURN_VOID, // Block number 2
@@ -126,7 +123,7 @@ TEST(OptimizerTest, CFG3) {
TestCode(data3, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG4) {
+TEST_F(OptimizerTest, CFG4) {
const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Instruction::NOP,
Instruction::GOTO | 0xFF00);
@@ -146,7 +143,7 @@ TEST(OptimizerTest, CFG4) {
TestCode(data2, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG5) {
+TEST_F(OptimizerTest, CFG5) {
const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Instruction::RETURN_VOID, // Block number 1
Instruction::GOTO | 0x100, // Dead block
@@ -163,7 +160,7 @@ TEST(OptimizerTest, CFG5) {
TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG6) {
+TEST_F(OptimizerTest, CFG6) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3,
@@ -182,7 +179,7 @@ TEST(OptimizerTest, CFG6) {
TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG7) {
+TEST_F(OptimizerTest, CFG7) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3, // Block number 1
@@ -202,7 +199,7 @@ TEST(OptimizerTest, CFG7) {
TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG8) {
+TEST_F(OptimizerTest, CFG8) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3, // Block number 1
@@ -223,7 +220,7 @@ TEST(OptimizerTest, CFG8) {
TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG9) {
+TEST_F(OptimizerTest, CFG9) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3, // Block number 1
@@ -244,7 +241,7 @@ TEST(OptimizerTest, CFG9) {
TestCode(data, dominators, sizeof(dominators) / sizeof(int));
}
-TEST(OptimizerTest, CFG10) {
+TEST_F(OptimizerTest, CFG10) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 6, // Block number 1
diff --git a/compiler/optimizing/find_loops_test.cc b/compiler/optimizing/find_loops_test.cc
index 4770fa2eca..04789d9a2d 100644
--- a/compiler/optimizing/find_loops_test.cc
+++ b/compiler/optimizing/find_loops_test.cc
@@ -27,16 +27,9 @@
namespace art {
-static HGraph* TestCode(const uint16_t* data, ArenaAllocator* allocator) {
- HGraph* graph = CreateGraph(allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- builder.BuildGraph(*item);
- graph->BuildDominatorTree();
- return graph;
-}
+class FindLoopsTest : public CommonCompilerTest {};
-TEST(FindLoopsTest, CFG1) {
+TEST_F(FindLoopsTest, CFG1) {
// Constant is not used.
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
@@ -44,26 +37,26 @@ TEST(FindLoopsTest, CFG1) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
for (HBasicBlock* block : graph->GetBlocks()) {
ASSERT_EQ(block->GetLoopInformation(), nullptr);
}
}
-TEST(FindLoopsTest, CFG2) {
+TEST_F(FindLoopsTest, CFG2) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::RETURN);
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
for (HBasicBlock* block : graph->GetBlocks()) {
ASSERT_EQ(block->GetLoopInformation(), nullptr);
}
}
-TEST(FindLoopsTest, CFG3) {
+TEST_F(FindLoopsTest, CFG3) {
const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
Instruction::CONST_4 | 3 << 12 | 0,
Instruction::CONST_4 | 4 << 12 | 1 << 8,
@@ -73,13 +66,13 @@ TEST(FindLoopsTest, CFG3) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
for (HBasicBlock* block : graph->GetBlocks()) {
ASSERT_EQ(block->GetLoopInformation(), nullptr);
}
}
-TEST(FindLoopsTest, CFG4) {
+TEST_F(FindLoopsTest, CFG4) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 4,
@@ -90,13 +83,13 @@ TEST(FindLoopsTest, CFG4) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
for (HBasicBlock* block : graph->GetBlocks()) {
ASSERT_EQ(block->GetLoopInformation(), nullptr);
}
}
-TEST(FindLoopsTest, CFG5) {
+TEST_F(FindLoopsTest, CFG5) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3,
@@ -105,7 +98,7 @@ TEST(FindLoopsTest, CFG5) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
for (HBasicBlock* block : graph->GetBlocks()) {
ASSERT_EQ(block->GetLoopInformation(), nullptr);
}
@@ -137,7 +130,7 @@ static void TestBlock(HGraph* graph,
}
}
-TEST(FindLoopsTest, Loop1) {
+TEST_F(FindLoopsTest, Loop1) {
// Simple loop with one preheader and one back edge.
// var a = 0;
// while (a == a) {
@@ -151,7 +144,7 @@ TEST(FindLoopsTest, Loop1) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
TestBlock(graph, 0, false, kInvalidBlockId); // entry block
TestBlock(graph, 1, false, kInvalidBlockId); // pre header
@@ -162,7 +155,7 @@ TEST(FindLoopsTest, Loop1) {
TestBlock(graph, 5, false, kInvalidBlockId); // exit block
}
-TEST(FindLoopsTest, Loop2) {
+TEST_F(FindLoopsTest, Loop2) {
// Make sure we support a preheader of a loop not being the first predecessor
// in the predecessor list of the header.
// var a = 0;
@@ -179,7 +172,7 @@ TEST(FindLoopsTest, Loop2) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
TestBlock(graph, 0, false, kInvalidBlockId); // entry block
TestBlock(graph, 1, false, kInvalidBlockId); // goto block
@@ -191,7 +184,7 @@ TEST(FindLoopsTest, Loop2) {
TestBlock(graph, 6, false, kInvalidBlockId); // exit block
}
-TEST(FindLoopsTest, Loop3) {
+TEST_F(FindLoopsTest, Loop3) {
// Make sure we create a preheader of a loop when a header originally has two
// incoming blocks and one back edge.
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
@@ -204,7 +197,7 @@ TEST(FindLoopsTest, Loop3) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
TestBlock(graph, 0, false, kInvalidBlockId); // entry block
TestBlock(graph, 1, false, kInvalidBlockId); // goto block
@@ -218,7 +211,7 @@ TEST(FindLoopsTest, Loop3) {
TestBlock(graph, 8, false, kInvalidBlockId); // synthesized pre header
}
-TEST(FindLoopsTest, Loop4) {
+TEST_F(FindLoopsTest, Loop4) {
// Test loop with originally two back edges.
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
@@ -230,7 +223,7 @@ TEST(FindLoopsTest, Loop4) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
TestBlock(graph, 0, false, kInvalidBlockId); // entry block
TestBlock(graph, 1, false, kInvalidBlockId); // pre header
@@ -244,7 +237,7 @@ TEST(FindLoopsTest, Loop4) {
}
-TEST(FindLoopsTest, Loop5) {
+TEST_F(FindLoopsTest, Loop5) {
// Test loop with two exit edges.
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
@@ -256,7 +249,7 @@ TEST(FindLoopsTest, Loop5) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
TestBlock(graph, 0, false, kInvalidBlockId); // entry block
TestBlock(graph, 1, false, kInvalidBlockId); // pre header
@@ -270,7 +263,7 @@ TEST(FindLoopsTest, Loop5) {
TestBlock(graph, 8, false, kInvalidBlockId); // synthesized block at the loop exit
}
-TEST(FindLoopsTest, InnerLoop) {
+TEST_F(FindLoopsTest, InnerLoop) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 6,
@@ -281,7 +274,7 @@ TEST(FindLoopsTest, InnerLoop) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
TestBlock(graph, 0, false, kInvalidBlockId); // entry block
TestBlock(graph, 1, false, kInvalidBlockId); // pre header of outer loop
@@ -301,7 +294,7 @@ TEST(FindLoopsTest, InnerLoop) {
*graph->GetBlocks()[3]->GetLoopInformation()));
}
-TEST(FindLoopsTest, TwoLoops) {
+TEST_F(FindLoopsTest, TwoLoops) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3,
@@ -312,7 +305,7 @@ TEST(FindLoopsTest, TwoLoops) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
TestBlock(graph, 0, false, kInvalidBlockId); // entry block
TestBlock(graph, 1, false, kInvalidBlockId); // pre header of first loop
@@ -331,7 +324,7 @@ TEST(FindLoopsTest, TwoLoops) {
*graph->GetBlocks()[4]->GetLoopInformation()));
}
-TEST(FindLoopsTest, NonNaturalLoop) {
+TEST_F(FindLoopsTest, NonNaturalLoop) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3,
@@ -342,14 +335,14 @@ TEST(FindLoopsTest, NonNaturalLoop) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
ASSERT_TRUE(graph->GetBlocks()[3]->IsLoopHeader());
HLoopInformation* info = graph->GetBlocks()[3]->GetLoopInformation();
ASSERT_EQ(1u, info->NumberOfBackEdges());
ASSERT_FALSE(info->GetHeader()->Dominates(info->GetBackEdges()[0]));
}
-TEST(FindLoopsTest, DoWhileLoop) {
+TEST_F(FindLoopsTest, DoWhileLoop) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::GOTO | 0x0100,
@@ -358,7 +351,7 @@ TEST(FindLoopsTest, DoWhileLoop) {
ArenaPool arena;
ArenaAllocator allocator(&arena);
- HGraph* graph = TestCode(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
TestBlock(graph, 0, false, kInvalidBlockId); // entry block
TestBlock(graph, 1, false, kInvalidBlockId); // pre header of first loop
diff --git a/compiler/optimizing/graph_checker.cc b/compiler/optimizing/graph_checker.cc
index 962e77dfc9..e6e9177841 100644
--- a/compiler/optimizing/graph_checker.cc
+++ b/compiler/optimizing/graph_checker.cc
@@ -149,6 +149,103 @@ void GraphChecker::VisitBasicBlock(HBasicBlock* block) {
}
current->Accept(this);
}
+
+ // Ensure that catch blocks are not normal successors, and normal blocks are
+ // never exceptional successors.
+ for (HBasicBlock* successor : block->GetNormalSuccessors()) {
+ if (successor->IsCatchBlock()) {
+ AddError(StringPrintf("Catch block %d is a normal successor of block %d.",
+ successor->GetBlockId(),
+ block->GetBlockId()));
+ }
+ }
+ for (HBasicBlock* successor : block->GetExceptionalSuccessors()) {
+ if (!successor->IsCatchBlock()) {
+ AddError(StringPrintf("Normal block %d is an exceptional successor of block %d.",
+ successor->GetBlockId(),
+ block->GetBlockId()));
+ }
+ }
+
+ // Ensure dominated blocks have `block` as the dominator.
+ for (HBasicBlock* dominated : block->GetDominatedBlocks()) {
+ if (dominated->GetDominator() != block) {
+ AddError(StringPrintf("Block %d should be the dominator of %d.",
+ block->GetBlockId(),
+ dominated->GetBlockId()));
+ }
+ }
+
+ // Ensure there is no critical edge (i.e., an edge connecting a
+ // block with multiple successors to a block with multiple
+ // predecessors). Exceptional edges are synthesized and hence
+ // not accounted for.
+ if (block->GetSuccessors().size() > 1) {
+ for (HBasicBlock* successor : block->GetNormalSuccessors()) {
+ if (successor->IsExitBlock() &&
+ block->IsSingleTryBoundary() &&
+ block->GetPredecessors().size() == 1u &&
+ block->GetSinglePredecessor()->GetLastInstruction()->IsThrow()) {
+ // Allowed critical edge Throw->TryBoundary->Exit.
+ } else if (successor->GetPredecessors().size() > 1) {
+ AddError(StringPrintf("Critical edge between blocks %d and %d.",
+ block->GetBlockId(),
+ successor->GetBlockId()));
+ }
+ }
+ }
+
+ // Ensure try membership information is consistent.
+ if (block->IsCatchBlock()) {
+ if (block->IsTryBlock()) {
+ const HTryBoundary& try_entry = block->GetTryCatchInformation()->GetTryEntry();
+ AddError(StringPrintf("Catch blocks should not be try blocks but catch block %d "
+ "has try entry %s:%d.",
+ block->GetBlockId(),
+ try_entry.DebugName(),
+ try_entry.GetId()));
+ }
+
+ if (block->IsLoopHeader()) {
+ AddError(StringPrintf("Catch blocks should not be loop headers but catch block %d is.",
+ block->GetBlockId()));
+ }
+ } else {
+ for (HBasicBlock* predecessor : block->GetPredecessors()) {
+ const HTryBoundary* incoming_try_entry = predecessor->ComputeTryEntryOfSuccessors();
+ if (block->IsTryBlock()) {
+ const HTryBoundary& stored_try_entry = block->GetTryCatchInformation()->GetTryEntry();
+ if (incoming_try_entry == nullptr) {
+ AddError(StringPrintf("Block %d has try entry %s:%d but no try entry follows "
+ "from predecessor %d.",
+ block->GetBlockId(),
+ stored_try_entry.DebugName(),
+ stored_try_entry.GetId(),
+ predecessor->GetBlockId()));
+ } else if (!incoming_try_entry->HasSameExceptionHandlersAs(stored_try_entry)) {
+ AddError(StringPrintf("Block %d has try entry %s:%d which is not consistent "
+ "with %s:%d that follows from predecessor %d.",
+ block->GetBlockId(),
+ stored_try_entry.DebugName(),
+ stored_try_entry.GetId(),
+ incoming_try_entry->DebugName(),
+ incoming_try_entry->GetId(),
+ predecessor->GetBlockId()));
+ }
+ } else if (incoming_try_entry != nullptr) {
+ AddError(StringPrintf("Block %d is not a try block but try entry %s:%d follows "
+ "from predecessor %d.",
+ block->GetBlockId(),
+ incoming_try_entry->DebugName(),
+ incoming_try_entry->GetId(),
+ predecessor->GetBlockId()));
+ }
+ }
+ }
+
+ if (block->IsLoopHeader()) {
+ HandleLoop(block);
+ }
}
void GraphChecker::VisitBoundsCheck(HBoundsCheck* check) {
@@ -168,7 +265,7 @@ void GraphChecker::VisitTryBoundary(HTryBoundary* try_boundary) {
// Ensure that all exception handlers are catch blocks.
// Note that a normal-flow successor may be a catch block before CFG
- // simplification. We only test normal-flow successors in SsaChecker.
+ // simplification. We only test normal-flow successors in GraphChecker.
for (HBasicBlock* handler : handlers) {
if (!handler->IsCatchBlock()) {
AddError(StringPrintf("Block %d with %s:%d has exceptional successor %d which "
@@ -303,6 +400,88 @@ void GraphChecker::VisitInstruction(HInstruction* instruction) {
input->GetId()));
}
}
+
+ // Ensure an instruction dominates all its uses.
+ for (HUseIterator<HInstruction*> use_it(instruction->GetUses());
+ !use_it.Done(); use_it.Advance()) {
+ HInstruction* use = use_it.Current()->GetUser();
+ if (!use->IsPhi() && !instruction->StrictlyDominates(use)) {
+ AddError(StringPrintf("Instruction %s:%d in block %d does not dominate "
+ "use %s:%d in block %d.",
+ instruction->DebugName(),
+ instruction->GetId(),
+ current_block_->GetBlockId(),
+ use->DebugName(),
+ use->GetId(),
+ use->GetBlock()->GetBlockId()));
+ }
+ }
+
+ if (instruction->NeedsEnvironment() && !instruction->HasEnvironment()) {
+ AddError(StringPrintf("Instruction %s:%d in block %d requires an environment "
+ "but does not have one.",
+ instruction->DebugName(),
+ instruction->GetId(),
+ current_block_->GetBlockId()));
+ }
+
+ // Ensure an instruction having an environment is dominated by the
+ // instructions contained in the environment.
+ for (HEnvironment* environment = instruction->GetEnvironment();
+ environment != nullptr;
+ environment = environment->GetParent()) {
+ for (size_t i = 0, e = environment->Size(); i < e; ++i) {
+ HInstruction* env_instruction = environment->GetInstructionAt(i);
+ if (env_instruction != nullptr
+ && !env_instruction->StrictlyDominates(instruction)) {
+ AddError(StringPrintf("Instruction %d in environment of instruction %d "
+ "from block %d does not dominate instruction %d.",
+ env_instruction->GetId(),
+ instruction->GetId(),
+ current_block_->GetBlockId(),
+ instruction->GetId()));
+ }
+ }
+ }
+
+ // Ensure that reference type instructions have reference type info.
+ if (instruction->GetType() == Primitive::kPrimNot) {
+ ScopedObjectAccess soa(Thread::Current());
+ if (!instruction->GetReferenceTypeInfo().IsValid()) {
+ AddError(StringPrintf("Reference type instruction %s:%d does not have "
+ "valid reference type information.",
+ instruction->DebugName(),
+ instruction->GetId()));
+ }
+ }
+
+ if (instruction->CanThrowIntoCatchBlock()) {
+ // Find the top-level environment. This corresponds to the environment of
+ // the catch block since we do not inline methods with try/catch.
+ HEnvironment* environment = instruction->GetEnvironment();
+ while (environment->GetParent() != nullptr) {
+ environment = environment->GetParent();
+ }
+
+ // Find all catch blocks and test that `instruction` has an environment
+ // value for each one.
+ const HTryBoundary& entry = instruction->GetBlock()->GetTryCatchInformation()->GetTryEntry();
+ for (HBasicBlock* catch_block : entry.GetExceptionHandlers()) {
+ for (HInstructionIterator phi_it(catch_block->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
+ HPhi* catch_phi = phi_it.Current()->AsPhi();
+ if (environment->GetInstructionAt(catch_phi->GetRegNumber()) == nullptr) {
+ AddError(StringPrintf("Instruction %s:%d throws into catch block %d "
+ "with catch phi %d for vreg %d but its "
+ "corresponding environment slot is empty.",
+ instruction->DebugName(),
+ instruction->GetId(),
+ catch_block->GetBlockId(),
+ catch_phi->GetId(),
+ catch_phi->GetRegNumber()));
+ }
+ }
+ }
+ }
}
void GraphChecker::VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) {
@@ -371,108 +550,7 @@ void GraphChecker::VisitInstanceOf(HInstanceOf* instruction) {
}
}
-void SSAChecker::VisitBasicBlock(HBasicBlock* block) {
- super_type::VisitBasicBlock(block);
-
- // Ensure that catch blocks are not normal successors, and normal blocks are
- // never exceptional successors.
- for (HBasicBlock* successor : block->GetNormalSuccessors()) {
- if (successor->IsCatchBlock()) {
- AddError(StringPrintf("Catch block %d is a normal successor of block %d.",
- successor->GetBlockId(),
- block->GetBlockId()));
- }
- }
- for (HBasicBlock* successor : block->GetExceptionalSuccessors()) {
- if (!successor->IsCatchBlock()) {
- AddError(StringPrintf("Normal block %d is an exceptional successor of block %d.",
- successor->GetBlockId(),
- block->GetBlockId()));
- }
- }
-
- // Ensure dominated blocks have `block` as the dominator.
- for (HBasicBlock* dominated : block->GetDominatedBlocks()) {
- if (dominated->GetDominator() != block) {
- AddError(StringPrintf("Block %d should be the dominator of %d.",
- block->GetBlockId(),
- dominated->GetBlockId()));
- }
- }
-
- // Ensure there is no critical edge (i.e., an edge connecting a
- // block with multiple successors to a block with multiple
- // predecessors). Exceptional edges are synthesized and hence
- // not accounted for.
- if (block->GetSuccessors().size() > 1) {
- for (HBasicBlock* successor : block->GetNormalSuccessors()) {
- if (successor->IsExitBlock() &&
- block->IsSingleTryBoundary() &&
- block->GetPredecessors().size() == 1u &&
- block->GetSinglePredecessor()->GetLastInstruction()->IsThrow()) {
- // Allowed critical edge Throw->TryBoundary->Exit.
- } else if (successor->GetPredecessors().size() > 1) {
- AddError(StringPrintf("Critical edge between blocks %d and %d.",
- block->GetBlockId(),
- successor->GetBlockId()));
- }
- }
- }
-
- // Ensure try membership information is consistent.
- if (block->IsCatchBlock()) {
- if (block->IsTryBlock()) {
- const HTryBoundary& try_entry = block->GetTryCatchInformation()->GetTryEntry();
- AddError(StringPrintf("Catch blocks should not be try blocks but catch block %d "
- "has try entry %s:%d.",
- block->GetBlockId(),
- try_entry.DebugName(),
- try_entry.GetId()));
- }
-
- if (block->IsLoopHeader()) {
- AddError(StringPrintf("Catch blocks should not be loop headers but catch block %d is.",
- block->GetBlockId()));
- }
- } else {
- for (HBasicBlock* predecessor : block->GetPredecessors()) {
- const HTryBoundary* incoming_try_entry = predecessor->ComputeTryEntryOfSuccessors();
- if (block->IsTryBlock()) {
- const HTryBoundary& stored_try_entry = block->GetTryCatchInformation()->GetTryEntry();
- if (incoming_try_entry == nullptr) {
- AddError(StringPrintf("Block %d has try entry %s:%d but no try entry follows "
- "from predecessor %d.",
- block->GetBlockId(),
- stored_try_entry.DebugName(),
- stored_try_entry.GetId(),
- predecessor->GetBlockId()));
- } else if (!incoming_try_entry->HasSameExceptionHandlersAs(stored_try_entry)) {
- AddError(StringPrintf("Block %d has try entry %s:%d which is not consistent "
- "with %s:%d that follows from predecessor %d.",
- block->GetBlockId(),
- stored_try_entry.DebugName(),
- stored_try_entry.GetId(),
- incoming_try_entry->DebugName(),
- incoming_try_entry->GetId(),
- predecessor->GetBlockId()));
- }
- } else if (incoming_try_entry != nullptr) {
- AddError(StringPrintf("Block %d is not a try block but try entry %s:%d follows "
- "from predecessor %d.",
- block->GetBlockId(),
- incoming_try_entry->DebugName(),
- incoming_try_entry->GetId(),
- predecessor->GetBlockId()));
- }
- }
- }
-
- if (block->IsLoopHeader()) {
- CheckLoop(block);
- }
-}
-
-void SSAChecker::CheckLoop(HBasicBlock* loop_header) {
+void GraphChecker::HandleLoop(HBasicBlock* loop_header) {
int id = loop_header->GetBlockId();
HLoopInformation* loop_information = loop_header->GetLoopInformation();
@@ -582,92 +660,6 @@ void SSAChecker::CheckLoop(HBasicBlock* loop_header) {
}
}
-void SSAChecker::VisitInstruction(HInstruction* instruction) {
- super_type::VisitInstruction(instruction);
-
- // Ensure an instruction dominates all its uses.
- for (HUseIterator<HInstruction*> use_it(instruction->GetUses());
- !use_it.Done(); use_it.Advance()) {
- HInstruction* use = use_it.Current()->GetUser();
- if (!use->IsPhi() && !instruction->StrictlyDominates(use)) {
- AddError(StringPrintf("Instruction %s:%d in block %d does not dominate "
- "use %s:%d in block %d.",
- instruction->DebugName(),
- instruction->GetId(),
- current_block_->GetBlockId(),
- use->DebugName(),
- use->GetId(),
- use->GetBlock()->GetBlockId()));
- }
- }
-
- if (instruction->NeedsEnvironment() && !instruction->HasEnvironment()) {
- AddError(StringPrintf("Instruction %s:%d in block %d requires an environment "
- "but does not have one.",
- instruction->DebugName(),
- instruction->GetId(),
- current_block_->GetBlockId()));
- }
-
- // Ensure an instruction having an environment is dominated by the
- // instructions contained in the environment.
- for (HEnvironment* environment = instruction->GetEnvironment();
- environment != nullptr;
- environment = environment->GetParent()) {
- for (size_t i = 0, e = environment->Size(); i < e; ++i) {
- HInstruction* env_instruction = environment->GetInstructionAt(i);
- if (env_instruction != nullptr
- && !env_instruction->StrictlyDominates(instruction)) {
- AddError(StringPrintf("Instruction %d in environment of instruction %d "
- "from block %d does not dominate instruction %d.",
- env_instruction->GetId(),
- instruction->GetId(),
- current_block_->GetBlockId(),
- instruction->GetId()));
- }
- }
- }
-
- // Ensure that reference type instructions have reference type info.
- if (instruction->GetType() == Primitive::kPrimNot) {
- ScopedObjectAccess soa(Thread::Current());
- if (!instruction->GetReferenceTypeInfo().IsValid()) {
- AddError(StringPrintf("Reference type instruction %s:%d does not have "
- "valid reference type information.",
- instruction->DebugName(),
- instruction->GetId()));
- }
- }
-
- if (instruction->CanThrowIntoCatchBlock()) {
- // Find the top-level environment. This corresponds to the environment of
- // the catch block since we do not inline methods with try/catch.
- HEnvironment* environment = instruction->GetEnvironment();
- while (environment->GetParent() != nullptr) {
- environment = environment->GetParent();
- }
-
- // Find all catch blocks and test that `instruction` has an environment
- // value for each one.
- const HTryBoundary& entry = instruction->GetBlock()->GetTryCatchInformation()->GetTryEntry();
- for (HBasicBlock* catch_block : entry.GetExceptionHandlers()) {
- for (HInstructionIterator phi_it(catch_block->GetPhis()); !phi_it.Done(); phi_it.Advance()) {
- HPhi* catch_phi = phi_it.Current()->AsPhi();
- if (environment->GetInstructionAt(catch_phi->GetRegNumber()) == nullptr) {
- AddError(StringPrintf("Instruction %s:%d throws into catch block %d "
- "with catch phi %d for vreg %d but its "
- "corresponding environment slot is empty.",
- instruction->DebugName(),
- instruction->GetId(),
- catch_block->GetBlockId(),
- catch_phi->GetId(),
- catch_phi->GetRegNumber()));
- }
- }
- }
- }
-}
-
static Primitive::Type PrimitiveKind(Primitive::Type type) {
switch (type) {
case Primitive::kPrimBoolean:
@@ -710,7 +702,7 @@ static bool IsConstantEquivalent(HInstruction* insn1, HInstruction* insn2, BitVe
}
}
-void SSAChecker::VisitPhi(HPhi* phi) {
+void GraphChecker::VisitPhi(HPhi* phi) {
VisitInstruction(phi);
// Ensure the first input of a phi is not itself.
@@ -846,7 +838,7 @@ void SSAChecker::VisitPhi(HPhi* phi) {
}
}
-void SSAChecker::HandleBooleanInput(HInstruction* instruction, size_t input_index) {
+void GraphChecker::HandleBooleanInput(HInstruction* instruction, size_t input_index) {
HInstruction* input = instruction->InputAt(input_index);
if (input->IsIntConstant()) {
int32_t value = input->AsIntConstant()->GetValue();
@@ -876,7 +868,7 @@ void SSAChecker::HandleBooleanInput(HInstruction* instruction, size_t input_inde
}
}
-void SSAChecker::VisitPackedSwitch(HPackedSwitch* instruction) {
+void GraphChecker::VisitPackedSwitch(HPackedSwitch* instruction) {
VisitInstruction(instruction);
// Check that the number of block successors matches the switch count plus
// one for the default block.
@@ -892,22 +884,22 @@ void SSAChecker::VisitPackedSwitch(HPackedSwitch* instruction) {
}
}
-void SSAChecker::VisitIf(HIf* instruction) {
+void GraphChecker::VisitIf(HIf* instruction) {
VisitInstruction(instruction);
HandleBooleanInput(instruction, 0);
}
-void SSAChecker::VisitSelect(HSelect* instruction) {
+void GraphChecker::VisitSelect(HSelect* instruction) {
VisitInstruction(instruction);
HandleBooleanInput(instruction, 2);
}
-void SSAChecker::VisitBooleanNot(HBooleanNot* instruction) {
+void GraphChecker::VisitBooleanNot(HBooleanNot* instruction) {
VisitInstruction(instruction);
HandleBooleanInput(instruction, 0);
}
-void SSAChecker::VisitCondition(HCondition* op) {
+void GraphChecker::VisitCondition(HCondition* op) {
VisitInstruction(op);
if (op->GetType() != Primitive::kPrimBoolean) {
AddError(StringPrintf(
@@ -937,7 +929,7 @@ void SSAChecker::VisitCondition(HCondition* op) {
}
}
-void SSAChecker::VisitBinaryOperation(HBinaryOperation* op) {
+void GraphChecker::VisitBinaryOperation(HBinaryOperation* op) {
VisitInstruction(op);
if (op->IsUShr() || op->IsShr() || op->IsShl() || op->IsRor()) {
if (PrimitiveKind(op->InputAt(1)->GetType()) != Primitive::kPrimInt) {
@@ -979,7 +971,7 @@ void SSAChecker::VisitBinaryOperation(HBinaryOperation* op) {
}
}
-void SSAChecker::VisitConstant(HConstant* instruction) {
+void GraphChecker::VisitConstant(HConstant* instruction) {
HBasicBlock* block = instruction->GetBlock();
if (!block->IsEntryBlock()) {
AddError(StringPrintf(
@@ -990,7 +982,7 @@ void SSAChecker::VisitConstant(HConstant* instruction) {
}
}
-void SSAChecker::VisitBoundType(HBoundType* instruction) {
+void GraphChecker::VisitBoundType(HBoundType* instruction) {
VisitInstruction(instruction);
ScopedObjectAccess soa(Thread::Current());
diff --git a/compiler/optimizing/graph_checker.h b/compiler/optimizing/graph_checker.h
index 8724cde5dd..52252cd3d4 100644
--- a/compiler/optimizing/graph_checker.h
+++ b/compiler/optimizing/graph_checker.h
@@ -32,34 +32,38 @@ class GraphChecker : public HGraphDelegateVisitor {
dump_prefix_(dump_prefix),
seen_ids_(graph->GetArena(), graph->GetCurrentInstructionId(), false) {}
- // Check the whole graph (in insertion order).
- virtual void Run() { VisitInsertionOrder(); }
+ // Check the whole graph (in reverse post-order).
+ void Run() {
+ // VisitReversePostOrder is used instead of VisitInsertionOrder,
+ // as the latter might visit dead blocks removed by the dominator
+ // computation.
+ VisitReversePostOrder();
+ }
- // Check `block`.
void VisitBasicBlock(HBasicBlock* block) OVERRIDE;
- // Check `instruction`.
void VisitInstruction(HInstruction* instruction) OVERRIDE;
+ void VisitPhi(HPhi* phi) OVERRIDE;
- // Perform control-flow graph checks on instruction.
- void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE;
-
- // Check that the HasBoundsChecks() flag is set for bounds checks.
+ void VisitBinaryOperation(HBinaryOperation* op) OVERRIDE;
+ void VisitBooleanNot(HBooleanNot* instruction) OVERRIDE;
+ void VisitBoundType(HBoundType* instruction) OVERRIDE;
void VisitBoundsCheck(HBoundsCheck* check) OVERRIDE;
-
- // Check successors of blocks ending in TryBoundary.
- void VisitTryBoundary(HTryBoundary* try_boundary) OVERRIDE;
-
- // Check that LoadException is the first instruction in a catch block.
- void VisitLoadException(HLoadException* load) OVERRIDE;
-
- // Check that HCheckCast and HInstanceOf have HLoadClass as second input.
void VisitCheckCast(HCheckCast* check) OVERRIDE;
+ void VisitCondition(HCondition* op) OVERRIDE;
+ void VisitConstant(HConstant* instruction) OVERRIDE;
+ void VisitIf(HIf* instruction) OVERRIDE;
void VisitInstanceOf(HInstanceOf* check) OVERRIDE;
-
- // Check that the Return and ReturnVoid jump to the exit block.
+ void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE;
+ void VisitLoadException(HLoadException* load) OVERRIDE;
+ void VisitPackedSwitch(HPackedSwitch* instruction) OVERRIDE;
void VisitReturn(HReturn* ret) OVERRIDE;
void VisitReturnVoid(HReturnVoid* ret) OVERRIDE;
+ void VisitSelect(HSelect* instruction) OVERRIDE;
+ void VisitTryBoundary(HTryBoundary* try_boundary) OVERRIDE;
+
+ void HandleLoop(HBasicBlock* loop_header);
+ void HandleBooleanInput(HInstruction* instruction, size_t input_index);
// Was the last visit of the graph valid?
bool IsValid() const {
@@ -97,46 +101,6 @@ class GraphChecker : public HGraphDelegateVisitor {
DISALLOW_COPY_AND_ASSIGN(GraphChecker);
};
-
-// An SSA graph visitor performing various checks.
-class SSAChecker : public GraphChecker {
- public:
- typedef GraphChecker super_type;
-
- explicit SSAChecker(HGraph* graph)
- : GraphChecker(graph, "art::SSAChecker: ") {}
-
- // Check the whole graph (in reverse post-order).
- void Run() OVERRIDE {
- // VisitReversePostOrder is used instead of VisitInsertionOrder,
- // as the latter might visit dead blocks removed by the dominator
- // computation.
- VisitReversePostOrder();
- }
-
- // Perform SSA form checks on `block`.
- void VisitBasicBlock(HBasicBlock* block) OVERRIDE;
- // Loop-related checks from block `loop_header`.
- void CheckLoop(HBasicBlock* loop_header);
-
- // Perform SSA form checks on instructions.
- void VisitInstruction(HInstruction* instruction) OVERRIDE;
- void VisitPhi(HPhi* phi) OVERRIDE;
- void VisitBinaryOperation(HBinaryOperation* op) OVERRIDE;
- void VisitCondition(HCondition* op) OVERRIDE;
- void VisitIf(HIf* instruction) OVERRIDE;
- void VisitPackedSwitch(HPackedSwitch* instruction) OVERRIDE;
- void VisitSelect(HSelect* instruction) OVERRIDE;
- void VisitBooleanNot(HBooleanNot* instruction) OVERRIDE;
- void VisitConstant(HConstant* instruction) OVERRIDE;
- void VisitBoundType(HBoundType* instruction) OVERRIDE;
-
- void HandleBooleanInput(HInstruction* instruction, size_t input_index);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SSAChecker);
-};
-
} // namespace art
#endif // ART_COMPILER_OPTIMIZING_GRAPH_CHECKER_H_
diff --git a/compiler/optimizing/graph_checker_test.cc b/compiler/optimizing/graph_checker_test.cc
index d10df4ce3f..659141fbf4 100644
--- a/compiler/optimizing/graph_checker_test.cc
+++ b/compiler/optimizing/graph_checker_test.cc
@@ -52,28 +52,16 @@ static void TestCode(const uint16_t* data) {
ASSERT_TRUE(graph_checker.IsValid());
}
-static void TestCodeSSA(const uint16_t* data) {
- ArenaPool pool;
- ArenaAllocator allocator(&pool);
- HGraph* graph = CreateCFG(&allocator, data);
- ASSERT_NE(graph, nullptr);
-
- TransformToSsa(graph);
+class GraphCheckerTest : public CommonCompilerTest {};
- SSAChecker ssa_checker(graph);
- ssa_checker.Run();
- ASSERT_TRUE(ssa_checker.IsValid());
-}
-
-
-TEST(GraphChecker, ReturnVoid) {
+TEST_F(GraphCheckerTest, ReturnVoid) {
const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Instruction::RETURN_VOID);
TestCode(data);
}
-TEST(GraphChecker, CFG1) {
+TEST_F(GraphCheckerTest, CFG1) {
const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Instruction::GOTO | 0x100,
Instruction::RETURN_VOID);
@@ -81,7 +69,7 @@ TEST(GraphChecker, CFG1) {
TestCode(data);
}
-TEST(GraphChecker, CFG2) {
+TEST_F(GraphCheckerTest, CFG2) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3,
@@ -91,7 +79,7 @@ TEST(GraphChecker, CFG2) {
TestCode(data);
}
-TEST(GraphChecker, CFG3) {
+TEST_F(GraphCheckerTest, CFG3) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 3,
@@ -103,7 +91,7 @@ TEST(GraphChecker, CFG3) {
// Test case with an invalid graph containing inconsistent
// predecessor/successor arcs in CFG.
-TEST(GraphChecker, InconsistentPredecessorsAndSuccessors) {
+TEST_F(GraphCheckerTest, InconsistentPredecessorsAndSuccessors) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
@@ -121,7 +109,7 @@ TEST(GraphChecker, InconsistentPredecessorsAndSuccessors) {
// Test case with an invalid graph containing a non-branch last
// instruction in a block.
-TEST(GraphChecker, BlockEndingWithNonBranchInstruction) {
+TEST_F(GraphCheckerTest, BlockEndingWithNonBranchInstruction) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
@@ -141,9 +129,7 @@ TEST(GraphChecker, BlockEndingWithNonBranchInstruction) {
ASSERT_FALSE(graph_checker.IsValid());
}
-class SSACheckerTest : public CommonCompilerTest {};
-
-TEST_F(SSACheckerTest, SSAPhi) {
+TEST_F(GraphCheckerTest, SSAPhi) {
// This code creates one Phi function during the conversion to SSA form.
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
@@ -151,7 +137,7 @@ TEST_F(SSACheckerTest, SSAPhi) {
Instruction::CONST_4 | 4 << 12 | 0,
Instruction::RETURN | 0 << 8);
- TestCodeSSA(data);
+ TestCode(data);
}
} // namespace art
diff --git a/compiler/optimizing/graph_visualizer.cc b/compiler/optimizing/graph_visualizer.cc
index 63b8fd05c0..4cf0eb1565 100644
--- a/compiler/optimizing/graph_visualizer.cc
+++ b/compiler/optimizing/graph_visualizer.cc
@@ -22,6 +22,7 @@
#include <sstream>
#include "bounds_check_elimination.h"
+#include "builder.h"
#include "code_generator.h"
#include "dead_code_elimination.h"
#include "disassembler.h"
@@ -31,7 +32,6 @@
#include "optimization.h"
#include "reference_type_propagation.h"
#include "register_allocator.h"
-#include "ssa_builder.h"
#include "ssa_liveness_analysis.h"
#include "utils/assembler.h"
@@ -510,7 +510,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
|| IsPass(HDeadCodeElimination::kInitialDeadCodeEliminationPassName)
|| IsPass(BoundsCheckElimination::kBoundsCheckEliminationPassName)
|| IsPass(RegisterAllocator::kRegisterAllocatorPassName)
- || IsPass(SsaBuilder::kSsaBuilderPassName)) {
+ || IsPass(HGraphBuilder::kBuilderPassName)) {
HLoopInformation* info = instruction->GetBlock()->GetLoopInformation();
if (info == nullptr) {
StartAttributeStream("loop") << "none";
@@ -527,7 +527,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
}
}
- if ((IsPass(SsaBuilder::kSsaBuilderPassName)
+ if ((IsPass(HGraphBuilder::kBuilderPassName)
|| IsPass(HInliner::kInlinerPassName))
&& (instruction->GetType() == Primitive::kPrimNot)) {
ReferenceTypeInfo info = instruction->IsLoadClass()
@@ -547,7 +547,7 @@ class HGraphVisualizerPrinter : public HGraphDelegateVisitor {
// doesn't run or doesn't inline anything, the NullConstant remains untyped.
// So we should check NullConstants for validity only after reference type propagation.
DCHECK(graph_in_bad_state_ ||
- (!is_after_pass_ && IsPass(SsaBuilder::kSsaBuilderPassName)))
+ (!is_after_pass_ && IsPass(HGraphBuilder::kBuilderPassName)))
<< instruction->DebugName() << instruction->GetId() << " has invalid rti "
<< (is_after_pass_ ? "after" : "before") << " pass " << pass_name_;
}
diff --git a/compiler/optimizing/gvn_test.cc b/compiler/optimizing/gvn_test.cc
index 1f4eaf3cfd..56dc08826b 100644
--- a/compiler/optimizing/gvn_test.cc
+++ b/compiler/optimizing/gvn_test.cc
@@ -100,7 +100,7 @@ TEST_F(GVNTest, LocalFieldElimination) {
ASSERT_EQ(different_offset->GetBlock(), block);
ASSERT_EQ(use_after_kill->GetBlock(), block);
- TransformToSsa(graph);
+ graph->BuildDominatorTree();
SideEffectsAnalysis side_effects(graph);
side_effects.Run();
GVNOptimization(graph, side_effects).Run();
@@ -182,7 +182,7 @@ TEST_F(GVNTest, GlobalFieldElimination) {
0));
join->AddInstruction(new (&allocator) HExit());
- TransformToSsa(graph);
+ graph->BuildDominatorTree();
SideEffectsAnalysis side_effects(graph);
side_effects.Run();
GVNOptimization(graph, side_effects).Run();
@@ -288,7 +288,7 @@ TEST_F(GVNTest, LoopFieldElimination) {
ASSERT_EQ(field_get_in_loop_body->GetBlock(), loop_body);
ASSERT_EQ(field_get_in_exit->GetBlock(), exit);
- TransformToSsa(graph);
+ graph->BuildDominatorTree();
{
SideEffectsAnalysis side_effects(graph);
side_effects.Run();
@@ -364,7 +364,7 @@ TEST_F(GVNTest, LoopSideEffects) {
inner_loop_exit->AddInstruction(new (&allocator) HGoto());
outer_loop_exit->AddInstruction(new (&allocator) HExit());
- TransformToSsa(graph);
+ graph->BuildDominatorTree();
ASSERT_TRUE(inner_loop_header->GetLoopInformation()->IsIn(
*outer_loop_header->GetLoopInformation()));
diff --git a/compiler/optimizing/induction_var_analysis_test.cc b/compiler/optimizing/induction_var_analysis_test.cc
index 29a1845658..fd197bc7a6 100644
--- a/compiler/optimizing/induction_var_analysis_test.cc
+++ b/compiler/optimizing/induction_var_analysis_test.cc
@@ -86,39 +86,28 @@ class InductionVarAnalysisTest : public CommonCompilerTest {
constant1_ = graph_->GetIntConstant(1);
constant100_ = graph_->GetIntConstant(100);
float_constant0_ = graph_->GetFloatConstant(0.0f);
- induc_ = new (&allocator_) HLocal(n);
- entry_->AddInstruction(induc_);
- entry_->AddInstruction(new (&allocator_) HStoreLocal(induc_, constant0_));
- tmp_ = new (&allocator_) HLocal(n + 1);
- entry_->AddInstruction(tmp_);
- entry_->AddInstruction(new (&allocator_) HStoreLocal(tmp_, constant100_));
- dum_ = new (&allocator_) HLocal(n + 2);
- entry_->AddInstruction(dum_);
return_->AddInstruction(new (&allocator_) HReturnVoid());
exit_->AddInstruction(new (&allocator_) HExit());
// Provide loop instructions.
for (int d = 0; d < n; d++) {
- basic_[d] = new (&allocator_) HLocal(d);
- entry_->AddInstruction(basic_[d]);
- loop_preheader_[d]->AddInstruction(new (&allocator_) HStoreLocal(basic_[d], constant0_));
+ basic_[d] = new (&allocator_) HPhi(&allocator_, d, 0, Primitive::kPrimInt);
loop_preheader_[d]->AddInstruction(new (&allocator_) HGoto());
- HInstruction* load = new (&allocator_) HLoadLocal(basic_[d], Primitive::kPrimInt);
- loop_header_[d]->AddInstruction(load);
- HInstruction* compare = new (&allocator_) HLessThan(load, constant100_);
+ loop_header_[d]->AddPhi(basic_[d]);
+ HInstruction* compare = new (&allocator_) HLessThan(basic_[d], constant100_);
loop_header_[d]->AddInstruction(compare);
loop_header_[d]->AddInstruction(new (&allocator_) HIf(compare));
- load = new (&allocator_) HLoadLocal(basic_[d], Primitive::kPrimInt);
- loop_body_[d]->AddInstruction(load);
- increment_[d] = new (&allocator_) HAdd(Primitive::kPrimInt, load, constant1_);
+ increment_[d] = new (&allocator_) HAdd(Primitive::kPrimInt, basic_[d], constant1_);
loop_body_[d]->AddInstruction(increment_[d]);
- loop_body_[d]->AddInstruction(new (&allocator_) HStoreLocal(basic_[d], increment_[d]));
loop_body_[d]->AddInstruction(new (&allocator_) HGoto());
+
+ basic_[d]->AddInput(constant0_);
+ basic_[d]->AddInput(increment_[d]);
}
}
// Builds if-statement at depth d.
- void BuildIf(int d, HBasicBlock** ifT, HBasicBlock **ifF) {
+ HPhi* BuildIf(int d, HBasicBlock** ifT, HBasicBlock **ifF) {
HBasicBlock* cond = new (&allocator_) HBasicBlock(graph_);
HBasicBlock* ifTrue = new (&allocator_) HBasicBlock(graph_);
HBasicBlock* ifFalse = new (&allocator_) HBasicBlock(graph_);
@@ -134,6 +123,10 @@ class InductionVarAnalysisTest : public CommonCompilerTest {
cond->AddInstruction(new (&allocator_) HIf(parameter_));
*ifT = ifTrue;
*ifF = ifFalse;
+
+ HPhi* select_phi = new (&allocator_) HPhi(&allocator_, -1, 0, Primitive::kPrimInt);
+ loop_body_[d]->AddPhi(select_phi);
+ return select_phi;
}
// Inserts instruction right before increment at depth d.
@@ -142,25 +135,20 @@ class InductionVarAnalysisTest : public CommonCompilerTest {
return instruction;
}
- // Inserts local load at depth d.
- HInstruction* InsertLocalLoad(HLocal* local, int d) {
- return InsertInstruction(new (&allocator_) HLoadLocal(local, Primitive::kPrimInt), d);
- }
-
- // Inserts local store at depth d.
- HInstruction* InsertLocalStore(HLocal* local, HInstruction* rhs, int d) {
- return InsertInstruction(new (&allocator_) HStoreLocal(local, rhs), d);
+ // Inserts a phi to loop header at depth d and returns it.
+ HPhi* InsertLoopPhi(int vreg, int d) {
+ HPhi* phi = new (&allocator_) HPhi(&allocator_, vreg, 0, Primitive::kPrimInt);
+ loop_header_[d]->AddPhi(phi);
+ return phi;
}
- // Inserts an array store with given local as subscript at depth d to
+ // Inserts an array store with given `subscript` at depth d to
// enable tests to inspect the computed induction at that point easily.
- HInstruction* InsertArrayStore(HLocal* subscript, int d) {
- HInstruction* load = InsertInstruction(
- new (&allocator_) HLoadLocal(subscript, Primitive::kPrimInt), d);
+ HInstruction* InsertArrayStore(HInstruction* subscript, int d) {
// ArraySet is given a float value in order to avoid SsaBuilder typing
// it from the array's non-existent reference type info.
return InsertInstruction(new (&allocator_) HArraySet(
- parameter_, load, float_constant0_, Primitive::kPrimFloat, 0), d);
+ parameter_, subscript, float_constant0_, Primitive::kPrimFloat, 0), d);
}
// Returns induction information of instruction in loop at depth d.
@@ -171,7 +159,7 @@ class InductionVarAnalysisTest : public CommonCompilerTest {
// Performs InductionVarAnalysis (after proper set up).
void PerformInductionVarAnalysis() {
- TransformToSsa(graph_);
+ graph_->BuildDominatorTree();
iva_ = new (&allocator_) HInductionVarAnalysis(graph_);
iva_->Run();
}
@@ -191,16 +179,13 @@ class InductionVarAnalysisTest : public CommonCompilerTest {
HInstruction* constant1_;
HInstruction* constant100_;
HInstruction* float_constant0_;
- HLocal* induc_; // "vreg_n", the "k"
- HLocal* tmp_; // "vreg_n+1"
- HLocal* dum_; // "vreg_n+2"
// Loop specifics.
HBasicBlock* loop_preheader_[10];
HBasicBlock* loop_header_[10];
HBasicBlock* loop_body_[10];
HInstruction* increment_[10];
- HLocal* basic_[10]; // "vreg_d", the "i_d"
+ HPhi* basic_[10]; // "vreg_d", the "i_d"
};
//
@@ -216,7 +201,7 @@ TEST_F(InductionVarAnalysisTest, ProperLoopSetup) {
// ..
// }
BuildLoopNest(10);
- TransformToSsa(graph_);
+ graph_->BuildDominatorTree();
ASSERT_EQ(entry_->GetLoopInformation(), nullptr);
for (int d = 0; d < 1; d++) {
ASSERT_EQ(loop_preheader_[d]->GetLoopInformation(),
@@ -258,20 +243,15 @@ TEST_F(InductionVarAnalysisTest, FindDerivedInduction) {
// }
BuildLoopNest(1);
HInstruction *add = InsertInstruction(
- new (&allocator_) HAdd(Primitive::kPrimInt, constant100_, InsertLocalLoad(basic_[0], 0)), 0);
- InsertLocalStore(induc_, add, 0);
+ new (&allocator_) HAdd(Primitive::kPrimInt, constant100_, basic_[0]), 0);
HInstruction *sub = InsertInstruction(
- new (&allocator_) HSub(Primitive::kPrimInt, constant100_, InsertLocalLoad(basic_[0], 0)), 0);
- InsertLocalStore(induc_, sub, 0);
+ new (&allocator_) HSub(Primitive::kPrimInt, constant100_, basic_[0]), 0);
HInstruction *mul = InsertInstruction(
- new (&allocator_) HMul(Primitive::kPrimInt, constant100_, InsertLocalLoad(basic_[0], 0)), 0);
- InsertLocalStore(induc_, mul, 0);
+ new (&allocator_) HMul(Primitive::kPrimInt, constant100_, basic_[0]), 0);
HInstruction *shl = InsertInstruction(
- new (&allocator_) HShl(Primitive::kPrimInt, InsertLocalLoad(basic_[0], 0), constant1_), 0);
- InsertLocalStore(induc_, shl, 0);
+ new (&allocator_) HShl(Primitive::kPrimInt, basic_[0], constant1_), 0);
HInstruction *neg = InsertInstruction(
- new (&allocator_) HNeg(Primitive::kPrimInt, InsertLocalLoad(basic_[0], 0)), 0);
- InsertLocalStore(induc_, neg, 0);
+ new (&allocator_) HNeg(Primitive::kPrimInt, basic_[0]), 0);
PerformInductionVarAnalysis();
EXPECT_STREQ("((1) * i + (100))", GetInductionInfo(add, 0).c_str());
@@ -291,14 +271,16 @@ TEST_F(InductionVarAnalysisTest, FindChainInduction) {
// a[k] = 0;
// }
BuildLoopNest(1);
+ HPhi* k = InsertLoopPhi(0, 0);
+ k->AddInput(constant0_);
+
HInstruction *add = InsertInstruction(
- new (&allocator_) HAdd(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant100_), 0);
- InsertLocalStore(induc_, add, 0);
- HInstruction* store1 = InsertArrayStore(induc_, 0);
+ new (&allocator_) HAdd(Primitive::kPrimInt, k, constant100_), 0);
+ HInstruction* store1 = InsertArrayStore(add, 0);
HInstruction *sub = InsertInstruction(
- new (&allocator_) HSub(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant1_), 0);
- InsertLocalStore(induc_, sub, 0);
- HInstruction* store2 = InsertArrayStore(induc_, 0);
+ new (&allocator_) HSub(Primitive::kPrimInt, add, constant1_), 0);
+ HInstruction* store2 = InsertArrayStore(sub, 0);
+ k->AddInput(sub);
PerformInductionVarAnalysis();
EXPECT_STREQ("(((100) - (1)) * i + (100))",
@@ -316,23 +298,24 @@ TEST_F(InductionVarAnalysisTest, FindTwoWayBasicInduction) {
// a[k] = 0;
// }
BuildLoopNest(1);
+ HPhi* k_header = InsertLoopPhi(0, 0);
+ k_header->AddInput(constant0_);
+
HBasicBlock* ifTrue;
HBasicBlock* ifFalse;
- BuildIf(0, &ifTrue, &ifFalse);
+ HPhi* k_body = BuildIf(0, &ifTrue, &ifFalse);
+
// True-branch.
- HInstruction* load1 = new (&allocator_) HLoadLocal(induc_, Primitive::kPrimInt);
- ifTrue->AddInstruction(load1);
- HInstruction* inc1 = new (&allocator_) HAdd(Primitive::kPrimInt, load1, constant1_);
+ HInstruction* inc1 = new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant1_);
ifTrue->AddInstruction(inc1);
- ifTrue->AddInstruction(new (&allocator_) HStoreLocal(induc_, inc1));
+ k_body->AddInput(inc1);
// False-branch.
- HInstruction* load2 = new (&allocator_) HLoadLocal(induc_, Primitive::kPrimInt);
- ifFalse->AddInstruction(load2);
- HInstruction* inc2 = new (&allocator_) HAdd(Primitive::kPrimInt, load2, constant1_);
+ HInstruction* inc2 = new (&allocator_) HAdd(Primitive::kPrimInt, k_header, constant1_);
ifFalse->AddInstruction(inc2);
- ifFalse->AddInstruction(new (&allocator_) HStoreLocal(induc_, inc2));
+ k_body->AddInput(inc2);
// Merge over a phi.
- HInstruction* store = InsertArrayStore(induc_, 0);
+ HInstruction* store = InsertArrayStore(k_body, 0);
+ k_header->AddInput(k_body);
PerformInductionVarAnalysis();
EXPECT_STREQ("((1) * i + (1))", GetInductionInfo(store->InputAt(1), 0).c_str());
@@ -348,21 +331,18 @@ TEST_F(InductionVarAnalysisTest, FindTwoWayDerivedInduction) {
BuildLoopNest(1);
HBasicBlock* ifTrue;
HBasicBlock* ifFalse;
- BuildIf(0, &ifTrue, &ifFalse);
+ HPhi* k = BuildIf(0, &ifTrue, &ifFalse);
+
// True-branch.
- HInstruction* load1 = new (&allocator_) HLoadLocal(basic_[0], Primitive::kPrimInt);
- ifTrue->AddInstruction(load1);
- HInstruction* inc1 = new (&allocator_) HAdd(Primitive::kPrimInt, load1, constant1_);
+ HInstruction* inc1 = new (&allocator_) HAdd(Primitive::kPrimInt, basic_[0], constant1_);
ifTrue->AddInstruction(inc1);
- ifTrue->AddInstruction(new (&allocator_) HStoreLocal(induc_, inc1));
+ k->AddInput(inc1);
// False-branch.
- HInstruction* load2 = new (&allocator_) HLoadLocal(basic_[0], Primitive::kPrimInt);
- ifFalse->AddInstruction(load2);
- HInstruction* inc2 = new (&allocator_) HAdd(Primitive::kPrimInt, load2, constant1_);
+ HInstruction* inc2 = new (&allocator_) HAdd(Primitive::kPrimInt, basic_[0], constant1_);
ifFalse->AddInstruction(inc2);
- ifFalse->AddInstruction(new (&allocator_) HStoreLocal(induc_, inc2));
+ k->AddInput(inc2);
// Merge over a phi.
- HInstruction* store = InsertArrayStore(induc_, 0);
+ HInstruction* store = InsertArrayStore(k, 0);
PerformInductionVarAnalysis();
EXPECT_STREQ("((1) * i + (1))", GetInductionInfo(store->InputAt(1), 0).c_str());
@@ -376,10 +356,13 @@ TEST_F(InductionVarAnalysisTest, FindFirstOrderWrapAroundInduction) {
// k = 100 - i;
// }
BuildLoopNest(1);
- HInstruction* store = InsertArrayStore(induc_, 0);
+ HPhi* k = InsertLoopPhi(0, 0);
+ k->AddInput(constant0_);
+
+ HInstruction* store = InsertArrayStore(k, 0);
HInstruction *sub = InsertInstruction(
- new (&allocator_) HSub(Primitive::kPrimInt, constant100_, InsertLocalLoad(basic_[0], 0)), 0);
- InsertLocalStore(induc_, sub, 0);
+ new (&allocator_) HSub(Primitive::kPrimInt, constant100_, basic_[0]), 0);
+ k->AddInput(sub);
PerformInductionVarAnalysis();
EXPECT_STREQ("wrap((0), (( - (1)) * i + (100)))",
@@ -396,11 +379,16 @@ TEST_F(InductionVarAnalysisTest, FindSecondOrderWrapAroundInduction) {
// t = 100 - i;
// }
BuildLoopNest(1);
- HInstruction* store = InsertArrayStore(induc_, 0);
- InsertLocalStore(induc_, InsertLocalLoad(tmp_, 0), 0);
+ HPhi* k = InsertLoopPhi(0, 0);
+ k->AddInput(constant0_);
+ HPhi* t = InsertLoopPhi(1, 0);
+ t->AddInput(constant100_);
+
+ HInstruction* store = InsertArrayStore(k, 0);
+ k->AddInput(t);
HInstruction *sub = InsertInstruction(
- new (&allocator_) HSub(Primitive::kPrimInt, constant100_, InsertLocalLoad(basic_[0], 0)), 0);
- InsertLocalStore(tmp_, sub, 0);
+ new (&allocator_) HSub(Primitive::kPrimInt, constant100_, basic_[0], 0), 0);
+ t->AddInput(sub);
PerformInductionVarAnalysis();
EXPECT_STREQ("wrap((0), wrap((100), (( - (1)) * i + (100))))",
@@ -419,26 +407,21 @@ TEST_F(InductionVarAnalysisTest, FindWrapAroundDerivedInduction) {
// k = i << 1;
// }
BuildLoopNest(1);
+ HPhi* k = InsertLoopPhi(0, 0);
+ k->AddInput(constant0_);
+
HInstruction *add = InsertInstruction(
- new (&allocator_) HAdd(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant100_), 0);
- InsertLocalStore(tmp_, add, 0);
+ new (&allocator_) HAdd(Primitive::kPrimInt, k, constant100_), 0);
HInstruction *sub = InsertInstruction(
- new (&allocator_) HSub(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant100_), 0);
- InsertLocalStore(tmp_, sub, 0);
+ new (&allocator_) HSub(Primitive::kPrimInt, k, constant100_), 0);
HInstruction *mul = InsertInstruction(
- new (&allocator_) HMul(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant100_), 0);
- InsertLocalStore(tmp_, mul, 0);
+ new (&allocator_) HMul(Primitive::kPrimInt, k, constant100_), 0);
HInstruction *shl = InsertInstruction(
- new (&allocator_) HShl(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant1_), 0);
- InsertLocalStore(tmp_, shl, 0);
+ new (&allocator_) HShl(Primitive::kPrimInt, k, constant1_), 0);
HInstruction *neg = InsertInstruction(
- new (&allocator_) HNeg(Primitive::kPrimInt, InsertLocalLoad(induc_, 0)), 0);
- InsertLocalStore(tmp_, neg, 0);
- InsertLocalStore(
- induc_,
- InsertInstruction(
- new (&allocator_)
- HShl(Primitive::kPrimInt, InsertLocalLoad(basic_[0], 0), constant1_), 0), 0);
+ new (&allocator_) HNeg(Primitive::kPrimInt, k), 0);
+ k->AddInput(
+ InsertInstruction(new (&allocator_) HShl(Primitive::kPrimInt, basic_[0], constant1_), 0));
PerformInductionVarAnalysis();
EXPECT_STREQ("wrap((100), ((2) * i + (100)))", GetInductionInfo(add, 0).c_str());
@@ -461,11 +444,15 @@ TEST_F(InductionVarAnalysisTest, FindPeriodicInduction) {
// k = d;
// }
BuildLoopNest(1);
- HInstruction* store1 = InsertArrayStore(induc_, 0);
- HInstruction* store2 = InsertArrayStore(tmp_, 0);
- InsertLocalStore(dum_, InsertLocalLoad(tmp_, 0), 0);
- InsertLocalStore(tmp_, InsertLocalLoad(induc_, 0), 0);
- InsertLocalStore(induc_, InsertLocalLoad(dum_, 0), 0);
+ HPhi* k = InsertLoopPhi(0, 0);
+ k->AddInput(constant0_);
+ HPhi* t = InsertLoopPhi(1, 0);
+ t->AddInput(constant100_);
+
+ HInstruction* store1 = InsertArrayStore(k, 0);
+ HInstruction* store2 = InsertArrayStore(t, 0);
+ k->AddInput(t);
+ t->AddInput(k);
PerformInductionVarAnalysis();
EXPECT_STREQ("periodic((0), (100))", GetInductionInfo(store1->InputAt(1), 0).c_str());
@@ -480,10 +467,13 @@ TEST_F(InductionVarAnalysisTest, FindIdiomaticPeriodicInduction) {
// k = 1 - k;
// }
BuildLoopNest(1);
- HInstruction* store = InsertArrayStore(induc_, 0);
+ HPhi* k = InsertLoopPhi(0, 0);
+ k->AddInput(constant0_);
+
+ HInstruction* store = InsertArrayStore(k, 0);
HInstruction *sub = InsertInstruction(
- new (&allocator_) HSub(Primitive::kPrimInt, constant1_, InsertLocalLoad(induc_, 0)), 0);
- InsertLocalStore(induc_, sub, 0);
+ new (&allocator_) HSub(Primitive::kPrimInt, constant1_, k), 0);
+ k->AddInput(sub);
PerformInductionVarAnalysis();
EXPECT_STREQ("periodic((0), (1))", GetInductionInfo(store->InputAt(1), 0).c_str());
@@ -502,26 +492,24 @@ TEST_F(InductionVarAnalysisTest, FindDerivedPeriodicInduction) {
// t = - k;
// }
BuildLoopNest(1);
- InsertLocalStore(
- induc_,
- InsertInstruction(new (&allocator_)
- HSub(Primitive::kPrimInt, constant1_, InsertLocalLoad(induc_, 0)), 0), 0);
+ HPhi* k_header = InsertLoopPhi(0, 0);
+ k_header->AddInput(constant0_);
+
+ HInstruction* k_body = InsertInstruction(
+ new (&allocator_) HSub(Primitive::kPrimInt, constant1_, k_header), 0);
+ k_header->AddInput(k_body);
+
// Derived expressions.
HInstruction *add = InsertInstruction(
- new (&allocator_) HAdd(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant100_), 0);
- InsertLocalStore(tmp_, add, 0);
+ new (&allocator_) HAdd(Primitive::kPrimInt, k_body, constant100_), 0);
HInstruction *sub = InsertInstruction(
- new (&allocator_) HSub(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant100_), 0);
- InsertLocalStore(tmp_, sub, 0);
+ new (&allocator_) HSub(Primitive::kPrimInt, k_body, constant100_), 0);
HInstruction *mul = InsertInstruction(
- new (&allocator_) HMul(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant100_), 0);
- InsertLocalStore(tmp_, mul, 0);
+ new (&allocator_) HMul(Primitive::kPrimInt, k_body, constant100_), 0);
HInstruction *shl = InsertInstruction(
- new (&allocator_) HShl(Primitive::kPrimInt, InsertLocalLoad(induc_, 0), constant1_), 0);
- InsertLocalStore(tmp_, shl, 0);
+ new (&allocator_) HShl(Primitive::kPrimInt, k_body, constant1_), 0);
HInstruction *neg = InsertInstruction(
- new (&allocator_) HNeg(Primitive::kPrimInt, InsertLocalLoad(induc_, 0)), 0);
- InsertLocalStore(tmp_, neg, 0);
+ new (&allocator_) HNeg(Primitive::kPrimInt, k_body), 0);
PerformInductionVarAnalysis();
EXPECT_STREQ("periodic(((1) + (100)), (100))", GetInductionInfo(add, 0).c_str());
@@ -543,10 +531,20 @@ TEST_F(InductionVarAnalysisTest, FindDeepLoopInduction) {
// ..
// }
BuildLoopNest(10);
+
+ HPhi* k[10];
+ for (int d = 0; d < 10; d++) {
+ k[d] = InsertLoopPhi(0, d);
+ }
+
HInstruction *inc = InsertInstruction(
- new (&allocator_) HAdd(Primitive::kPrimInt, constant1_, InsertLocalLoad(induc_, 9)), 9);
- InsertLocalStore(induc_, inc, 9);
- HInstruction* store = InsertArrayStore(induc_, 9);
+ new (&allocator_) HAdd(Primitive::kPrimInt, constant1_, k[9]), 9);
+ HInstruction* store = InsertArrayStore(inc, 9);
+
+ for (int d = 0; d < 10; d++) {
+ k[d]->AddInput((d != 0) ? k[d - 1] : constant0_ );
+ k[d]->AddInput((d != 9) ? k[d + 1] : inc);
+ }
PerformInductionVarAnalysis();
// Avoid exact phi number, since that depends on the SSA building phase.
diff --git a/compiler/optimizing/induction_var_range_test.cc b/compiler/optimizing/induction_var_range_test.cc
index eda9c01a01..55a654e301 100644
--- a/compiler/optimizing/induction_var_range_test.cc
+++ b/compiler/optimizing/induction_var_range_test.cc
@@ -86,25 +86,20 @@ class InductionVarRangeTest : public CommonCompilerTest {
loop_body->AddSuccessor(loop_header);
return_block->AddSuccessor(exit_block_);
// Instructions.
- HLocal* induc = new (&allocator_) HLocal(0);
- entry_block_->AddInstruction(induc);
- loop_preheader_->AddInstruction(
- new (&allocator_) HStoreLocal(induc, graph_->GetIntConstant(lower))); // i = l
loop_preheader_->AddInstruction(new (&allocator_) HGoto());
- HInstruction* load = new (&allocator_) HLoadLocal(induc, Primitive::kPrimInt);
- loop_header->AddInstruction(load);
+ HPhi* phi = new (&allocator_) HPhi(&allocator_, 0, 0, Primitive::kPrimInt);
+ loop_header->AddPhi(phi);
+ phi->AddInput(graph_->GetIntConstant(lower)); // i = l
if (stride > 0) {
- condition_ = new (&allocator_) HLessThan(load, upper); // i < u
+ condition_ = new (&allocator_) HLessThan(phi, upper); // i < u
} else {
- condition_ = new (&allocator_) HGreaterThan(load, upper); // i > u
+ condition_ = new (&allocator_) HGreaterThan(phi, upper); // i > u
}
loop_header->AddInstruction(condition_);
loop_header->AddInstruction(new (&allocator_) HIf(condition_));
- load = new (&allocator_) HLoadLocal(induc, Primitive::kPrimInt);
- loop_body->AddInstruction(load);
- increment_ = new (&allocator_) HAdd(Primitive::kPrimInt, load, graph_->GetIntConstant(stride));
- loop_body->AddInstruction(increment_);
- loop_body->AddInstruction(new (&allocator_) HStoreLocal(induc, increment_)); // i += s
+ increment_ = new (&allocator_) HAdd(Primitive::kPrimInt, phi, graph_->GetIntConstant(stride));
+ loop_body->AddInstruction(increment_); // i += s
+ phi->AddInput(increment_);
loop_body->AddInstruction(new (&allocator_) HGoto());
return_block->AddInstruction(new (&allocator_) HReturnVoid());
exit_block_->AddInstruction(new (&allocator_) HExit());
@@ -112,7 +107,7 @@ class InductionVarRangeTest : public CommonCompilerTest {
/** Constructs SSA and performs induction variable analysis. */
void PerformInductionVarAnalysis() {
- TransformToSsa(graph_);
+ graph_->BuildDominatorTree();
iva_->Run();
}
diff --git a/compiler/optimizing/inliner.cc b/compiler/optimizing/inliner.cc
index 3740c405c1..68e96fba74 100644
--- a/compiler/optimizing/inliner.cc
+++ b/compiler/optimizing/inliner.cc
@@ -829,7 +829,7 @@ bool HInliner::TryBuildAndInline(ArtMethod* resolved_method,
resolved_method->GetQuickenedInfo(),
dex_cache);
- if (!builder.BuildGraph(*code_item)) {
+ if (builder.BuildGraph(*code_item, handles_) != kAnalysisSuccess) {
VLOG(compiler) << "Method " << PrettyMethod(method_index, callee_dex_file)
<< " could not be built, so cannot be inlined";
return false;
@@ -842,12 +842,6 @@ bool HInliner::TryBuildAndInline(ArtMethod* resolved_method,
return false;
}
- if (callee_graph->TryBuildingSsa(handles_) != kAnalysisSuccess) {
- VLOG(compiler) << "Method " << PrettyMethod(method_index, callee_dex_file)
- << " could not be transformed to SSA";
- return false;
- }
-
size_t parameter_index = 0;
for (HInstructionIterator instructions(callee_graph->GetEntryBlock()->GetInstructions());
!instructions.Done();
diff --git a/compiler/optimizing/licm_test.cc b/compiler/optimizing/licm_test.cc
index 2b63ec8971..9fb32f4001 100644
--- a/compiler/optimizing/licm_test.cc
+++ b/compiler/optimizing/licm_test.cc
@@ -76,7 +76,7 @@ class LICMTest : public CommonCompilerTest {
// Performs LICM optimizations (after proper set up).
void PerformLICM() {
- TransformToSsa(graph_);
+ graph_->BuildDominatorTree();
SideEffectsAnalysis side_effects(graph_);
side_effects.Run();
LICM(graph_, side_effects).Run();
diff --git a/compiler/optimizing/linearize_test.cc b/compiler/optimizing/linearize_test.cc
index ed275b1544..13e14c53b5 100644
--- a/compiler/optimizing/linearize_test.cc
+++ b/compiler/optimizing/linearize_test.cc
@@ -39,14 +39,7 @@ template <size_t number_of_blocks>
static void TestCode(const uint16_t* data, const uint32_t (&expected_order)[number_of_blocks]) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = CreateGraph(&allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- bool graph_built = builder.BuildGraph(*item);
- ASSERT_TRUE(graph_built);
-
- TransformToSsa(graph);
-
+ HGraph* graph = CreateCFG(&allocator, data);
std::unique_ptr<const X86InstructionSetFeatures> features_x86(
X86InstructionSetFeatures::FromCppDefines());
x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
diff --git a/compiler/optimizing/live_ranges_test.cc b/compiler/optimizing/live_ranges_test.cc
index 991f8f70ea..3202493c3a 100644
--- a/compiler/optimizing/live_ranges_test.cc
+++ b/compiler/optimizing/live_ranges_test.cc
@@ -32,14 +32,10 @@ namespace art {
class LiveRangesTest : public CommonCompilerTest {};
static HGraph* BuildGraph(const uint16_t* data, ArenaAllocator* allocator) {
- HGraph* graph = CreateGraph(allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- builder.BuildGraph(*item);
+ HGraph* graph = CreateCFG(allocator, data);
// Suspend checks implementation may change in the future, and this test relies
// on how instructions are ordered.
RemoveSuspendChecks(graph);
- TransformToSsa(graph);
// `Inline` conditions into ifs.
PrepareForRegisterAllocation(graph).Run();
return graph;
@@ -303,13 +299,12 @@ TEST_F(LiveRangesTest, Loop2) {
* 12: equal
* 14: if +++++
* | \ +
- * | 18: suspend
- * | 20: add
- * | 22: goto
+ * | 18: add
+ * | 20: goto
* |
- * 26: return
+ * 24: return
* |
- * 30: exit
+ * 28: exit
*
* We want to make sure the phi at 10 has a lifetime hole after the add at 20.
*/
@@ -345,18 +340,18 @@ TEST_F(LiveRangesTest, Loop2) {
interval = phi->GetLiveInterval();
range = interval->GetFirstRange();
ASSERT_EQ(10u, range->GetStart());
- ASSERT_EQ(21u, range->GetEnd());
+ ASSERT_EQ(19u, range->GetEnd());
range = range->GetNext();
ASSERT_TRUE(range != nullptr);
- ASSERT_EQ(24u, range->GetStart());
- ASSERT_EQ(26u, range->GetEnd());
+ ASSERT_EQ(22u, range->GetStart());
+ ASSERT_EQ(24u, range->GetEnd());
// Test for the add instruction.
HAdd* add = liveness.GetInstructionFromSsaIndex(2)->AsAdd();
interval = add->GetLiveInterval();
range = interval->GetFirstRange();
- ASSERT_EQ(20u, range->GetStart());
- ASSERT_EQ(24u, range->GetEnd());
+ ASSERT_EQ(18u, range->GetStart());
+ ASSERT_EQ(22u, range->GetEnd());
ASSERT_TRUE(range->GetNext() == nullptr);
}
diff --git a/compiler/optimizing/liveness_test.cc b/compiler/optimizing/liveness_test.cc
index 7736eedae1..92a987cb1d 100644
--- a/compiler/optimizing/liveness_test.cc
+++ b/compiler/optimizing/liveness_test.cc
@@ -46,12 +46,7 @@ static void DumpBitVector(BitVector* vector,
static void TestCode(const uint16_t* data, const char* expected) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = CreateGraph(&allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- bool graph_built = builder.BuildGraph(*item);
- ASSERT_TRUE(graph_built);
- TransformToSsa(graph);
+ HGraph* graph = CreateCFG(&allocator, data);
// `Inline` conditions into ifs.
PrepareForRegisterAllocation(graph).Run();
std::unique_ptr<const X86InstructionSetFeatures> features_x86(
diff --git a/compiler/optimizing/nodes.cc b/compiler/optimizing/nodes.cc
index 453571451c..ca66f631a6 100644
--- a/compiler/optimizing/nodes.cc
+++ b/compiler/optimizing/nodes.cc
@@ -27,6 +27,15 @@
namespace art {
+void HGraph::InitializeInexactObjectRTI(StackHandleScopeCollection* handles) {
+ ScopedObjectAccess soa(Thread::Current());
+ // Create the inexact Object reference type and store it in the HGraph.
+ ClassLinker* linker = Runtime::Current()->GetClassLinker();
+ inexact_object_rti_ = ReferenceTypeInfo::Create(
+ handles->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangObject)),
+ /* is_exact */ false);
+}
+
void HGraph::AddBlock(HBasicBlock* block) {
block->SetBlockId(blocks_.size());
blocks_.push_back(block);
@@ -236,29 +245,6 @@ void HGraph::ComputeDominanceInformation() {
}
}
-GraphAnalysisResult HGraph::TryBuildingSsa(StackHandleScopeCollection* handles) {
- GraphAnalysisResult result = BuildDominatorTree();
- if (result != kAnalysisSuccess) {
- return result;
- }
-
- // Create the inexact Object reference type and store it in the HGraph.
- ScopedObjectAccess soa(Thread::Current());
- ClassLinker* linker = Runtime::Current()->GetClassLinker();
- inexact_object_rti_ = ReferenceTypeInfo::Create(
- handles->NewHandle(linker->GetClassRoot(ClassLinker::kJavaLangObject)),
- /* is_exact */ false);
-
- // Tranforms graph to SSA form.
- result = SsaBuilder(this, handles).BuildSsa();
- if (result != kAnalysisSuccess) {
- return result;
- }
-
- in_ssa_form_ = true;
- return kAnalysisSuccess;
-}
-
HBasicBlock* HGraph::SplitEdge(HBasicBlock* block, HBasicBlock* successor) {
HBasicBlock* new_block = new (arena_) HBasicBlock(this, successor->GetDexPc());
AddBlock(new_block);
@@ -1592,7 +1578,7 @@ void HBasicBlock::DisconnectAndDelete() {
loop_info->Remove(this);
if (loop_info->IsBackEdge(*this)) {
// If this was the last back edge of the loop, we deliberately leave the
- // loop in an inconsistent state and will fail SSAChecker unless the
+ // loop in an inconsistent state and will fail GraphChecker unless the
// entire loop is removed during the pass.
loop_info->RemoveBackEdge(this);
}
@@ -1631,7 +1617,7 @@ void HBasicBlock::DisconnectAndDelete() {
} else if (num_pred_successors == 0u) {
// The predecessor has no remaining successors and therefore must be dead.
// We deliberately leave it without a control-flow instruction so that the
- // SSAChecker fails unless it is not removed during the pass too.
+ // GraphChecker fails unless it is not removed during the pass too.
predecessor->RemoveInstruction(last_instruction);
} else {
// There are multiple successors left. The removed block might be a successor
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 2697af33eb..1c9b09f1e6 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -98,6 +98,7 @@ enum IfCondition {
};
enum GraphAnalysisResult {
+ kAnalysisInvalidBytecode,
kAnalysisFailThrowCatchLoop,
kAnalysisFailAmbiguousArrayOp,
kAnalysisSuccess,
@@ -308,10 +309,14 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
blocks_.reserve(kDefaultNumberOfBlocks);
}
+ // Acquires and stores RTI of inexact Object to be used when creating HNullConstant.
+ void InitializeInexactObjectRTI(StackHandleScopeCollection* handles);
+
ArenaAllocator* GetArena() const { return arena_; }
const ArenaVector<HBasicBlock*>& GetBlocks() const { return blocks_; }
bool IsInSsaForm() const { return in_ssa_form_; }
+ void SetInSsaForm() { in_ssa_form_ = true; }
HBasicBlock* GetEntryBlock() const { return entry_block_; }
HBasicBlock* GetExitBlock() const { return exit_block_; }
@@ -322,11 +327,6 @@ class HGraph : public ArenaObject<kArenaAllocGraph> {
void AddBlock(HBasicBlock* block);
- // Try building the SSA form of this graph, with dominance computation and
- // loop recognition. Returns a code specifying that it was successful or the
- // reason for failure.
- GraphAnalysisResult TryBuildingSsa(StackHandleScopeCollection* handles);
-
void ComputeDominanceInformation();
void ClearDominanceInformation();
void ClearLoopInformation();
diff --git a/compiler/optimizing/optimizing_compiler.cc b/compiler/optimizing/optimizing_compiler.cc
index dcd8e7d216..12b748b7b6 100644
--- a/compiler/optimizing/optimizing_compiler.cc
+++ b/compiler/optimizing/optimizing_compiler.cc
@@ -186,18 +186,10 @@ class PassObserver : public ValueObject {
// Validate the HGraph if running in debug mode.
if (kIsDebugBuild) {
if (!graph_in_bad_state_) {
- if (graph_->IsInSsaForm()) {
- SSAChecker checker(graph_);
- checker.Run();
- if (!checker.IsValid()) {
- LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<SSAChecker>(checker);
- }
- } else {
- GraphChecker checker(graph_);
- checker.Run();
- if (!checker.IsValid()) {
- LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<GraphChecker>(checker);
- }
+ GraphChecker checker(graph_);
+ checker.Run();
+ if (!checker.IsValid()) {
+ LOG(FATAL) << "Error after " << pass_name << ": " << Dumpable<GraphChecker>(checker);
}
}
}
@@ -665,6 +657,7 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena,
&& compiler_driver->RequiresConstructorBarrier(Thread::Current(),
dex_compilation_unit.GetDexFile(),
dex_compilation_unit.GetClassDefIndex());
+
HGraph* graph = new (arena) HGraph(
arena,
dex_file,
@@ -675,6 +668,21 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena,
compiler_driver->GetCompilerOptions().GetDebuggable(),
osr);
+ const uint8_t* interpreter_metadata = nullptr;
+ {
+ ScopedObjectAccess soa(Thread::Current());
+ StackHandleScope<1> hs(soa.Self());
+ Handle<mirror::ClassLoader> loader(hs.NewHandle(
+ soa.Decode<mirror::ClassLoader*>(class_loader)));
+ ArtMethod* art_method = compiler_driver->ResolveMethod(
+ soa, dex_cache, loader, &dex_compilation_unit, method_idx, invoke_type);
+ // We may not get a method, for example if its class is erroneous.
+ if (art_method != nullptr) {
+ graph->SetArtMethod(art_method);
+ interpreter_metadata = art_method->GetQuickenedInfo();
+ }
+ }
+
std::unique_ptr<CodeGenerator> codegen(
CodeGenerator::Create(graph,
instruction_set,
@@ -692,74 +700,55 @@ CodeGenerator* OptimizingCompiler::TryCompile(ArenaAllocator* arena,
visualizer_output_.get(),
compiler_driver);
- const uint8_t* interpreter_metadata = nullptr;
- {
- ScopedObjectAccess soa(Thread::Current());
- StackHandleScope<1> hs(soa.Self());
- Handle<mirror::ClassLoader> loader(hs.NewHandle(
- soa.Decode<mirror::ClassLoader*>(class_loader)));
- ArtMethod* art_method = compiler_driver->ResolveMethod(
- soa, dex_cache, loader, &dex_compilation_unit, method_idx, invoke_type);
- // We may not get a method, for example if its class is erroneous.
- if (art_method != nullptr) {
- graph->SetArtMethod(art_method);
- interpreter_metadata = art_method->GetQuickenedInfo();
- }
- }
- HGraphBuilder builder(graph,
- &dex_compilation_unit,
- &dex_compilation_unit,
- &dex_file,
- compiler_driver,
- compilation_stats_.get(),
- interpreter_metadata,
- dex_cache);
-
VLOG(compiler) << "Building " << pass_observer.GetMethodName();
{
- PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
- if (!builder.BuildGraph(*code_item)) {
- pass_observer.SetGraphInBadState();
- return nullptr;
+ ScopedObjectAccess soa(Thread::Current());
+ StackHandleScopeCollection handles(soa.Self());
+ // Do not hold `mutator_lock_` between optimizations.
+ ScopedThreadSuspension sts(soa.Self(), kNative);
+
+ {
+ PassScope scope(HGraphBuilder::kBuilderPassName, &pass_observer);
+ HGraphBuilder builder(graph,
+ &dex_compilation_unit,
+ &dex_compilation_unit,
+ &dex_file,
+ compiler_driver,
+ compilation_stats_.get(),
+ interpreter_metadata,
+ dex_cache);
+ GraphAnalysisResult result = builder.BuildGraph(*code_item, &handles);
+ if (result != kAnalysisSuccess) {
+ switch (result) {
+ case kAnalysisInvalidBytecode:
+ break;
+ case kAnalysisFailThrowCatchLoop:
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledThrowCatchLoop);
+ break;
+ case kAnalysisFailAmbiguousArrayOp:
+ MaybeRecordStat(MethodCompilationStat::kNotCompiledAmbiguousArrayOp);
+ break;
+ case kAnalysisSuccess:
+ UNREACHABLE();
+ }
+ pass_observer.SetGraphInBadState();
+ return nullptr;
+ }
}
- }
- VLOG(compiler) << "Optimizing " << pass_observer.GetMethodName();
+ RunOptimizations(graph,
+ codegen.get(),
+ compiler_driver,
+ compilation_stats_.get(),
+ dex_compilation_unit,
+ &pass_observer,
+ &handles);
- ScopedObjectAccess soa(Thread::Current());
- StackHandleScopeCollection handles(soa.Self());
- ScopedThreadSuspension sts(soa.Self(), kNative);
-
- {
- PassScope scope(SsaBuilder::kSsaBuilderPassName, &pass_observer);
- GraphAnalysisResult result = graph->TryBuildingSsa(&handles);
- if (result != kAnalysisSuccess) {
- switch (result) {
- case kAnalysisFailThrowCatchLoop:
- MaybeRecordStat(MethodCompilationStat::kNotCompiledThrowCatchLoop);
- break;
- case kAnalysisFailAmbiguousArrayOp:
- MaybeRecordStat(MethodCompilationStat::kNotCompiledAmbiguousArrayOp);
- break;
- case kAnalysisSuccess:
- UNREACHABLE();
- }
- pass_observer.SetGraphInBadState();
- return nullptr;
- }
+ codegen->Compile(code_allocator);
+ pass_observer.DumpDisassembly();
}
- RunOptimizations(graph,
- codegen.get(),
- compiler_driver,
- compilation_stats_.get(),
- dex_compilation_unit,
- &pass_observer,
- &handles);
- codegen->Compile(code_allocator);
- pass_observer.DumpDisassembly();
-
if (kArenaAllocatorCountAllocations) {
if (arena->BytesAllocated() > 4 * MB) {
MemStats mem_stats(arena->GetMemStats());
diff --git a/compiler/optimizing/optimizing_unit_test.h b/compiler/optimizing/optimizing_unit_test.h
index 5a910433b4..0c7648edc2 100644
--- a/compiler/optimizing/optimizing_unit_test.h
+++ b/compiler/optimizing/optimizing_unit_test.h
@@ -64,10 +64,12 @@ LiveInterval* BuildInterval(const size_t ranges[][2],
void RemoveSuspendChecks(HGraph* graph) {
for (HBasicBlock* block : graph->GetBlocks()) {
- for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
- HInstruction* current = it.Current();
- if (current->IsSuspendCheck()) {
- current->GetBlock()->RemoveInstruction(current);
+ if (block != nullptr) {
+ for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
+ HInstruction* current = it.Current();
+ if (current->IsSuspendCheck()) {
+ current->GetBlock()->RemoveInstruction(current);
+ }
}
}
}
@@ -83,12 +85,17 @@ inline HGraph* CreateGraph(ArenaAllocator* allocator) {
inline HGraph* CreateCFG(ArenaAllocator* allocator,
const uint16_t* data,
Primitive::Type return_type = Primitive::kPrimInt) {
- HGraph* graph = CreateGraph(allocator);
- HGraphBuilder builder(graph, return_type);
const DexFile::CodeItem* item =
reinterpret_cast<const DexFile::CodeItem*>(data);
- bool graph_built = builder.BuildGraph(*item);
- return graph_built ? graph : nullptr;
+ HGraph* graph = CreateGraph(allocator);
+
+ {
+ ScopedObjectAccess soa(Thread::Current());
+ StackHandleScopeCollection handles(soa.Self());
+ HGraphBuilder builder(graph, return_type);
+ bool graph_built = (builder.BuildGraph(*item, &handles) == kAnalysisSuccess);
+ return graph_built ? graph : nullptr;
+ }
}
// Naive string diff data type.
@@ -114,12 +121,6 @@ inline bool IsRemoved(HInstruction* instruction) {
return instruction->GetBlock() == nullptr;
}
-inline void TransformToSsa(HGraph* graph) {
- ScopedObjectAccess soa(Thread::Current());
- StackHandleScopeCollection handles(soa.Self());
- EXPECT_EQ(graph->TryBuildingSsa(&handles), kAnalysisSuccess);
-}
-
} // namespace art
#endif // ART_COMPILER_OPTIMIZING_OPTIMIZING_UNIT_TEST_H_
diff --git a/compiler/optimizing/pretty_printer_test.cc b/compiler/optimizing/pretty_printer_test.cc
index c56100dfa1..2de0c1be72 100644
--- a/compiler/optimizing/pretty_printer_test.cc
+++ b/compiler/optimizing/pretty_printer_test.cc
@@ -30,17 +30,15 @@ namespace art {
static void TestCode(const uint16_t* data, const char* expected) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = CreateGraph(&allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- bool graph_built = builder.BuildGraph(*item);
- ASSERT_TRUE(graph_built);
+ HGraph* graph = CreateCFG(&allocator, data);
StringPrettyPrinter printer(graph);
printer.VisitInsertionOrder();
ASSERT_STREQ(expected, printer.str().c_str());
}
-TEST(PrettyPrinterTest, ReturnVoid) {
+class PrettyPrinterTest : public CommonCompilerTest {};
+
+TEST_F(PrettyPrinterTest, ReturnVoid) {
const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Instruction::RETURN_VOID);
@@ -56,7 +54,7 @@ TEST(PrettyPrinterTest, ReturnVoid) {
TestCode(data, expected);
}
-TEST(PrettyPrinterTest, CFG1) {
+TEST_F(PrettyPrinterTest, CFG1) {
const char* expected =
"BasicBlock 0, succ: 1\n"
" 3: SuspendCheck\n"
@@ -76,7 +74,7 @@ TEST(PrettyPrinterTest, CFG1) {
TestCode(data, expected);
}
-TEST(PrettyPrinterTest, CFG2) {
+TEST_F(PrettyPrinterTest, CFG2) {
const char* expected =
"BasicBlock 0, succ: 1\n"
" 4: SuspendCheck\n"
@@ -98,7 +96,7 @@ TEST(PrettyPrinterTest, CFG2) {
TestCode(data, expected);
}
-TEST(PrettyPrinterTest, CFG3) {
+TEST_F(PrettyPrinterTest, CFG3) {
const char* expected =
"BasicBlock 0, succ: 1\n"
" 4: SuspendCheck\n"
@@ -134,16 +132,16 @@ TEST(PrettyPrinterTest, CFG3) {
TestCode(data3, expected);
}
-TEST(PrettyPrinterTest, CFG4) {
+TEST_F(PrettyPrinterTest, CFG4) {
const char* expected =
- "BasicBlock 0, succ: 1\n"
+ "BasicBlock 0, succ: 3\n"
" 3: SuspendCheck\n"
- " 4: Goto 1\n"
- "BasicBlock 1, pred: 0, 1, succ: 1\n"
+ " 4: Goto 3\n"
+ "BasicBlock 1, pred: 3, 1, succ: 1\n"
" 0: SuspendCheck\n"
" 1: Goto 1\n"
- "BasicBlock 2\n"
- " 2: Exit\n";
+ "BasicBlock 3, pred: 0, succ: 1\n"
+ " 5: Goto 1\n";
const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
Instruction::NOP,
@@ -157,15 +155,13 @@ TEST(PrettyPrinterTest, CFG4) {
TestCode(data2, expected);
}
-TEST(PrettyPrinterTest, CFG5) {
+TEST_F(PrettyPrinterTest, CFG5) {
const char* expected =
"BasicBlock 0, succ: 1\n"
" 3: SuspendCheck\n"
" 4: Goto 1\n"
- "BasicBlock 1, pred: 0, 2, succ: 3\n"
+ "BasicBlock 1, pred: 0, succ: 3\n"
" 0: ReturnVoid\n"
- "BasicBlock 2, succ: 1\n"
- " 1: Goto 1\n"
"BasicBlock 3, pred: 1\n"
" 2: Exit\n";
@@ -177,25 +173,23 @@ TEST(PrettyPrinterTest, CFG5) {
TestCode(data, expected);
}
-TEST(PrettyPrinterTest, CFG6) {
+TEST_F(PrettyPrinterTest, CFG6) {
const char* expected =
"BasicBlock 0, succ: 1\n"
- " 0: Local [4, 3, 2]\n"
- " 1: IntConstant [2]\n"
+ " 1: IntConstant [5, 5]\n"
" 10: SuspendCheck\n"
" 11: Goto 1\n"
- "BasicBlock 1, pred: 0, succ: 3, 2\n"
- " 2: StoreLocal(0, 1)\n"
- " 3: LoadLocal(0) [5]\n"
- " 4: LoadLocal(0) [5]\n"
- " 5: Equal(3, 4) [6]\n"
+ "BasicBlock 1, pred: 0, succ: 5, 2\n"
+ " 5: Equal(1, 1) [6]\n"
" 6: If(5)\n"
"BasicBlock 2, pred: 1, succ: 3\n"
" 7: Goto 3\n"
- "BasicBlock 3, pred: 1, 2, succ: 4\n"
+ "BasicBlock 3, pred: 5, 2, succ: 4\n"
" 8: ReturnVoid\n"
"BasicBlock 4, pred: 3\n"
- " 9: Exit\n";
+ " 9: Exit\n"
+ "BasicBlock 5, pred: 1, succ: 3\n"
+ " 12: Goto 3\n";
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
@@ -206,26 +200,24 @@ TEST(PrettyPrinterTest, CFG6) {
TestCode(data, expected);
}
-TEST(PrettyPrinterTest, CFG7) {
+TEST_F(PrettyPrinterTest, CFG7) {
const char* expected =
"BasicBlock 0, succ: 1\n"
- " 0: Local [4, 3, 2]\n"
- " 1: IntConstant [2]\n"
+ " 1: IntConstant [5, 5]\n"
" 11: SuspendCheck\n"
" 12: Goto 1\n"
- "BasicBlock 1, pred: 0, succ: 3, 2\n"
- " 2: StoreLocal(0, 1)\n"
- " 3: LoadLocal(0) [5]\n"
- " 4: LoadLocal(0) [5]\n"
- " 5: Equal(3, 4) [6]\n"
+ "BasicBlock 1, pred: 0, succ: 5, 6\n"
+ " 5: Equal(1, 1) [6]\n"
" 6: If(5)\n"
- "BasicBlock 2, pred: 1, 3, succ: 3\n"
+ "BasicBlock 2, pred: 6, 3, succ: 3\n"
" 7: Goto 3\n"
- "BasicBlock 3, pred: 1, 2, succ: 2\n"
+ "BasicBlock 3, pred: 5, 2, succ: 2\n"
" 8: SuspendCheck\n"
" 9: Goto 2\n"
- "BasicBlock 4\n"
- " 10: Exit\n";
+ "BasicBlock 5, pred: 1, succ: 3\n"
+ " 13: Goto 3\n"
+ "BasicBlock 6, pred: 1, succ: 2\n"
+ " 14: Goto 2\n";
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
@@ -236,15 +228,13 @@ TEST(PrettyPrinterTest, CFG7) {
TestCode(data, expected);
}
-TEST(PrettyPrinterTest, IntConstant) {
+TEST_F(PrettyPrinterTest, IntConstant) {
const char* expected =
"BasicBlock 0, succ: 1\n"
- " 0: Local [2]\n"
- " 1: IntConstant [2]\n"
+ " 1: IntConstant\n"
" 5: SuspendCheck\n"
" 6: Goto 1\n"
"BasicBlock 1, pred: 0, succ: 2\n"
- " 2: StoreLocal(0, 1)\n"
" 3: ReturnVoid\n"
"BasicBlock 2, pred: 1\n"
" 4: Exit\n";
diff --git a/compiler/optimizing/register_allocator_test.cc b/compiler/optimizing/register_allocator_test.cc
index 572faa841e..a9de7c3e59 100644
--- a/compiler/optimizing/register_allocator_test.cc
+++ b/compiler/optimizing/register_allocator_test.cc
@@ -38,11 +38,7 @@ class RegisterAllocatorTest : public CommonCompilerTest {};
static bool Check(const uint16_t* data) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = CreateGraph(&allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- builder.BuildGraph(*item);
- TransformToSsa(graph);
+ HGraph* graph = CreateCFG(&allocator, data);
std::unique_ptr<const X86InstructionSetFeatures> features_x86(
X86InstructionSetFeatures::FromCppDefines());
x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
@@ -254,15 +250,6 @@ TEST_F(RegisterAllocatorTest, Loop2) {
ASSERT_TRUE(Check(data));
}
-static HGraph* BuildSSAGraph(const uint16_t* data, ArenaAllocator* allocator) {
- HGraph* graph = CreateGraph(allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- builder.BuildGraph(*item);
- TransformToSsa(graph);
- return graph;
-}
-
TEST_F(RegisterAllocatorTest, Loop3) {
/*
* Test the following snippet:
@@ -302,7 +289,7 @@ TEST_F(RegisterAllocatorTest, Loop3) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = BuildSSAGraph(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
std::unique_ptr<const X86InstructionSetFeatures> features_x86(
X86InstructionSetFeatures::FromCppDefines());
x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
@@ -336,7 +323,7 @@ TEST_F(RegisterAllocatorTest, FirstRegisterUse) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = BuildSSAGraph(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
std::unique_ptr<const X86InstructionSetFeatures> features_x86(
X86InstructionSetFeatures::FromCppDefines());
x86::CodeGeneratorX86 codegen(graph, *features_x86.get(), CompilerOptions());
@@ -390,7 +377,7 @@ TEST_F(RegisterAllocatorTest, DeadPhi) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = BuildSSAGraph(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
SsaDeadPhiElimination(graph).Run();
std::unique_ptr<const X86InstructionSetFeatures> features_x86(
X86InstructionSetFeatures::FromCppDefines());
@@ -414,7 +401,7 @@ TEST_F(RegisterAllocatorTest, FreeUntil) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = BuildSSAGraph(data, &allocator);
+ HGraph* graph = CreateCFG(&allocator, data);
SsaDeadPhiElimination(graph).Run();
std::unique_ptr<const X86InstructionSetFeatures> features_x86(
X86InstructionSetFeatures::FromCppDefines());
diff --git a/compiler/optimizing/ssa_builder.cc b/compiler/optimizing/ssa_builder.cc
index 2d0a399290..308a25414a 100644
--- a/compiler/optimizing/ssa_builder.cc
+++ b/compiler/optimizing/ssa_builder.cc
@@ -451,6 +451,8 @@ void SsaBuilder::RemoveRedundantUninitializedStrings() {
}
GraphAnalysisResult SsaBuilder::BuildSsa() {
+ DCHECK(!GetGraph()->IsInSsaForm());
+
// 1) Visit in reverse post order. We need to have all predecessors of a block
// visited (with the exception of loops) in order to create the right environment
// for that block. For loops, we create phis whose inputs will be set in 2).
@@ -533,6 +535,7 @@ GraphAnalysisResult SsaBuilder::BuildSsa() {
}
}
+ GetGraph()->SetInSsaForm();
return kAnalysisSuccess;
}
diff --git a/compiler/optimizing/ssa_builder.h b/compiler/optimizing/ssa_builder.h
index 4cba41f389..2dae9c2de0 100644
--- a/compiler/optimizing/ssa_builder.h
+++ b/compiler/optimizing/ssa_builder.h
@@ -79,8 +79,6 @@ class SsaBuilder : public HGraphVisitor {
void VisitArraySet(HArraySet* aset) OVERRIDE;
void VisitInvokeStaticOrDirect(HInvokeStaticOrDirect* invoke) OVERRIDE;
- static constexpr const char* kSsaBuilderPassName = "ssa_builder";
-
private:
void SetLoopHeaderPhiInputs();
void FixEnvironmentPhis();
diff --git a/compiler/optimizing/ssa_liveness_analysis.cc b/compiler/optimizing/ssa_liveness_analysis.cc
index 1dd35080a6..83e9dacb1a 100644
--- a/compiler/optimizing/ssa_liveness_analysis.cc
+++ b/compiler/optimizing/ssa_liveness_analysis.cc
@@ -226,7 +226,7 @@ void SsaLivenessAnalysis::ComputeLiveRanges() {
// The only instructions which may not be recorded in the environments
// are constants created by the SSA builder as typed equivalents of
// untyped constants from the bytecode, or phis with only such constants
- // as inputs (verified by SSAChecker). Their raw binary value must
+ // as inputs (verified by GraphChecker). Their raw binary value must
// therefore be the same and we only need to keep alive one.
} else {
size_t phi_input_index = successor->GetPredecessorIndexOf(block);
diff --git a/compiler/optimizing/ssa_test.cc b/compiler/optimizing/ssa_test.cc
index d2885a8fd7..a6880921c5 100644
--- a/compiler/optimizing/ssa_test.cc
+++ b/compiler/optimizing/ssa_test.cc
@@ -79,13 +79,7 @@ static void ReNumberInstructions(HGraph* graph) {
static void TestCode(const uint16_t* data, const char* expected) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = CreateGraph(&allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- bool graph_built = builder.BuildGraph(*item);
- ASSERT_TRUE(graph_built);
-
- TransformToSsa(graph);
+ HGraph* graph = CreateCFG(&allocator, data);
// Suspend checks implementation may change in the future, and this test relies
// on how instructions are ordered.
RemoveSuspendChecks(graph);
diff --git a/compiler/optimizing/suspend_check_test.cc b/compiler/optimizing/suspend_check_test.cc
index b6c704c1b1..15cd4e8a08 100644
--- a/compiler/optimizing/suspend_check_test.cc
+++ b/compiler/optimizing/suspend_check_test.cc
@@ -18,6 +18,7 @@
#include "dex_instruction.h"
#include "nodes.h"
#include "optimizing_unit_test.h"
+#include "pretty_printer.h"
#include "gtest/gtest.h"
@@ -30,20 +31,17 @@ namespace art {
static void TestCode(const uint16_t* data) {
ArenaPool pool;
ArenaAllocator allocator(&pool);
- HGraph* graph = CreateGraph(&allocator);
- HGraphBuilder builder(graph);
- const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
- bool graph_built = builder.BuildGraph(*item);
- ASSERT_TRUE(graph_built);
-
- HBasicBlock* first_block = graph->GetEntryBlock()->GetSuccessors()[0];
- HInstruction* first_instruction = first_block->GetFirstInstruction();
- // Account for some tests having a store local as first instruction.
- ASSERT_TRUE(first_instruction->IsSuspendCheck()
- || first_instruction->GetNext()->IsSuspendCheck());
+ HGraph* graph = CreateCFG(&allocator, data);
+ HBasicBlock* first_block = graph->GetEntryBlock()->GetSingleSuccessor();
+ HBasicBlock* loop_header = first_block->GetSingleSuccessor();
+ ASSERT_TRUE(loop_header->IsLoopHeader());
+ ASSERT_EQ(loop_header->GetLoopInformation()->GetPreHeader(), first_block);
+ ASSERT_TRUE(loop_header->GetFirstInstruction()->IsSuspendCheck());
}
-TEST(CodegenTest, CFG1) {
+class SuspendCheckTest : public CommonCompilerTest {};
+
+TEST_F(SuspendCheckTest, CFG1) {
const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Instruction::NOP,
Instruction::GOTO | 0xFF00);
@@ -51,14 +49,14 @@ TEST(CodegenTest, CFG1) {
TestCode(data);
}
-TEST(CodegenTest, CFG2) {
+TEST_F(SuspendCheckTest, CFG2) {
const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
Instruction::GOTO_32, 0, 0);
TestCode(data);
}
-TEST(CodegenTest, CFG3) {
+TEST_F(SuspendCheckTest, CFG3) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQ, 0xFFFF,
@@ -67,7 +65,7 @@ TEST(CodegenTest, CFG3) {
TestCode(data);
}
-TEST(CodegenTest, CFG4) {
+TEST_F(SuspendCheckTest, CFG4) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_NE, 0xFFFF,
@@ -76,7 +74,7 @@ TEST(CodegenTest, CFG4) {
TestCode(data);
}
-TEST(CodegenTest, CFG5) {
+TEST_F(SuspendCheckTest, CFG5) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_EQZ, 0xFFFF,
@@ -85,7 +83,7 @@ TEST(CodegenTest, CFG5) {
TestCode(data);
}
-TEST(CodegenTest, CFG6) {
+TEST_F(SuspendCheckTest, CFG6) {
const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
Instruction::CONST_4 | 0 | 0,
Instruction::IF_NEZ, 0xFFFF,
diff --git a/test/127-checker-secondarydex/src/Test.java b/test/127-checker-secondarydex/src/Test.java
index 266ed191bc..438e8545ff 100644
--- a/test/127-checker-secondarydex/src/Test.java
+++ b/test/127-checker-secondarydex/src/Test.java
@@ -23,7 +23,7 @@ public class Test extends Super {
System.out.println("Test");
}
- /// CHECK-START: java.lang.Integer Test.toInteger() ssa_builder (after)
+ /// CHECK-START: java.lang.Integer Test.toInteger() builder (after)
/// CHECK: LoadClass needs_access_check:false klass:java.lang.Integer
public Integer toInteger() {
diff --git a/test/444-checker-nce/src/Main.java b/test/444-checker-nce/src/Main.java
index 865355ce97..c96b18c71b 100644
--- a/test/444-checker-nce/src/Main.java
+++ b/test/444-checker-nce/src/Main.java
@@ -27,7 +27,7 @@ public class Main {
return m.g();
}
- /// CHECK-START: Main Main.thisTest() ssa_builder (after)
+ /// CHECK-START: Main Main.thisTest() builder (after)
/// CHECK: NullCheck
/// CHECK: InvokeStaticOrDirect
@@ -38,7 +38,7 @@ public class Main {
return g();
}
- /// CHECK-START: Main Main.newInstanceRemoveTest() ssa_builder (after)
+ /// CHECK-START: Main Main.newInstanceRemoveTest() builder (after)
/// CHECK: NewInstance
/// CHECK: NullCheck
/// CHECK: InvokeStaticOrDirect
@@ -52,7 +52,7 @@ public class Main {
return m.g();
}
- /// CHECK-START: Main Main.newArrayRemoveTest() ssa_builder (after)
+ /// CHECK-START: Main Main.newArrayRemoveTest() builder (after)
/// CHECK: NewArray
/// CHECK: NullCheck
/// CHECK: ArrayGet
@@ -178,7 +178,7 @@ public class Main {
return n.g();
}
- /// CHECK-START: Main Main.scopeRemoveTest(int, Main) ssa_builder (after)
+ /// CHECK-START: Main Main.scopeRemoveTest(int, Main) builder (after)
/// CHECK: NullCheck
/// CHECK-START: Main Main.scopeRemoveTest(int, Main) instruction_simplifier (after)
diff --git a/test/450-checker-types/src/Main.java b/test/450-checker-types/src/Main.java
index d48b30e324..027a9d9487 100644
--- a/test/450-checker-types/src/Main.java
+++ b/test/450-checker-types/src/Main.java
@@ -205,7 +205,7 @@ public class Main {
public static boolean $inline$InstanceofSubclassB(Object o) { return o instanceof SubclassB; }
public static boolean $inline$InstanceofSubclassC(Object o) { return o instanceof SubclassC; }
- /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) ssa_builder (after)
+ /// CHECK-START: void Main.testInstanceOf_NotInlined(java.lang.Object) builder (after)
/// CHECK-DAG: <<Cst0:i\d+>> IntConstant 0
/// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
/// CHECK-DAG: <<IOf1:z\d+>> InstanceOf
@@ -229,7 +229,7 @@ public class Main {
}
}
- /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) ssa_builder (after)
+ /// CHECK-START: void Main.testNotInstanceOf_NotInlined(java.lang.Object) builder (after)
/// CHECK-DAG: <<Cst0:i\d+>> IntConstant 0
/// CHECK-DAG: <<Cst1:i\d+>> IntConstant 1
/// CHECK-DAG: <<IOf1:z\d+>> InstanceOf
@@ -487,7 +487,7 @@ public class Main {
((SubclassA)a[0]).$noinline$g();
}
- /// CHECK-START: int Main.testLoadExceptionInCatchNonExact(int, int) ssa_builder (after)
+ /// CHECK-START: int Main.testLoadExceptionInCatchNonExact(int, int) builder (after)
/// CHECK: LoadException klass:java.lang.ArithmeticException can_be_null:false exact:false
public int testLoadExceptionInCatchNonExact(int x, int y) {
try {
@@ -497,7 +497,7 @@ public class Main {
}
}
- /// CHECK-START: int Main.testLoadExceptionInCatchExact(int) ssa_builder (after)
+ /// CHECK-START: int Main.testLoadExceptionInCatchExact(int) builder (after)
/// CHECK: LoadException klass:FinalException can_be_null:false exact:true
public int testLoadExceptionInCatchExact(int x) {
try {
@@ -511,7 +511,7 @@ public class Main {
}
}
- /// CHECK-START: int Main.testLoadExceptionInCatchAll(int, int) ssa_builder (after)
+ /// CHECK-START: int Main.testLoadExceptionInCatchAll(int, int) builder (after)
/// CHECK: LoadException klass:java.lang.Throwable can_be_null:false exact:false
public int testLoadExceptionInCatchAll(int x, int y) {
try {
@@ -532,7 +532,7 @@ public class Main {
return genericFinal.get();
}
- /// CHECK-START: SubclassC Main.inlineGenerics() ssa_builder (after)
+ /// CHECK-START: SubclassC Main.inlineGenerics() builder (after)
/// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:SubclassC exact:false
/// CHECK-NEXT: Return [<<Invoke>>]
@@ -544,7 +544,7 @@ public class Main {
return c;
}
- /// CHECK-START: Final Main.inlineGenericsFinal() ssa_builder (after)
+ /// CHECK-START: Final Main.inlineGenericsFinal() builder (after)
/// CHECK: <<Invoke:l\d+>> InvokeStaticOrDirect klass:Final exact:true
/// CHECK-NEXT: Return [<<Invoke>>]
@@ -586,7 +586,7 @@ public class Main {
return new SubclassA();
}
- /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) ssa_builder (after)
+ /// CHECK-START: void Main.updateNodesInTheSameBlockAsPhi(boolean) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:Super
/// CHECK: NullCheck [<<Phi>>] klass:Super
@@ -620,7 +620,7 @@ public class Main {
}
- /// CHECK-START: void Main.argumentCheck(Super, double, SubclassA, Final) ssa_builder (after)
+ /// CHECK-START: void Main.argumentCheck(Super, double, SubclassA, Final) builder (after)
/// CHECK: ParameterValue klass:Main can_be_null:false exact:false
/// CHECK: ParameterValue klass:Super can_be_null:true exact:false
/// CHECK: ParameterValue
@@ -636,7 +636,7 @@ public class Main {
private int mainField = 0;
- /// CHECK-START: SuperInterface Main.getWiderType(boolean, Interface, OtherInterface) ssa_builder (after)
+ /// CHECK-START: SuperInterface Main.getWiderType(boolean, Interface, OtherInterface) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
/// CHECK: Return [<<Phi>>]
private SuperInterface getWiderType(boolean cond, Interface a, OtherInterface b) {
@@ -692,7 +692,7 @@ public class Main {
getSuper();
}
- /// CHECK-START: void Main.testLoopPhiWithNullFirstInput(boolean) ssa_builder (after)
+ /// CHECK-START: void Main.testLoopPhiWithNullFirstInput(boolean) builder (after)
/// CHECK-DAG: <<Null:l\d+>> NullConstant
/// CHECK-DAG: <<Main:l\d+>> NewInstance klass:Main exact:true
/// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<LoopPhi>>,<<Main>>] klass:Main exact:true
@@ -705,7 +705,7 @@ public class Main {
}
}
- /// CHECK-START: java.lang.Object[] Main.testInstructionsWithUntypedParent() ssa_builder (after)
+ /// CHECK-START: java.lang.Object[] Main.testInstructionsWithUntypedParent() builder (after)
/// CHECK-DAG: <<Null:l\d+>> NullConstant
/// CHECK-DAG: <<LoopPhi:l\d+>> Phi [<<Null>>,<<Phi:l\d+>>] klass:java.lang.Object[] exact:true
/// CHECK-DAG: <<Array:l\d+>> NewArray klass:java.lang.Object[] exact:true
diff --git a/test/458-checker-instruction-simplification/src/Main.java b/test/458-checker-instruction-simplification/src/Main.java
index 2f80470cb3..f2cba478c1 100644
--- a/test/458-checker-instruction-simplification/src/Main.java
+++ b/test/458-checker-instruction-simplification/src/Main.java
@@ -1401,7 +1401,7 @@ public class Main {
// Test that conditions on float/double are not flipped.
- /// CHECK-START: int Main.floatConditionNotEqualOne(float) ssa_builder (after)
+ /// CHECK-START: int Main.floatConditionNotEqualOne(float) builder (after)
/// CHECK: LessThanOrEqual
/// CHECK-START: int Main.floatConditionNotEqualOne(float) instruction_simplifier_before_codegen (after)
@@ -1417,7 +1417,7 @@ public class Main {
return ((f > 42.0f) == true) ? 13 : 54;
}
- /// CHECK-START: int Main.doubleConditionEqualZero(double) ssa_builder (after)
+ /// CHECK-START: int Main.doubleConditionEqualZero(double) builder (after)
/// CHECK: LessThanOrEqual
/// CHECK-START: int Main.doubleConditionEqualZero(double) instruction_simplifier_before_codegen (after)
diff --git a/test/464-checker-inline-sharpen-calls/src/Main.java b/test/464-checker-inline-sharpen-calls/src/Main.java
index 2222e0fa0c..3f256352b7 100644
--- a/test/464-checker-inline-sharpen-calls/src/Main.java
+++ b/test/464-checker-inline-sharpen-calls/src/Main.java
@@ -39,7 +39,7 @@ public final class Main {
m.invokeVirtual();
}
- /// CHECK-START: int Main.inlineSharpenHelperInvoke() ssa_builder (after)
+ /// CHECK-START: int Main.inlineSharpenHelperInvoke() builder (after)
/// CHECK-DAG: <<Invoke:i\d+>> InvokeVirtual {{.*\.getFoo.*}}
/// CHECK-DAG: Return [<<Invoke>>]
diff --git a/test/477-checker-bound-type/src/Main.java b/test/477-checker-bound-type/src/Main.java
index 0f65e44678..2504ab2839 100644
--- a/test/477-checker-bound-type/src/Main.java
+++ b/test/477-checker-bound-type/src/Main.java
@@ -17,7 +17,7 @@
public class Main {
- /// CHECK-START: java.lang.Object Main.boundTypeForIf(java.lang.Object) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.boundTypeForIf(java.lang.Object) builder (after)
/// CHECK: BoundType
public static Object boundTypeForIf(Object a) {
if (a != null) {
@@ -27,7 +27,7 @@ public class Main {
}
}
- /// CHECK-START: java.lang.Object Main.boundTypeForInstanceOf(java.lang.Object) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.boundTypeForInstanceOf(java.lang.Object) builder (after)
/// CHECK: BoundType
public static Object boundTypeForInstanceOf(Object a) {
if (a instanceof Main) {
@@ -37,7 +37,7 @@ public class Main {
}
}
- /// CHECK-START: java.lang.Object Main.noBoundTypeForIf(java.lang.Object) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.noBoundTypeForIf(java.lang.Object) builder (after)
/// CHECK-NOT: BoundType
public static Object noBoundTypeForIf(Object a) {
if (a == null) {
@@ -47,7 +47,7 @@ public class Main {
}
}
- /// CHECK-START: java.lang.Object Main.noBoundTypeForInstanceOf(java.lang.Object) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.noBoundTypeForInstanceOf(java.lang.Object) builder (after)
/// CHECK-NOT: BoundType
public static Object noBoundTypeForInstanceOf(Object a) {
if (a instanceof Main) {
diff --git a/test/492-checker-inline-invoke-interface/src/Main.java b/test/492-checker-inline-invoke-interface/src/Main.java
index 3106ce4f3e..a919690000 100644
--- a/test/492-checker-inline-invoke-interface/src/Main.java
+++ b/test/492-checker-inline-invoke-interface/src/Main.java
@@ -31,7 +31,7 @@ public class Main implements Itf {
int a = ForceStatic.field;
}
- /// CHECK-START: void Main.main(java.lang.String[]) ssa_builder (after)
+ /// CHECK-START: void Main.main(java.lang.String[]) builder (after)
/// CHECK: InvokeStaticOrDirect {{.*Main.<init>.*}}
/// CHECK: InvokeInterface
diff --git a/test/510-checker-try-catch/smali/Builder.smali b/test/510-checker-try-catch/smali/Builder.smali
index c91b83e18a..8ec840d159 100644
--- a/test/510-checker-try-catch/smali/Builder.smali
+++ b/test/510-checker-try-catch/smali/Builder.smali
@@ -41,28 +41,35 @@
## CHECK: predecessors "<<BEnterTry2>>"
## CHECK: successors "<<BExitTry2:B\d+>>"
## CHECK: DivZeroCheck
+## CHECK: <<Div:i\d+>> Div
-## CHECK: name "<<BReturn:B\d+>>"
-## CHECK: predecessors "<<BExitTry2>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>" "<<BCatch3:B\d+>>"
+## CHECK: name "<<BAfterTry2:B\d+>>"
+## CHECK: predecessors "<<BExitTry2>>"
+## CHECK: successors "<<BReturn:B\d+>>"
+## CHECK: Goto
+
+## CHECK: name "<<BReturn>>"
+## CHECK: predecessors "<<BAfterTry2>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>" "<<BCatch3:B\d+>>"
+## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>,<<Minus3>>]
## CHECK: Return
## CHECK: name "<<BCatch1>>"
## CHECK: predecessors "<<BEnterTry1>>" "<<BExitTry1>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus1>>]
+## CHECK: Goto
## CHECK: name "<<BCatch2>>"
## CHECK: predecessors "<<BEnterTry2>>" "<<BExitTry2>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus2>>]
+## CHECK: Goto
## CHECK: name "<<BCatch3>>"
## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus3>>]
+## CHECK: Goto
## CHECK: name "<<BEnterTry1>>"
## CHECK: predecessors "B0"
@@ -84,7 +91,7 @@
## CHECK: name "<<BExitTry2>>"
## CHECK: predecessors "<<BTry2>>"
-## CHECK: successors "<<BReturn>>"
+## CHECK: successors "<<BAfterTry2>>"
## CHECK: xhandlers "<<BCatch2>>" "<<BCatch3>>"
## CHECK: TryBoundary kind:exit
@@ -105,6 +112,8 @@
.catch Ljava/lang/OutOfMemoryError; {:try_start_2 .. :try_end_2} :catch_mem
.catchall {:try_start_2 .. :try_end_2} :catch_other
+ nop
+
:return
return p0
@@ -131,7 +140,7 @@
## CHECK: name "<<BIf>>"
## CHECK: predecessors "B0"
-## CHECK: successors "<<BEnterTry2:B\d+>>" "<<BThen:B\d+>>"
+## CHECK: successors "<<BSplit1:B\d+>>" "<<BThen:B\d+>>"
## CHECK: If
## CHECK: name "<<BThen>>"
@@ -145,19 +154,19 @@
## CHECK: Div
## CHECK: name "<<BTry2:B\d+>>"
-## CHECK: predecessors "<<BEnterTry2>>"
+## CHECK: predecessors "<<BEnterTry2:B\d+>>"
## CHECK: successors "<<BExitTry2:B\d+>>"
## CHECK: Div
## CHECK: name "<<BReturn:B\d+>>"
-## CHECK: predecessors "<<BExitTry2>>" "<<BCatch:B\d+>>"
+## CHECK: predecessors "<<BSplit3:B\d+>>" "<<BCatch:B\d+>>"
## CHECK: Return
## CHECK: name "<<BCatch>>"
## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus1>>]
+## CHECK: Goto
## CHECK: name "<<BEnterTry1>>"
## CHECK: predecessors "<<BThen>>"
@@ -166,23 +175,38 @@
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BEnterTry2>>"
-## CHECK: predecessors "<<BIf>>" "<<BExitTry1>>"
+## CHECK: predecessors "<<BSplit1>>" "<<BSplit2:B\d+>>"
## CHECK: successors "<<BTry2>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BExitTry1>>"
## CHECK: predecessors "<<BTry1>>"
-## CHECK: successors "<<BEnterTry2>>"
+## CHECK: successors "<<BSplit2>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
## CHECK: name "<<BExitTry2>>"
## CHECK: predecessors "<<BTry2>>"
-## CHECK: successors "<<BReturn>>"
+## CHECK: successors "<<BSplit3>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit1>>"
+## CHECK: predecessors "<<BIf>>"
+## CHECK: successors "<<BEnterTry2>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit2>>"
+## CHECK: predecessors "<<BExitTry1>>"
+## CHECK: successors "<<BEnterTry2>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit3>>"
+## CHECK: predecessors "<<BExitTry2>>"
+## CHECK: successors "<<BReturn>>"
+## CHECK: Goto
+
.method public static testMultipleEntries(IIII)I
.registers 4
@@ -220,23 +244,24 @@
## CHECK: name "<<BTry:B\d+>>"
## CHECK: predecessors "<<BEnterTry>>"
## CHECK: successors "<<BExitTry1:B\d+>>" "<<BExitTry2:B\d+>>"
-## CHECK: Div
+## CHECK: <<Div:i\d+>> Div
## CHECK: If
## CHECK: name "<<BReturn:B\d+>>"
-## CHECK: predecessors "<<BExitTry2>>" "<<BThen:B\d+>>" "<<BCatch:B\d+>>"
+## CHECK: predecessors "<<BSplit:B\d+>>" "<<BThen:B\d+>>" "<<BCatch:B\d+>>"
+## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
## CHECK: Return
## CHECK: name "<<BThen>>"
## CHECK: predecessors "<<BExitTry1>>"
## CHECK: successors "<<BReturn>>"
-## CHECK: StoreLocal [v0,<<Minus1>>]
+## CHECK: Goto
## CHECK: name "<<BCatch>>"
## CHECK: predecessors "<<BEnterTry>>" "<<BExitTry1>>" "<<BExitTry2>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus2>>]
+## CHECK: Goto
## CHECK: name "<<BEnterTry>>"
## CHECK: predecessors "B0"
@@ -252,10 +277,15 @@
## CHECK: name "<<BExitTry2>>"
## CHECK: predecessors "<<BTry>>"
-## CHECK: successors "<<BReturn>>"
+## CHECK: successors "<<BSplit>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit>>"
+## CHECK: predecessors "<<BExitTry2>>"
+## CHECK: successors "<<BReturn>>"
+## CHECK: Goto
+
.method public static testMultipleExits(II)I
.registers 2
@@ -295,23 +325,25 @@
## CHECK: name "<<BTry2:B\d+>>"
## CHECK: predecessors "<<BEnter2:B\d+>>"
## CHECK: successors "<<BExit2:B\d+>>"
-## CHECK: Div
+## CHECK: <<Div:i\d+>> Div
+## CHECK: Goto
## CHECK: name "<<BReturn:B\d+>>"
-## CHECK: predecessors "<<BExit2>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>"
+## CHECK: predecessors "<<BSplit:B\d+>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>"
+## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
## CHECK: Return
## CHECK: name "<<BCatch1>>"
## CHECK: predecessors "<<BEnter1>>" "<<BExit1>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus1>>]
+## CHECK: Goto
## CHECK: name "<<BCatch2>>"
## CHECK: predecessors "<<BEnter2>>" "<<BExit2>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus2>>]
+## CHECK: Goto
## CHECK: name "<<BEnter1>>"
## CHECK: predecessors "B0"
@@ -333,10 +365,15 @@
## CHECK: name "<<BExit2>>"
## CHECK: predecessors "<<BTry2>>"
-## CHECK: successors "<<BReturn>>"
+## CHECK: successors "<<BSplit>>"
## CHECK: xhandlers "<<BCatch2>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit>>"
+## CHECK: predecessors "<<BExit2>>"
+## CHECK: successors "<<BReturn>>"
+## CHECK: Goto
+
.method public static testSharedBoundary(III)I
.registers 3
@@ -378,28 +415,31 @@
## CHECK: name "<<BTry1:B\d+>>"
## CHECK: predecessors "<<BEnter1:B\d+>>"
## CHECK: successors "<<BExit1:B\d+>>"
-## CHECK: Div
+## CHECK: <<Div:i\d+>> Div
+## CHECK: Goto
## CHECK: name "<<BTry2:B\d+>>"
## CHECK: predecessors "<<BEnter2>>"
## CHECK: successors "<<BExit2:B\d+>>"
## CHECK: Div
+## CHECK: Goto
## CHECK: name "<<BReturn:B\d+>>"
-## CHECK: predecessors "<<BExit1>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>"
+## CHECK: predecessors "<<BSplit:B\d+>>" "<<BCatch1:B\d+>>" "<<BCatch2:B\d+>>"
+## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
## CHECK: Return
## CHECK: name "<<BCatch1>>"
## CHECK: predecessors "<<BEnter1>>" "<<BExit1>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus1>>]
+## CHECK: Goto
## CHECK: name "<<BCatch2>>"
## CHECK: predecessors "<<BEnter2>>" "<<BExit2>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus2>>]
+## CHECK: Goto
## CHECK: name "<<BEnter1>>"
## CHECK: predecessors "<<BExit2>>"
@@ -415,7 +455,7 @@
## CHECK: name "<<BExit1>>"
## CHECK: predecessors "<<BTry1>>"
-## CHECK: successors "<<BReturn>>"
+## CHECK: successors "<<BSplit>>"
## CHECK: xhandlers "<<BCatch1>>"
## CHECK: TryBoundary kind:exit
@@ -425,6 +465,11 @@
## CHECK: xhandlers "<<BCatch2>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit>>"
+## CHECK: predecessors "<<BExit1>>"
+## CHECK: successors "<<BReturn>>"
+## CHECK: Goto
+
.method public static testSharedBoundary_Reverse(III)I
.registers 3
@@ -472,26 +517,30 @@
## CHECK: predecessors "<<BEnter2:B\d+>>"
## CHECK: successors "<<BExit2:B\d+>>"
## CHECK: Div
+## CHECK: Goto
## CHECK: name "<<BTry3:B\d+>>"
## CHECK: predecessors "<<BEnter3:B\d+>>"
## CHECK: successors "<<BExit3:B\d+>>"
-## CHECK: Div
+## CHECK: <<Div:i\d+>> Div
+## CHECK: Goto
## CHECK: name "<<BReturn:B\d+>>"
-## CHECK: predecessors "<<BExit3>>" "<<BCatchArith:B\d+>>" "<<BCatchAll:B\d+>>"
+## CHECK: predecessors "<<BSplit:B\d+>>" "<<BCatchArith:B\d+>>" "<<BCatchAll:B\d+>>"
+## CHECK: Phi [<<Div>>,<<Minus1>>,<<Minus2>>]
+## CHECK: Return
## CHECK: name "<<BCatchArith>>"
## CHECK: predecessors "<<BEnter2>>" "<<BExit2>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus1>>]
+## CHECK: Goto
## CHECK: name "<<BCatchAll>>"
## CHECK: predecessors "<<BEnter1>>" "<<BEnter2>>" "<<BEnter3>>" "<<BExit1>>" "<<BExit2>>" "<<BExit3>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus2>>]
+## CHECK: Goto
## CHECK: name "<<BEnter1>>"
## CHECK: predecessors "B0"
@@ -525,10 +574,15 @@
## CHECK: name "<<BExit3>>"
## CHECK: predecessors "<<BTry3>>"
-## CHECK: successors "<<BReturn>>"
+## CHECK: successors "<<BSplit>>"
## CHECK: xhandlers "<<BCatchAll>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit>>"
+## CHECK: predecessors "<<BExit3>>"
+## CHECK: successors "<<BReturn>>"
+## CHECK: Goto
+
.method public static testNestedTry(IIII)I
.registers 4
@@ -567,14 +621,18 @@
## CHECK: predecessors "<<BEnterTry1:B\d+>>"
## CHECK: successors "<<BExitTry1:B\d+>>"
## CHECK: Div
+## CHECK: Goto
## CHECK: name "<<BTry2:B\d+>>"
## CHECK: predecessors "<<BEnterTry2:B\d+>>"
## CHECK: successors "<<BExitTry2:B\d+>>"
-## CHECK: Div
+## CHECK: <<Div:i\d+>> Div
+## CHECK: Goto
## CHECK: name "<<BReturn:B\d+>>"
-## CHECK: predecessors "<<BExitTry2>>" "<<BCatch:B\d+>>"
+## CHECK: predecessors "<<BSplit:B\d+>>" "<<BCatch:B\d+>>"
+## CHECK: Phi [<<Div>>,<<Minus1>>]
+## CHECK: Return
## CHECK: name "<<BOutside:B\d+>>"
## CHECK: predecessors "<<BExitTry1>>"
@@ -585,7 +643,7 @@
## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus1>>]
+## CHECK: Goto
## CHECK: name "<<BEnterTry1>>"
## CHECK: predecessors "B0"
@@ -607,10 +665,15 @@
## CHECK: name "<<BExitTry2>>"
## CHECK: predecessors "<<BTry2>>"
-## CHECK: successors "<<BReturn>>"
+## CHECK: successors "<<BSplit>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit>>"
+## CHECK: predecessors "<<BExitTry2>>"
+## CHECK: successors "<<BReturn>>"
+## CHECK: Goto
+
.method public static testIncontinuousTry(IIII)I
.registers 4
@@ -642,12 +705,12 @@
## CHECK: name "<<BPSwitch0>>"
## CHECK: predecessors "B0"
-## CHECK: successors "<<BEnterTry2:B\d+>>" "<<BPSwitch1:B\d+>>"
+## CHECK: successors "<<BSplit1:B\d+>>" "<<BPSwitch1:B\d+>>"
## CHECK: If
## CHECK: name "<<BPSwitch1>>"
## CHECK: predecessors "<<BPSwitch0>>"
-## CHECK: successors "<<BOutside:B\d+>>" "<<BEnterTry1:B\d+>>"
+## CHECK: successors "<<BSplit2:B\d+>>" "<<BEnterTry1:B\d+>>"
## CHECK: If
## CHECK: name "<<BTry1:B\d+>>"
@@ -656,44 +719,68 @@
## CHECK: Div
## CHECK: name "<<BTry2:B\d+>>"
-## CHECK: predecessors "<<BEnterTry2>>"
+## CHECK: predecessors "<<BEnterTry2:B\d+>>"
## CHECK: successors "<<BExitTry2:B\d+>>"
## CHECK: Div
-## CHECK: name "<<BOutside>>"
-## CHECK: predecessors "<<BPSwitch1>>" "<<BExitTry2>>"
-## CHECK: successors "<<BCatchReturn:B\d+>>"
+## CHECK: name "<<BOutside:B\d+>>"
+## CHECK: predecessors "<<BSplit2>>" "<<BSplit4:B\d+>>"
+## CHECK: successors "<<BReturn:B\d+>>"
## CHECK: Div
-## CHECK: name "<<BCatchReturn>>"
-## CHECK: predecessors "<<BOutside>>" "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
+## CHECK: name "<<BCatch:B\d+>>"
+## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
## CHECK: flags "catch_block"
-## CHECK: Return
+## CHECK: Goto
## CHECK: name "<<BEnterTry1>>"
## CHECK: predecessors "<<BPSwitch1>>"
## CHECK: successors "<<BTry1>>"
-## CHECK: xhandlers "<<BCatchReturn>>"
+## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BEnterTry2>>"
-## CHECK: predecessors "<<BPSwitch0>>"
+## CHECK: predecessors "<<BSplit1>>" "<<BSplit3:B\d+>>"
## CHECK: successors "<<BTry2>>"
-## CHECK: xhandlers "<<BCatchReturn>>"
+## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BExitTry1>>"
## CHECK: predecessors "<<BTry1>>"
-## CHECK: successors "<<BEnterTry2>>"
-## CHECK: xhandlers "<<BCatchReturn>>"
+## CHECK: successors "<<BSplit3>>"
+## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
## CHECK: name "<<BExitTry2>>"
## CHECK: predecessors "<<BTry2>>"
-## CHECK: successors "<<BOutside>>"
-## CHECK: xhandlers "<<BCatchReturn>>"
+## CHECK: successors "<<BSplit4>>"
+## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BReturn>>"
+## CHECK: predecessors "<<BCatch>>" "<<BOutside>>"
+## CHECK: Return
+
+## CHECK: name "<<BSplit1>>"
+## CHECK: predecessors "<<BPSwitch0>>"
+## CHECK: successors "<<BEnterTry2>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit2>>"
+## CHECK: predecessors "<<BPSwitch1>>"
+## CHECK: successors "<<BOutside>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit3>>"
+## CHECK: predecessors "<<BExitTry1>>"
+## CHECK: successors "<<BEnterTry2>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit4>>"
+## CHECK: predecessors "<<BExitTry2>>"
+## CHECK: successors "<<BOutside>>"
+## CHECK: Goto
+
.method public static testSwitchTryEnter(IIII)I
.registers 4
@@ -728,58 +815,78 @@
## CHECK: name "<<BPSwitch0:B\d+>>"
## CHECK: predecessors "<<BEnterTry1>>"
-## CHECK: successors "<<BTry2:B\d+>>" "<<BExitTry1:B\d+>>"
+## CHECK: successors "<<BSplit1:B\d+>>" "<<BExitTry1:B\d+>>"
## CHECK: If
## CHECK: name "<<BPSwitch1:B\d+>>"
## CHECK: predecessors "<<BExitTry1>>"
-## CHECK: successors "<<BOutside:B\d+>>" "<<BEnterTry2:B\d+>>"
+## CHECK: successors "<<BSplit2:B\d+>>" "<<BEnterTry2:B\d+>>"
## CHECK: If
## CHECK: name "<<BTry1:B\d+>>"
## CHECK: predecessors "<<BEnterTry2>>"
-## CHECK: successors "<<BTry2>>"
+## CHECK: successors "<<BTry2:B\d+>>"
## CHECK: Div
## CHECK: name "<<BTry2>>"
-## CHECK: predecessors "<<BPSwitch0>>"
+## CHECK: predecessors "<<BSplit1>>" "<<BTry1>>"
## CHECK: successors "<<BExitTry2:B\d+>>"
## CHECK: Div
-## CHECK: name "<<BOutside>>"
-## CHECK: predecessors "<<BPSwitch1>>" "<<BExitTry2>>"
-## CHECK: successors "<<BCatchReturn:B\d+>>"
+## CHECK: name "<<BOutside:B\d+>>"
+## CHECK: predecessors "<<BSplit2>>" "<<BSplit3:B\d+>>"
+## CHECK: successors "<<BReturn:B\d+>>"
## CHECK: Div
-## CHECK: name "<<BCatchReturn>>"
-## CHECK: predecessors "<<BOutside>>" "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
+## CHECK: name "<<BCatch:B\d+>>"
+## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2>>" "<<BExitTry1>>" "<<BExitTry2>>"
+## CHECK: successors "<<BReturn>>"
## CHECK: flags "catch_block"
-## CHECK: Return
+## CHECK: Goto
## CHECK: name "<<BEnterTry1>>"
## CHECK: predecessors "B0"
## CHECK: successors "<<BPSwitch0>>"
-## CHECK: xhandlers "<<BCatchReturn>>"
+## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BEnterTry2>>"
## CHECK: predecessors "<<BPSwitch1>>"
## CHECK: successors "<<BTry1>>"
-## CHECK: xhandlers "<<BCatchReturn>>"
+## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BExitTry1>>"
## CHECK: predecessors "<<BPSwitch0>>"
## CHECK: successors "<<BPSwitch1>>"
-## CHECK: xhandlers "<<BCatchReturn>>"
+## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
## CHECK: name "<<BExitTry2>>"
## CHECK: predecessors "<<BTry2>>"
-## CHECK: successors "<<BOutside>>"
-## CHECK: xhandlers "<<BCatchReturn>>"
+## CHECK: successors "<<BSplit3>>"
+## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BReturn>>"
+## CHECK: predecessors "<<BCatch>>" "<<BOutside>>"
+## CHECK: Return
+
+## CHECK: name "<<BSplit1>>"
+## CHECK: predecessors "<<BPSwitch0>>"
+## CHECK: successors "<<BTry2>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit2>>"
+## CHECK: predecessors "<<BPSwitch1>>"
+## CHECK: successors "<<BOutside>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit3>>"
+## CHECK: predecessors "<<BExitTry2>>"
+## CHECK: successors "<<BOutside>>"
+## CHECK: Goto
+
.method public static testSwitchTryExit(IIII)I
.registers 4
@@ -825,7 +932,7 @@
## CHECK: predecessors "<<BEnterTry>>" "<<BExitTry>>"
## CHECK: successors "<<BExit:B\d+>>"
## CHECK: flags "catch_block"
-## CHECK: StoreLocal [v0,<<Minus1>>]
+## CHECK: Return [<<Minus1>>]
## CHECK: name "<<BExit>>"
## CHECK: predecessors "<<BExitTry>>" "<<BCatch>>"
@@ -861,18 +968,21 @@
## CHECK-START: int Builder.testCatchLoop(int, int, int) builder (after)
## CHECK: name "B0"
-## CHECK: successors "<<BCatch:B\d+>>"
+## CHECK: successors "<<BSplit2:B\d+>>"
-## CHECK: name "<<BCatch>>"
-## CHECK: predecessors "B0" "<<BEnterTry:B\d+>>" "<<BExitTry:B\d+>>"
-## CHECK: successors "<<BEnterTry>>"
+## CHECK: name "<<BCatch:B\d+>>"
+## CHECK: predecessors "<<BEnterTry:B\d+>>" "<<BExitTry:B\d+>>"
+## CHECK: successors "<<BSplit1:B\d+>>"
## CHECK: flags "catch_block"
## CHECK: name "<<BReturn:B\d+>>"
## CHECK: predecessors "<<BExitTry>>"
## CHECK: successors "<<BExit:B\d+>>"
+## CHECK: Return
## CHECK: name "<<BExit>>"
+## CHECK: predecessors "<<BReturn>>"
+## CHECK: Exit
## CHECK: name "<<BTry:B\d+>>"
## CHECK: predecessors "<<BEnterTry>>"
@@ -880,7 +990,7 @@
## CHECK: Div
## CHECK: name "<<BEnterTry>>"
-## CHECK: predecessors "<<BCatch>>"
+## CHECK: predecessors "<<BSplit1>>"
## CHECK: successors "<<BTry>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:entry
@@ -891,6 +1001,16 @@
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit1>>"
+## CHECK: predecessors "<<BSplit2>>" "<<BCatch>>"
+## CHECK: successors "<<BEnterTry>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit2>>"
+## CHECK: predecessors "B0"
+## CHECK: successors "<<BSplit1>>"
+## CHECK: Goto
+
.method public static testCatchLoop(III)I
.registers 4
@@ -918,14 +1038,16 @@
## CHECK: Div
## CHECK: name "<<BCatch:B\d+>>"
-## CHECK: predecessors "<<BExitTry1>>" "<<BEnterTry1>>" "<<BEnterTry2:B\d+>>" "<<BExitTry1>>" "<<BExitTry2:B\d+>>"
-## CHECK: successors "<<BEnterTry2>>"
+## CHECK: predecessors "<<BEnterTry1>>" "<<BEnterTry2:B\d+>>" "<<BExitTry1>>" "<<BExitTry2:B\d+>>"
+## CHECK: successors "<<BSplit1:B\d+>>"
## CHECK: flags "catch_block"
## CHECK: name "<<BReturn:B\d+>>"
## CHECK: predecessors "<<BExitTry2>>"
+## CHECK: successors "<<BExit:B\d+>>"
-## CHECK: name "{{B\d+}}"
+## CHECK: name "<<BExit>>"
+## CHECK: predecessors "<<BReturn>>"
## CHECK: Exit
## CHECK: name "<<BTry2:B\d+>>"
@@ -940,14 +1062,14 @@
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BEnterTry2>>"
-## CHECK: predecessors "<<BCatch>>"
+## CHECK: predecessors "<<BSplit1>>"
## CHECK: successors "<<BTry2>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BExitTry1>>"
## CHECK: predecessors "<<BTry1>>"
-## CHECK: successors "<<BCatch>>"
+## CHECK: successors "<<BSplit2:B\d+>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
@@ -957,6 +1079,16 @@
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit1>>"
+## CHECK: predecessors "<<BSplit2>>" "<<BCatch>>"
+## CHECK: successors "<<BEnterTry2>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit2>>"
+## CHECK: predecessors "<<BExitTry1>>"
+## CHECK: successors "<<BSplit1>>"
+## CHECK: Goto
+
.method public static testHandlerEdge1(III)I
.registers 4
@@ -977,16 +1109,16 @@
## CHECK-START: int Builder.testHandlerEdge2(int, int, int) builder (after)
## CHECK: name "B0"
-## CHECK: successors "<<BCatch1:B\d+>>"
+## CHECK: successors "<<BSplit4:B\d+>>"
-## CHECK: name "<<BCatch1>>"
-## CHECK: predecessors "B0" "<<BEnterTry2:B\d+>>" "<<BExitTry2:B\d+>>"
-## CHECK: successors "<<BEnterTry1:B\d+>>"
+## CHECK: name "<<BCatch1:B\d+>>"
+## CHECK: predecessors "<<BEnterTry2:B\d+>>" "<<BExitTry2:B\d+>>"
+## CHECK: successors "<<BSplit1:B\d+>>"
## CHECK: flags "catch_block"
## CHECK: name "<<BCatch2:B\d+>>"
-## CHECK: predecessors "<<BExitTry1:B\d+>>" "<<BEnterTry1>>" "<<BExitTry1>>"
-## CHECK: successors "<<BEnterTry2>>"
+## CHECK: predecessors "<<BEnterTry1:B\d+>>" "<<BExitTry1:B\d+>>"
+## CHECK: successors "<<BSplit2:B\d+>>"
## CHECK: flags "catch_block"
## CHECK: name "<<BReturn:B\d+>>"
@@ -995,6 +1127,7 @@
## CHECK: Return
## CHECK: name "<<BExit>>"
+## CHECK: Exit
## CHECK: name "<<BTry1:B\d+>>"
## CHECK: predecessors "<<BEnterTry1>>"
@@ -1007,20 +1140,20 @@
## CHECK: Div
## CHECK: name "<<BEnterTry1>>"
-## CHECK: predecessors "<<BCatch1>>"
+## CHECK: predecessors "<<BSplit1>>"
## CHECK: successors "<<BTry1>>"
## CHECK: xhandlers "<<BCatch2>>"
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BEnterTry2>>"
-## CHECK: predecessors "<<BCatch2>>"
+## CHECK: predecessors "<<BSplit2>>"
## CHECK: successors "<<BTry2>>"
## CHECK: xhandlers "<<BCatch1>>"
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BExitTry1>>"
## CHECK: predecessors "<<BTry1>>"
-## CHECK: successors "<<BCatch2>>"
+## CHECK: successors "<<BSplit3:B\d+>>"
## CHECK: xhandlers "<<BCatch2>>"
## CHECK: TryBoundary kind:exit
@@ -1030,6 +1163,26 @@
## CHECK: xhandlers "<<BCatch1>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit1>>"
+## CHECK: predecessors "<<BSplit4>>" "<<BCatch1>>"
+## CHECK: successors "<<BEnterTry1>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit2>>"
+## CHECK: predecessors "<<BCatch2>>" "<<BSplit3>>"
+## CHECK: successors "<<BEnterTry2>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit3>>"
+## CHECK: predecessors "<<BExitTry1>>"
+## CHECK: successors "<<BSplit2>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit4>>"
+## CHECK: predecessors "B0"
+## CHECK: successors "<<BSplit1>>"
+## CHECK: Goto
+
.method public static testHandlerEdge2(III)I
.registers 4
@@ -1053,10 +1206,10 @@
## CHECK-START: int Builder.testTryInLoop(int, int) builder (after)
## CHECK: name "B0"
-## CHECK: successors "<<BEnterTry:B\d+>>"
+## CHECK: successors "<<BSplit1:B\d+>>"
## CHECK: name "<<BTry:B\d+>>"
-## CHECK: predecessors "<<BEnterTry>>"
+## CHECK: predecessors "<<BEnterTry:B\d+>>"
## CHECK: successors "<<BExitTry:B\d+>>"
## CHECK: Div
@@ -1065,22 +1218,28 @@
## CHECK: successors "<<BEnterTry>>"
## CHECK: flags "catch_block"
-## CHECK: name "<<BExit:B\d+>>"
-## CHECK-NOT: predecessors "{{B\d+}}"
-## CHECK: end_block
-
## CHECK: name "<<BEnterTry>>"
-## CHECK: predecessors "B0"
+## CHECK: predecessors "<<BSplit1>>"
## CHECK: successors "<<BTry>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:entry
## CHECK: name "<<BExitTry>>"
## CHECK: predecessors "<<BTry>>"
-## CHECK: successors "<<BEnterTry>>"
+## CHECK: successors "<<BSplit2:B\d+>>"
## CHECK: xhandlers "<<BCatch>>"
## CHECK: TryBoundary kind:exit
+## CHECK: name "<<BSplit1>>"
+## CHECK: predecessors "B0"
+## CHECK: successors "<<BEnterTry>>"
+## CHECK: Goto
+
+## CHECK: name "<<BSplit2>>"
+## CHECK: predecessors "<<BExitTry>>"
+## CHECK: successors "<<BEnterTry>>"
+## CHECK: Goto
+
.method public static testTryInLoop(II)I
.registers 3
@@ -1098,9 +1257,10 @@
# INVOKE it follows, even if there is a try boundary between them.
## CHECK-START: int Builder.testMoveResult_Invoke(int, int, int) builder (after)
-
-## CHECK: <<Res:i\d+>> InvokeStaticOrDirect
-## CHECK-NEXT: StoreLocal [v0,<<Res>>]
+## CHECK-DAG: <<M1:i\d+>> IntConstant -1
+## CHECK-DAG: <<Res:i\d+>> InvokeStaticOrDirect
+## CHECK-DAG: <<Phi:i\d+>> Phi [<<Res>>,<<M1>>]
+## CHECK-DAG: Return [<<Phi>>]
.method public static testMoveResult_Invoke(III)I
.registers 3
@@ -1124,15 +1284,16 @@
# FILLED_NEW_ARRAY it follows, even if there is a try boundary between them.
## CHECK-START: int[] Builder.testMoveResult_FilledNewArray(int, int, int) builder (after)
-
-## CHECK: <<Res:l\d+>> NewArray
-## CHECK-NEXT: <<Local1:i\d+>> LoadLocal [v0]
-## CHECK-NEXT: ArraySet [<<Res>>,{{i\d+}},<<Local1>>]
-## CHECK-NEXT: <<Local2:i\d+>> LoadLocal [v1]
-## CHECK-NEXT: ArraySet [<<Res>>,{{i\d+}},<<Local2>>]
-## CHECK-NEXT: <<Local3:i\d+>> LoadLocal [v2]
-## CHECK-NEXT: ArraySet [<<Res>>,{{i\d+}},<<Local3>>]
-## CHECK-NEXT: StoreLocal [v0,<<Res>>]
+## CHECK-DAG: <<Arg1:i\d+>> ParameterValue
+## CHECK-DAG: <<Arg2:i\d+>> ParameterValue
+## CHECK-DAG: <<Arg3:i\d+>> ParameterValue
+## CHECK-DAG: <<Null:l\d+>> NullConstant
+## CHECK-DAG: <<Res:l\d+>> NewArray
+## CHECK-DAG: ArraySet [<<Res>>,{{i\d+}},<<Arg1>>]
+## CHECK-DAG: ArraySet [<<Res>>,{{i\d+}},<<Arg2>>]
+## CHECK-DAG: ArraySet [<<Res>>,{{i\d+}},<<Arg3>>]
+## CHECK-DAG: <<Phi:l\d+>> Phi [<<Res>>,<<Null>>]
+## CHECK-DAG: Return [<<Phi>>]
.method public static testMoveResult_FilledNewArray(III)[I
.registers 3
diff --git a/test/510-checker-try-catch/smali/SsaBuilder.smali b/test/510-checker-try-catch/smali/SsaBuilder.smali
index a6a5bfebee..1fd5fb2dd6 100644
--- a/test/510-checker-try-catch/smali/SsaBuilder.smali
+++ b/test/510-checker-try-catch/smali/SsaBuilder.smali
@@ -19,7 +19,7 @@
# Tests that catch blocks with both normal and exceptional predecessors are
# split in two.
-## CHECK-START: int SsaBuilder.testSimplifyCatchBlock(int, int, int) ssa_builder (after)
+## CHECK-START: int SsaBuilder.testSimplifyCatchBlock(int, int, int) builder (after)
## CHECK: name "B1"
## CHECK-NEXT: from_bci
@@ -62,7 +62,7 @@
# Should be rejected because :catch_all is a loop header.
-## CHECK-START: int SsaBuilder.testCatchLoopHeader(int, int, int) ssa_builder (after, bad_state)
+## CHECK-START: int SsaBuilder.testCatchLoopHeader(int, int, int) builder (after, bad_state)
.method public static testCatchLoopHeader(III)I
.registers 4
@@ -84,7 +84,7 @@
# Tests creation of catch Phis.
-## CHECK-START: int SsaBuilder.testPhiCreation(int, int, int) ssa_builder (after)
+## CHECK-START: int SsaBuilder.testPhiCreation(int, int, int) builder (after)
## CHECK-DAG: <<P0:i\d+>> ParameterValue
## CHECK-DAG: <<P1:i\d+>> ParameterValue
## CHECK-DAG: <<P2:i\d+>> ParameterValue
@@ -127,7 +127,7 @@
# Tests that phi elimination does not remove catch phis where the value does
# not dominate the phi.
-## CHECK-START: int SsaBuilder.testPhiElimination_Domination(int, int) ssa_builder (after)
+## CHECK-START: int SsaBuilder.testPhiElimination_Domination(int, int) builder (after)
## CHECK-DAG: <<P0:i\d+>> ParameterValue
## CHECK-DAG: <<P1:i\d+>> ParameterValue
## CHECK-DAG: <<Cst5:i\d+>> IntConstant 5
@@ -168,7 +168,7 @@
# Tests that phi elimination loops until no more phis can be removed.
-## CHECK-START: int SsaBuilder.testPhiElimination_Dependencies(int, int, int) ssa_builder (after)
+## CHECK-START: int SsaBuilder.testPhiElimination_Dependencies(int, int, int) builder (after)
## CHECK-NOT: Phi
.method public static testPhiElimination_Dependencies(III)I
@@ -200,10 +200,7 @@
# Tests that dead catch blocks are removed.
-## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) ssa_builder (before)
-## CHECK: Mul
-
-## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) ssa_builder (after)
+## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) builder (after)
## CHECK-DAG: <<P0:i\d+>> ParameterValue
## CHECK-DAG: <<P1:i\d+>> ParameterValue
## CHECK-DAG: <<P2:i\d+>> ParameterValue
@@ -211,7 +208,7 @@
## CHECK-DAG: <<Add2:i\d+>> Add [<<Add1>>,<<P2>>]
## CHECK-DAG: Return [<<Add2>>]
-## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) ssa_builder (after)
+## CHECK-START: int SsaBuilder.testDeadCatchBlock(int, int, int) builder (after)
## CHECK-NOT: flags "catch_block"
## CHECK-NOT: Mul
diff --git a/test/517-checker-builder-fallthrough/smali/TestCase.smali b/test/517-checker-builder-fallthrough/smali/TestCase.smali
index bc9502b31a..946f169948 100644
--- a/test/517-checker-builder-fallthrough/smali/TestCase.smali
+++ b/test/517-checker-builder-fallthrough/smali/TestCase.smali
@@ -25,8 +25,8 @@
## CHECK: name "B1"
## CHECK: successors "B5" "B2"
-## CHECK: StoreLocal [v0,<<Const0>>]
-## CHECK: If
+## CHECK: <<Cond:z\d+>> Equal [<<Const0>>,<<Const0>>]
+## CHECK: If [<<Cond>>]
## CHECK: name "B2"
## CHECK: successors "B4"
diff --git a/test/523-checker-can-throw-regression/smali/Test.smali b/test/523-checker-can-throw-regression/smali/Test.smali
index 87192ea123..4b737a9057 100644
--- a/test/523-checker-can-throw-regression/smali/Test.smali
+++ b/test/523-checker-can-throw-regression/smali/Test.smali
@@ -46,8 +46,10 @@
div-int/2addr p0, p1
:else
div-int/2addr p0, p2
- return p0
:try_end_2
- .catchall {:try_start_2 .. :try_end_2} :catchall
+ .catchall {:try_start_2 .. :try_end_2} :catchall2
+
+ :catchall2
+ return p0
.end method
diff --git a/test/537-checker-debuggable/smali/TestCase.smali b/test/537-checker-debuggable/smali/TestCase.smali
index 8e6c7ef727..5714d3aeae 100644
--- a/test/537-checker-debuggable/smali/TestCase.smali
+++ b/test/537-checker-debuggable/smali/TestCase.smali
@@ -20,10 +20,10 @@
# be eliminated in normal mode but kept live in debuggable mode. Test that
# Checker runs the correct test for each compilation mode.
-## CHECK-START: int TestCase.deadPhi(int, int, int) ssa_builder (after)
+## CHECK-START: int TestCase.deadPhi(int, int, int) builder (after)
## CHECK-NOT: Phi
-## CHECK-START-DEBUGGABLE: int TestCase.deadPhi(int, int, int) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: int TestCase.deadPhi(int, int, int) builder (after)
## CHECK: Phi
.method public static deadPhi(III)I
diff --git a/test/540-checker-rtp-bug/src/Main.java b/test/540-checker-rtp-bug/src/Main.java
index 9a9f0b6048..17b11db295 100644
--- a/test/540-checker-rtp-bug/src/Main.java
+++ b/test/540-checker-rtp-bug/src/Main.java
@@ -21,7 +21,7 @@ final class Final {
}
public class Main {
- /// CHECK-START: Final Main.testKeepCheckCast(java.lang.Object, boolean) ssa_builder (after)
+ /// CHECK-START: Final Main.testKeepCheckCast(java.lang.Object, boolean) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
/// CHECK: <<Class:l\d+>> LoadClass
/// CHECK: CheckCast [<<Phi>>,<<Class>>]
@@ -43,7 +43,7 @@ public class Main {
return (Final) x;
}
- /// CHECK-START: void Main.testKeepInstanceOf(java.lang.Object, boolean) ssa_builder (after)
+ /// CHECK-START: void Main.testKeepInstanceOf(java.lang.Object, boolean) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
/// CHECK: <<Class:l\d+>> LoadClass
/// CHECK: InstanceOf [<<Phi>>,<<Class>>]
@@ -65,7 +65,7 @@ public class Main {
}
}
- /// CHECK-START: java.lang.String Main.testNoInline(java.lang.Object, boolean) ssa_builder (after)
+ /// CHECK-START: java.lang.String Main.testNoInline(java.lang.Object, boolean) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
/// CHECK: <<NC:l\d+>> NullCheck [<<Phi>>]
/// CHECK: <<Ret:l\d+>> InvokeVirtual [<<NC>>] method_name:java.lang.Object.toString
diff --git a/test/549-checker-types-merge/src/Main.java b/test/549-checker-types-merge/src/Main.java
index 917073b1c9..51af3cff10 100644
--- a/test/549-checker-types-merge/src/Main.java
+++ b/test/549-checker-types-merge/src/Main.java
@@ -38,14 +38,14 @@ class ClassImplementsInterfaceA extends ClassSuper implements InterfaceA {}
public class Main {
- /// CHECK-START: java.lang.Object Main.testMergeNullContant(boolean) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeNullContant(boolean) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:Main
/// CHECK: Return [<<Phi>>]
private Object testMergeNullContant(boolean cond) {
return cond ? null : new Main();
}
- /// CHECK-START: java.lang.Object Main.testMergeClasses(boolean, ClassExtendsA, ClassExtendsB) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeClasses(boolean, ClassExtendsA, ClassExtendsB) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:ClassSuper
/// CHECK: Return [<<Phi>>]
private Object testMergeClasses(boolean cond, ClassExtendsA a, ClassExtendsB b) {
@@ -53,7 +53,7 @@ public class Main {
return cond ? a : b;
}
- /// CHECK-START: java.lang.Object Main.testMergeClasses(boolean, ClassExtendsA, ClassSuper) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeClasses(boolean, ClassExtendsA, ClassSuper) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:ClassSuper
/// CHECK: Return [<<Phi>>]
private Object testMergeClasses(boolean cond, ClassExtendsA a, ClassSuper b) {
@@ -61,7 +61,7 @@ public class Main {
return cond ? a : b;
}
- /// CHECK-START: java.lang.Object Main.testMergeClasses(boolean, ClassSuper, ClassSuper) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeClasses(boolean, ClassSuper, ClassSuper) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:ClassSuper
/// CHECK: Return [<<Phi>>]
private Object testMergeClasses(boolean cond, ClassSuper a, ClassSuper b) {
@@ -69,7 +69,7 @@ public class Main {
return cond ? a : b;
}
- /// CHECK-START: java.lang.Object Main.testMergeClasses(boolean, ClassOtherSuper, ClassSuper) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeClasses(boolean, ClassOtherSuper, ClassSuper) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
/// CHECK: Return [<<Phi>>]
private Object testMergeClasses(boolean cond, ClassOtherSuper a, ClassSuper b) {
@@ -77,7 +77,7 @@ public class Main {
return cond ? a : b;
}
- /// CHECK-START: java.lang.Object Main.testMergeClassWithInterface(boolean, ClassImplementsInterfaceA, InterfaceSuper) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeClassWithInterface(boolean, ClassImplementsInterfaceA, InterfaceSuper) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:InterfaceSuper
/// CHECK: Return [<<Phi>>]
private Object testMergeClassWithInterface(boolean cond, ClassImplementsInterfaceA a, InterfaceSuper b) {
@@ -85,7 +85,7 @@ public class Main {
return cond ? a : b;
}
- /// CHECK-START: java.lang.Object Main.testMergeClassWithInterface(boolean, ClassSuper, InterfaceSuper) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeClassWithInterface(boolean, ClassSuper, InterfaceSuper) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
/// CHECK: Return [<<Phi>>]
private Object testMergeClassWithInterface(boolean cond, ClassSuper a, InterfaceSuper b) {
@@ -93,7 +93,7 @@ public class Main {
return cond ? a : b;
}
- /// CHECK-START: java.lang.Object Main.testMergeInterfaces(boolean, InterfaceExtendsA, InterfaceSuper) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeInterfaces(boolean, InterfaceExtendsA, InterfaceSuper) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:InterfaceSuper
/// CHECK: Return [<<Phi>>]
private Object testMergeInterfaces(boolean cond, InterfaceExtendsA a, InterfaceSuper b) {
@@ -101,7 +101,7 @@ public class Main {
return cond ? a : b;
}
- /// CHECK-START: java.lang.Object Main.testMergeInterfaces(boolean, InterfaceSuper, InterfaceSuper) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeInterfaces(boolean, InterfaceSuper, InterfaceSuper) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:InterfaceSuper
/// CHECK: Return [<<Phi>>]
private Object testMergeInterfaces(boolean cond, InterfaceSuper a, InterfaceSuper b) {
@@ -109,7 +109,7 @@ public class Main {
return cond ? a : b;
}
- /// CHECK-START: java.lang.Object Main.testMergeInterfaces(boolean, InterfaceExtendsA, InterfaceExtendsB) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeInterfaces(boolean, InterfaceExtendsA, InterfaceExtendsB) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
/// CHECK: Return [<<Phi>>]
private Object testMergeInterfaces(boolean cond, InterfaceExtendsA a, InterfaceExtendsB b) {
@@ -117,7 +117,7 @@ public class Main {
return cond ? a : b;
}
- /// CHECK-START: java.lang.Object Main.testMergeInterfaces(boolean, InterfaceSuper, InterfaceOtherSuper) ssa_builder (after)
+ /// CHECK-START: java.lang.Object Main.testMergeInterfaces(boolean, InterfaceSuper, InterfaceOtherSuper) builder (after)
/// CHECK: <<Phi:l\d+>> Phi klass:java.lang.Object
/// CHECK: Return [<<Phi>>]
private Object testMergeInterfaces(boolean cond, InterfaceSuper a, InterfaceOtherSuper b) {
diff --git a/test/550-checker-regression-wide-store/smali/TestCase.smali b/test/550-checker-regression-wide-store/smali/TestCase.smali
index 7974d56a8f..9133c82365 100644
--- a/test/550-checker-regression-wide-store/smali/TestCase.smali
+++ b/test/550-checker-regression-wide-store/smali/TestCase.smali
@@ -25,7 +25,7 @@
# Test storing into the high vreg of a wide pair. This scenario has runtime
# behaviour implications so we run it from Main.main.
-## CHECK-START: int TestCase.invalidateLow(long) ssa_builder (after)
+## CHECK-START: int TestCase.invalidateLow(long) builder (after)
## CHECK-DAG: <<Cst0:i\d+>> IntConstant 0
## CHECK-DAG: <<Arg:j\d+>> ParameterValue
## CHECK-DAG: <<Cast:i\d+>> TypeConversion [<<Arg>>]
@@ -53,7 +53,7 @@
# Test that storing a wide invalidates the value in the high vreg. This
# cannot be detected from runtime so we only test the environment with Checker.
-## CHECK-START: void TestCase.invalidateHigh1(long) ssa_builder (after)
+## CHECK-START: void TestCase.invalidateHigh1(long) builder (after)
## CHECK-DAG: <<Arg:j\d+>> ParameterValue
## CHECK-DAG: InvokeStaticOrDirect method_name:java.lang.System.nanoTime env:[[<<Arg>>,_,<<Arg>>,_]]
@@ -67,7 +67,7 @@
.end method
-## CHECK-START: void TestCase.invalidateHigh2(long) ssa_builder (after)
+## CHECK-START: void TestCase.invalidateHigh2(long) builder (after)
## CHECK-DAG: <<Arg:j\d+>> ParameterValue
## CHECK-DAG: InvokeStaticOrDirect method_name:java.lang.System.nanoTime env:[[<<Arg>>,_,_,<<Arg>>,_]]
diff --git a/test/552-checker-primitive-typeprop/smali/ArrayGet.smali b/test/552-checker-primitive-typeprop/smali/ArrayGet.smali
index 042fa0c80c..de3229064c 100644
--- a/test/552-checker-primitive-typeprop/smali/ArrayGet.smali
+++ b/test/552-checker-primitive-typeprop/smali/ArrayGet.smali
@@ -19,10 +19,10 @@
# Test phi with fixed-type ArrayGet as an input and a matching second input.
# The phi should be typed accordingly.
-## CHECK-START: void ArrayGet.matchingFixedType(float[], float) ssa_builder (after)
+## CHECK-START: void ArrayGet.matchingFixedType(float[], float) builder (after)
## CHECK-NOT: Phi
-## CHECK-START-DEBUGGABLE: void ArrayGet.matchingFixedType(float[], float) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void ArrayGet.matchingFixedType(float[], float) builder (after)
## CHECK-DAG: <<Arg1:f\d+>> ParameterValue
## CHECK-DAG: <<Aget:f\d+>> ArrayGet
## CHECK-DAG: {{f\d+}} Phi [<<Aget>>,<<Arg1>>] reg:0
@@ -49,10 +49,10 @@
# Test phi with fixed-type ArrayGet as an input and a conflicting second input.
# The phi should be eliminated due to the conflict.
-## CHECK-START: void ArrayGet.conflictingFixedType(float[], int) ssa_builder (after)
+## CHECK-START: void ArrayGet.conflictingFixedType(float[], int) builder (after)
## CHECK-NOT: Phi
-## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType(float[], int) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType(float[], int) builder (after)
## CHECK-NOT: Phi
.method public static conflictingFixedType([FI)V
.registers 8
@@ -76,13 +76,13 @@
# Same test as the one above, only this time tests that type of ArrayGet is not
# changed.
-## CHECK-START: void ArrayGet.conflictingFixedType2(int[], float) ssa_builder (after)
+## CHECK-START: void ArrayGet.conflictingFixedType2(int[], float) builder (after)
## CHECK-NOT: Phi
-## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType2(int[], float) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType2(int[], float) builder (after)
## CHECK-NOT: Phi
-## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType2(int[], float) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFixedType2(int[], float) builder (after)
## CHECK: {{i\d+}} ArrayGet
.method public static conflictingFixedType2([IF)V
.registers 8
@@ -107,10 +107,10 @@
# Test phi with free-type ArrayGet as an input and a matching second input.
# The phi should be typed accordingly.
-## CHECK-START: void ArrayGet.matchingFreeType(float[], float) ssa_builder (after)
+## CHECK-START: void ArrayGet.matchingFreeType(float[], float) builder (after)
## CHECK-NOT: Phi
-## CHECK-START-DEBUGGABLE: void ArrayGet.matchingFreeType(float[], float) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void ArrayGet.matchingFreeType(float[], float) builder (after)
## CHECK-DAG: <<Arg1:f\d+>> ParameterValue
## CHECK-DAG: <<Aget:f\d+>> ArrayGet
## CHECK-DAG: ArraySet [{{l\d+}},{{i\d+}},<<Aget>>]
@@ -139,10 +139,10 @@
# The phi will be kept and typed according to the second input despite the
# conflict.
-## CHECK-START: void ArrayGet.conflictingFreeType(int[], float) ssa_builder (after)
+## CHECK-START: void ArrayGet.conflictingFreeType(int[], float) builder (after)
## CHECK-NOT: Phi
-## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFreeType(int[], float) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void ArrayGet.conflictingFreeType(int[], float) builder (after)
## CHECK-NOT: Phi
.method public static conflictingFreeType([IF)V
@@ -169,7 +169,7 @@
# case uses ArrayGet indirectly through two phis. It also creates an unused
# conflicting phi which should not be preserved.
-## CHECK-START: void ArrayGet.conflictingPhiUses(int[], float, boolean, boolean, boolean) ssa_builder (after)
+## CHECK-START: void ArrayGet.conflictingPhiUses(int[], float, boolean, boolean, boolean) builder (after)
## CHECK: InvokeStaticOrDirect env:[[{{i\d+}},{{i\d+}},_,{{i\d+}},{{.*}}
.method public static conflictingPhiUses([IFZZZ)V
@@ -209,10 +209,10 @@
# another. The situation needs to be resolved so that only one instruction
# remains.
-## CHECK-START: void ArrayGet.typedVsUntypedPhiUse(float[], float, boolean, boolean) ssa_builder (after)
+## CHECK-START: void ArrayGet.typedVsUntypedPhiUse(float[], float, boolean, boolean) builder (after)
## CHECK: {{f\d+}} ArrayGet
-## CHECK-START: void ArrayGet.typedVsUntypedPhiUse(float[], float, boolean, boolean) ssa_builder (after)
+## CHECK-START: void ArrayGet.typedVsUntypedPhiUse(float[], float, boolean, boolean) builder (after)
## CHECK-NOT: {{i\d+}} ArrayGet
.method public static typedVsUntypedPhiUse([FFZZ)V
diff --git a/test/552-checker-primitive-typeprop/smali/ArraySet.smali b/test/552-checker-primitive-typeprop/smali/ArraySet.smali
index 57d8606abb..087460aef2 100644
--- a/test/552-checker-primitive-typeprop/smali/ArraySet.smali
+++ b/test/552-checker-primitive-typeprop/smali/ArraySet.smali
@@ -19,7 +19,7 @@
# Note that the input is a Phi to make sure primitive type propagation is re-run
# on the replaced inputs.
-## CHECK-START: void ArraySet.ambiguousSet(int[], float[], boolean) ssa_builder (after)
+## CHECK-START: void ArraySet.ambiguousSet(int[], float[], boolean) builder (after)
## CHECK-DAG: <<IntArray:l\d+>> ParameterValue klass:int[]
## CHECK-DAG: <<IntA:i\d+>> IntConstant 0
## CHECK-DAG: <<IntB:i\d+>> IntConstant 1073741824
diff --git a/test/552-checker-primitive-typeprop/smali/SsaBuilder.smali b/test/552-checker-primitive-typeprop/smali/SsaBuilder.smali
index 395feaaf61..0d067ed1ca 100644
--- a/test/552-checker-primitive-typeprop/smali/SsaBuilder.smali
+++ b/test/552-checker-primitive-typeprop/smali/SsaBuilder.smali
@@ -22,7 +22,7 @@
# otherwise running the code with an array short enough to throw will crash at
# runtime because v0 is undefined.
-## CHECK-START: int SsaBuilder.environmentPhi(boolean, int[]) ssa_builder (after)
+## CHECK-START: int SsaBuilder.environmentPhi(boolean, int[]) builder (after)
## CHECK-DAG: <<Cst0:f\d+>> FloatConstant 0
## CHECK-DAG: <<Cst2:f\d+>> FloatConstant 2
## CHECK-DAG: <<Phi:f\d+>> Phi [<<Cst0>>,<<Cst2>>]
diff --git a/test/552-checker-primitive-typeprop/smali/TypePropagation.smali b/test/552-checker-primitive-typeprop/smali/TypePropagation.smali
index 58682a1923..d34e43e160 100644
--- a/test/552-checker-primitive-typeprop/smali/TypePropagation.smali
+++ b/test/552-checker-primitive-typeprop/smali/TypePropagation.smali
@@ -15,7 +15,7 @@
.class public LTypePropagation;
.super Ljava/lang/Object;
-## CHECK-START-DEBUGGABLE: void TypePropagation.mergeDeadPhi(boolean, boolean, int, float, float) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void TypePropagation.mergeDeadPhi(boolean, boolean, int, float, float) builder (after)
## CHECK-NOT: Phi
.method public static mergeDeadPhi(ZZIFF)V
.registers 8
@@ -34,7 +34,7 @@
return-void
.end method
-## CHECK-START-DEBUGGABLE: void TypePropagation.mergeSameType(boolean, int, int) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void TypePropagation.mergeSameType(boolean, int, int) builder (after)
## CHECK: {{i\d+}} Phi
## CHECK-NOT: Phi
.method public static mergeSameType(ZII)V
@@ -47,7 +47,7 @@
return-void
.end method
-## CHECK-START-DEBUGGABLE: void TypePropagation.mergeVoidInput(boolean, boolean, int, int) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void TypePropagation.mergeVoidInput(boolean, boolean, int, int) builder (after)
## CHECK: {{i\d+}} Phi
## CHECK: {{i\d+}} Phi
## CHECK-NOT: Phi
@@ -64,7 +64,7 @@
return-void
.end method
-## CHECK-START-DEBUGGABLE: void TypePropagation.mergeDifferentSize(boolean, int, long) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void TypePropagation.mergeDifferentSize(boolean, int, long) builder (after)
## CHECK-NOT: Phi
.method public static mergeDifferentSize(ZIJ)V
.registers 8
@@ -76,7 +76,7 @@
return-void
.end method
-## CHECK-START-DEBUGGABLE: void TypePropagation.mergeRefFloat(boolean, float, java.lang.Object) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void TypePropagation.mergeRefFloat(boolean, float, java.lang.Object) builder (after)
## CHECK-NOT: Phi
.method public static mergeRefFloat(ZFLjava/lang/Object;)V
.registers 8
@@ -88,7 +88,7 @@
return-void
.end method
-## CHECK-START-DEBUGGABLE: void TypePropagation.mergeIntFloat_Success(boolean, float) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void TypePropagation.mergeIntFloat_Success(boolean, float) builder (after)
## CHECK: {{f\d+}} Phi
## CHECK-NOT: Phi
.method public static mergeIntFloat_Success(ZF)V
@@ -101,7 +101,7 @@
return-void
.end method
-## CHECK-START-DEBUGGABLE: void TypePropagation.mergeIntFloat_Fail(boolean, int, float) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void TypePropagation.mergeIntFloat_Fail(boolean, int, float) builder (after)
## CHECK-NOT: Phi
.method public static mergeIntFloat_Fail(ZIF)V
.registers 8
@@ -113,7 +113,7 @@
return-void
.end method
-## CHECK-START-DEBUGGABLE: void TypePropagation.updateAllUsersOnConflict(boolean, boolean, int, float, int) ssa_builder (after)
+## CHECK-START-DEBUGGABLE: void TypePropagation.updateAllUsersOnConflict(boolean, boolean, int, float, int) builder (after)
## CHECK-NOT: Phi
.method public static updateAllUsersOnConflict(ZZIFI)V
.registers 8
diff --git a/test/554-checker-rtp-checkcast/src/Main.java b/test/554-checker-rtp-checkcast/src/Main.java
index 607f71afb5..5bf766ff4e 100644
--- a/test/554-checker-rtp-checkcast/src/Main.java
+++ b/test/554-checker-rtp-checkcast/src/Main.java
@@ -19,7 +19,7 @@ public class Main {
public static Object returnIntArray() { return new int[10]; }
- /// CHECK-START: void Main.boundTypeForMergingPhi() ssa_builder (after)
+ /// CHECK-START: void Main.boundTypeForMergingPhi() builder (after)
/// CHECK-DAG: ArraySet [<<NC:l\d+>>,{{i\d+}},{{i\d+}}]
/// CHECK-DAG: <<NC>> NullCheck [<<Phi:l\d+>>]
/// CHECK-DAG: <<Phi>> Phi klass:int[]
@@ -32,7 +32,7 @@ public class Main {
array[0] = 14;
}
- /// CHECK-START: void Main.boundTypeForLoopPhi() ssa_builder (after)
+ /// CHECK-START: void Main.boundTypeForLoopPhi() builder (after)
/// CHECK-DAG: ArraySet [<<NC:l\d+>>,{{i\d+}},{{i\d+}}]
/// CHECK-DAG: <<NC>> NullCheck [<<Phi:l\d+>>]
/// CHECK-DAG: <<Phi>> Phi klass:int[]
@@ -50,7 +50,7 @@ public class Main {
array[0] = 14;
}
- /// CHECK-START: void Main.boundTypeForCatchPhi() ssa_builder (after)
+ /// CHECK-START: void Main.boundTypeForCatchPhi() builder (after)
/// CHECK-DAG: ArraySet [<<NC:l\d+>>,{{i\d+}},{{i\d+}}]
/// CHECK-DAG: <<NC>> NullCheck [<<Phi:l\d+>>]
/// CHECK-DAG: <<Phi>> Phi is_catch_phi:true klass:int[]
diff --git a/test/557-checker-ref-equivalent/smali/TestCase.smali b/test/557-checker-ref-equivalent/smali/TestCase.smali
index 24729572c4..1347554aad 100644
--- a/test/557-checker-ref-equivalent/smali/TestCase.smali
+++ b/test/557-checker-ref-equivalent/smali/TestCase.smali
@@ -16,7 +16,7 @@
.super Ljava/lang/Object;
-## CHECK-START: void TestCase.testIntRefEquivalent() ssa_builder (after)
+## CHECK-START: void TestCase.testIntRefEquivalent() builder (after)
## CHECK-NOT: Phi
.method public static testIntRefEquivalent()V
.registers 4
diff --git a/test/557-checker-ref-equivalent/src/Main.java b/test/557-checker-ref-equivalent/src/Main.java
index a970af5cdf..9323757d92 100644
--- a/test/557-checker-ref-equivalent/src/Main.java
+++ b/test/557-checker-ref-equivalent/src/Main.java
@@ -16,7 +16,7 @@
public class Main {
- /// CHECK-START: void Main.testRedundantPhiCycle(boolean) ssa_builder (after)
+ /// CHECK-START: void Main.testRedundantPhiCycle(boolean) builder (after)
/// CHECK-NOT: Phi
private void testRedundantPhiCycle(boolean cond) {
Object o = null;
@@ -28,7 +28,7 @@ public class Main {
}
}
- /// CHECK-START: void Main.testLoopPhisWithNullAndCrossUses(boolean) ssa_builder (after)
+ /// CHECK-START: void Main.testLoopPhisWithNullAndCrossUses(boolean) builder (after)
/// CHECK-NOT: Phi
private void testLoopPhisWithNullAndCrossUses(boolean cond) {
Main a = null;
diff --git a/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali b/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali
index 971ad84241..7ce60a304b 100644
--- a/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali
+++ b/test/559-checker-irreducible-loop/smali/IrreducibleLoop.smali
@@ -323,7 +323,7 @@
# - / \-
# irreducible_loop_back_edge loop_within_back_edge
#
-## CHECK-START: void IrreducibleLoop.analyze1(int) ssa_builder (after)
+## CHECK-START: void IrreducibleLoop.analyze1(int) builder (after)
## CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none irreducible:true
## CHECK-DAG: Goto outer_loop:<<OuterLoop>> irreducible:false
.method public static analyze1(I)V
@@ -371,7 +371,7 @@
# exit \- /
# irreducible_loop_body
#
-## CHECK-START: void IrreducibleLoop.analyze2(int) ssa_builder (after)
+## CHECK-START: void IrreducibleLoop.analyze2(int) builder (after)
## CHECK-DAG: Goto outer_loop:none irreducible:false
## CHECK-DAG: Goto outer_loop:none irreducible:true
.method public static analyze2(I)V
@@ -418,7 +418,7 @@
# |
# exit
#
-## CHECK-START: void IrreducibleLoop.analyze3(int) ssa_builder (after)
+## CHECK-START: void IrreducibleLoop.analyze3(int) builder (after)
## CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none irreducible:true
## CHECK-DAG: Goto outer_loop:<<OuterLoop>> irreducible:true
.method public static analyze3(I)V
@@ -467,7 +467,7 @@
# |
# exit
#
-## CHECK-START: void IrreducibleLoop.analyze4(int) ssa_builder (after)
+## CHECK-START: void IrreducibleLoop.analyze4(int) builder (after)
## CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none irreducible:true
## CHECK-DAG: Goto outer_loop:<<OuterLoop>> irreducible:true
.method public static analyze4(I)V
@@ -519,7 +519,7 @@
# |
# exit
#
-## CHECK-START: void IrreducibleLoop.analyze5(int) ssa_builder (after)
+## CHECK-START: void IrreducibleLoop.analyze5(int) builder (after)
## CHECK-DAG: Goto loop:<<OuterLoop:B\d+>> outer_loop:none irreducible:true
## CHECK-DAG: Goto outer_loop:<<OuterLoop>> irreducible:true
.method public static analyze5(I)V
diff --git a/test/559-checker-rtp-ifnotnull/src/Main.java b/test/559-checker-rtp-ifnotnull/src/Main.java
index 8f401292da..2dc5666e18 100644
--- a/test/559-checker-rtp-ifnotnull/src/Main.java
+++ b/test/559-checker-rtp-ifnotnull/src/Main.java
@@ -17,7 +17,7 @@
public class Main {
- /// CHECK-START: void Main.boundTypeForIfNotNull() ssa_builder (after)
+ /// CHECK-START: void Main.boundTypeForIfNotNull() builder (after)
/// CHECK-DAG: <<Method:(i|j)\d+>> CurrentMethod
/// CHECK-DAG: <<Null:l\d+>> NullConstant
/// CHECK-DAG: <<Cst5:i\d+>> IntConstant 5