constant_folding_test.cc revision fb8d279bc011b31d0765dc7ca59afea324fd0d0c
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
19fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell#include "arch/x86/instruction_set_features_x86.h"
2075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain#include "code_generator_x86.h"
2175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain#include "constant_folding.h"
22556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "dead_code_elimination.h"
23cd6dffedf1bd8e6dfb3fb0c933551f9a90f7de3fCalin Juravle#include "driver/compiler_options.h"
24556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "graph_checker.h"
25556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "optimizing_unit_test.h"
2675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain#include "pretty_printer.h"
27556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
28556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain#include "gtest/gtest.h"
29556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
30556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillainnamespace art {
31556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
32556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillainstatic void TestCode(const uint16_t* data,
33556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain                     const std::string& expected_before,
3475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain                     const std::string& expected_after_cf,
357fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                     const std::string& expected_after_dce,
3675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain                     std::function<void(HGraph*)> check_after_cf,
377fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray                     Primitive::Type return_type = Primitive::kPrimInt) {
38556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ArenaPool pool;
39556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ArenaAllocator allocator(&pool);
407fb49da8ec62e8a10ed9419ade9f32c6b1174687Nicolas Geoffray  HGraph* graph = CreateCFG(&allocator, data, return_type);
41556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ASSERT_NE(graph, nullptr);
42556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
43e53798a7e3267305f696bf658e418c92e63e0834Nicolas Geoffray  graph->TryBuildingSsa();
44556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
45556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  StringPrettyPrinter printer_before(graph);
46556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  printer_before.VisitInsertionOrder();
47556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string actual_before = printer_before.str();
48556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ASSERT_EQ(expected_before, actual_before);
49556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
50fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell  std::unique_ptr<const X86InstructionSetFeatures> features_x86(
51fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell      X86InstructionSetFeatures::FromCppDefines());
52fb8d279bc011b31d0765dc7ca59afea324fd0d0cMark Mendell  x86::CodeGeneratorX86 codegenX86(graph, *features_x86.get(), CompilerOptions());
535e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffray  HConstantFolding(graph).Run();
54942a3785dca38feaae9d01b35d6bfb09c39315ebNicolas Geoffray  SSAChecker ssa_checker_cf(&allocator, graph);
55942a3785dca38feaae9d01b35d6bfb09c39315ebNicolas Geoffray  ssa_checker_cf.Run();
56942a3785dca38feaae9d01b35d6bfb09c39315ebNicolas Geoffray  ASSERT_TRUE(ssa_checker_cf.IsValid());
57556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
5875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  StringPrettyPrinter printer_after_cf(graph);
5975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  printer_after_cf.VisitInsertionOrder();
6075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string actual_after_cf = printer_after_cf.str();
6175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  ASSERT_EQ(expected_after_cf, actual_after_cf);
62556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
6375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  check_after_cf(graph);
6493445689c714e53cabf347da4321ecf3023e926cRoland Levillain
655e6916cea259897baaca019c5c7a5d05746306edNicolas Geoffray  HDeadCodeElimination(graph).Run();
66942a3785dca38feaae9d01b35d6bfb09c39315ebNicolas Geoffray  SSAChecker ssa_checker_dce(&allocator, graph);
67942a3785dca38feaae9d01b35d6bfb09c39315ebNicolas Geoffray  ssa_checker_dce.Run();
68942a3785dca38feaae9d01b35d6bfb09c39315ebNicolas Geoffray  ASSERT_TRUE(ssa_checker_dce.IsValid());
69556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
70556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  StringPrettyPrinter printer_after_dce(graph);
71556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  printer_after_dce.VisitInsertionOrder();
72556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string actual_after_dce = printer_after_dce.str();
73556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  ASSERT_EQ(expected_after_dce, actual_after_dce);
74556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
75556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
76556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
77556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
789240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain * Tiny three-register program exercising int constant folding on negation.
799240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *
809240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *                              16-bit
819240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *                              offset
829240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *                              ------
839240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
849240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *     v1 <- -v0                1.      neg-int v0, v1
859240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *     return v1                2.      return v1
869240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain */
879240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland LevillainTEST(ConstantFolding, IntConstantFoldingNegation) {
889240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
899240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
909240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    Instruction::NEG_INT | 1 << 8 | 0 << 12,
919240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    Instruction::RETURN | 1 << 8);
929240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
939240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  std::string expected_before =
949240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "BasicBlock 0, succ: 1\n"
959240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  2: IntConstant [5]\n"
969240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  10: SuspendCheck\n"
979240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  11: Goto 1\n"
989240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "BasicBlock 1, pred: 0, succ: 2\n"
999240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  5: Neg(2) [8]\n"
1009240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  8: Return(5)\n"
1019240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "BasicBlock 2, pred: 1\n"
1029240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  9: Exit\n";
1039240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1049240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  // Expected difference after constant folding.
1059240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  diff_t expected_cf_diff = {
1069240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    { "  2: IntConstant [5]\n", "  2: IntConstant\n" },
1078d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  10: SuspendCheck\n",   "  10: SuspendCheck\n"
1088d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                "  12: IntConstant [8]\n" },
1098d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  5: Neg(2) [8]\n",      removed },
1109240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    { "  8: Return(5)\n",       "  8: Return(12)\n" }
1119240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  };
1129240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
1139240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1149240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  // Check the value of the computed constant.
1159240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  auto check_after_cf = [](HGraph* graph) {
1168d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction()->InputAt(0);
1179240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    ASSERT_TRUE(inst->IsIntConstant());
1189240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), -1);
1199240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  };
1209240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1219240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  // Expected difference after dead code elimination.
1229240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  diff_t expected_dce_diff = {
1239240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    { "  2: IntConstant\n", removed },
1249240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  };
1259240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
1269240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1279240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  TestCode(data,
1289240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           expected_before,
1299240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           expected_after_cf,
1309240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           expected_after_dce,
1319240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           check_after_cf);
1329240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain}
1339240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1349240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain/**
135556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on addition.
136556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
137556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
138556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
139556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
140556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
141556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
142556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1            2.      add-int v2, v0, v1
143556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                4.      return v2
144556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
14575be28332b278cff9039b54bfb228ac72f539cccRoland LevillainTEST(ConstantFolding, IntConstantFoldingOnAddition1) {
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 | 2 << 8, 0 | 1 << 8,
150556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
151556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
152556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
153556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
154556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [9]\n"
155556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [9]\n"
156556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  14: SuspendCheck\n"
157556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Goto 1\n"
158556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
159556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: Add(3, 5) [12]\n"
160556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Return(9)\n"
161556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
162556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  13: Exit\n";
163556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
16475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
16575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
166556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n", "  3: IntConstant\n" },
167556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n", "  5: IntConstant\n" },
1688d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  14: SuspendCheck\n",   "  14: SuspendCheck\n"
1698d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                "  16: IntConstant [12]\n" },
1708d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: Add(3, 5) [12]\n",  removed },
171556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  12: Return(9)\n",      "  12: Return(16)\n" }
172556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
17375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
174556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
17593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
17675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
1778d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction()->InputAt(0);
17893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
17993445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 3);
18093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
18193445689c714e53cabf347da4321ecf3023e926cRoland Levillain
182556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
183556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
184556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n", removed },
185556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n", removed }
186556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
18775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
188556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
18993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
19093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
19175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
19293445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
19375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
194556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
195556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
196556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
197556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Small three-register program exercising int constant folding on addition.
198556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
199556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
200556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
201556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
202556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
203556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
204556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- v0 + v1            2.      add-int/2addr v0, v1
2058d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v1 <- 4                  3.      const/4 v1, #+4
2068d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v2 <- 5                  4.      const/4 v2, #+5
207556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- v1 + v2            5.      add-int/2addr v1, v2
208556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1            6.      add-int v2, v0, v1
209556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                8.      return v2
210556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
21175be28332b278cff9039b54bfb228ac72f539cccRoland LevillainTEST(ConstantFolding, IntConstantFoldingOnAddition2) {
212556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
213556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
214556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
215556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_2ADDR | 0 << 8 | 1 << 12,
2168d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 1 << 8 | 4 << 12,
2178d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 2 << 8 | 5 << 12,
218556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_2ADDR | 1 << 8 | 2 << 12,
219556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
220556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
221556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
222556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
223556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
224556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [9]\n"
225556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [9]\n"
226556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  11: IntConstant [17]\n"
227556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  13: IntConstant [17]\n"
228556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  26: SuspendCheck\n"
229556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  27: Goto 1\n"
230556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
231556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: Add(3, 5) [21]\n"
232556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: Add(11, 13) [21]\n"
233556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  21: Add(9, 17) [24]\n"
234556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  24: Return(21)\n"
235556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
236556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  25: Exit\n";
237556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
23875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
23975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
240556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n",   "  3: IntConstant\n" },
241556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n",   "  5: IntConstant\n" },
242556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  11: IntConstant [17]\n", "  11: IntConstant\n" },
243556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant [17]\n", "  13: IntConstant\n" },
2448d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  26: SuspendCheck\n",     "  26: SuspendCheck\n"
2458d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  28: IntConstant\n"
2468d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  29: IntConstant\n"
2478d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  30: IntConstant [24]\n" },
2488d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: Add(3, 5) [21]\n",    removed },
2498d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  17: Add(11, 13) [21]\n", removed },
2508d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  21: Add(9, 17) [24]\n",  removed  },
251556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  24: Return(21)\n",       "  24: Return(30)\n" }
252556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
25375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
254556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
25593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
25675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
2578d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst1 = graph->GetBlock(1)->GetFirstInstruction()->InputAt(0);
25893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst1->IsIntConstant());
2598d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 12);
2608d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst2 = inst1->GetPrevious();
26193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst2->IsIntConstant());
2628d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 9);
2638d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst3 = inst2->GetPrevious();
26493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst3->IsIntConstant());
2658d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 3);
26693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
26793445689c714e53cabf347da4321ecf3023e926cRoland Levillain
268556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
269556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
270556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n",  removed },
271556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n",  removed },
272556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  11: IntConstant\n", removed },
273556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant\n", removed },
274556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  28: IntConstant\n", removed },
275556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  29: IntConstant\n", removed }
276556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
27775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
278556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
27993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
28093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
28175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
28293445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
28375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
284556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
285556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
286556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
287556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on subtraction.
288556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
289556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
290556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
291556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
292556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 3                  0.      const/4 v0, #+3
293556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
294556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 - v1            2.      sub-int v2, v0, v1
295556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                4.      return v2
296556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
29775be28332b278cff9039b54bfb228ac72f539cccRoland LevillainTEST(ConstantFolding, IntConstantFoldingOnSubtraction) {
298556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
299556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 3 << 12,
300556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
301556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::SUB_INT | 2 << 8, 0 | 1 << 8,
302556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
303556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
304556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
305556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
306556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [9]\n"
307556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [9]\n"
308556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  14: SuspendCheck\n"
309556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Goto 1\n"
310556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
311556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: Sub(3, 5) [12]\n"
312556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Return(9)\n"
313556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
314556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  13: Exit\n";
315556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
31675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
31775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
318556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n", "  3: IntConstant\n" },
319556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n", "  5: IntConstant\n" },
3208d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  14: SuspendCheck\n",   "  14: SuspendCheck\n"
3218d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                "  16: IntConstant [12]\n" },
3228d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: Sub(3, 5) [12]\n",  removed },
323556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  12: Return(9)\n",      "  12: Return(16)\n" }
324556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
32575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
326556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
32793445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
32875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
3298d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction()->InputAt(0);
33093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
33193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
33293445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
33393445689c714e53cabf347da4321ecf3023e926cRoland Levillain
334556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
335556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
336556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n", removed },
337556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n", removed }
338556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
33975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
340556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
34193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
34293445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
34375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
34493445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
34575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
346556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
347556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
348556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
349556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding
350556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on addition.
351556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
352556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
353556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
354556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
355556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v0, v1) <- 1            0.      const-wide/16 v0, #+1
356556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v2, v3) <- 2            2.      const-wide/16 v2, #+2
357556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v4, v5) <-
358556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *       (v0, v1) + (v1, v2)    4.      add-long v4, v0, v2
359556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return (v4, v5)          6.      return-wide v4
360556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
36175be28332b278cff9039b54bfb228ac72f539cccRoland LevillainTEST(ConstantFolding, LongConstantFoldingOnAddition) {
362556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
363556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 0 << 8, 1,
364556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 2 << 8, 2,
365556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_LONG | 4 << 8, 0 | 2 << 8,
366556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_WIDE | 4 << 8);
367556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
368556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
369556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
370556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  6: LongConstant [12]\n"
371556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  8: LongConstant [12]\n"
372556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: SuspendCheck\n"
373556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  18: Goto 1\n"
374556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
375556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Add(6, 8) [15]\n"
376556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Return(12)\n"
377556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
378556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  16: Exit\n";
379556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
38075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
38175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
382556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant [12]\n", "  6: LongConstant\n" },
383556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant [12]\n", "  8: LongConstant\n" },
3848d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  17: SuspendCheck\n",     "  17: SuspendCheck\n"
3858d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  19: LongConstant [15]\n" },
3868d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  12: Add(6, 8) [15]\n",   removed },
387556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  15: Return(12)\n",       "  15: Return(19)\n" }
388556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
38975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
390556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
39193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
39275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
3938d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction()->InputAt(0);
39493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsLongConstant());
39593445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), 3);
39693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
39793445689c714e53cabf347da4321ecf3023e926cRoland Levillain
398556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
399556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
400556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant\n", removed },
401556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant\n", removed }
402556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
40375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
404556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
40593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
40693445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
40775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
40893445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
40975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf,
41093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           Primitive::kPrimLong);
411556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
412556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
413556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
414556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding
415556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on subtraction.
416556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
417556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
418556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
419556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
420556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v0, v1) <- 3            0.      const-wide/16 v0, #+3
421556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v2, v3) <- 2            2.      const-wide/16 v2, #+2
422556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v4, v5) <-
423556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *       (v0, v1) - (v1, v2)    4.      sub-long v4, v0, v2
424556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return (v4, v5)          6.      return-wide v4
425556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
42675be28332b278cff9039b54bfb228ac72f539cccRoland LevillainTEST(ConstantFolding, LongConstantFoldingOnSubtraction) {
427556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
428556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 0 << 8, 3,
429556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 2 << 8, 2,
430556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::SUB_LONG | 4 << 8, 0 | 2 << 8,
431556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_WIDE | 4 << 8);
432556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
433556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
434556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
435556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  6: LongConstant [12]\n"
436556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  8: LongConstant [12]\n"
437556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: SuspendCheck\n"
438556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  18: Goto 1\n"
439556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
440556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Sub(6, 8) [15]\n"
441556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Return(12)\n"
442556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
443556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  16: Exit\n";
444556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
44575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
44675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
447556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant [12]\n", "  6: LongConstant\n" },
448556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant [12]\n", "  8: LongConstant\n" },
4498d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  17: SuspendCheck\n",     "  17: SuspendCheck\n"
4508d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  19: LongConstant [15]\n" },
4518d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  12: Sub(6, 8) [15]\n",   removed },
452556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  15: Return(12)\n",       "  15: Return(19)\n" }
453556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
45475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
455556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
45693445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
45775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
4588d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction()->InputAt(0);
45993445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsLongConstant());
46093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), 1);
46193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
46293445689c714e53cabf347da4321ecf3023e926cRoland Levillain
463556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
464556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
465556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant\n", removed },
466556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant\n", removed }
467556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
46875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
469556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
47093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
47193445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
47275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
47393445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
47475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf,
47593445689c714e53cabf347da4321ecf3023e926cRoland Levillain           Primitive::kPrimLong);
476556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
477556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
478556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
479556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with jumps leading to the creation of many
480556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * blocks.
481556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
482556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * The intent of this test is to ensure that all constant expressions
483556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * are actually evaluated at compile-time, thanks to the reverse
484556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (forward) post-order traversal of the the dominator tree.
485556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
486556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
487556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
488556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
4898d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v0 <- 1                   0.     const/4 v0, #+1
4908d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v1 <- 2                   1.     const/4 v1, #+2
491556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1             2.     add-int v2, v0, v1
492556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L2                   4.     goto +4
4938d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil * L1: v1 <- v0 + 5              5.     add-int/lit16 v1, v0, #+5
494556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L3                   7.     goto +4
4958d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil * L2: v0 <- v2 + 4              8.     add-int/lit16 v0, v2, #+4
496556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L1                  10.     goto +(-5)
4978d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil * L3: v2 <- v1 + 8             11.     add-int/lit16 v2, v1, #+8
498556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                13.     return v2
499556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
50075be28332b278cff9039b54bfb228ac72f539cccRoland LevillainTEST(ConstantFolding, IntConstantFoldingAndJumps) {
501556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
5028d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 0 << 8 | 1 << 12,
5038d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 1 << 8 | 2 << 12,
504556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
505556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::GOTO | 4 << 8,
5068d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::ADD_INT_LIT16 | 1 << 8 | 0 << 12, 5,
507556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::GOTO | 4 << 8,
5088d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::ADD_INT_LIT16 | 0 << 8 | 2 << 12, 4,
509556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    static_cast<uint16_t>(Instruction::GOTO | -5 << 8),
5108d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::ADD_INT_LIT16 | 2 << 8 | 1 << 12, 8,
511556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
512556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
513556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
514556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
5158d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  3: IntConstant [9]\n"            // v0 <- 1
5168d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  5: IntConstant [9]\n"            // v1 <- 2
5178d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  13: IntConstant [14]\n"          // const 5
5188d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  18: IntConstant [19]\n"          // const 4
5198d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  24: IntConstant [25]\n"          // const 8
520556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  30: SuspendCheck\n"
521556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  31: Goto 1\n"
522556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 3\n"
5238d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  9: Add(3, 5) [19]\n"             // v2 <- v0 + v1 = 1 + 2 = 3
52493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  11: Goto 3\n"                    // goto L2
52593445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "BasicBlock 2, pred: 3, succ: 4\n"  // L1:
5268d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  14: Add(19, 13) [25]\n"          // v1 <- v0 + 3 = 7 + 5 = 12
52793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  16: Goto 4\n"                    // goto L3
52893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "BasicBlock 3, pred: 1, succ: 2\n"  // L2:
5298d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  19: Add(9, 18) [14]\n"           // v0 <- v2 + 2 = 3 + 4 = 7
530556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  21: SuspendCheck\n"
53193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  22: Goto 2\n"                    // goto L1
53293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "BasicBlock 4, pred: 2, succ: 5\n"  // L3:
5338d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  25: Add(14, 24) [28]\n"          // v2 <- v1 + 4 = 12 + 8 = 20
53493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  28: Return(25)\n"                // return v2
535556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 5, pred: 4\n"
536556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  29: Exit\n";
537556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
53875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
53975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
540556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n",   "  3: IntConstant\n" },
541556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n",   "  5: IntConstant []\n" },
542556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant [14]\n", "  13: IntConstant\n" },
543556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  18: IntConstant [19]\n", "  18: IntConstant\n" },
544556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  24: IntConstant [25]\n", "  24: IntConstant\n" },
5458d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  30: SuspendCheck\n",     "  30: SuspendCheck\n"
5468d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  32: IntConstant []\n"
5478d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  33: IntConstant []\n"
5488d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  34: IntConstant\n"
5498d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  35: IntConstant [28]\n" },
5508d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: Add(3, 5) [19]\n",    removed },
5518d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  14: Add(19, 13) [25]\n", removed },
5528d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  19: Add(9, 18) [14]\n",  removed },
5538d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  25: Add(14, 24) [28]\n", removed },
554556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  28: Return(25)\n",       "  28: Return(35)\n"}
555556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
55675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
557556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
55893445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
55975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
5608d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst1 = graph->GetBlock(4)->GetFirstInstruction()->InputAt(0);
56193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst1->IsIntConstant());
5628d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 20);
5638d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst2 = inst1->GetPrevious();
56493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst2->IsIntConstant());
5658d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 12);
5668d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst3 = inst2->GetPrevious();
56793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst3->IsIntConstant());
5688d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 7);
5698d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst4 = inst3->GetPrevious();
57093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst4->IsIntConstant());
5718d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst4->AsIntConstant()->GetValue(), 3);
57293445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
57393445689c714e53cabf347da4321ecf3023e926cRoland Levillain
574556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
575556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
576556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n",     removed },
577556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant\n",    removed },
578556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  18: IntConstant\n",    removed },
579556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  24: IntConstant\n",    removed },
580556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  34: IntConstant\n",    removed },
581556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
58275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
583556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
58493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
58593445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
58675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
58793445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
58875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
589556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
590556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
591556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
592556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
593556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with a constant (static) condition.
594556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
595556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
596556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
597556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
598556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 1                  0.      const/4 v1, #+1
599556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 0                  1.      const/4 v0, #+0
600556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     if v1 >= 0 goto L1       2.      if-gez v1, +3
601556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- v1                 4.      move v0, v1
602556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L1: v2 <- v0 + v1            5.      add-int v2, v0, v1
603556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return-void              7.      return
604556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
60575be28332b278cff9039b54bfb228ac72f539cccRoland LevillainTEST(ConstantFolding, ConstantCondition) {
606556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
607556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 1 << 12,
608556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 0 << 12,
609556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::IF_GEZ | 1 << 8, 3,
610556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::MOVE | 0 << 8 | 1 << 12,
611556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
612556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_VOID);
613556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
614556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
615556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
616556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [15, 22, 8]\n"
617556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [22, 8]\n"
618556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  19: SuspendCheck\n"
619556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  20: Goto 1\n"
620556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 5, 2\n"
621556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  8: GreaterThanOrEqual(3, 5) [9]\n"
622556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: If(8)\n"
623556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1, succ: 3\n"
624556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Goto 3\n"
625556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 3, pred: 2, 5, succ: 4\n"
626556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  22: Phi(3, 5) [15]\n"
627556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Add(22, 3)\n"
628556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: ReturnVoid\n"
629556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 4, pred: 3\n"
630556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  18: Exit\n"
631556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 5, pred: 1, succ: 3\n"
632556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  21: Goto 3\n";
633556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
63475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
63575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
6368d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  3: IntConstant [15, 22, 8]\n",      "  3: IntConstant [9, 15, 22]\n" },
637556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [22, 8]\n",          "  5: IntConstant [22]\n" },
6388d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  8: GreaterThanOrEqual(3, 5) [9]\n", removed },
6398d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: If(8)\n",                        "  9: If(3)\n" }
640556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
64175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
642556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
64393445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
64475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
6458d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst = graph->GetBlock(1)->GetFirstInstruction()->InputAt(0);
64693445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
64793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
64893445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
64993445689c714e53cabf347da4321ecf3023e926cRoland Levillain
650556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
651556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
6528d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  3: IntConstant [9, 15, 22]\n", "  3: IntConstant [9, 22]\n" },
6538d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  22: Phi(3, 5) [15]\n",         "  22: Phi(3, 5)\n" },
6548d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  15: Add(22, 3)\n",             removed }
655556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
65675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
657556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
65893445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
65993445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
66075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
66193445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
66275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
663556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
664556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
665556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}  // namespace art
666