ssa_test.cc revision ec7e4727e99aa1416398ac5a684f5024817a25c7
1c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray/*
2c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray * Copyright (C) 2014 The Android Open Source Project
3c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray *
4c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray * Licensed under the Apache License, Version 2.0 (the "License");
5c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray * you may not use this file except in compliance with the License.
6c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray * You may obtain a copy of the License at
7c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray *
8c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray *      http://www.apache.org/licenses/LICENSE-2.0
9c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray *
10c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray * Unless required by applicable law or agreed to in writing, software
11c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray * distributed under the License is distributed on an "AS IS" BASIS,
12c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray * See the License for the specific language governing permissions and
14c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray * limitations under the License.
15c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray */
16c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
17c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "base/stringprintf.h"
18c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "builder.h"
19c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "dex_file.h"
20c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "dex_instruction.h"
21c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "nodes.h"
22c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "optimizing_unit_test.h"
23c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "pretty_printer.h"
24c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "ssa_builder.h"
25c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "utils/arena_allocator.h"
26c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
27c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray#include "gtest/gtest.h"
28c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
29c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffraynamespace art {
30c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
310d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffrayclass SsaPrettyPrinter : public HPrettyPrinter {
32c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray public:
330d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  explicit SsaPrettyPrinter(HGraph* graph) : HPrettyPrinter(graph), str_("") {}
34c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
35c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  virtual void PrintInt(int value) {
36c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    str_ += StringPrintf("%d", value);
37c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
38c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
39c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  virtual void PrintString(const char* value) {
40c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    str_ += value;
41c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
42c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
43c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  virtual void PrintNewLine() {
44c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    str_ += '\n';
45c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
46c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
47c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  void Clear() { str_.clear(); }
48c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
49c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  std::string str() const { return str_; }
50c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
51c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  virtual void VisitIntConstant(HIntConstant* constant) {
52c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    PrintPreInstruction(constant);
53c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    str_ += constant->DebugName();
54c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    str_ += " ";
55c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    PrintInt(constant->GetValue());
56c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    PrintPostInstruction(constant);
57c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
58c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
59c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray private:
60c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  std::string str_;
61c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
620d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  DISALLOW_COPY_AND_ASSIGN(SsaPrettyPrinter);
63c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray};
64c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
65c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffraystatic void ReNumberInstructions(HGraph* graph) {
66c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  int id = 0;
67804d09372cc3d80d537da1489da4a45e0e19aa5dNicolas Geoffray  for (size_t i = 0, e = graph->GetBlocks().Size(); i < e; ++i) {
68804d09372cc3d80d537da1489da4a45e0e19aa5dNicolas Geoffray    HBasicBlock* block = graph->GetBlocks().Get(i);
69f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
70c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray      it.Current()->SetId(id++);
71c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    }
72f635e63318447ca04731b265a86a573c9ed1737cNicolas Geoffray    for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
73c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray      it.Current()->SetId(id++);
74c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    }
75c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  }
76c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
77c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
78c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffraystatic void TestCode(const uint16_t* data, const char* expected) {
79c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  ArenaPool pool;
80c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  ArenaAllocator allocator(&pool);
81c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  HGraphBuilder builder(&allocator);
82c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
83c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  HGraph* graph = builder.BuildGraph(*item);
84c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  ASSERT_NE(graph, nullptr);
850d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray
86c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  graph->BuildDominatorTree();
87c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  graph->TransformToSSA();
88c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  ReNumberInstructions(graph);
89c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
900d3f578909d0d1ea072ca68d78301b6fb7a44451Nicolas Geoffray  SsaPrettyPrinter printer(graph);
91c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  printer.VisitInsertionOrder();
92c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
93c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  ASSERT_STREQ(expected, printer.str().c_str());
94c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
95c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
96c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, CFG1) {
97c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Test that we get rid of loads and stores.
98c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
99c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
100c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [2, 2]\n"
101c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: Goto\n"
102ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 1, pred: 0, succ: 5, 2\n"
103c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: Equal(0, 0) [3]\n"
104c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: If(2)\n"
105c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 2, pred: 1, succ: 3\n"
106c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  4: Goto\n"
107622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 3, pred: 2, 5, succ: 4\n"
108c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  5: ReturnVoid\n"
109c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 4, pred: 3\n"
110622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  6: Exit\n"
111622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    // Synthesized block to avoid critical edge.
112622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 5, pred: 1, succ: 3\n"
113622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  7: Goto\n";
114c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
115c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
116c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
117c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 3,
118c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0x100,
119c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN_VOID);
120c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
121c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
122c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
123c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
124c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, CFG2) {
125c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Test that we create a phi for the join block of an if control flow instruction
126c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // when there is only code in the else branch.
127c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
128c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
129c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [6, 3, 3]\n"
130c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: IntConstant 4 [6]\n"
131c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: Goto\n"
132ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 1, pred: 0, succ: 5, 2\n"
133c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: Equal(0, 0) [4]\n"
134c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  4: If(3)\n"
135c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 2, pred: 1, succ: 3\n"
136c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  5: Goto\n"
137622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 3, pred: 2, 5, succ: 4\n"
138622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  6: Phi(1, 0) [7]\n"
139c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  7: Return(6)\n"
140c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 4, pred: 3\n"
141622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  8: Exit\n"
142622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    // Synthesized block to avoid critical edge.
143622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 5, pred: 1, succ: 3\n"
144622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  9: Goto\n";
145c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
146c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
147c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
148c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 3,
149c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0,
150c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN | 0 << 8);
151c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
152c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
153c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
154c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
155c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, CFG3) {
156c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Test that we create a phi for the join block of an if control flow instruction
157804d09372cc3d80d537da1489da4a45e0e19aa5dNicolas Geoffray  // when both branches update a local.
158c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
159c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
160c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [4, 4]\n"
161c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: IntConstant 4 [8]\n"
162c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: IntConstant 5 [8]\n"
163c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: Goto\n"
164c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 1, pred: 0, succ: 3, 2\n"
165c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  4: Equal(0, 0) [5]\n"
166c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  5: If(4)\n"
167c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 2, pred: 1, succ: 4\n"
168c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  6: Goto\n"
169c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 3, pred: 1, succ: 4\n"
170c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  7: Goto\n"
171c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 4, pred: 2, 3, succ: 5\n"
172c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  8: Phi(1, 2) [9]\n"
173c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  9: Return(8)\n"
174c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 5, pred: 4\n"
175c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  10: Exit\n";
176c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
177c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
178c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
179c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 4,
180c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0,
181c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0x200,
182c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 5 << 12 | 0,
183c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN | 0 << 8);
184c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
185c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
186c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
187c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
188c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, Loop1) {
189c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Test that we create a phi for an initialized local at entry of a loop.
190c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
191c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
192c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [6, 4, 2, 2]\n"
193c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: Goto\n"
194622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 1, pred: 0, succ: 5, 6\n"
195c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: Equal(0, 0) [3]\n"
196c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: If(2)\n"
197622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 2, pred: 3, 6, succ: 3\n"
198622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  4: Phi(6, 0) [6]\n"
199c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  5: Goto\n"
200622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 3, pred: 2, 5, succ: 2\n"
201622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  6: Phi(4, 0) [4]\n"
202c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  7: Goto\n"
203622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 4\n"
204622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    // Synthesized blocks to avoid critical edge.
205622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 5, pred: 1, succ: 3\n"
206622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  8: Goto\n"
207622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 6, pred: 1, succ: 2\n"
208622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  9: Goto\n";
209c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
210c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
211c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
212c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 3,
213c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0x100,
214c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0xFF00);
215c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
216c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
217c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
218c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
219c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, Loop2) {
220c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Simple loop with one preheader and one back edge.
221c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
222c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
223c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [4]\n"
224c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: IntConstant 4 [4]\n"
225c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: Goto\n"
226c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 1, pred: 0, succ: 2\n"
227c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: Goto\n"
228c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 2, pred: 1, 3, succ: 4, 3\n"
229c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  4: Phi(0, 1) [5, 5]\n"
230c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  5: Equal(4, 4) [6]\n"
231c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  6: If(5)\n"
232c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 3, pred: 2, succ: 2\n"
233c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  7: Goto\n"
234c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 4, pred: 2, succ: 5\n"
235c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  8: ReturnVoid\n"
236c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 5, pred: 4\n"
237c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  9: Exit\n";
238c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
239c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
240c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
241c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 4,
242c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0,
243c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0xFD00,
244c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN_VOID);
245c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
246c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
247c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
248c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
249c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, Loop3) {
250c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Test that a local not yet defined at the entry of a loop is handled properly.
251c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
252c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
253c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [5]\n"
254c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: IntConstant 4 [5]\n"
255c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: IntConstant 5 [9]\n"
256c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: Goto\n"
257c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 1, pred: 0, succ: 2\n"
258c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  4: Goto\n"
259c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 2, pred: 1, 3, succ: 4, 3\n"
260c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  5: Phi(0, 1) [6, 6]\n"
261c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  6: Equal(5, 5) [7]\n"
262c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  7: If(6)\n"
263c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 3, pred: 2, succ: 2\n"
264c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  8: Goto\n"
265c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 4, pred: 2, succ: 5\n"
266c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  9: Return(2)\n"
267c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 5, pred: 4\n"
268c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  10: Exit\n";
269c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
270c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
271c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
272c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 4,
273c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0,
274c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0xFD00,
275c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 5 << 12 | 1 << 8,
276c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN | 1 << 8);
277c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
278c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
279c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
280c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
281c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, Loop4) {
282c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Make sure we support a preheader of a loop not being the first predecessor
283c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // in the predecessor list of the header.
284c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
285c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
286c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [4]\n"
287c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: IntConstant 4 [4]\n"
288c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: Goto\n"
289c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 1, pred: 0, succ: 4\n"
290c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: Goto\n"
291c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 2, pred: 3, 4, succ: 5, 3\n"
292c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  4: Phi(1, 0) [9, 5, 5]\n"
293c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  5: Equal(4, 4) [6]\n"
294c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  6: If(5)\n"
295c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 3, pred: 2, succ: 2\n"
296c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  7: Goto\n"
297c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 4, pred: 1, succ: 2\n"
298c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  8: Goto\n"
299c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 5, pred: 2, succ: 6\n"
300c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  9: Return(4)\n"
301c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 6, pred: 5\n"
302c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  10: Exit\n";
303c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
304c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
305c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
306c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0x500,
307c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 5,
308c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0,
309c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0xFD00,
310c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0xFC00,
311c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN | 0 << 8);
312c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
313c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
314c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
315c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
316c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, Loop5) {
317c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Make sure we create a preheader of a loop when a header originally has two
318c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // incoming blocks and one back edge.
319c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
320c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
321c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [4, 4]\n"
322c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: IntConstant 4 [14]\n"
323c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: IntConstant 5 [14]\n"
324c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: Goto\n"
325c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 1, pred: 0, succ: 3, 2\n"
326c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  4: Equal(0, 0) [5]\n"
327c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  5: If(4)\n"
328c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 2, pred: 1, succ: 8\n"
329c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  6: Goto\n"
330c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 3, pred: 1, succ: 8\n"
331c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  7: Goto\n"
332c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 4, pred: 5, 8, succ: 6, 5\n"
333c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  8: Phi(8, 14) [8, 12, 9, 9]\n"
334c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  9: Equal(8, 8) [10]\n"
335c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  10: If(9)\n"
336c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 5, pred: 4, succ: 4\n"
337c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  11: Goto\n"
338c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 6, pred: 4, succ: 7\n"
339c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  12: Return(8)\n"
340c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 7, pred: 6\n"
341c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  13: Exit\n"
342c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 8, pred: 2, 3, succ: 4\n"
343c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  14: Phi(1, 2) [8]\n"
344c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  15: Goto\n";
345c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
346c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
347c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
348c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 4,
349c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0,
350c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0x200,
351c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 5 << 12 | 0,
352c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 3,
353c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0xFE00,
354c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN | 0 << 8);
355c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
356c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
357c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
358c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
359c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, Loop6) {
360c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Test a loop with one preheader and two back edges (e.g. continue).
361c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
362c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
363c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [5]\n"
364622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  1: IntConstant 4 [14, 8, 8]\n"
365622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  2: IntConstant 5 [14]\n"
366c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: Goto\n"
367c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 1, pred: 0, succ: 2\n"
368c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  4: Goto\n"
369622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 2, pred: 1, 8, succ: 6, 3\n"
370622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  5: Phi(0, 14) [12, 6, 6]\n"
371c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  6: Equal(5, 5) [7]\n"
372c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  7: If(6)\n"
373c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 3, pred: 2, succ: 5, 4\n"
374c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  8: Equal(1, 1) [9]\n"
375c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  9: If(8)\n"
376622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 4, pred: 3, succ: 8\n"
377c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  10: Goto\n"
378622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 5, pred: 3, succ: 8\n"
379c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  11: Goto\n"
380c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 6, pred: 2, succ: 7\n"
381c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  12: Return(5)\n"
382c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 7, pred: 6\n"
383622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  13: Exit\n"
384622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    // Synthesized single back edge of loop.
385622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 8, pred: 5, 4, succ: 2\n"
386622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  14: Phi(1, 2) [5]\n"
387622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  15: Goto\n";
388c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
389c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
390c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
391c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 8,
392c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0,
393c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 4,
394c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 5 << 12 | 0,
395c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0xFA00,
396c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0xF900,
397c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN | 0 << 8);
398c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
399c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
400c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
401c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
402c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, Loop7) {
403c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Test a loop with one preheader, one back edge, and two exit edges (e.g. break).
404c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
405c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
406c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0 [5]\n"
407c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: IntConstant 4 [5, 8, 8]\n"
408c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: IntConstant 5 [12]\n"
409c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: Goto\n"
410c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 1, pred: 0, succ: 2\n"
411c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  4: Goto\n"
412ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 2, pred: 1, 5, succ: 8, 3\n"
413c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  5: Phi(0, 1) [12, 6, 6]\n"
414c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  6: Equal(5, 5) [7]\n"
415c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  7: If(6)\n"
416c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 3, pred: 2, succ: 5, 4\n"
417c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  8: Equal(1, 1) [9]\n"
418c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  9: If(8)\n"
419c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 4, pred: 3, succ: 6\n"
420c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  10: Goto\n"
421c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 5, pred: 3, succ: 2\n"
422c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  11: Goto\n"
423622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 6, pred: 4, 8, succ: 7\n"
424622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  12: Phi(2, 5) [13]\n"
425c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  13: Return(12)\n"
426c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 7, pred: 6\n"
427622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  14: Exit\n"
428622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "BasicBlock 8, pred: 2, succ: 6\n"
429622d9c31febd950255b36a48b47e1f630197c5feNicolas Geoffray    "  15: Goto\n";
430c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
431c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
432c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
433c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 8,
434c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 0,
435c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::IF_EQ, 4,
436c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 5 << 12 | 0,
437c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0x0200,
438c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::GOTO | 0xF900,
439c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN | 0 << 8);
440c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
441c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
442c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
443c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
444c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas GeoffrayTEST(SsaTest, DeadLocal) {
445c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  // Test that we correctly handle a local not being used.
446c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const char* expected =
447c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 0, succ: 1\n"
448c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  0: IntConstant 0\n"
449c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  1: Goto\n"
450c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 1, pred: 0, succ: 2\n"
451c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  2: ReturnVoid\n"
452c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "BasicBlock 2, pred: 1\n"
453c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    "  3: Exit\n";
454c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
455c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
456c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
457c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray    Instruction::RETURN_VOID);
458c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
459c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray  TestCode(data, expected);
460c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}
461c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray
4627c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas GeoffrayTEST(SsaTest, LocalInIf) {
4637c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray  // Test that we do not create a phi in the join block when one predecessor
4647c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray  // does not update the local.
4657c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray  const char* expected =
4667c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "BasicBlock 0, succ: 1\n"
4677c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "  0: IntConstant 0 [3, 3]\n"
4687c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "  1: IntConstant 4\n"
4697c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "  2: Goto\n"
470ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 1, pred: 0, succ: 5, 2\n"
4717c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "  3: Equal(0, 0) [4]\n"
4727c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "  4: If(3)\n"
4737c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "BasicBlock 2, pred: 1, succ: 3\n"
4747c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "  5: Goto\n"
4757c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "BasicBlock 3, pred: 2, 5, succ: 4\n"
4767c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "  6: ReturnVoid\n"
4777c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "BasicBlock 4, pred: 3\n"
4787c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "  7: Exit\n"
4797c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    // Synthesized block to avoid critical edge.
4807c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "BasicBlock 5, pred: 1, succ: 3\n"
4817c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    "  8: Goto\n";
4827c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray
4837c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
4847c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    Instruction::CONST_4 | 0 | 0,
4857c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    Instruction::IF_EQ, 3,
4867c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    Instruction::CONST_4 | 4 << 12 | 1 << 8,
4877c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray    Instruction::RETURN_VOID);
4887c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray
4897c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray  TestCode(data, expected);
4907c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray}
4917c3560f2ce0ec9484004d05a94bfaa6e02f5a96aNicolas Geoffray
492ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas GeoffrayTEST(SsaTest, MultiplePredecessors) {
493ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray  // Test that we do not create a phi when one predecessor
494ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray  // does not update the local.
495ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray  const char* expected =
496ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 0, succ: 1\n"
497ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  0: IntConstant 0 [4, 8, 6, 6, 2, 2, 8, 4]\n"
498ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  1: Goto\n"
499ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 1, pred: 0, succ: 3, 2\n"
500ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  2: Equal(0, 0) [3]\n"
501ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  3: If(2)\n"
502ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 2, pred: 1, succ: 5\n"
503ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  4: Add(0, 0)\n"
504ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  5: Goto\n"
505ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 3, pred: 1, succ: 7, 4\n"
506ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  6: Equal(0, 0) [7]\n"
507ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  7: If(6)\n"
508ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 4, pred: 3, succ: 5\n"
509ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  8: Add(0, 0)\n"
510ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  9: Goto\n"
511ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    // This block should not get a phi for local 1.
512ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 5, pred: 2, 4, 7, succ: 6\n"
513ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  10: ReturnVoid\n"
514ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 6, pred: 5\n"
515ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  11: Exit\n"
516ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "BasicBlock 7, pred: 3, succ: 5\n"
517ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    "  12: Goto\n";
518ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray
519ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
520ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    Instruction::CONST_4 | 0 | 0,
521ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    Instruction::IF_EQ, 5,
522ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    Instruction::ADD_INT_LIT8 | 1 << 8, 0 << 8,
523ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    Instruction::GOTO | 0x0500,
524ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    Instruction::IF_EQ, 4,
525ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    Instruction::ADD_INT_LIT8 | 1 << 8, 0 << 8,
526ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray    Instruction::RETURN_VOID);
527ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray
528ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray  TestCode(data, expected);
529ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray}
530ec7e4727e99aa1416398ac5a684f5024817a25c7Nicolas Geoffray
531c32e770f21540e4e9eda6dc7f770e745d33f1b9fNicolas Geoffray}  // namespace art
532