constant_folding_test.cc revision 93445689c714e53cabf347da4321ecf3023e926c
1556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/*
2556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Copyright (C) 2014 The Android Open Source Project
3556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
4556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Licensed under the Apache License, Version 2.0 (the "License");
5556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * you may not use this file except in compliance with the License.
6556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * You may obtain a copy of the License at
7556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
8556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *      http://www.apache.org/licenses/LICENSE-2.0
9556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
10556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Unless required by applicable law or agreed to in writing, software
11556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * distributed under the License is distributed on an "AS IS" BASIS,
12556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * See the License for the specific language governing permissions and
14556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * limitations under the License.
15556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
16556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
1793445689c714e53cabf347da4321ecf3023e926cRoland Levillain#include <functional>
1893445689c714e53cabf347da4321ecf3023e926cRoland Levillain
191ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray#include "constant_propagation.h"
20556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "dead_code_elimination.h"
211ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray#include "pretty_printer.h"
22556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "graph_checker.h"
23556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "optimizing_unit_test.h"
24556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
25556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "gtest/gtest.h"
26556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
27556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillainnamespace art {
28556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
29556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillainstatic void TestCode(const uint16_t* data,
30556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain                     const std::string& expected_before,
31556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain                     const std::string& expected_after_cp,
327fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                     const std::string& expected_after_dce,
3393445689c714e53cabf347da4321ecf3023e926cRoland Levillain                     std::function<void(HGraph*)> check_after_cp,
347fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                     Primitive::Type return_type = Primitive::kPrimInt) {
35556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ArenaPool pool;
36556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ArenaAllocator allocator(&pool);
377fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  HGraph* graph = CreateCFG(&allocator, data, return_type);
38556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ASSERT_NE(graph, nullptr);
39556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
40556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  graph->BuildDominatorTree();
41556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  graph->TransformToSSA();
42556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
43556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  StringPrettyPrinter printer_before(graph);
44556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  printer_before.VisitInsertionOrder();
45556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string actual_before = printer_before.str();
46556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ASSERT_EQ(expected_before, actual_before);
47556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
481ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  ConstantPropagation(graph).Run();
49556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
50556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  StringPrettyPrinter printer_after_cp(graph);
51556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  printer_after_cp.VisitInsertionOrder();
52556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string actual_after_cp = printer_after_cp.str();
53556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ASSERT_EQ(expected_after_cp, actual_after_cp);
54556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
5593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  check_after_cp(graph);
5693445689c714e53cabf347da4321ecf3023e926cRoland Levillain
571ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  DeadCodeElimination(graph).Run();
58556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
59556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  StringPrettyPrinter printer_after_dce(graph);
60556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  printer_after_dce.VisitInsertionOrder();
61556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string actual_after_dce = printer_after_dce.str();
62556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ASSERT_EQ(expected_after_dce, actual_after_dce);
631ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray
641ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  SSAChecker ssa_checker(&allocator, graph);
651ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  ssa_checker.VisitInsertionOrder();
661ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  ASSERT_TRUE(ssa_checker.IsValid());
67556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
68556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
69556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
70556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
71556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on addition.
72556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
73556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
74556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
75556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
76556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
77556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
78556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1            2.      add-int v2, v0, v1
79556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                4.      return v2
80556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
811ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, IntConstantFoldingOnAddition1) {
82556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
83556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
84556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
85556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
86556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
87556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
88556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
89556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
90556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [9]\n"
91556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [9]\n"
92556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  14: SuspendCheck\n"
93556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Goto 1\n"
94556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
95556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: Add(3, 5) [12]\n"
96556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Return(9)\n"
97556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
98556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  13: Exit\n";
99556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
1001ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  // Expected difference after constant propagation.
101556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_cp_diff = {
102556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n", "  3: IntConstant\n" },
103556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n", "  5: IntConstant\n" },
104556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  9: Add(3, 5) [12]\n",  "  16: IntConstant [12]\n" },
105556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  12: Return(9)\n",      "  12: Return(16)\n" }
106556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
107556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
108556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
10993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
11093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  auto check_after_cp = [](HGraph* graph) {
11193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
11293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
11393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 3);
11493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
11593445689c714e53cabf347da4321ecf3023e926cRoland Levillain
116556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
117556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
118556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n", removed },
119556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n", removed }
120556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
121556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
122556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
12393445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
12493445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
12593445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_cp,
12693445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
12793445689c714e53cabf347da4321ecf3023e926cRoland Levillain           check_after_cp);
128556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
129556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
130556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
131556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Small three-register program exercising int constant folding on addition.
132556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
133556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
134556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
135556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
136556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
137556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
138556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- v0 + v1            2.      add-int/2addr v0, v1
139556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 3                  3.      const/4 v1, #+3
140556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- 4                  4.      const/4 v2, #+4
141556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- v1 + v2            5.      add-int/2addr v1, v2
142556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1            6.      add-int v2, v0, v1
143556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                8.      return v2
144556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
1451ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, IntConstantFoldingOnAddition2) {
146556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
147556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
148556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
149556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_2ADDR | 0 << 8 | 1 << 12,
150556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 3 << 12,
151556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 2 << 8 | 4 << 12,
152556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_2ADDR | 1 << 8 | 2 << 12,
153556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
154556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
155556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
156556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
157556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
158556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [9]\n"
159556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [9]\n"
160556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  11: IntConstant [17]\n"
161556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  13: IntConstant [17]\n"
162556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  26: SuspendCheck\n"
163556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  27: Goto 1\n"
164556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
165556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: Add(3, 5) [21]\n"
166556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: Add(11, 13) [21]\n"
167556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  21: Add(9, 17) [24]\n"
168556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  24: Return(21)\n"
169556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
170556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  25: Exit\n";
171556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
1721ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  // Expected difference after constant propagation.
173556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_cp_diff = {
174556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n",   "  3: IntConstant\n" },
175556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n",   "  5: IntConstant\n" },
176556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  11: IntConstant [17]\n", "  11: IntConstant\n" },
177556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant [17]\n", "  13: IntConstant\n" },
178556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  9: Add(3, 5) [21]\n",    "  28: IntConstant\n" },
179556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  17: Add(11, 13) [21]\n", "  29: IntConstant\n" },
180556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  21: Add(9, 17) [24]\n",  "  30: IntConstant [24]\n" },
181556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  24: Return(21)\n",       "  24: Return(30)\n" }
182556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
183556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
184556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
18593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
18693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  auto check_after_cp = [](HGraph* graph) {
18793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst1 = graph->GetBlock(1)->GetFirstInstruction();
18893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst1->IsIntConstant());
18993445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 3);
19093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst2 = inst1->GetNext();
19193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst2->IsIntConstant());
19293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 7);
19393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst3 = inst2->GetNext();
19493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst3->IsIntConstant());
19593445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 10);
19693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
19793445689c714e53cabf347da4321ecf3023e926cRoland Levillain
198556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
199556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
200556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n",  removed },
201556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n",  removed },
202556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  11: IntConstant\n", removed },
203556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant\n", removed },
204556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  28: IntConstant\n", removed },
205556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  29: IntConstant\n", removed }
206556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
207556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
208556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
20993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
21093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
21193445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_cp,
21293445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
21393445689c714e53cabf347da4321ecf3023e926cRoland Levillain           check_after_cp);
214556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
215556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
216556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
217556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on subtraction.
218556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
219556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
220556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
221556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
222556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 3                  0.      const/4 v0, #+3
223556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
224556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 - v1            2.      sub-int v2, v0, v1
225556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                4.      return v2
226556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
2271ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, IntConstantFoldingOnSubtraction) {
228556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
229556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 3 << 12,
230556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
231556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::SUB_INT | 2 << 8, 0 | 1 << 8,
232556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
233556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
234556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
235556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
236556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [9]\n"
237556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [9]\n"
238556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  14: SuspendCheck\n"
239556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Goto 1\n"
240556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
241556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: Sub(3, 5) [12]\n"
242556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Return(9)\n"
243556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
244556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  13: Exit\n";
245556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
2461ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  // Expected difference after constant propagation.
247556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_cp_diff = {
248556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n", "  3: IntConstant\n" },
249556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n", "  5: IntConstant\n" },
250556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  9: Sub(3, 5) [12]\n",  "  16: IntConstant [12]\n" },
251556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  12: Return(9)\n",      "  12: Return(16)\n" }
252556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
253556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
254556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
25593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
25693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  auto check_after_cp = [](HGraph* graph) {
25793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
25893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
25993445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
26093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
26193445689c714e53cabf347da4321ecf3023e926cRoland Levillain
262556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
263556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
264556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n", removed },
265556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n", removed }
266556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
267556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
268556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
26993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
27093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
27193445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_cp,
27293445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
27393445689c714e53cabf347da4321ecf3023e926cRoland Levillain           check_after_cp);
274556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
275556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
276556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#define SIX_REGISTERS_CODE_ITEM(...)                                     \
277556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { 6, 0, 0, 0, 0, 0, NUM_INSTRUCTIONS(__VA_ARGS__), 0, __VA_ARGS__ }
278556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
279556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
280556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding
281556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on addition.
282556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
283556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
284556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
285556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
286556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v0, v1) <- 1            0.      const-wide/16 v0, #+1
287556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v2, v3) <- 2            2.      const-wide/16 v2, #+2
288556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v4, v5) <-
289556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *       (v0, v1) + (v1, v2)    4.      add-long v4, v0, v2
290556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return (v4, v5)          6.      return-wide v4
291556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
2921ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, LongConstantFoldingOnAddition) {
293556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
294556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 0 << 8, 1,
295556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 2 << 8, 2,
296556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_LONG | 4 << 8, 0 | 2 << 8,
297556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_WIDE | 4 << 8);
298556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
299556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
300556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
301556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  6: LongConstant [12]\n"
302556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  8: LongConstant [12]\n"
303556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: SuspendCheck\n"
304556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  18: Goto 1\n"
305556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
306556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Add(6, 8) [15]\n"
307556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Return(12)\n"
308556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
309556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  16: Exit\n";
310556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
3111ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  // Expected difference after constant propagation.
312556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_cp_diff = {
313556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant [12]\n", "  6: LongConstant\n" },
314556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant [12]\n", "  8: LongConstant\n" },
315556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  12: Add(6, 8) [15]\n",   "  19: LongConstant [15]\n" },
316556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  15: Return(12)\n",       "  15: Return(19)\n" }
317556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
318556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
319556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
32093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
32193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  auto check_after_cp = [](HGraph* graph) {
32293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
32393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsLongConstant());
32493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), 3);
32593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
32693445689c714e53cabf347da4321ecf3023e926cRoland Levillain
327556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
328556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
329556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant\n", removed },
330556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant\n", removed }
331556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
332556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
333556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
33493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
33593445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
33693445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_cp,
33793445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
33893445689c714e53cabf347da4321ecf3023e926cRoland Levillain           check_after_cp,
33993445689c714e53cabf347da4321ecf3023e926cRoland Levillain           Primitive::kPrimLong);
340556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
341556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
342556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
343556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding
344556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on subtraction.
345556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
346556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
347556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
348556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
349556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v0, v1) <- 3            0.      const-wide/16 v0, #+3
350556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v2, v3) <- 2            2.      const-wide/16 v2, #+2
351556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v4, v5) <-
352556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *       (v0, v1) - (v1, v2)    4.      sub-long v4, v0, v2
353556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return (v4, v5)          6.      return-wide v4
354556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
3551ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, LongConstantFoldingOnSubtraction) {
356556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
357556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 0 << 8, 3,
358556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 2 << 8, 2,
359556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::SUB_LONG | 4 << 8, 0 | 2 << 8,
360556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_WIDE | 4 << 8);
361556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
362556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
363556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
364556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  6: LongConstant [12]\n"
365556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  8: LongConstant [12]\n"
366556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: SuspendCheck\n"
367556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  18: Goto 1\n"
368556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
369556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Sub(6, 8) [15]\n"
370556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Return(12)\n"
371556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
372556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  16: Exit\n";
373556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
3741ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  // Expected difference after constant propagation.
375556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_cp_diff = {
376556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant [12]\n", "  6: LongConstant\n" },
377556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant [12]\n", "  8: LongConstant\n" },
378556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  12: Sub(6, 8) [15]\n",   "  19: LongConstant [15]\n" },
379556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  15: Return(12)\n",       "  15: Return(19)\n" }
380556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
381556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
382556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
38393445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
38493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  auto check_after_cp = [](HGraph* graph) {
38593445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
38693445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsLongConstant());
38793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), 1);
38893445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
38993445689c714e53cabf347da4321ecf3023e926cRoland Levillain
390556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
391556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
392556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant\n", removed },
393556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant\n", removed }
394556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
395556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
396556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
39793445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
39893445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
39993445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_cp,
40093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
40193445689c714e53cabf347da4321ecf3023e926cRoland Levillain           check_after_cp,
40293445689c714e53cabf347da4321ecf3023e926cRoland Levillain           Primitive::kPrimLong);
403556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
404556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
405556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
406556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with jumps leading to the creation of many
407556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * blocks.
408556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
409556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * The intent of this test is to ensure that all constant expressions
410556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * are actually evaluated at compile-time, thanks to the reverse
411556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (forward) post-order traversal of the the dominator tree.
412556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
413556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
414556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
415556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
416556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 0                   0.     const/4 v0, #+0
417556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 1                   1.     const/4 v1, #+1
418556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1             2.     add-int v2, v0, v1
419556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L2                   4.     goto +4
420556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L1: v1 <- v0 + 3              5.     add-int/lit16 v1, v0, #+3
421556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L3                   7.     goto +4
422556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L2: v0 <- v2 + 2              8.     add-int/lit16 v0, v2, #+2
423556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L1                  10.     goto +(-5)
424556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L3: v2 <- v1 + 4             11.     add-int/lit16 v2, v1, #+4
425556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                13.     return v2
426556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
4271ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, IntConstantFoldingAndJumps) {
428556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
429556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 0 << 12,
430556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 1 << 12,
431556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
432556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::GOTO | 4 << 8,
433556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_LIT16 | 1 << 8 | 0 << 12, 3,
434556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::GOTO | 4 << 8,
435556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_LIT16 | 0 << 8 | 2 << 12, 2,
436556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    static_cast<uint16_t>(Instruction::GOTO | -5 << 8),
437556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_LIT16 | 2 << 8 | 1 << 12, 4,
438556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
439556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
440556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
441556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
44293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  3: IntConstant [9]\n"            // v0 <- 0
44393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  5: IntConstant [9]\n"            // v1 <- 1
44493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  13: IntConstant [14]\n"          // const 3
44593445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  18: IntConstant [19]\n"          // const 2
44693445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  24: IntConstant [25]\n"          // const 4
447556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  30: SuspendCheck\n"
448556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  31: Goto 1\n"
449556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 3\n"
45093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  9: Add(3, 5) [19]\n"             // v2 <- v0 + v1 = 0 + 1 = 1
45193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  11: Goto 3\n"                    // goto L2
45293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "BasicBlock 2, pred: 3, succ: 4\n"  // L1:
45393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  14: Add(19, 13) [25]\n"          // v1 <- v0 + 3 = 3 + 3 = 6
45493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  16: Goto 4\n"                    // goto L3
45593445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "BasicBlock 3, pred: 1, succ: 2\n"  // L2:
45693445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  19: Add(9, 18) [14]\n"           // v0 <- v2 + 2 = 1 + 2 = 3
457556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  21: SuspendCheck\n"
45893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  22: Goto 2\n"                    // goto L1
45993445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "BasicBlock 4, pred: 2, succ: 5\n"  // L3:
46093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  25: Add(14, 24) [28]\n"          // v2 <- v1 + 4 = 6 + 4 = 10
46193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  28: Return(25)\n"                // return v2
462556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 5, pred: 4\n"
463556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  29: Exit\n";
464556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
4651ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  // Expected difference after constant propagation.
466556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_cp_diff = {
467556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n",   "  3: IntConstant\n" },
468556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n",   "  5: IntConstant []\n" },
469556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant [14]\n", "  13: IntConstant\n" },
470556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  18: IntConstant [19]\n", "  18: IntConstant\n" },
471556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  24: IntConstant [25]\n", "  24: IntConstant\n" },
472556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  9: Add(3, 5) [19]\n",    "  32: IntConstant []\n" },
473556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  14: Add(19, 13) [25]\n", "  34: IntConstant\n" },
474556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  19: Add(9, 18) [14]\n",  "  33: IntConstant []\n" },
475556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  25: Add(14, 24) [28]\n", "  35: IntConstant [28]\n" },
476556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  28: Return(25)\n",       "  28: Return(35)\n"}
477556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
478556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
479556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
48093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
48193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  auto check_after_cp = [](HGraph* graph) {
48293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst1 = graph->GetBlock(1)->GetFirstInstruction();
48393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst1->IsIntConstant());
48493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 1);
48593445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst2 = graph->GetBlock(2)->GetFirstInstruction();
48693445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst2->IsIntConstant());
48793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 6);
48893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst3 = graph->GetBlock(3)->GetFirstInstruction();
48993445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst3->IsIntConstant());
49093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 3);
49193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst4 = graph->GetBlock(4)->GetFirstInstruction();
49293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst4->IsIntConstant());
49393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst4->AsIntConstant()->GetValue(), 10);
49493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
49593445689c714e53cabf347da4321ecf3023e926cRoland Levillain
496556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
497556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
498556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n",     removed },
499556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant\n",    removed },
500556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  18: IntConstant\n",    removed },
501556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  24: IntConstant\n",    removed },
502556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  34: IntConstant\n",    removed },
503556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
504556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
505556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
50693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
50793445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
50893445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_cp,
50993445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
51093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           check_after_cp);
511556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
512556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
513556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
514556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
515556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with a constant (static) condition.
516556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
517556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
518556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
519556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
520556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 1                  0.      const/4 v1, #+1
521556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 0                  1.      const/4 v0, #+0
522556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     if v1 >= 0 goto L1       2.      if-gez v1, +3
523556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- v1                 4.      move v0, v1
524556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L1: v2 <- v0 + v1            5.      add-int v2, v0, v1
525556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return-void              7.      return
526556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
5271ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas GeoffrayTEST(ConstantPropagation, ConstantCondition) {
528556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
529556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 1 << 12,
530556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 0 << 12,
531556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::IF_GEZ | 1 << 8, 3,
532556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::MOVE | 0 << 8 | 1 << 12,
533556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
534556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_VOID);
535556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
536556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
537556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
538556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [15, 22, 8]\n"
539556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [22, 8]\n"
540556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  19: SuspendCheck\n"
541556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  20: Goto 1\n"
542556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 5, 2\n"
543556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  8: GreaterThanOrEqual(3, 5) [9]\n"
544556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: If(8)\n"
545556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1, succ: 3\n"
546556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Goto 3\n"
547556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 3, pred: 2, 5, succ: 4\n"
548556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  22: Phi(3, 5) [15]\n"
549556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Add(22, 3)\n"
550556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: ReturnVoid\n"
551556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 4, pred: 3\n"
552556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  18: Exit\n"
553556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 5, pred: 1, succ: 3\n"
554556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  21: Goto 3\n";
555556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
5561ddbf6d4b37979a9f11a203c12befd5ae8b65df4Nicolas Geoffray  // Expected difference after constant propagation.
557556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_cp_diff = {
558556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [15, 22, 8]\n",      "  3: IntConstant [15, 22]\n" },
559556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [22, 8]\n",          "  5: IntConstant [22]\n" },
560556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: GreaterThanOrEqual(3, 5) [9]\n", "  23: IntConstant [9]\n" },
561556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  9: If(8)\n",                        "  9: If(23)\n" }
562556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
563556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_cp = Patch(expected_before, expected_cp_diff);
564556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
56593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
56693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  auto check_after_cp = [](HGraph* graph) {
56793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction();
56893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
56993445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
57093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
57193445689c714e53cabf347da4321ecf3023e926cRoland Levillain
572556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
573556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
574556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [15, 22]\n", "  3: IntConstant [22]\n" },
575556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  22: Phi(3, 5) [15]\n",      "  22: Phi(3, 5)\n" },
576556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  15: Add(22, 3)\n",          removed }
577556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
578556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_after_dce = Patch(expected_after_cp, expected_dce_diff);
579556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
58093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
58193445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
58293445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_cp,
58393445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
58493445689c714e53cabf347da4321ecf3023e926cRoland Levillain           check_after_cp);
585556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
586556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
587556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}  // namespace art
588