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 <functional>
18*795d594fSAndroid Build Coastguard Worker
19*795d594fSAndroid Build Coastguard Worker #include "constant_folding.h"
20*795d594fSAndroid Build Coastguard Worker
21*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
22*795d594fSAndroid Build Coastguard Worker #include "dead_code_elimination.h"
23*795d594fSAndroid Build Coastguard Worker #include "driver/compiler_options.h"
24*795d594fSAndroid Build Coastguard Worker #include "graph_checker.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
28*795d594fSAndroid Build Coastguard Worker #include "gtest/gtest.h"
29*795d594fSAndroid Build Coastguard Worker
30*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
31*795d594fSAndroid Build Coastguard Worker
32*795d594fSAndroid Build Coastguard Worker /**
33*795d594fSAndroid Build Coastguard Worker * Fixture class for the constant folding and dce tests.
34*795d594fSAndroid Build Coastguard Worker */
35*795d594fSAndroid Build Coastguard Worker class ConstantFoldingTest : public CommonCompilerTest, public OptimizingUnitTestHelper {
36*795d594fSAndroid Build Coastguard Worker public:
ConstantFoldingTest()37*795d594fSAndroid Build Coastguard Worker ConstantFoldingTest() { }
38*795d594fSAndroid Build Coastguard Worker
TestCode(const std::vector<uint16_t> & data,const std::string & expected_before,const std::string & expected_after_cf,const std::string & expected_after_dce,const std::function<void (HGraph *)> & check_after_cf,DataType::Type return_type=DataType::Type::kInt32)39*795d594fSAndroid Build Coastguard Worker void TestCode(const std::vector<uint16_t>& data,
40*795d594fSAndroid Build Coastguard Worker const std::string& expected_before,
41*795d594fSAndroid Build Coastguard Worker const std::string& expected_after_cf,
42*795d594fSAndroid Build Coastguard Worker const std::string& expected_after_dce,
43*795d594fSAndroid Build Coastguard Worker const std::function<void(HGraph*)>& check_after_cf,
44*795d594fSAndroid Build Coastguard Worker DataType::Type return_type = DataType::Type::kInt32) {
45*795d594fSAndroid Build Coastguard Worker graph_ = CreateCFG(data, return_type);
46*795d594fSAndroid Build Coastguard Worker TestCodeOnReadyGraph(expected_before,
47*795d594fSAndroid Build Coastguard Worker expected_after_cf,
48*795d594fSAndroid Build Coastguard Worker expected_after_dce,
49*795d594fSAndroid Build Coastguard Worker check_after_cf);
50*795d594fSAndroid Build Coastguard Worker }
51*795d594fSAndroid Build Coastguard Worker
TestCodeOnReadyGraph(const std::string & expected_before,const std::string & expected_after_cf,const std::string & expected_after_dce,const std::function<void (HGraph *)> & check_after_cf)52*795d594fSAndroid Build Coastguard Worker void TestCodeOnReadyGraph(const std::string& expected_before,
53*795d594fSAndroid Build Coastguard Worker const std::string& expected_after_cf,
54*795d594fSAndroid Build Coastguard Worker const std::string& expected_after_dce,
55*795d594fSAndroid Build Coastguard Worker const std::function<void(HGraph*)>& check_after_cf) {
56*795d594fSAndroid Build Coastguard Worker ASSERT_NE(graph_, nullptr);
57*795d594fSAndroid Build Coastguard Worker
58*795d594fSAndroid Build Coastguard Worker StringPrettyPrinter printer_before(graph_);
59*795d594fSAndroid Build Coastguard Worker printer_before.VisitInsertionOrder();
60*795d594fSAndroid Build Coastguard Worker std::string actual_before = printer_before.str();
61*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(expected_before, actual_before);
62*795d594fSAndroid Build Coastguard Worker
63*795d594fSAndroid Build Coastguard Worker HConstantFolding(graph_, /* stats= */ nullptr, "constant_folding").Run();
64*795d594fSAndroid Build Coastguard Worker GraphChecker graph_checker_cf(graph_);
65*795d594fSAndroid Build Coastguard Worker graph_checker_cf.Run();
66*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(graph_checker_cf.IsValid());
67*795d594fSAndroid Build Coastguard Worker
68*795d594fSAndroid Build Coastguard Worker StringPrettyPrinter printer_after_cf(graph_);
69*795d594fSAndroid Build Coastguard Worker printer_after_cf.VisitInsertionOrder();
70*795d594fSAndroid Build Coastguard Worker std::string actual_after_cf = printer_after_cf.str();
71*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(expected_after_cf, actual_after_cf);
72*795d594fSAndroid Build Coastguard Worker
73*795d594fSAndroid Build Coastguard Worker check_after_cf(graph_);
74*795d594fSAndroid Build Coastguard Worker
75*795d594fSAndroid Build Coastguard Worker HDeadCodeElimination(graph_, /* stats= */ nullptr, "dead_code_elimination").Run();
76*795d594fSAndroid Build Coastguard Worker GraphChecker graph_checker_dce(graph_);
77*795d594fSAndroid Build Coastguard Worker graph_checker_dce.Run();
78*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(graph_checker_dce.IsValid());
79*795d594fSAndroid Build Coastguard Worker
80*795d594fSAndroid Build Coastguard Worker StringPrettyPrinter printer_after_dce(graph_);
81*795d594fSAndroid Build Coastguard Worker printer_after_dce.VisitInsertionOrder();
82*795d594fSAndroid Build Coastguard Worker std::string actual_after_dce = printer_after_dce.str();
83*795d594fSAndroid Build Coastguard Worker EXPECT_EQ(expected_after_dce, actual_after_dce);
84*795d594fSAndroid Build Coastguard Worker }
85*795d594fSAndroid Build Coastguard Worker };
86*795d594fSAndroid Build Coastguard Worker
87*795d594fSAndroid Build Coastguard Worker /**
88*795d594fSAndroid Build Coastguard Worker * Tiny three-register program exercising int constant folding on negation.
89*795d594fSAndroid Build Coastguard Worker *
90*795d594fSAndroid Build Coastguard Worker * 16-bit
91*795d594fSAndroid Build Coastguard Worker * offset
92*795d594fSAndroid Build Coastguard Worker * ------
93*795d594fSAndroid Build Coastguard Worker * v0 <- 1 0. const/4 v0, #+1
94*795d594fSAndroid Build Coastguard Worker * v1 <- -v0 1. neg-int v1, v0
95*795d594fSAndroid Build Coastguard Worker * return v1 2. return v1
96*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,IntConstantFoldingNegation)97*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, IntConstantFoldingNegation) {
98*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = TWO_REGISTERS_CODE_ITEM(
99*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 << 8 | 1 << 12,
100*795d594fSAndroid Build Coastguard Worker Instruction::NEG_INT | 1 << 8 | 0 << 12,
101*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 1 << 8);
102*795d594fSAndroid Build Coastguard Worker
103*795d594fSAndroid Build Coastguard Worker std::string expected_before =
104*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
105*795d594fSAndroid Build Coastguard Worker " 2: IntConstant [3]\n"
106*795d594fSAndroid Build Coastguard Worker " 0: SuspendCheck\n"
107*795d594fSAndroid Build Coastguard Worker " 1: Goto 1\n"
108*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
109*795d594fSAndroid Build Coastguard Worker " 3: Neg(2) [4]\n"
110*795d594fSAndroid Build Coastguard Worker " 4: Return(3)\n"
111*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
112*795d594fSAndroid Build Coastguard Worker " 5: Exit\n";
113*795d594fSAndroid Build Coastguard Worker
114*795d594fSAndroid Build Coastguard Worker // Expected difference after constant folding.
115*795d594fSAndroid Build Coastguard Worker diff_t expected_cf_diff = {
116*795d594fSAndroid Build Coastguard Worker { " 2: IntConstant [3]\n", " 2: IntConstant\n"
117*795d594fSAndroid Build Coastguard Worker " 6: IntConstant [4]\n" },
118*795d594fSAndroid Build Coastguard Worker { " 3: Neg(2) [4]\n", removed },
119*795d594fSAndroid Build Coastguard Worker { " 4: Return(3)\n", " 4: Return(6)\n" }
120*795d594fSAndroid Build Coastguard Worker };
121*795d594fSAndroid Build Coastguard Worker std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
122*795d594fSAndroid Build Coastguard Worker
123*795d594fSAndroid Build Coastguard Worker // Check the value of the computed constant.
124*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
125*795d594fSAndroid Build Coastguard Worker HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
126*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst->IsIntConstant());
127*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst->AsIntConstant()->GetValue(), -1);
128*795d594fSAndroid Build Coastguard Worker };
129*795d594fSAndroid Build Coastguard Worker
130*795d594fSAndroid Build Coastguard Worker // Expected difference after dead code elimination.
131*795d594fSAndroid Build Coastguard Worker diff_t expected_dce_diff = {
132*795d594fSAndroid Build Coastguard Worker { " 2: IntConstant\n", removed },
133*795d594fSAndroid Build Coastguard Worker };
134*795d594fSAndroid Build Coastguard Worker std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
135*795d594fSAndroid Build Coastguard Worker
136*795d594fSAndroid Build Coastguard Worker TestCode(data,
137*795d594fSAndroid Build Coastguard Worker expected_before,
138*795d594fSAndroid Build Coastguard Worker expected_after_cf,
139*795d594fSAndroid Build Coastguard Worker expected_after_dce,
140*795d594fSAndroid Build Coastguard Worker check_after_cf);
141*795d594fSAndroid Build Coastguard Worker }
142*795d594fSAndroid Build Coastguard Worker
143*795d594fSAndroid Build Coastguard Worker /**
144*795d594fSAndroid Build Coastguard Worker * Tiny three-register program exercising long constant folding on negation.
145*795d594fSAndroid Build Coastguard Worker *
146*795d594fSAndroid Build Coastguard Worker * 16-bit
147*795d594fSAndroid Build Coastguard Worker * offset
148*795d594fSAndroid Build Coastguard Worker * ------
149*795d594fSAndroid Build Coastguard Worker * (v0, v1) <- 4294967296 0. const-wide v0 #+4294967296
150*795d594fSAndroid Build Coastguard Worker * (v2, v3) <- -(v0, v1) 1. neg-long v2, v0
151*795d594fSAndroid Build Coastguard Worker * return (v2, v3) 2. return-wide v2
152*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,LongConstantFoldingNegation)153*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, LongConstantFoldingNegation) {
154*795d594fSAndroid Build Coastguard Worker const int64_t input = INT64_C(4294967296); // 2^32
155*795d594fSAndroid Build Coastguard Worker const uint16_t word0 = Low16Bits(Low32Bits(input)); // LSW.
156*795d594fSAndroid Build Coastguard Worker const uint16_t word1 = High16Bits(Low32Bits(input));
157*795d594fSAndroid Build Coastguard Worker const uint16_t word2 = Low16Bits(High32Bits(input));
158*795d594fSAndroid Build Coastguard Worker const uint16_t word3 = High16Bits(High32Bits(input)); // MSW.
159*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = FOUR_REGISTERS_CODE_ITEM(
160*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,
161*795d594fSAndroid Build Coastguard Worker Instruction::NEG_LONG | 2 << 8 | 0 << 12,
162*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_WIDE | 2 << 8);
163*795d594fSAndroid Build Coastguard Worker
164*795d594fSAndroid Build Coastguard Worker std::string expected_before =
165*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
166*795d594fSAndroid Build Coastguard Worker " 2: LongConstant [3]\n"
167*795d594fSAndroid Build Coastguard Worker " 0: SuspendCheck\n"
168*795d594fSAndroid Build Coastguard Worker " 1: Goto 1\n"
169*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
170*795d594fSAndroid Build Coastguard Worker " 3: Neg(2) [4]\n"
171*795d594fSAndroid Build Coastguard Worker " 4: Return(3)\n"
172*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
173*795d594fSAndroid Build Coastguard Worker " 5: Exit\n";
174*795d594fSAndroid Build Coastguard Worker
175*795d594fSAndroid Build Coastguard Worker // Expected difference after constant folding.
176*795d594fSAndroid Build Coastguard Worker diff_t expected_cf_diff = {
177*795d594fSAndroid Build Coastguard Worker { " 2: LongConstant [3]\n", " 2: LongConstant\n"
178*795d594fSAndroid Build Coastguard Worker " 6: LongConstant [4]\n" },
179*795d594fSAndroid Build Coastguard Worker { " 3: Neg(2) [4]\n", removed },
180*795d594fSAndroid Build Coastguard Worker { " 4: Return(3)\n", " 4: Return(6)\n" }
181*795d594fSAndroid Build Coastguard Worker };
182*795d594fSAndroid Build Coastguard Worker std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
183*795d594fSAndroid Build Coastguard Worker
184*795d594fSAndroid Build Coastguard Worker // Check the value of the computed constant.
185*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
186*795d594fSAndroid Build Coastguard Worker HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
187*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst->IsLongConstant());
188*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst->AsLongConstant()->GetValue(), INT64_C(-4294967296));
189*795d594fSAndroid Build Coastguard Worker };
190*795d594fSAndroid Build Coastguard Worker
191*795d594fSAndroid Build Coastguard Worker // Expected difference after dead code elimination.
192*795d594fSAndroid Build Coastguard Worker diff_t expected_dce_diff = {
193*795d594fSAndroid Build Coastguard Worker { " 2: LongConstant\n", removed },
194*795d594fSAndroid Build Coastguard Worker };
195*795d594fSAndroid Build Coastguard Worker std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
196*795d594fSAndroid Build Coastguard Worker
197*795d594fSAndroid Build Coastguard Worker TestCode(data,
198*795d594fSAndroid Build Coastguard Worker expected_before,
199*795d594fSAndroid Build Coastguard Worker expected_after_cf,
200*795d594fSAndroid Build Coastguard Worker expected_after_dce,
201*795d594fSAndroid Build Coastguard Worker check_after_cf,
202*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt64);
203*795d594fSAndroid Build Coastguard Worker }
204*795d594fSAndroid Build Coastguard Worker
205*795d594fSAndroid Build Coastguard Worker /**
206*795d594fSAndroid Build Coastguard Worker * Tiny three-register program exercising int constant folding on addition.
207*795d594fSAndroid Build Coastguard Worker *
208*795d594fSAndroid Build Coastguard Worker * 16-bit
209*795d594fSAndroid Build Coastguard Worker * offset
210*795d594fSAndroid Build Coastguard Worker * ------
211*795d594fSAndroid Build Coastguard Worker * v0 <- 1 0. const/4 v0, #+1
212*795d594fSAndroid Build Coastguard Worker * v1 <- 2 1. const/4 v1, #+2
213*795d594fSAndroid Build Coastguard Worker * v2 <- v0 + v1 2. add-int v2, v0, v1
214*795d594fSAndroid Build Coastguard Worker * return v2 4. return v2
215*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,IntConstantFoldingOnAddition1)216*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, IntConstantFoldingOnAddition1) {
217*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = THREE_REGISTERS_CODE_ITEM(
218*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 << 8 | 1 << 12,
219*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 1 << 8 | 2 << 12,
220*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
221*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 2 << 8);
222*795d594fSAndroid Build Coastguard Worker
223*795d594fSAndroid Build Coastguard Worker std::string expected_before =
224*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
225*795d594fSAndroid Build Coastguard Worker " 2: IntConstant [4]\n"
226*795d594fSAndroid Build Coastguard Worker " 3: IntConstant [4]\n"
227*795d594fSAndroid Build Coastguard Worker " 0: SuspendCheck\n"
228*795d594fSAndroid Build Coastguard Worker " 1: Goto 1\n"
229*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
230*795d594fSAndroid Build Coastguard Worker " 4: Add(2, 3) [5]\n"
231*795d594fSAndroid Build Coastguard Worker " 5: Return(4)\n"
232*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
233*795d594fSAndroid Build Coastguard Worker " 6: Exit\n";
234*795d594fSAndroid Build Coastguard Worker
235*795d594fSAndroid Build Coastguard Worker // Expected difference after constant folding.
236*795d594fSAndroid Build Coastguard Worker diff_t expected_cf_diff = {
237*795d594fSAndroid Build Coastguard Worker { " 2: IntConstant [4]\n", " 2: IntConstant\n" },
238*795d594fSAndroid Build Coastguard Worker { " 3: IntConstant [4]\n", " 3: IntConstant\n"
239*795d594fSAndroid Build Coastguard Worker " 7: IntConstant [5]\n" },
240*795d594fSAndroid Build Coastguard Worker { " 4: Add(2, 3) [5]\n", removed },
241*795d594fSAndroid Build Coastguard Worker { " 5: Return(4)\n", " 5: Return(7)\n" }
242*795d594fSAndroid Build Coastguard Worker };
243*795d594fSAndroid Build Coastguard Worker std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
244*795d594fSAndroid Build Coastguard Worker
245*795d594fSAndroid Build Coastguard Worker // Check the value of the computed constant.
246*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
247*795d594fSAndroid Build Coastguard Worker HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
248*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst->IsIntConstant());
249*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst->AsIntConstant()->GetValue(), 3);
250*795d594fSAndroid Build Coastguard Worker };
251*795d594fSAndroid Build Coastguard Worker
252*795d594fSAndroid Build Coastguard Worker // Expected difference after dead code elimination.
253*795d594fSAndroid Build Coastguard Worker diff_t expected_dce_diff = {
254*795d594fSAndroid Build Coastguard Worker { " 2: IntConstant\n", removed },
255*795d594fSAndroid Build Coastguard Worker { " 3: IntConstant\n", removed }
256*795d594fSAndroid Build Coastguard Worker };
257*795d594fSAndroid Build Coastguard Worker std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
258*795d594fSAndroid Build Coastguard Worker
259*795d594fSAndroid Build Coastguard Worker TestCode(data,
260*795d594fSAndroid Build Coastguard Worker expected_before,
261*795d594fSAndroid Build Coastguard Worker expected_after_cf,
262*795d594fSAndroid Build Coastguard Worker expected_after_dce,
263*795d594fSAndroid Build Coastguard Worker check_after_cf);
264*795d594fSAndroid Build Coastguard Worker }
265*795d594fSAndroid Build Coastguard Worker
266*795d594fSAndroid Build Coastguard Worker /**
267*795d594fSAndroid Build Coastguard Worker * Small three-register program exercising int constant folding on addition.
268*795d594fSAndroid Build Coastguard Worker *
269*795d594fSAndroid Build Coastguard Worker * 16-bit
270*795d594fSAndroid Build Coastguard Worker * offset
271*795d594fSAndroid Build Coastguard Worker * ------
272*795d594fSAndroid Build Coastguard Worker * v0 <- 1 0. const/4 v0, #+1
273*795d594fSAndroid Build Coastguard Worker * v1 <- 2 1. const/4 v1, #+2
274*795d594fSAndroid Build Coastguard Worker * v0 <- v0 + v1 2. add-int/2addr v0, v1
275*795d594fSAndroid Build Coastguard Worker * v1 <- 4 3. const/4 v1, #+4
276*795d594fSAndroid Build Coastguard Worker * v2 <- 5 4. const/4 v2, #+5
277*795d594fSAndroid Build Coastguard Worker * v1 <- v1 + v2 5. add-int/2addr v1, v2
278*795d594fSAndroid Build Coastguard Worker * v2 <- v0 + v1 6. add-int v2, v0, v1
279*795d594fSAndroid Build Coastguard Worker * return v2 8. return v2
280*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,IntConstantFoldingOnAddition2)281*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, IntConstantFoldingOnAddition2) {
282*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = THREE_REGISTERS_CODE_ITEM(
283*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 << 8 | 1 << 12,
284*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 1 << 8 | 2 << 12,
285*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_2ADDR | 0 << 8 | 1 << 12,
286*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 1 << 8 | 4 << 12,
287*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 2 << 8 | 5 << 12,
288*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_2ADDR | 1 << 8 | 2 << 12,
289*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
290*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 2 << 8);
291*795d594fSAndroid Build Coastguard Worker
292*795d594fSAndroid Build Coastguard Worker std::string expected_before =
293*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
294*795d594fSAndroid Build Coastguard Worker " 2: IntConstant [4]\n"
295*795d594fSAndroid Build Coastguard Worker " 3: IntConstant [4]\n"
296*795d594fSAndroid Build Coastguard Worker " 5: IntConstant [7]\n"
297*795d594fSAndroid Build Coastguard Worker " 6: IntConstant [7]\n"
298*795d594fSAndroid Build Coastguard Worker " 0: SuspendCheck\n"
299*795d594fSAndroid Build Coastguard Worker " 1: Goto 1\n"
300*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
301*795d594fSAndroid Build Coastguard Worker " 4: Add(2, 3) [8]\n"
302*795d594fSAndroid Build Coastguard Worker " 7: Add(5, 6) [8]\n"
303*795d594fSAndroid Build Coastguard Worker " 8: Add(4, 7) [9]\n"
304*795d594fSAndroid Build Coastguard Worker " 9: Return(8)\n"
305*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
306*795d594fSAndroid Build Coastguard Worker " 10: Exit\n";
307*795d594fSAndroid Build Coastguard Worker
308*795d594fSAndroid Build Coastguard Worker // Expected difference after constant folding.
309*795d594fSAndroid Build Coastguard Worker diff_t expected_cf_diff = {
310*795d594fSAndroid Build Coastguard Worker { " 2: IntConstant [4]\n", " 2: IntConstant\n" },
311*795d594fSAndroid Build Coastguard Worker { " 3: IntConstant [4]\n", " 3: IntConstant\n" },
312*795d594fSAndroid Build Coastguard Worker { " 5: IntConstant [7]\n", " 5: IntConstant\n" },
313*795d594fSAndroid Build Coastguard Worker { " 6: IntConstant [7]\n", " 6: IntConstant\n"
314*795d594fSAndroid Build Coastguard Worker " 11: IntConstant\n"
315*795d594fSAndroid Build Coastguard Worker " 12: IntConstant\n"
316*795d594fSAndroid Build Coastguard Worker " 13: IntConstant [9]\n" },
317*795d594fSAndroid Build Coastguard Worker { " 4: Add(2, 3) [8]\n", removed },
318*795d594fSAndroid Build Coastguard Worker { " 7: Add(5, 6) [8]\n", removed },
319*795d594fSAndroid Build Coastguard Worker { " 8: Add(4, 7) [9]\n", removed },
320*795d594fSAndroid Build Coastguard Worker { " 9: Return(8)\n", " 9: Return(13)\n" }
321*795d594fSAndroid Build Coastguard Worker };
322*795d594fSAndroid Build Coastguard Worker std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
323*795d594fSAndroid Build Coastguard Worker
324*795d594fSAndroid Build Coastguard Worker // Check the values of the computed constants.
325*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
326*795d594fSAndroid Build Coastguard Worker HInstruction* inst1 = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
327*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst1->IsIntConstant());
328*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 12);
329*795d594fSAndroid Build Coastguard Worker HInstruction* inst2 = inst1->GetPrevious();
330*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst2->IsIntConstant());
331*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 9);
332*795d594fSAndroid Build Coastguard Worker HInstruction* inst3 = inst2->GetPrevious();
333*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst3->IsIntConstant());
334*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 3);
335*795d594fSAndroid Build Coastguard Worker };
336*795d594fSAndroid Build Coastguard Worker
337*795d594fSAndroid Build Coastguard Worker // Expected difference after dead code elimination.
338*795d594fSAndroid Build Coastguard Worker diff_t expected_dce_diff = {
339*795d594fSAndroid Build Coastguard Worker { " 2: IntConstant\n", removed },
340*795d594fSAndroid Build Coastguard Worker { " 3: IntConstant\n", removed },
341*795d594fSAndroid Build Coastguard Worker { " 5: IntConstant\n", removed },
342*795d594fSAndroid Build Coastguard Worker { " 6: IntConstant\n", removed },
343*795d594fSAndroid Build Coastguard Worker { " 11: IntConstant\n", removed },
344*795d594fSAndroid Build Coastguard Worker { " 12: IntConstant\n", removed }
345*795d594fSAndroid Build Coastguard Worker };
346*795d594fSAndroid Build Coastguard Worker std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
347*795d594fSAndroid Build Coastguard Worker
348*795d594fSAndroid Build Coastguard Worker TestCode(data,
349*795d594fSAndroid Build Coastguard Worker expected_before,
350*795d594fSAndroid Build Coastguard Worker expected_after_cf,
351*795d594fSAndroid Build Coastguard Worker expected_after_dce,
352*795d594fSAndroid Build Coastguard Worker check_after_cf);
353*795d594fSAndroid Build Coastguard Worker }
354*795d594fSAndroid Build Coastguard Worker
355*795d594fSAndroid Build Coastguard Worker /**
356*795d594fSAndroid Build Coastguard Worker * Tiny three-register program exercising int constant folding on subtraction.
357*795d594fSAndroid Build Coastguard Worker *
358*795d594fSAndroid Build Coastguard Worker * 16-bit
359*795d594fSAndroid Build Coastguard Worker * offset
360*795d594fSAndroid Build Coastguard Worker * ------
361*795d594fSAndroid Build Coastguard Worker * v0 <- 3 0. const/4 v0, #+3
362*795d594fSAndroid Build Coastguard Worker * v1 <- 2 1. const/4 v1, #+2
363*795d594fSAndroid Build Coastguard Worker * v2 <- v0 - v1 2. sub-int v2, v0, v1
364*795d594fSAndroid Build Coastguard Worker * return v2 4. return v2
365*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,IntConstantFoldingOnSubtraction)366*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, IntConstantFoldingOnSubtraction) {
367*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = THREE_REGISTERS_CODE_ITEM(
368*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 << 8 | 3 << 12,
369*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 1 << 8 | 2 << 12,
370*795d594fSAndroid Build Coastguard Worker Instruction::SUB_INT | 2 << 8, 0 | 1 << 8,
371*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 2 << 8);
372*795d594fSAndroid Build Coastguard Worker
373*795d594fSAndroid Build Coastguard Worker std::string expected_before =
374*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
375*795d594fSAndroid Build Coastguard Worker " 2: IntConstant [4]\n"
376*795d594fSAndroid Build Coastguard Worker " 3: IntConstant [4]\n"
377*795d594fSAndroid Build Coastguard Worker " 0: SuspendCheck\n"
378*795d594fSAndroid Build Coastguard Worker " 1: Goto 1\n"
379*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
380*795d594fSAndroid Build Coastguard Worker " 4: Sub(2, 3) [5]\n"
381*795d594fSAndroid Build Coastguard Worker " 5: Return(4)\n"
382*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
383*795d594fSAndroid Build Coastguard Worker " 6: Exit\n";
384*795d594fSAndroid Build Coastguard Worker
385*795d594fSAndroid Build Coastguard Worker // Expected difference after constant folding.
386*795d594fSAndroid Build Coastguard Worker diff_t expected_cf_diff = {
387*795d594fSAndroid Build Coastguard Worker { " 2: IntConstant [4]\n", " 2: IntConstant\n" },
388*795d594fSAndroid Build Coastguard Worker { " 3: IntConstant [4]\n", " 3: IntConstant\n"
389*795d594fSAndroid Build Coastguard Worker " 7: IntConstant [5]\n" },
390*795d594fSAndroid Build Coastguard Worker { " 4: Sub(2, 3) [5]\n", removed },
391*795d594fSAndroid Build Coastguard Worker { " 5: Return(4)\n", " 5: Return(7)\n" }
392*795d594fSAndroid Build Coastguard Worker };
393*795d594fSAndroid Build Coastguard Worker std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
394*795d594fSAndroid Build Coastguard Worker
395*795d594fSAndroid Build Coastguard Worker // Check the value of the computed constant.
396*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
397*795d594fSAndroid Build Coastguard Worker HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
398*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst->IsIntConstant());
399*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
400*795d594fSAndroid Build Coastguard Worker };
401*795d594fSAndroid Build Coastguard Worker
402*795d594fSAndroid Build Coastguard Worker // Expected difference after dead code elimination.
403*795d594fSAndroid Build Coastguard Worker diff_t expected_dce_diff = {
404*795d594fSAndroid Build Coastguard Worker { " 2: IntConstant\n", removed },
405*795d594fSAndroid Build Coastguard Worker { " 3: IntConstant\n", removed }
406*795d594fSAndroid Build Coastguard Worker };
407*795d594fSAndroid Build Coastguard Worker std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
408*795d594fSAndroid Build Coastguard Worker
409*795d594fSAndroid Build Coastguard Worker TestCode(data,
410*795d594fSAndroid Build Coastguard Worker expected_before,
411*795d594fSAndroid Build Coastguard Worker expected_after_cf,
412*795d594fSAndroid Build Coastguard Worker expected_after_dce,
413*795d594fSAndroid Build Coastguard Worker check_after_cf);
414*795d594fSAndroid Build Coastguard Worker }
415*795d594fSAndroid Build Coastguard Worker
416*795d594fSAndroid Build Coastguard Worker /**
417*795d594fSAndroid Build Coastguard Worker * Tiny three-register-pair program exercising long constant folding
418*795d594fSAndroid Build Coastguard Worker * on addition.
419*795d594fSAndroid Build Coastguard Worker *
420*795d594fSAndroid Build Coastguard Worker * 16-bit
421*795d594fSAndroid Build Coastguard Worker * offset
422*795d594fSAndroid Build Coastguard Worker * ------
423*795d594fSAndroid Build Coastguard Worker * (v0, v1) <- 1 0. const-wide/16 v0, #+1
424*795d594fSAndroid Build Coastguard Worker * (v2, v3) <- 2 2. const-wide/16 v2, #+2
425*795d594fSAndroid Build Coastguard Worker * (v4, v5) <-
426*795d594fSAndroid Build Coastguard Worker * (v0, v1) + (v1, v2) 4. add-long v4, v0, v2
427*795d594fSAndroid Build Coastguard Worker * return (v4, v5) 6. return-wide v4
428*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,LongConstantFoldingOnAddition)429*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, LongConstantFoldingOnAddition) {
430*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = SIX_REGISTERS_CODE_ITEM(
431*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE_16 | 0 << 8, 1,
432*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE_16 | 2 << 8, 2,
433*795d594fSAndroid Build Coastguard Worker Instruction::ADD_LONG | 4 << 8, 0 | 2 << 8,
434*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_WIDE | 4 << 8);
435*795d594fSAndroid Build Coastguard Worker
436*795d594fSAndroid Build Coastguard Worker std::string expected_before =
437*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
438*795d594fSAndroid Build Coastguard Worker " 2: LongConstant [4]\n"
439*795d594fSAndroid Build Coastguard Worker " 3: LongConstant [4]\n"
440*795d594fSAndroid Build Coastguard Worker " 0: SuspendCheck\n"
441*795d594fSAndroid Build Coastguard Worker " 1: Goto 1\n"
442*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
443*795d594fSAndroid Build Coastguard Worker " 4: Add(2, 3) [5]\n"
444*795d594fSAndroid Build Coastguard Worker " 5: Return(4)\n"
445*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
446*795d594fSAndroid Build Coastguard Worker " 6: Exit\n";
447*795d594fSAndroid Build Coastguard Worker
448*795d594fSAndroid Build Coastguard Worker // Expected difference after constant folding.
449*795d594fSAndroid Build Coastguard Worker diff_t expected_cf_diff = {
450*795d594fSAndroid Build Coastguard Worker { " 2: LongConstant [4]\n", " 2: LongConstant\n" },
451*795d594fSAndroid Build Coastguard Worker { " 3: LongConstant [4]\n", " 3: LongConstant\n"
452*795d594fSAndroid Build Coastguard Worker " 7: LongConstant [5]\n" },
453*795d594fSAndroid Build Coastguard Worker { " 4: Add(2, 3) [5]\n", removed },
454*795d594fSAndroid Build Coastguard Worker { " 5: Return(4)\n", " 5: Return(7)\n" }
455*795d594fSAndroid Build Coastguard Worker };
456*795d594fSAndroid Build Coastguard Worker std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
457*795d594fSAndroid Build Coastguard Worker
458*795d594fSAndroid Build Coastguard Worker // Check the value of the computed constant.
459*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
460*795d594fSAndroid Build Coastguard Worker HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
461*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst->IsLongConstant());
462*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst->AsLongConstant()->GetValue(), 3);
463*795d594fSAndroid Build Coastguard Worker };
464*795d594fSAndroid Build Coastguard Worker
465*795d594fSAndroid Build Coastguard Worker // Expected difference after dead code elimination.
466*795d594fSAndroid Build Coastguard Worker diff_t expected_dce_diff = {
467*795d594fSAndroid Build Coastguard Worker { " 2: LongConstant\n", removed },
468*795d594fSAndroid Build Coastguard Worker { " 3: LongConstant\n", removed }
469*795d594fSAndroid Build Coastguard Worker };
470*795d594fSAndroid Build Coastguard Worker std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
471*795d594fSAndroid Build Coastguard Worker
472*795d594fSAndroid Build Coastguard Worker TestCode(data,
473*795d594fSAndroid Build Coastguard Worker expected_before,
474*795d594fSAndroid Build Coastguard Worker expected_after_cf,
475*795d594fSAndroid Build Coastguard Worker expected_after_dce,
476*795d594fSAndroid Build Coastguard Worker check_after_cf,
477*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt64);
478*795d594fSAndroid Build Coastguard Worker }
479*795d594fSAndroid Build Coastguard Worker
480*795d594fSAndroid Build Coastguard Worker /**
481*795d594fSAndroid Build Coastguard Worker * Tiny three-register-pair program exercising long constant folding
482*795d594fSAndroid Build Coastguard Worker * on subtraction.
483*795d594fSAndroid Build Coastguard Worker *
484*795d594fSAndroid Build Coastguard Worker * 16-bit
485*795d594fSAndroid Build Coastguard Worker * offset
486*795d594fSAndroid Build Coastguard Worker * ------
487*795d594fSAndroid Build Coastguard Worker * (v0, v1) <- 3 0. const-wide/16 v0, #+3
488*795d594fSAndroid Build Coastguard Worker * (v2, v3) <- 2 2. const-wide/16 v2, #+2
489*795d594fSAndroid Build Coastguard Worker * (v4, v5) <-
490*795d594fSAndroid Build Coastguard Worker * (v0, v1) - (v1, v2) 4. sub-long v4, v0, v2
491*795d594fSAndroid Build Coastguard Worker * return (v4, v5) 6. return-wide v4
492*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,LongConstantFoldingOnSubtraction)493*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, LongConstantFoldingOnSubtraction) {
494*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = SIX_REGISTERS_CODE_ITEM(
495*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE_16 | 0 << 8, 3,
496*795d594fSAndroid Build Coastguard Worker Instruction::CONST_WIDE_16 | 2 << 8, 2,
497*795d594fSAndroid Build Coastguard Worker Instruction::SUB_LONG | 4 << 8, 0 | 2 << 8,
498*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_WIDE | 4 << 8);
499*795d594fSAndroid Build Coastguard Worker
500*795d594fSAndroid Build Coastguard Worker std::string expected_before =
501*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
502*795d594fSAndroid Build Coastguard Worker " 2: LongConstant [4]\n"
503*795d594fSAndroid Build Coastguard Worker " 3: LongConstant [4]\n"
504*795d594fSAndroid Build Coastguard Worker " 0: SuspendCheck\n"
505*795d594fSAndroid Build Coastguard Worker " 1: Goto 1\n"
506*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
507*795d594fSAndroid Build Coastguard Worker " 4: Sub(2, 3) [5]\n"
508*795d594fSAndroid Build Coastguard Worker " 5: Return(4)\n"
509*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
510*795d594fSAndroid Build Coastguard Worker " 6: Exit\n";
511*795d594fSAndroid Build Coastguard Worker
512*795d594fSAndroid Build Coastguard Worker // Expected difference after constant folding.
513*795d594fSAndroid Build Coastguard Worker diff_t expected_cf_diff = {
514*795d594fSAndroid Build Coastguard Worker { " 2: LongConstant [4]\n", " 2: LongConstant\n" },
515*795d594fSAndroid Build Coastguard Worker { " 3: LongConstant [4]\n", " 3: LongConstant\n"
516*795d594fSAndroid Build Coastguard Worker " 7: LongConstant [5]\n" },
517*795d594fSAndroid Build Coastguard Worker { " 4: Sub(2, 3) [5]\n", removed },
518*795d594fSAndroid Build Coastguard Worker { " 5: Return(4)\n", " 5: Return(7)\n" }
519*795d594fSAndroid Build Coastguard Worker };
520*795d594fSAndroid Build Coastguard Worker std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
521*795d594fSAndroid Build Coastguard Worker
522*795d594fSAndroid Build Coastguard Worker // Check the value of the computed constant.
523*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
524*795d594fSAndroid Build Coastguard Worker HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
525*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst->IsLongConstant());
526*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst->AsLongConstant()->GetValue(), 1);
527*795d594fSAndroid Build Coastguard Worker };
528*795d594fSAndroid Build Coastguard Worker
529*795d594fSAndroid Build Coastguard Worker // Expected difference after dead code elimination.
530*795d594fSAndroid Build Coastguard Worker diff_t expected_dce_diff = {
531*795d594fSAndroid Build Coastguard Worker { " 2: LongConstant\n", removed },
532*795d594fSAndroid Build Coastguard Worker { " 3: LongConstant\n", removed }
533*795d594fSAndroid Build Coastguard Worker };
534*795d594fSAndroid Build Coastguard Worker std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
535*795d594fSAndroid Build Coastguard Worker
536*795d594fSAndroid Build Coastguard Worker TestCode(data,
537*795d594fSAndroid Build Coastguard Worker expected_before,
538*795d594fSAndroid Build Coastguard Worker expected_after_cf,
539*795d594fSAndroid Build Coastguard Worker expected_after_dce,
540*795d594fSAndroid Build Coastguard Worker check_after_cf,
541*795d594fSAndroid Build Coastguard Worker DataType::Type::kInt64);
542*795d594fSAndroid Build Coastguard Worker }
543*795d594fSAndroid Build Coastguard Worker
544*795d594fSAndroid Build Coastguard Worker /**
545*795d594fSAndroid Build Coastguard Worker * Three-register program with jumps leading to the creation of many
546*795d594fSAndroid Build Coastguard Worker * blocks.
547*795d594fSAndroid Build Coastguard Worker *
548*795d594fSAndroid Build Coastguard Worker * The intent of this test is to ensure that all constant expressions
549*795d594fSAndroid Build Coastguard Worker * are actually evaluated at compile-time, thanks to the reverse
550*795d594fSAndroid Build Coastguard Worker * (forward) post-order traversal of the dominator tree.
551*795d594fSAndroid Build Coastguard Worker *
552*795d594fSAndroid Build Coastguard Worker * 16-bit
553*795d594fSAndroid Build Coastguard Worker * offset
554*795d594fSAndroid Build Coastguard Worker * ------
555*795d594fSAndroid Build Coastguard Worker * v0 <- 1 0. const/4 v0, #+1
556*795d594fSAndroid Build Coastguard Worker * v1 <- 2 1. const/4 v1, #+2
557*795d594fSAndroid Build Coastguard Worker * v2 <- v0 + v1 2. add-int v2, v0, v1
558*795d594fSAndroid Build Coastguard Worker * goto L2 4. goto +4
559*795d594fSAndroid Build Coastguard Worker * L1: v1 <- v0 + 5 5. add-int/lit16 v1, v0, #+5
560*795d594fSAndroid Build Coastguard Worker * goto L3 7. goto +4
561*795d594fSAndroid Build Coastguard Worker * L2: v0 <- v2 + 4 8. add-int/lit16 v0, v2, #+4
562*795d594fSAndroid Build Coastguard Worker * goto L1 10. goto +(-5)
563*795d594fSAndroid Build Coastguard Worker * L3: v2 <- v1 + 8 11. add-int/lit16 v2, v1, #+8
564*795d594fSAndroid Build Coastguard Worker * return v2 13. return v2
565*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,IntConstantFoldingAndJumps)566*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, IntConstantFoldingAndJumps) {
567*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = THREE_REGISTERS_CODE_ITEM(
568*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 << 8 | 1 << 12,
569*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 1 << 8 | 2 << 12,
570*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
571*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 4 << 8,
572*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_LIT16 | 1 << 8 | 0 << 12, 5,
573*795d594fSAndroid Build Coastguard Worker Instruction::GOTO | 4 << 8,
574*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_LIT16 | 0 << 8 | 2 << 12, 4,
575*795d594fSAndroid Build Coastguard Worker static_cast<uint16_t>(Instruction::GOTO | 0xFFFFFFFB << 8),
576*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT_LIT16 | 2 << 8 | 1 << 12, 8,
577*795d594fSAndroid Build Coastguard Worker Instruction::RETURN | 2 << 8);
578*795d594fSAndroid Build Coastguard Worker
579*795d594fSAndroid Build Coastguard Worker std::string expected_before =
580*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
581*795d594fSAndroid Build Coastguard Worker " 2: IntConstant [4]\n" // v0 <- 1
582*795d594fSAndroid Build Coastguard Worker " 3: IntConstant [4]\n" // v1 <- 2
583*795d594fSAndroid Build Coastguard Worker " 6: IntConstant [7]\n" // const 5
584*795d594fSAndroid Build Coastguard Worker " 9: IntConstant [10]\n" // const 4
585*795d594fSAndroid Build Coastguard Worker " 12: IntConstant [13]\n" // const 8
586*795d594fSAndroid Build Coastguard Worker " 0: SuspendCheck\n"
587*795d594fSAndroid Build Coastguard Worker " 1: Goto 1\n"
588*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 3\n"
589*795d594fSAndroid Build Coastguard Worker " 4: Add(2, 3) [7]\n" // v2 <- v0 + v1 = 1 + 2 = 3
590*795d594fSAndroid Build Coastguard Worker " 5: Goto 3\n" // goto L2
591*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 3, succ: 4\n" // L1:
592*795d594fSAndroid Build Coastguard Worker " 10: Add(7, 9) [13]\n" // v1 <- v0 + 3 = 7 + 5 = 12
593*795d594fSAndroid Build Coastguard Worker " 11: Goto 4\n" // goto L3
594*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 1, succ: 2\n" // L2:
595*795d594fSAndroid Build Coastguard Worker " 7: Add(4, 6) [10]\n" // v0 <- v2 + 2 = 3 + 4 = 7
596*795d594fSAndroid Build Coastguard Worker " 8: Goto 2\n" // goto L1
597*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 2, succ: 5\n" // L3:
598*795d594fSAndroid Build Coastguard Worker " 13: Add(10, 12) [14]\n" // v2 <- v1 + 4 = 12 + 8 = 20
599*795d594fSAndroid Build Coastguard Worker " 14: Return(13)\n" // return v2
600*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 4\n"
601*795d594fSAndroid Build Coastguard Worker " 15: Exit\n";
602*795d594fSAndroid Build Coastguard Worker
603*795d594fSAndroid Build Coastguard Worker // Expected difference after constant folding.
604*795d594fSAndroid Build Coastguard Worker diff_t expected_cf_diff = {
605*795d594fSAndroid Build Coastguard Worker { " 2: IntConstant [4]\n", " 2: IntConstant\n" },
606*795d594fSAndroid Build Coastguard Worker { " 3: IntConstant [4]\n", " 3: IntConstant\n" },
607*795d594fSAndroid Build Coastguard Worker { " 6: IntConstant [7]\n", " 6: IntConstant\n" },
608*795d594fSAndroid Build Coastguard Worker { " 9: IntConstant [10]\n", " 9: IntConstant\n" },
609*795d594fSAndroid Build Coastguard Worker { " 12: IntConstant [13]\n", " 12: IntConstant\n"
610*795d594fSAndroid Build Coastguard Worker " 16: IntConstant\n"
611*795d594fSAndroid Build Coastguard Worker " 17: IntConstant\n"
612*795d594fSAndroid Build Coastguard Worker " 18: IntConstant\n"
613*795d594fSAndroid Build Coastguard Worker " 19: IntConstant [14]\n" },
614*795d594fSAndroid Build Coastguard Worker { " 4: Add(2, 3) [7]\n", removed },
615*795d594fSAndroid Build Coastguard Worker { " 10: Add(7, 9) [13]\n", removed },
616*795d594fSAndroid Build Coastguard Worker { " 7: Add(4, 6) [10]\n", removed },
617*795d594fSAndroid Build Coastguard Worker { " 13: Add(10, 12) [14]\n", removed },
618*795d594fSAndroid Build Coastguard Worker { " 14: Return(13)\n", " 14: Return(19)\n"}
619*795d594fSAndroid Build Coastguard Worker };
620*795d594fSAndroid Build Coastguard Worker std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
621*795d594fSAndroid Build Coastguard Worker
622*795d594fSAndroid Build Coastguard Worker // Check the values of the computed constants.
623*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
624*795d594fSAndroid Build Coastguard Worker HInstruction* inst1 = graph->GetBlocks()[4]->GetFirstInstruction()->InputAt(0);
625*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst1->IsIntConstant());
626*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 20);
627*795d594fSAndroid Build Coastguard Worker HInstruction* inst2 = inst1->GetPrevious();
628*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst2->IsIntConstant());
629*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 12);
630*795d594fSAndroid Build Coastguard Worker HInstruction* inst3 = inst2->GetPrevious();
631*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst3->IsIntConstant());
632*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 7);
633*795d594fSAndroid Build Coastguard Worker HInstruction* inst4 = inst3->GetPrevious();
634*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst4->IsIntConstant());
635*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst4->AsIntConstant()->GetValue(), 3);
636*795d594fSAndroid Build Coastguard Worker };
637*795d594fSAndroid Build Coastguard Worker
638*795d594fSAndroid Build Coastguard Worker // Expected difference after dead code elimination.
639*795d594fSAndroid Build Coastguard Worker std::string expected_after_dce =
640*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
641*795d594fSAndroid Build Coastguard Worker " 19: IntConstant [14]\n"
642*795d594fSAndroid Build Coastguard Worker " 0: SuspendCheck\n"
643*795d594fSAndroid Build Coastguard Worker " 1: Goto 1\n"
644*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 5\n"
645*795d594fSAndroid Build Coastguard Worker " 14: Return(19)\n"
646*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 1\n"
647*795d594fSAndroid Build Coastguard Worker " 15: Exit\n";
648*795d594fSAndroid Build Coastguard Worker
649*795d594fSAndroid Build Coastguard Worker TestCode(data,
650*795d594fSAndroid Build Coastguard Worker expected_before,
651*795d594fSAndroid Build Coastguard Worker expected_after_cf,
652*795d594fSAndroid Build Coastguard Worker expected_after_dce,
653*795d594fSAndroid Build Coastguard Worker check_after_cf);
654*795d594fSAndroid Build Coastguard Worker }
655*795d594fSAndroid Build Coastguard Worker
656*795d594fSAndroid Build Coastguard Worker /**
657*795d594fSAndroid Build Coastguard Worker * Three-register program with a constant (static) condition.
658*795d594fSAndroid Build Coastguard Worker *
659*795d594fSAndroid Build Coastguard Worker * 16-bit
660*795d594fSAndroid Build Coastguard Worker * offset
661*795d594fSAndroid Build Coastguard Worker * ------
662*795d594fSAndroid Build Coastguard Worker * v1 <- 1 0. const/4 v1, #+1
663*795d594fSAndroid Build Coastguard Worker * v0 <- 0 1. const/4 v0, #+0
664*795d594fSAndroid Build Coastguard Worker * if v1 >= 0 goto L1 2. if-gez v1, +3
665*795d594fSAndroid Build Coastguard Worker * v0 <- v1 4. move v0, v1
666*795d594fSAndroid Build Coastguard Worker * L1: v2 <- v0 + v1 5. add-int v2, v0, v1
667*795d594fSAndroid Build Coastguard Worker * return-void 7. return
668*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,ConstantCondition)669*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, ConstantCondition) {
670*795d594fSAndroid Build Coastguard Worker const std::vector<uint16_t> data = THREE_REGISTERS_CODE_ITEM(
671*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 1 << 8 | 1 << 12,
672*795d594fSAndroid Build Coastguard Worker Instruction::CONST_4 | 0 << 8 | 0 << 12,
673*795d594fSAndroid Build Coastguard Worker Instruction::IF_GEZ | 1 << 8, 3,
674*795d594fSAndroid Build Coastguard Worker Instruction::MOVE | 0 << 8 | 1 << 12,
675*795d594fSAndroid Build Coastguard Worker Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
676*795d594fSAndroid Build Coastguard Worker Instruction::RETURN_VOID);
677*795d594fSAndroid Build Coastguard Worker
678*795d594fSAndroid Build Coastguard Worker std::string expected_before =
679*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
680*795d594fSAndroid Build Coastguard Worker " 3: IntConstant [9, 8, 5]\n"
681*795d594fSAndroid Build Coastguard Worker " 4: IntConstant [8, 5]\n"
682*795d594fSAndroid Build Coastguard Worker " 1: SuspendCheck\n"
683*795d594fSAndroid Build Coastguard Worker " 2: Goto 1\n"
684*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 5, 2\n"
685*795d594fSAndroid Build Coastguard Worker " 5: GreaterThanOrEqual(3, 4) [6]\n"
686*795d594fSAndroid Build Coastguard Worker " 6: If(5)\n"
687*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1, succ: 3\n"
688*795d594fSAndroid Build Coastguard Worker " 7: Goto 3\n"
689*795d594fSAndroid Build Coastguard Worker "BasicBlock 3, pred: 5, 2, succ: 4\n"
690*795d594fSAndroid Build Coastguard Worker " 8: Phi(4, 3) [9]\n"
691*795d594fSAndroid Build Coastguard Worker " 9: Add(8, 3)\n"
692*795d594fSAndroid Build Coastguard Worker " 10: ReturnVoid\n"
693*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 3\n"
694*795d594fSAndroid Build Coastguard Worker " 11: Exit\n"
695*795d594fSAndroid Build Coastguard Worker "BasicBlock 5, pred: 1, succ: 3\n"
696*795d594fSAndroid Build Coastguard Worker " 0: Goto 3\n";
697*795d594fSAndroid Build Coastguard Worker
698*795d594fSAndroid Build Coastguard Worker // Expected difference after constant folding.
699*795d594fSAndroid Build Coastguard Worker diff_t expected_cf_diff = {
700*795d594fSAndroid Build Coastguard Worker { " 3: IntConstant [9, 8, 5]\n", " 3: IntConstant [6, 9, 8]\n" },
701*795d594fSAndroid Build Coastguard Worker { " 4: IntConstant [8, 5]\n", " 4: IntConstant [8]\n" },
702*795d594fSAndroid Build Coastguard Worker { " 5: GreaterThanOrEqual(3, 4) [6]\n", removed },
703*795d594fSAndroid Build Coastguard Worker { " 6: If(5)\n", " 6: If(3)\n" }
704*795d594fSAndroid Build Coastguard Worker };
705*795d594fSAndroid Build Coastguard Worker std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
706*795d594fSAndroid Build Coastguard Worker
707*795d594fSAndroid Build Coastguard Worker // Check the values of the computed constants.
708*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
709*795d594fSAndroid Build Coastguard Worker HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
710*795d594fSAndroid Build Coastguard Worker ASSERT_TRUE(inst->IsIntConstant());
711*795d594fSAndroid Build Coastguard Worker ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
712*795d594fSAndroid Build Coastguard Worker };
713*795d594fSAndroid Build Coastguard Worker
714*795d594fSAndroid Build Coastguard Worker // Expected graph after dead code elimination.
715*795d594fSAndroid Build Coastguard Worker std::string expected_after_dce =
716*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
717*795d594fSAndroid Build Coastguard Worker " 1: SuspendCheck\n"
718*795d594fSAndroid Build Coastguard Worker " 2: Goto 1\n"
719*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 4\n"
720*795d594fSAndroid Build Coastguard Worker " 10: ReturnVoid\n"
721*795d594fSAndroid Build Coastguard Worker "BasicBlock 4, pred: 1\n"
722*795d594fSAndroid Build Coastguard Worker " 11: Exit\n";
723*795d594fSAndroid Build Coastguard Worker
724*795d594fSAndroid Build Coastguard Worker TestCode(data,
725*795d594fSAndroid Build Coastguard Worker expected_before,
726*795d594fSAndroid Build Coastguard Worker expected_after_cf,
727*795d594fSAndroid Build Coastguard Worker expected_after_dce,
728*795d594fSAndroid Build Coastguard Worker check_after_cf);
729*795d594fSAndroid Build Coastguard Worker }
730*795d594fSAndroid Build Coastguard Worker
731*795d594fSAndroid Build Coastguard Worker /**
732*795d594fSAndroid Build Coastguard Worker * Unsigned comparisons with zero. Since these instructions are not present
733*795d594fSAndroid Build Coastguard Worker * in the bytecode, we need to set up the graph explicitly.
734*795d594fSAndroid Build Coastguard Worker */
TEST_F(ConstantFoldingTest,UnsignedComparisonsWithZero)735*795d594fSAndroid Build Coastguard Worker TEST_F(ConstantFoldingTest, UnsignedComparisonsWithZero) {
736*795d594fSAndroid Build Coastguard Worker HBasicBlock* block = InitEntryMainExitGraph();
737*795d594fSAndroid Build Coastguard Worker
738*795d594fSAndroid Build Coastguard Worker // Make various unsigned comparisons with zero against a parameter.
739*795d594fSAndroid Build Coastguard Worker HInstruction* parameter = MakeParam(DataType::Type::kInt32);
740*795d594fSAndroid Build Coastguard Worker HInstruction* zero = graph_->GetIntConstant(0);
741*795d594fSAndroid Build Coastguard Worker
742*795d594fSAndroid Build Coastguard Worker HInstruction* a1 = MakeCondition(block, kCondA, zero, parameter);
743*795d594fSAndroid Build Coastguard Worker MakeSelect(block, a1, parameter, parameter);
744*795d594fSAndroid Build Coastguard Worker HInstruction* a2 = MakeCondition(block, kCondA, parameter, zero);
745*795d594fSAndroid Build Coastguard Worker MakeSelect(block, a2, parameter, parameter);
746*795d594fSAndroid Build Coastguard Worker HInstruction* ae1 = MakeCondition(block, kCondAE, zero, parameter);
747*795d594fSAndroid Build Coastguard Worker MakeSelect(block, ae1, parameter, parameter);
748*795d594fSAndroid Build Coastguard Worker HInstruction* ae2 = MakeCondition(block, kCondAE, parameter, zero);
749*795d594fSAndroid Build Coastguard Worker MakeSelect(block, ae2, parameter, parameter);
750*795d594fSAndroid Build Coastguard Worker HInstruction* b1 = MakeCondition(block, kCondB, zero, parameter);
751*795d594fSAndroid Build Coastguard Worker MakeSelect(block, b1, parameter, parameter);
752*795d594fSAndroid Build Coastguard Worker HInstruction* b2 = MakeCondition(block, kCondB, parameter, zero);
753*795d594fSAndroid Build Coastguard Worker MakeSelect(block, b2, parameter, parameter);
754*795d594fSAndroid Build Coastguard Worker HInstruction* be1 = MakeCondition(block, kCondBE, zero, parameter);
755*795d594fSAndroid Build Coastguard Worker MakeSelect(block, be1, parameter, parameter);
756*795d594fSAndroid Build Coastguard Worker HInstruction* be2 = MakeCondition(block, kCondBE, parameter, zero);
757*795d594fSAndroid Build Coastguard Worker MakeSelect(block, be2, parameter, parameter);
758*795d594fSAndroid Build Coastguard Worker MakeReturn(block, zero);
759*795d594fSAndroid Build Coastguard Worker
760*795d594fSAndroid Build Coastguard Worker graph_->BuildDominatorTree();
761*795d594fSAndroid Build Coastguard Worker
762*795d594fSAndroid Build Coastguard Worker const std::string expected_before =
763*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
764*795d594fSAndroid Build Coastguard Worker " 2: ParameterValue [19, 19, 18, 17, 17, 16, 15, 15, 14, 13, 13, 12, 11, 11, 10, "
765*795d594fSAndroid Build Coastguard Worker "9, 9, 8, 7, 7, 6, 5, 5, 4]\n"
766*795d594fSAndroid Build Coastguard Worker " 3: IntConstant [20, 18, 16, 14, 12, 10, 8, 6, 4]\n"
767*795d594fSAndroid Build Coastguard Worker " 0: Goto 1\n"
768*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
769*795d594fSAndroid Build Coastguard Worker " 4: Above(3, 2) [5]\n"
770*795d594fSAndroid Build Coastguard Worker " 5: Select(2, 2, 4)\n"
771*795d594fSAndroid Build Coastguard Worker " 6: Above(2, 3) [7]\n"
772*795d594fSAndroid Build Coastguard Worker " 7: Select(2, 2, 6)\n"
773*795d594fSAndroid Build Coastguard Worker " 8: AboveOrEqual(3, 2) [9]\n"
774*795d594fSAndroid Build Coastguard Worker " 9: Select(2, 2, 8)\n"
775*795d594fSAndroid Build Coastguard Worker " 10: AboveOrEqual(2, 3) [11]\n"
776*795d594fSAndroid Build Coastguard Worker " 11: Select(2, 2, 10)\n"
777*795d594fSAndroid Build Coastguard Worker " 12: Below(3, 2) [13]\n"
778*795d594fSAndroid Build Coastguard Worker " 13: Select(2, 2, 12)\n"
779*795d594fSAndroid Build Coastguard Worker " 14: Below(2, 3) [15]\n"
780*795d594fSAndroid Build Coastguard Worker " 15: Select(2, 2, 14)\n"
781*795d594fSAndroid Build Coastguard Worker " 16: BelowOrEqual(3, 2) [17]\n"
782*795d594fSAndroid Build Coastguard Worker " 17: Select(2, 2, 16)\n"
783*795d594fSAndroid Build Coastguard Worker " 18: BelowOrEqual(2, 3) [19]\n"
784*795d594fSAndroid Build Coastguard Worker " 19: Select(2, 2, 18)\n"
785*795d594fSAndroid Build Coastguard Worker " 20: Return(3)\n"
786*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
787*795d594fSAndroid Build Coastguard Worker " 1: Exit\n";
788*795d594fSAndroid Build Coastguard Worker
789*795d594fSAndroid Build Coastguard Worker const std::string expected_after_cf =
790*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
791*795d594fSAndroid Build Coastguard Worker " 2: ParameterValue [19, 19, 18, 17, 17, 15, 15, 13, 13, 12, 11, 11, "
792*795d594fSAndroid Build Coastguard Worker "9, 9, 8, 7, 7, 6, 5, 5]\n"
793*795d594fSAndroid Build Coastguard Worker " 3: IntConstant [15, 5, 20, 18, 12, 8, 6]\n"
794*795d594fSAndroid Build Coastguard Worker " 21: IntConstant [17, 11]\n"
795*795d594fSAndroid Build Coastguard Worker " 0: Goto 1\n"
796*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
797*795d594fSAndroid Build Coastguard Worker " 5: Select(2, 2, 3)\n"
798*795d594fSAndroid Build Coastguard Worker " 6: Above(2, 3) [7]\n"
799*795d594fSAndroid Build Coastguard Worker " 7: Select(2, 2, 6)\n"
800*795d594fSAndroid Build Coastguard Worker " 8: AboveOrEqual(3, 2) [9]\n"
801*795d594fSAndroid Build Coastguard Worker " 9: Select(2, 2, 8)\n"
802*795d594fSAndroid Build Coastguard Worker " 11: Select(2, 2, 21)\n"
803*795d594fSAndroid Build Coastguard Worker " 12: Below(3, 2) [13]\n"
804*795d594fSAndroid Build Coastguard Worker " 13: Select(2, 2, 12)\n"
805*795d594fSAndroid Build Coastguard Worker " 15: Select(2, 2, 3)\n"
806*795d594fSAndroid Build Coastguard Worker " 17: Select(2, 2, 21)\n"
807*795d594fSAndroid Build Coastguard Worker " 18: BelowOrEqual(2, 3) [19]\n"
808*795d594fSAndroid Build Coastguard Worker " 19: Select(2, 2, 18)\n"
809*795d594fSAndroid Build Coastguard Worker " 20: Return(3)\n"
810*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
811*795d594fSAndroid Build Coastguard Worker " 1: Exit\n";
812*795d594fSAndroid Build Coastguard Worker
813*795d594fSAndroid Build Coastguard Worker const std::string expected_after_dce =
814*795d594fSAndroid Build Coastguard Worker "BasicBlock 0, succ: 1\n"
815*795d594fSAndroid Build Coastguard Worker " 2: ParameterValue\n"
816*795d594fSAndroid Build Coastguard Worker " 3: IntConstant [20]\n"
817*795d594fSAndroid Build Coastguard Worker " 0: Goto 1\n"
818*795d594fSAndroid Build Coastguard Worker "BasicBlock 1, pred: 0, succ: 2\n"
819*795d594fSAndroid Build Coastguard Worker " 20: Return(3)\n"
820*795d594fSAndroid Build Coastguard Worker "BasicBlock 2, pred: 1\n"
821*795d594fSAndroid Build Coastguard Worker " 1: Exit\n";
822*795d594fSAndroid Build Coastguard Worker
823*795d594fSAndroid Build Coastguard Worker auto check_after_cf = [](HGraph* graph) {
824*795d594fSAndroid Build Coastguard Worker CHECK(graph != nullptr);
825*795d594fSAndroid Build Coastguard Worker };
826*795d594fSAndroid Build Coastguard Worker
827*795d594fSAndroid Build Coastguard Worker TestCodeOnReadyGraph(expected_before,
828*795d594fSAndroid Build Coastguard Worker expected_after_cf,
829*795d594fSAndroid Build Coastguard Worker expected_after_dce,
830*795d594fSAndroid Build Coastguard Worker check_after_cf);
831*795d594fSAndroid Build Coastguard Worker }
832*795d594fSAndroid Build Coastguard Worker
833*795d594fSAndroid Build Coastguard Worker } // namespace art
834