1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker * Copyright (C) 2014 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker *
4*795d594fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker *
8*795d594fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker *
10*795d594fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker */
16*795d594fSAndroid Build Coastguard Worker
17*795d594fSAndroid Build Coastguard Worker #include "android-base/stringprintf.h"
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include "base/arena_allocator.h"
20*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
21*795d594fSAndroid Build Coastguard Worker #include "builder.h"
22*795d594fSAndroid Build Coastguard Worker #include "dex/dex_file.h"
23*795d594fSAndroid Build Coastguard Worker #include "dex/dex_instruction.h"
24*795d594fSAndroid Build Coastguard Worker #include "nodes.h"
25*795d594fSAndroid Build Coastguard Worker #include "optimizing_unit_test.h"
26*795d594fSAndroid Build Coastguard Worker #include "pretty_printer.h"
27*795d594fSAndroid Build Coastguard Worker #include "ssa_builder.h"
28*795d594fSAndroid Build Coastguard Worker
29*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h"
30*795d594fSAndroid Build Coastguard Worker
31*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
32*795d594fSAndroid Build Coastguard Worker
33*795d594fSAndroid Build Coastguard Worker class SsaTest : public CommonCompilerTest, public OptimizingUnitTestHelper {
34*795d594fSAndroid Build Coastguard Worker protected:
35*795d594fSAndroid Build Coastguard Worker void TestCode(const std::vector<uint16_t>& data, const char* expected);
36*795d594fSAndroid Build Coastguard Worker };
37*795d594fSAndroid Build Coastguard Worker
38*795d594fSAndroid Build Coastguard Worker class SsaPrettyPrinter : public HPrettyPrinter {
39*795d594fSAndroid Build Coastguard Worker public:
SsaPrettyPrinter(HGraph * graph)40*795d594fSAndroid Build Coastguard Worker explicit SsaPrettyPrinter(HGraph* graph) : HPrettyPrinter(graph), str_("") {}
41*795d594fSAndroid Build Coastguard Worker
PrintInt(int value)42*795d594fSAndroid Build Coastguard Worker void PrintInt(int value) override {
43*795d594fSAndroid Build Coastguard Worker str_ += android::base::StringPrintf("%d", value);
44*795d594fSAndroid Build Coastguard Worker }
45*795d594fSAndroid Build Coastguard Worker
PrintString(const char * value)46*795d594fSAndroid Build Coastguard Worker void PrintString(const char* value) override {
47*795d594fSAndroid Build Coastguard Worker str_ += value;
48*795d594fSAndroid Build Coastguard Worker }
49*795d594fSAndroid Build Coastguard Worker
PrintNewLine()50*795d594fSAndroid Build Coastguard Worker void PrintNewLine() override {
51*795d594fSAndroid Build Coastguard Worker str_ += '\n';
52*795d594fSAndroid Build Coastguard Worker }
53*795d594fSAndroid Build Coastguard Worker
Clear()54*795d594fSAndroid Build Coastguard Worker void Clear() { str_.clear(); }
55*795d594fSAndroid Build Coastguard Worker
str() const56*795d594fSAndroid Build Coastguard Worker std::string str() const { return str_; }
57*795d594fSAndroid Build Coastguard Worker
VisitIntConstant(HIntConstant * constant)58*795d594fSAndroid Build Coastguard Worker void VisitIntConstant(HIntConstant* constant) override {
59*795d594fSAndroid Build Coastguard Worker PrintPreInstruction(constant);
60*795d594fSAndroid Build Coastguard Worker str_ += constant->DebugName();
61*795d594fSAndroid Build Coastguard Worker str_ += " ";
62*795d594fSAndroid Build Coastguard Worker PrintInt(constant->GetValue());
63*795d594fSAndroid Build Coastguard Worker PrintPostInstruction(constant);
64*795d594fSAndroid Build Coastguard Worker }
65*795d594fSAndroid Build Coastguard Worker
66*795d594fSAndroid Build Coastguard Worker private:
67*795d594fSAndroid Build Coastguard Worker std::string str_;
68*795d594fSAndroid Build Coastguard Worker
69*795d594fSAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(SsaPrettyPrinter);
70*795d594fSAndroid Build Coastguard Worker };
71*795d594fSAndroid Build Coastguard Worker
ReNumberInstructions(HGraph * graph)72*795d594fSAndroid Build Coastguard Worker static void ReNumberInstructions(HGraph* graph) {
73*795d594fSAndroid Build Coastguard Worker int id = 0;
74*795d594fSAndroid Build Coastguard Worker for (HBasicBlock* block : graph->GetBlocks()) {
75*795d594fSAndroid Build Coastguard Worker for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
76*795d594fSAndroid Build Coastguard Worker it.Current()->SetId(id++);
77*795d594fSAndroid Build Coastguard Worker }
78*795d594fSAndroid Build Coastguard Worker for (HInstructionIterator it(block->GetInstructions()); !it.Done(); it.Advance()) {
79*795d594fSAndroid Build Coastguard Worker it.Current()->SetId(id++);
80*795d594fSAndroid Build Coastguard Worker }
81*795d594fSAndroid Build Coastguard Worker }
82*795d594fSAndroid Build Coastguard Worker }
83*795d594fSAndroid Build Coastguard Worker
TestCode(const std::vector<uint16_t> & data,const char * expected)84*795d594fSAndroid Build Coastguard Worker void SsaTest::TestCode(const std::vector<uint16_t>& data, const char* expected) {
85*795d594fSAndroid Build Coastguard Worker HGraph* graph = CreateCFG(data);
86*795d594fSAndroid Build Coastguard Worker // Suspend checks implementation may change in the future, and this test relies
87*795d594fSAndroid Build Coastguard Worker // on how instructions are ordered.
88*795d594fSAndroid Build Coastguard Worker RemoveSuspendChecks(graph);
89*795d594fSAndroid Build Coastguard Worker ReNumberInstructions(graph);
90*795d594fSAndroid Build Coastguard Worker
91*795d594fSAndroid Build Coastguard Worker // Test that phis had their type set.
92*795d594fSAndroid Build Coastguard Worker for (HBasicBlock* block : graph->GetBlocks()) {
93*795d594fSAndroid Build Coastguard Worker for (HInstructionIterator it(block->GetPhis()); !it.Done(); it.Advance()) {
94*795d594fSAndroid Build Coastguard Worker ASSERT_NE(it.Current()->GetType(), DataType::Type::kVoid);
95*795d594fSAndroid Build Coastguard Worker }
96*795d594fSAndroid Build Coastguard Worker }
97*795d594fSAndroid Build Coastguard Worker
98*795d594fSAndroid Build Coastguard Worker SsaPrettyPrinter printer(graph);
99*795d594fSAndroid Build Coastguard Worker printer.VisitInsertionOrder();
100*795d594fSAndroid Build Coastguard Worker
101*795d594fSAndroid Build Coastguard Worker ASSERT_STREQ(expected, printer.str().c_str());
102*795d594fSAndroid Build Coastguard Worker }
103*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,CFG1)104*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, CFG1) {
105*795d594fSAndroid Build Coastguard Worker // Test that we get rid of loads and stores.
106*795d594fSAndroid Build Coastguard Worker const char* expected =
107*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
108*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [2, 2]\n"
109*795d594fSAndroid Build Coastguard Worker " 1: Goto\n"
110*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 5, 2\n"
111*795d594fSAndroid Build Coastguard Worker " 2: Equal(0, 0) [3]\n"
112*795d594fSAndroid Build Coastguard Worker " 3: If(2)\n"
113*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, succ: 3\n"
114*795d594fSAndroid Build Coastguard Worker " 4: Goto\n"
115*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 5, 2, succ: 4\n"
116*795d594fSAndroid Build Coastguard Worker " 5: ReturnVoid\n"
117*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 3\n"
118*795d594fSAndroid Build Coastguard Worker " 6: Exit\n"
119*795d594fSAndroid Build Coastguard Worker // Synthesized block to avoid critical edge.
120*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 1, succ: 3\n"
121*795d594fSAndroid Build Coastguard Worker " 7: Goto\n";
122*795d594fSAndroid Build Coastguard Worker
123*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
124*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
125*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 3,
126*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x100,
127*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
128*795d594fSAndroid Build Coastguard Worker
129*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
130*795d594fSAndroid Build Coastguard Worker }
131*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,CFG2)132*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, CFG2) {
133*795d594fSAndroid Build Coastguard Worker // Test that we create a phi for the join block of an if control flow instruction
134*795d594fSAndroid Build Coastguard Worker // when there is only code in the else branch.
135*795d594fSAndroid Build Coastguard Worker const char* expected =
136*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
137*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [6, 3, 3]\n"
138*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 4 [6]\n"
139*795d594fSAndroid Build Coastguard Worker " 2: Goto\n"
140*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 5, 2\n"
141*795d594fSAndroid Build Coastguard Worker " 3: Equal(0, 0) [4]\n"
142*795d594fSAndroid Build Coastguard Worker " 4: If(3)\n"
143*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, succ: 3\n"
144*795d594fSAndroid Build Coastguard Worker " 5: Goto\n"
145*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 5, 2, succ: 4\n"
146*795d594fSAndroid Build Coastguard Worker " 6: Phi(0, 1) [7]\n"
147*795d594fSAndroid Build Coastguard Worker " 7: Return(6)\n"
148*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 3\n"
149*795d594fSAndroid Build Coastguard Worker " 8: Exit\n"
150*795d594fSAndroid Build Coastguard Worker // Synthesized block to avoid critical edge.
151*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 1, succ: 3\n"
152*795d594fSAndroid Build Coastguard Worker " 9: Goto\n";
153*795d594fSAndroid Build Coastguard Worker
154*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
155*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
156*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 3,
157*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
158*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0 << 8);
159*795d594fSAndroid Build Coastguard Worker
160*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
161*795d594fSAndroid Build Coastguard Worker }
162*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,CFG3)163*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, CFG3) {
164*795d594fSAndroid Build Coastguard Worker // Test that we create a phi for the join block of an if control flow instruction
165*795d594fSAndroid Build Coastguard Worker // when both branches update a local.
166*795d594fSAndroid Build Coastguard Worker const char* expected =
167*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
168*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [4, 4]\n"
169*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 5 [8]\n"
170*795d594fSAndroid Build Coastguard Worker " 2: IntConstant 4 [8]\n"
171*795d594fSAndroid Build Coastguard Worker " 3: Goto\n"
172*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 3, 2\n"
173*795d594fSAndroid Build Coastguard Worker " 4: Equal(0, 0) [5]\n"
174*795d594fSAndroid Build Coastguard Worker " 5: If(4)\n"
175*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, succ: 4\n"
176*795d594fSAndroid Build Coastguard Worker " 6: Goto\n"
177*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 1, succ: 4\n"
178*795d594fSAndroid Build Coastguard Worker " 7: Goto\n"
179*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 2, 3, succ: 5\n"
180*795d594fSAndroid Build Coastguard Worker " 8: Phi(2, 1) [9]\n"
181*795d594fSAndroid Build Coastguard Worker " 9: Return(8)\n"
182*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 4\n"
183*795d594fSAndroid Build Coastguard Worker " 10: Exit\n";
184*795d594fSAndroid Build Coastguard Worker
185*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
186*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
187*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 4,
188*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
189*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x200,
190*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 5 << 12 | 0,
191*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0 << 8);
192*795d594fSAndroid Build Coastguard Worker
193*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
194*795d594fSAndroid Build Coastguard Worker }
195*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,Loop1)196*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, Loop1) {
197*795d594fSAndroid Build Coastguard Worker // Test that we create a phi for an initialized local at entry of a loop.
198*795d594fSAndroid Build Coastguard Worker const char* expected =
199*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
200*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [6, 3, 3]\n"
201*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 4 [6]\n"
202*795d594fSAndroid Build Coastguard Worker " 2: Goto\n"
203*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 4, 2\n"
204*795d594fSAndroid Build Coastguard Worker " 3: Equal(0, 0) [4]\n"
205*795d594fSAndroid Build Coastguard Worker " 4: If(3)\n"
206*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, succ: 3\n"
207*795d594fSAndroid Build Coastguard Worker " 5: Goto\n"
208*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 2, 4, succ: 5\n"
209*795d594fSAndroid Build Coastguard Worker " 6: Phi(1, 0) [9]\n"
210*795d594fSAndroid Build Coastguard Worker " 7: Goto\n"
211*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 1, succ: 3\n"
212*795d594fSAndroid Build Coastguard Worker " 8: Goto\n"
213*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 3, succ: 6\n"
214*795d594fSAndroid Build Coastguard Worker " 9: Return(6)\n"
215*795d594fSAndroid Build Coastguard Worker "BasicBlock 6, pred: 5\n"
216*795d594fSAndroid Build Coastguard Worker " 10: Exit\n";
217*795d594fSAndroid Build Coastguard Worker
218*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
219*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
220*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 4,
221*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
222*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x200,
223*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xFF00,
224*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0 << 8);
225*795d594fSAndroid Build Coastguard Worker
226*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
227*795d594fSAndroid Build Coastguard Worker }
228*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,Loop2)229*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, Loop2) {
230*795d594fSAndroid Build Coastguard Worker // Simple loop with one preheader and one back edge.
231*795d594fSAndroid Build Coastguard Worker const char* expected =
232*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
233*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [4]\n"
234*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 4 [4]\n"
235*795d594fSAndroid Build Coastguard Worker " 2: Goto\n"
236*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
237*795d594fSAndroid Build Coastguard Worker " 3: Goto\n"
238*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, 3, succ: 4, 3\n"
239*795d594fSAndroid Build Coastguard Worker " 4: Phi(0, 1) [5, 5]\n"
240*795d594fSAndroid Build Coastguard Worker " 5: Equal(4, 4) [6]\n"
241*795d594fSAndroid Build Coastguard Worker " 6: If(5)\n"
242*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 2, succ: 2\n"
243*795d594fSAndroid Build Coastguard Worker " 7: Goto\n"
244*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 2, succ: 5\n"
245*795d594fSAndroid Build Coastguard Worker " 8: ReturnVoid\n"
246*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 4\n"
247*795d594fSAndroid Build Coastguard Worker " 9: Exit\n";
248*795d594fSAndroid Build Coastguard Worker
249*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
250*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
251*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 4,
252*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
253*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xFD00,
254*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
255*795d594fSAndroid Build Coastguard Worker
256*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
257*795d594fSAndroid Build Coastguard Worker }
258*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,Loop3)259*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, Loop3) {
260*795d594fSAndroid Build Coastguard Worker // Test that a local not yet defined at the entry of a loop is handled properly.
261*795d594fSAndroid Build Coastguard Worker const char* expected =
262*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
263*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [5]\n"
264*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 5 [9]\n"
265*795d594fSAndroid Build Coastguard Worker " 2: IntConstant 4 [5]\n"
266*795d594fSAndroid Build Coastguard Worker " 3: Goto\n"
267*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
268*795d594fSAndroid Build Coastguard Worker " 4: Goto\n"
269*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, 3, succ: 4, 3\n"
270*795d594fSAndroid Build Coastguard Worker " 5: Phi(0, 2) [6, 6]\n"
271*795d594fSAndroid Build Coastguard Worker " 6: Equal(5, 5) [7]\n"
272*795d594fSAndroid Build Coastguard Worker " 7: If(6)\n"
273*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 2, succ: 2\n"
274*795d594fSAndroid Build Coastguard Worker " 8: Goto\n"
275*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 2, succ: 5\n"
276*795d594fSAndroid Build Coastguard Worker " 9: Return(1)\n"
277*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 4\n"
278*795d594fSAndroid Build Coastguard Worker " 10: Exit\n";
279*795d594fSAndroid Build Coastguard Worker
280*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
281*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
282*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 4,
283*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
284*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xFD00,
285*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 5 << 12 | 1 << 8,
286*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 1 << 8);
287*795d594fSAndroid Build Coastguard Worker
288*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
289*795d594fSAndroid Build Coastguard Worker }
290*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,Loop4)291*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, Loop4) {
292*795d594fSAndroid Build Coastguard Worker // Make sure we support a preheader of a loop not being the first predecessor
293*795d594fSAndroid Build Coastguard Worker // in the predecessor list of the header.
294*795d594fSAndroid Build Coastguard Worker const char* expected =
295*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
296*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [4]\n"
297*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 4 [4]\n"
298*795d594fSAndroid Build Coastguard Worker " 2: Goto\n"
299*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 4\n"
300*795d594fSAndroid Build Coastguard Worker " 3: Goto\n"
301*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 4, 3, succ: 5, 3\n"
302*795d594fSAndroid Build Coastguard Worker " 4: Phi(0, 1) [9, 5, 5]\n"
303*795d594fSAndroid Build Coastguard Worker " 5: Equal(4, 4) [6]\n"
304*795d594fSAndroid Build Coastguard Worker " 6: If(5)\n"
305*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 2, succ: 2\n"
306*795d594fSAndroid Build Coastguard Worker " 7: Goto\n"
307*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 1, succ: 2\n"
308*795d594fSAndroid Build Coastguard Worker " 8: Goto\n"
309*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 2, succ: 6\n"
310*795d594fSAndroid Build Coastguard Worker " 9: Return(4)\n"
311*795d594fSAndroid Build Coastguard Worker "BasicBlock 6, pred: 5\n"
312*795d594fSAndroid Build Coastguard Worker " 10: Exit\n";
313*795d594fSAndroid Build Coastguard Worker
314*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
315*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
316*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x500,
317*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 5,
318*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
319*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xFD00,
320*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xFC00,
321*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0 << 8);
322*795d594fSAndroid Build Coastguard Worker
323*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
324*795d594fSAndroid Build Coastguard Worker }
325*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,Loop5)326*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, Loop5) {
327*795d594fSAndroid Build Coastguard Worker // Make sure we create a preheader of a loop when a header originally has two
328*795d594fSAndroid Build Coastguard Worker // incoming blocks and one back edge.
329*795d594fSAndroid Build Coastguard Worker const char* expected =
330*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
331*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [4, 4]\n"
332*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 5 [13]\n"
333*795d594fSAndroid Build Coastguard Worker " 2: IntConstant 4 [13]\n"
334*795d594fSAndroid Build Coastguard Worker " 3: Goto\n"
335*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 3, 2\n"
336*795d594fSAndroid Build Coastguard Worker " 4: Equal(0, 0) [5]\n"
337*795d594fSAndroid Build Coastguard Worker " 5: If(4)\n"
338*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, succ: 8\n"
339*795d594fSAndroid Build Coastguard Worker " 6: Goto\n"
340*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 1, succ: 8\n"
341*795d594fSAndroid Build Coastguard Worker " 7: Goto\n"
342*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 8, 5, succ: 6, 5\n"
343*795d594fSAndroid Build Coastguard Worker " 8: Equal(13, 13) [9]\n"
344*795d594fSAndroid Build Coastguard Worker " 9: If(8)\n"
345*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 4, succ: 4\n"
346*795d594fSAndroid Build Coastguard Worker " 10: Goto\n"
347*795d594fSAndroid Build Coastguard Worker "BasicBlock 6, pred: 4, succ: 7\n"
348*795d594fSAndroid Build Coastguard Worker " 11: Return(13)\n"
349*795d594fSAndroid Build Coastguard Worker "BasicBlock 7, pred: 6\n"
350*795d594fSAndroid Build Coastguard Worker " 12: Exit\n"
351*795d594fSAndroid Build Coastguard Worker "BasicBlock 8, pred: 2, 3, succ: 4\n"
352*795d594fSAndroid Build Coastguard Worker " 13: Phi(2, 1) [11, 8, 8]\n"
353*795d594fSAndroid Build Coastguard Worker " 14: Goto\n";
354*795d594fSAndroid Build Coastguard Worker
355*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
356*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
357*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 4,
358*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
359*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x200,
360*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 5 << 12 | 0,
361*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 3,
362*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xFE00,
363*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0 << 8);
364*795d594fSAndroid Build Coastguard Worker
365*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
366*795d594fSAndroid Build Coastguard Worker }
367*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,Loop6)368*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, Loop6) {
369*795d594fSAndroid Build Coastguard Worker // Test a loop with one preheader and two back edges (e.g. continue).
370*795d594fSAndroid Build Coastguard Worker const char* expected =
371*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
372*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [5]\n"
373*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 4 [5, 8, 8]\n"
374*795d594fSAndroid Build Coastguard Worker " 2: IntConstant 5 [5]\n"
375*795d594fSAndroid Build Coastguard Worker " 3: Goto\n"
376*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
377*795d594fSAndroid Build Coastguard Worker " 4: Goto\n"
378*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, 4, 5, succ: 6, 3\n"
379*795d594fSAndroid Build Coastguard Worker " 5: Phi(0, 2, 1) [12, 6, 6]\n"
380*795d594fSAndroid Build Coastguard Worker " 6: Equal(5, 5) [7]\n"
381*795d594fSAndroid Build Coastguard Worker " 7: If(6)\n"
382*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 2, succ: 5, 4\n"
383*795d594fSAndroid Build Coastguard Worker " 8: Equal(1, 1) [9]\n"
384*795d594fSAndroid Build Coastguard Worker " 9: If(8)\n"
385*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 3, succ: 2\n"
386*795d594fSAndroid Build Coastguard Worker " 10: Goto\n"
387*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 3, succ: 2\n"
388*795d594fSAndroid Build Coastguard Worker " 11: Goto\n"
389*795d594fSAndroid Build Coastguard Worker "BasicBlock 6, pred: 2, succ: 7\n"
390*795d594fSAndroid Build Coastguard Worker " 12: Return(5)\n"
391*795d594fSAndroid Build Coastguard Worker "BasicBlock 7, pred: 6\n"
392*795d594fSAndroid Build Coastguard Worker " 13: Exit\n";
393*795d594fSAndroid Build Coastguard Worker
394*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
395*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
396*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 8,
397*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
398*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 4,
399*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 5 << 12 | 0,
400*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xFA00,
401*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xF900,
402*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0 << 8);
403*795d594fSAndroid Build Coastguard Worker
404*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
405*795d594fSAndroid Build Coastguard Worker }
406*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,Loop7)407*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, Loop7) {
408*795d594fSAndroid Build Coastguard Worker // Test a loop with one preheader, one back edge, and two exit edges (e.g. break).
409*795d594fSAndroid Build Coastguard Worker const char* expected =
410*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
411*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [5]\n"
412*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 4 [5, 8, 8]\n"
413*795d594fSAndroid Build Coastguard Worker " 2: IntConstant 5 [12]\n"
414*795d594fSAndroid Build Coastguard Worker " 3: Goto\n"
415*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
416*795d594fSAndroid Build Coastguard Worker " 4: Goto\n"
417*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, 5, succ: 8, 3\n"
418*795d594fSAndroid Build Coastguard Worker " 5: Phi(0, 1) [12, 6, 6]\n"
419*795d594fSAndroid Build Coastguard Worker " 6: Equal(5, 5) [7]\n"
420*795d594fSAndroid Build Coastguard Worker " 7: If(6)\n"
421*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 2, succ: 5, 4\n"
422*795d594fSAndroid Build Coastguard Worker " 8: Equal(1, 1) [9]\n"
423*795d594fSAndroid Build Coastguard Worker " 9: If(8)\n"
424*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 3, succ: 6\n"
425*795d594fSAndroid Build Coastguard Worker " 10: Goto\n"
426*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 3, succ: 2\n"
427*795d594fSAndroid Build Coastguard Worker " 11: Goto\n"
428*795d594fSAndroid Build Coastguard Worker "BasicBlock 6, pred: 8, 4, succ: 7\n"
429*795d594fSAndroid Build Coastguard Worker " 12: Phi(5, 2) [13]\n"
430*795d594fSAndroid Build Coastguard Worker " 13: Return(12)\n"
431*795d594fSAndroid Build Coastguard Worker "BasicBlock 7, pred: 6\n"
432*795d594fSAndroid Build Coastguard Worker " 14: Exit\n"
433*795d594fSAndroid Build Coastguard Worker "BasicBlock 8, pred: 2, succ: 6\n"
434*795d594fSAndroid Build Coastguard Worker " 15: Goto\n";
435*795d594fSAndroid Build Coastguard Worker
436*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
437*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
438*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 8,
439*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 0,
440*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 4,
441*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 5 << 12 | 0,
442*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x0200,
443*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0xF900,
444*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 0 << 8);
445*795d594fSAndroid Build Coastguard Worker
446*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
447*795d594fSAndroid Build Coastguard Worker }
448*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,DeadLocal)449*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, DeadLocal) {
450*795d594fSAndroid Build Coastguard Worker // Test that we correctly handle a local not being used.
451*795d594fSAndroid Build Coastguard Worker const char* expected =
452*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
453*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0\n"
454*795d594fSAndroid Build Coastguard Worker " 1: Goto\n"
455*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
456*795d594fSAndroid Build Coastguard Worker " 2: ReturnVoid\n"
457*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
458*795d594fSAndroid Build Coastguard Worker " 3: Exit\n";
459*795d594fSAndroid Build Coastguard Worker
460*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = ONE_REGISTER_CODE_ITEM(
461*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
462*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
463*795d594fSAndroid Build Coastguard Worker
464*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
465*795d594fSAndroid Build Coastguard Worker }
466*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,LocalInIf)467*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, LocalInIf) {
468*795d594fSAndroid Build Coastguard Worker // Test that we do not create a phi in the join block when one predecessor
469*795d594fSAndroid Build Coastguard Worker // does not update the local.
470*795d594fSAndroid Build Coastguard Worker const char* expected =
471*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
472*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [3, 3]\n"
473*795d594fSAndroid Build Coastguard Worker " 1: IntConstant 4\n"
474*795d594fSAndroid Build Coastguard Worker " 2: Goto\n"
475*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 5, 2\n"
476*795d594fSAndroid Build Coastguard Worker " 3: Equal(0, 0) [4]\n"
477*795d594fSAndroid Build Coastguard Worker " 4: If(3)\n"
478*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, succ: 3\n"
479*795d594fSAndroid Build Coastguard Worker " 5: Goto\n"
480*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 5, 2, succ: 4\n"
481*795d594fSAndroid Build Coastguard Worker " 6: ReturnVoid\n"
482*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 3\n"
483*795d594fSAndroid Build Coastguard Worker " 7: Exit\n"
484*795d594fSAndroid Build Coastguard Worker // Synthesized block to avoid critical edge.
485*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 1, succ: 3\n"
486*795d594fSAndroid Build Coastguard Worker " 8: Goto\n";
487*795d594fSAndroid Build Coastguard Worker
488*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
489*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
490*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 3,
491*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 4 << 12 | 1 << 8,
492*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
493*795d594fSAndroid Build Coastguard Worker
494*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
495*795d594fSAndroid Build Coastguard Worker }
496*795d594fSAndroid Build Coastguard Worker
TEST_F(SsaTest,MultiplePredecessors)497*795d594fSAndroid Build Coastguard Worker TEST_F(SsaTest, MultiplePredecessors) {
498*795d594fSAndroid Build Coastguard Worker // Test that we do not create a phi when one predecessor
499*795d594fSAndroid Build Coastguard Worker // does not update the local.
500*795d594fSAndroid Build Coastguard Worker const char* expected =
501*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
502*795d594fSAndroid Build Coastguard Worker " 0: IntConstant 0 [4, 4, 8, 8, 6, 6, 2, 2]\n"
503*795d594fSAndroid Build Coastguard Worker " 1: Goto\n"
504*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 3, 2\n"
505*795d594fSAndroid Build Coastguard Worker " 2: Equal(0, 0) [3]\n"
506*795d594fSAndroid Build Coastguard Worker " 3: If(2)\n"
507*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, succ: 5\n"
508*795d594fSAndroid Build Coastguard Worker " 4: Add(0, 0)\n"
509*795d594fSAndroid Build Coastguard Worker " 5: Goto\n"
510*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 1, succ: 7, 4\n"
511*795d594fSAndroid Build Coastguard Worker " 6: Equal(0, 0) [7]\n"
512*795d594fSAndroid Build Coastguard Worker " 7: If(6)\n"
513*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 3, succ: 5\n"
514*795d594fSAndroid Build Coastguard Worker " 8: Add(0, 0)\n"
515*795d594fSAndroid Build Coastguard Worker " 9: Goto\n"
516*795d594fSAndroid Build Coastguard Worker // This block should not get a phi for local 1.
517*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 2, 7, 4, succ: 6\n"
518*795d594fSAndroid Build Coastguard Worker " 10: ReturnVoid\n"
519*795d594fSAndroid Build Coastguard Worker "BasicBlock 6, pred: 5\n"
520*795d594fSAndroid Build Coastguard Worker " 11: Exit\n"
521*795d594fSAndroid Build Coastguard Worker "BasicBlock 7, pred: 3, succ: 5\n"
522*795d594fSAndroid Build Coastguard Worker " 12: Goto\n";
523*795d594fSAndroid Build Coastguard Worker
524*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
525*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 | 0,
526*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 5,
527*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_LIT8 | 1 << 8, 0 << 8,
528*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 0x0500,
529*795d594fSAndroid Build Coastguard Worker Instruction::IF_EQ, 4,
530*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_LIT8 | 1 << 8, 0 << 8,
531*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
532*795d594fSAndroid Build Coastguard Worker
533*795d594fSAndroid Build Coastguard Worker TestCode(data, expected);
534*795d594fSAndroid Build Coastguard Worker }
535*795d594fSAndroid Build Coastguard Worker
536*795d594fSAndroid Build Coastguard Worker } // namespace art
537