constant_folding_test.cc revision 96709f17347cb7a6aae15816244d2200ca95a649
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
3296709f17347cb7a6aae15816244d2200ca95a649Aart Bik/**
3396709f17347cb7a6aae15816244d2200ca95a649Aart Bik * Fixture class for the constant folding and dce tests.
3496709f17347cb7a6aae15816244d2200ca95a649Aart Bik */
3596709f17347cb7a6aae15816244d2200ca95a649Aart Bikclass ConstantFoldingTest : public testing::Test {
3696709f17347cb7a6aae15816244d2200ca95a649Aart Bik public:
3796709f17347cb7a6aae15816244d2200ca95a649Aart Bik  ConstantFoldingTest() : pool_(), allocator_(&pool_) {
3896709f17347cb7a6aae15816244d2200ca95a649Aart Bik    graph_ = CreateGraph(&allocator_);
3996709f17347cb7a6aae15816244d2200ca95a649Aart Bik  }
4096709f17347cb7a6aae15816244d2200ca95a649Aart Bik
4196709f17347cb7a6aae15816244d2200ca95a649Aart Bik  void TestCode(const uint16_t* data,
4296709f17347cb7a6aae15816244d2200ca95a649Aart Bik                const std::string& expected_before,
4396709f17347cb7a6aae15816244d2200ca95a649Aart Bik                const std::string& expected_after_cf,
4496709f17347cb7a6aae15816244d2200ca95a649Aart Bik                const std::string& expected_after_dce,
4596709f17347cb7a6aae15816244d2200ca95a649Aart Bik                std::function<void(HGraph*)> check_after_cf,
4696709f17347cb7a6aae15816244d2200ca95a649Aart Bik                Primitive::Type return_type = Primitive::kPrimInt) {
4796709f17347cb7a6aae15816244d2200ca95a649Aart Bik    graph_ = CreateCFG(&allocator_, data, return_type);
4896709f17347cb7a6aae15816244d2200ca95a649Aart Bik    TestCodeOnReadyGraph(expected_before,
4996709f17347cb7a6aae15816244d2200ca95a649Aart Bik                         expected_after_cf,
5096709f17347cb7a6aae15816244d2200ca95a649Aart Bik                         expected_after_dce,
5196709f17347cb7a6aae15816244d2200ca95a649Aart Bik                         check_after_cf);
5296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  }
5396709f17347cb7a6aae15816244d2200ca95a649Aart Bik
5496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  void TestCodeOnReadyGraph(const std::string& expected_before,
5596709f17347cb7a6aae15816244d2200ca95a649Aart Bik                            const std::string& expected_after_cf,
5696709f17347cb7a6aae15816244d2200ca95a649Aart Bik                            const std::string& expected_after_dce,
5796709f17347cb7a6aae15816244d2200ca95a649Aart Bik                            std::function<void(HGraph*)> check_after_cf) {
5896709f17347cb7a6aae15816244d2200ca95a649Aart Bik    ASSERT_NE(graph_, nullptr);
5996709f17347cb7a6aae15816244d2200ca95a649Aart Bik    graph_->TryBuildingSsa();
6096709f17347cb7a6aae15816244d2200ca95a649Aart Bik
6196709f17347cb7a6aae15816244d2200ca95a649Aart Bik    StringPrettyPrinter printer_before(graph_);
6296709f17347cb7a6aae15816244d2200ca95a649Aart Bik    printer_before.VisitInsertionOrder();
6396709f17347cb7a6aae15816244d2200ca95a649Aart Bik    std::string actual_before = printer_before.str();
6496709f17347cb7a6aae15816244d2200ca95a649Aart Bik    EXPECT_EQ(expected_before, actual_before);
6596709f17347cb7a6aae15816244d2200ca95a649Aart Bik
6696709f17347cb7a6aae15816244d2200ca95a649Aart Bik    std::unique_ptr<const X86InstructionSetFeatures> features_x86(
6796709f17347cb7a6aae15816244d2200ca95a649Aart Bik        X86InstructionSetFeatures::FromCppDefines());
6896709f17347cb7a6aae15816244d2200ca95a649Aart Bik    x86::CodeGeneratorX86 codegenX86(graph_, *features_x86.get(), CompilerOptions());
6996709f17347cb7a6aae15816244d2200ca95a649Aart Bik    HConstantFolding(graph_).Run();
7096709f17347cb7a6aae15816244d2200ca95a649Aart Bik    SSAChecker ssa_checker_cf(graph_);
7196709f17347cb7a6aae15816244d2200ca95a649Aart Bik    ssa_checker_cf.Run();
7296709f17347cb7a6aae15816244d2200ca95a649Aart Bik    ASSERT_TRUE(ssa_checker_cf.IsValid());
7396709f17347cb7a6aae15816244d2200ca95a649Aart Bik
7496709f17347cb7a6aae15816244d2200ca95a649Aart Bik    StringPrettyPrinter printer_after_cf(graph_);
7596709f17347cb7a6aae15816244d2200ca95a649Aart Bik    printer_after_cf.VisitInsertionOrder();
7696709f17347cb7a6aae15816244d2200ca95a649Aart Bik    std::string actual_after_cf = printer_after_cf.str();
7796709f17347cb7a6aae15816244d2200ca95a649Aart Bik    EXPECT_EQ(expected_after_cf, actual_after_cf);
7896709f17347cb7a6aae15816244d2200ca95a649Aart Bik
7996709f17347cb7a6aae15816244d2200ca95a649Aart Bik    check_after_cf(graph_);
8096709f17347cb7a6aae15816244d2200ca95a649Aart Bik
8196709f17347cb7a6aae15816244d2200ca95a649Aart Bik    HDeadCodeElimination(graph_).Run();
8296709f17347cb7a6aae15816244d2200ca95a649Aart Bik    SSAChecker ssa_checker_dce(graph_);
8396709f17347cb7a6aae15816244d2200ca95a649Aart Bik    ssa_checker_dce.Run();
8496709f17347cb7a6aae15816244d2200ca95a649Aart Bik    ASSERT_TRUE(ssa_checker_dce.IsValid());
8596709f17347cb7a6aae15816244d2200ca95a649Aart Bik
8696709f17347cb7a6aae15816244d2200ca95a649Aart Bik    StringPrettyPrinter printer_after_dce(graph_);
8796709f17347cb7a6aae15816244d2200ca95a649Aart Bik    printer_after_dce.VisitInsertionOrder();
8896709f17347cb7a6aae15816244d2200ca95a649Aart Bik    std::string actual_after_dce = printer_after_dce.str();
8996709f17347cb7a6aae15816244d2200ca95a649Aart Bik    EXPECT_EQ(expected_after_dce, actual_after_dce);
9096709f17347cb7a6aae15816244d2200ca95a649Aart Bik  }
9196709f17347cb7a6aae15816244d2200ca95a649Aart Bik
9296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  ArenaPool pool_;
9396709f17347cb7a6aae15816244d2200ca95a649Aart Bik  ArenaAllocator allocator_;
9496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HGraph* graph_;
9596709f17347cb7a6aae15816244d2200ca95a649Aart Bik};
96556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
97556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
989240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain * Tiny three-register program exercising int constant folding on negation.
999240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *
1009240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *                              16-bit
1019240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *                              offset
1029240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *                              ------
1039240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
104c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *     v1 <- -v0                1.      neg-int v1, v0
1059240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain *     return v1                2.      return v1
1069240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain */
10796709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingNegation) {
1089240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  const uint16_t data[] = TWO_REGISTERS_CODE_ITEM(
1099240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
1109240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    Instruction::NEG_INT | 1 << 8 | 0 << 12,
1119240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    Instruction::RETURN | 1 << 8);
1129240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1139240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  std::string expected_before =
1149240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "BasicBlock 0, succ: 1\n"
1159240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  2: IntConstant [5]\n"
1169240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  10: SuspendCheck\n"
1179240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  11: Goto 1\n"
1189240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "BasicBlock 1, pred: 0, succ: 2\n"
1199240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  5: Neg(2) [8]\n"
1209240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  8: Return(5)\n"
1219240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "BasicBlock 2, pred: 1\n"
1229240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain      "  9: Exit\n";
1239240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1249240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  // Expected difference after constant folding.
1259240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  diff_t expected_cf_diff = {
1269240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    { "  2: IntConstant [5]\n", "  2: IntConstant\n" },
1278d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  10: SuspendCheck\n",   "  10: SuspendCheck\n"
1288d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                "  12: IntConstant [8]\n" },
1298d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  5: Neg(2) [8]\n",      removed },
1309240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    { "  8: Return(5)\n",       "  8: Return(12)\n" }
1319240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  };
1329240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
1339240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1349240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  // Check the value of the computed constant.
1359240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  auto check_after_cf = [](HGraph* graph) {
136ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
1379240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    ASSERT_TRUE(inst->IsIntConstant());
1389240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), -1);
1399240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  };
1409240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1419240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  // Expected difference after dead code elimination.
1429240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  diff_t expected_dce_diff = {
1439240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain    { "  2: IntConstant\n", removed },
1449240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  };
1459240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
1469240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1479240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain  TestCode(data,
1489240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           expected_before,
1499240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           expected_after_cf,
1509240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           expected_after_dce,
1519240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain           check_after_cf);
1529240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain}
1539240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain
1549240d6a2baa9ed1e18ee08744b461fe49a1ee269Roland Levillain/**
155c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain * Tiny three-register program exercising long constant folding on negation.
156c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *
157c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *                              16-bit
158c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *                              offset
159c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *                              ------
160c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *     (v0, v1) <- 4294967296   0.      const-wide v0 #+4294967296
161c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *     (v2, v3) <- -(v0, v1)    1.      neg-long v2, v0
162c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain *     return (v2, v3)          2.      return-wide v2
163c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain */
16496709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, LongConstantFoldingNegation) {
165c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const int64_t input = INT64_C(4294967296);             // 2^32
166c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t word0 = Low16Bits(Low32Bits(input));    // LSW.
167c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t word1 = High16Bits(Low32Bits(input));
168c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t word2 = Low16Bits(High32Bits(input));
169c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t word3 = High16Bits(High32Bits(input));  // MSW.
170c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  const uint16_t data[] = FOUR_REGISTERS_CODE_ITEM(
171c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    Instruction::CONST_WIDE | 0 << 8, word0, word1, word2, word3,
172c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    Instruction::NEG_LONG | 2 << 8 | 0 << 12,
173c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    Instruction::RETURN_WIDE | 2 << 8);
174c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
175c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  std::string expected_before =
176c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "BasicBlock 0, succ: 1\n"
177c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "  4: LongConstant [7]\n"
178c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "  12: SuspendCheck\n"
179c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "  13: Goto 1\n"
180c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "BasicBlock 1, pred: 0, succ: 2\n"
181c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "  7: Neg(4) [10]\n"
182c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "  10: Return(7)\n"
183c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "BasicBlock 2, pred: 1\n"
184c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain      "  11: Exit\n";
185c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
186c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  // Expected difference after constant folding.
187c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  diff_t expected_cf_diff = {
188c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    { "  4: LongConstant [7]\n", "  4: LongConstant\n" },
189c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    { "  12: SuspendCheck\n",    "  12: SuspendCheck\n"
190c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain                                 "  14: LongConstant [10]\n" },
191c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    { "  7: Neg(4) [10]\n",      removed },
192c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    { "  10: Return(7)\n",       "  10: Return(14)\n" }
193c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  };
194c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
195c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
196c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  // Check the value of the computed constant.
197c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  auto check_after_cf = [](HGraph* graph) {
198ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
199c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    ASSERT_TRUE(inst->IsLongConstant());
200c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), INT64_C(-4294967296));
201c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  };
202c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
203c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  // Expected difference after dead code elimination.
204c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  diff_t expected_dce_diff = {
205c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain    { "  4: LongConstant\n", removed },
206c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  };
207c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
208c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
209c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain  TestCode(data,
210c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           expected_before,
211c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           expected_after_cf,
212c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           expected_after_dce,
213c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           check_after_cf,
214c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain           Primitive::kPrimLong);
215c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain}
216c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain
217c90bc7c07f9bd24b5424cfb1e3f064fbae5334d6Roland Levillain/**
218556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on addition.
219556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
220556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
221556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
222556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
223556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
224556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
225556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1            2.      add-int v2, v0, v1
226556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                4.      return v2
227556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
22896709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingOnAddition1) {
229556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
230556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
231556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
232556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
233556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
234556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
235556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
236556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
237556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [9]\n"
238556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [9]\n"
239556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  14: SuspendCheck\n"
240556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Goto 1\n"
241556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
242556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: Add(3, 5) [12]\n"
243556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Return(9)\n"
244556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
245556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  13: Exit\n";
246556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
24775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
24875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
249556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n", "  3: IntConstant\n" },
250556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n", "  5: IntConstant\n" },
2518d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  14: SuspendCheck\n",   "  14: SuspendCheck\n"
2528d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                "  16: IntConstant [12]\n" },
2538d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: Add(3, 5) [12]\n",  removed },
254556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  12: Return(9)\n",      "  12: Return(16)\n" }
255556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
25675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
257556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
25893445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
25975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
260ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
26193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
26293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 3);
26393445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
26493445689c714e53cabf347da4321ecf3023e926cRoland Levillain
265556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
266556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
267556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n", removed },
268556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n", removed }
269556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
27075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
271556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
27293445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
27393445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
27475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
27593445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
27675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
277556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
278556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
279556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
280556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Small three-register program exercising int constant folding on addition.
281556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
282556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
283556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
284556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
285556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 1                  0.      const/4 v0, #+1
286556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
287556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- v0 + v1            2.      add-int/2addr v0, v1
2888d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v1 <- 4                  3.      const/4 v1, #+4
2898d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v2 <- 5                  4.      const/4 v2, #+5
290556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- v1 + v2            5.      add-int/2addr v1, v2
291556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1            6.      add-int v2, v0, v1
292556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                8.      return v2
293556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
29496709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingOnAddition2) {
295556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
296556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 1 << 12,
297556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
298556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_2ADDR | 0 << 8 | 1 << 12,
2998d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 1 << 8 | 4 << 12,
3008d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 2 << 8 | 5 << 12,
301556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT_2ADDR | 1 << 8 | 2 << 12,
302556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
303556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
304556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
305556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
306556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
307556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [9]\n"
308556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [9]\n"
309556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  11: IntConstant [17]\n"
310556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  13: IntConstant [17]\n"
311556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  26: SuspendCheck\n"
312556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  27: Goto 1\n"
313556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
314556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: Add(3, 5) [21]\n"
315556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: Add(11, 13) [21]\n"
316556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  21: Add(9, 17) [24]\n"
317556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  24: Return(21)\n"
318556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
319556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  25: Exit\n";
320556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
32175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
32275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
323556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n",   "  3: IntConstant\n" },
324556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n",   "  5: IntConstant\n" },
325556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  11: IntConstant [17]\n", "  11: IntConstant\n" },
326556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant [17]\n", "  13: IntConstant\n" },
3278d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  26: SuspendCheck\n",     "  26: SuspendCheck\n"
3288d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  28: IntConstant\n"
3298d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  29: IntConstant\n"
3308d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  30: IntConstant [24]\n" },
3318d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: Add(3, 5) [21]\n",    removed },
3328d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  17: Add(11, 13) [21]\n", removed },
3338d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  21: Add(9, 17) [24]\n",  removed  },
334556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  24: Return(21)\n",       "  24: Return(30)\n" }
335556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
33675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
337556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
33893445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
33975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
340ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst1 = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
34193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst1->IsIntConstant());
3428d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 12);
3438d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst2 = inst1->GetPrevious();
34493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst2->IsIntConstant());
3458d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 9);
3468d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst3 = inst2->GetPrevious();
34793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst3->IsIntConstant());
3488d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 3);
34993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
35093445689c714e53cabf347da4321ecf3023e926cRoland Levillain
351556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
352556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
353556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n",  removed },
354556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n",  removed },
355556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  11: IntConstant\n", removed },
356556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant\n", removed },
357556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  28: IntConstant\n", removed },
358556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  29: IntConstant\n", removed }
359556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
36075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
361556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
36293445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
36393445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
36475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
36593445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
36675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
367556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
368556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
369556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
370556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register program exercising int constant folding on subtraction.
371556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
372556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
373556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
374556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
375556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 3                  0.      const/4 v0, #+3
376556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 2                  1.      const/4 v1, #+2
377556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 - v1            2.      sub-int v2, v0, v1
378556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                4.      return v2
379556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
38096709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingOnSubtraction) {
381556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
382556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 3 << 12,
383556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 2 << 12,
384556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::SUB_INT | 2 << 8, 0 | 1 << 8,
385556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
386556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
387556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
388556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
389556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [9]\n"
390556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [9]\n"
391556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  14: SuspendCheck\n"
392556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Goto 1\n"
393556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
394556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: Sub(3, 5) [12]\n"
395556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Return(9)\n"
396556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
397556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  13: Exit\n";
398556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
39975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
40075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
401556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n", "  3: IntConstant\n" },
402556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n", "  5: IntConstant\n" },
4038d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  14: SuspendCheck\n",   "  14: SuspendCheck\n"
4048d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                "  16: IntConstant [12]\n" },
4058d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: Sub(3, 5) [12]\n",  removed },
406556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  12: Return(9)\n",      "  12: Return(16)\n" }
407556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
40875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
409556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
41093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
41175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
412ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
41393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
41493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
41593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
41693445689c714e53cabf347da4321ecf3023e926cRoland Levillain
417556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
418556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
419556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant\n", removed },
420556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant\n", removed }
421556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
42275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
423556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
42493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
42593445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
42675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
42793445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
42875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
429556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
430556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
431556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
432556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding
433556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on addition.
434556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
435556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
436556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
437556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
438556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v0, v1) <- 1            0.      const-wide/16 v0, #+1
439556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v2, v3) <- 2            2.      const-wide/16 v2, #+2
440556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v4, v5) <-
441556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *       (v0, v1) + (v1, v2)    4.      add-long v4, v0, v2
442556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return (v4, v5)          6.      return-wide v4
443556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
44496709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, LongConstantFoldingOnAddition) {
445556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
446556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 0 << 8, 1,
447556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 2 << 8, 2,
448556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_LONG | 4 << 8, 0 | 2 << 8,
449556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_WIDE | 4 << 8);
450556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
451556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
452556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
453556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  6: LongConstant [12]\n"
454556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  8: LongConstant [12]\n"
455556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: SuspendCheck\n"
456556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  18: Goto 1\n"
457556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
458556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Add(6, 8) [15]\n"
459556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Return(12)\n"
460556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
461556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  16: Exit\n";
462556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
46375be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
46475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
465556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant [12]\n", "  6: LongConstant\n" },
466556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant [12]\n", "  8: LongConstant\n" },
4678d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  17: SuspendCheck\n",     "  17: SuspendCheck\n"
4688d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  19: LongConstant [15]\n" },
4698d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  12: Add(6, 8) [15]\n",   removed },
470556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  15: Return(12)\n",       "  15: Return(19)\n" }
471556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
47275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
473556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
47493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
47575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
476ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
47793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsLongConstant());
47893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), 3);
47993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
48093445689c714e53cabf347da4321ecf3023e926cRoland Levillain
481556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
482556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
483556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant\n", removed },
484556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant\n", removed }
485556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
48675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
487556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
48893445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
48993445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
49075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
49193445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
49275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf,
49393445689c714e53cabf347da4321ecf3023e926cRoland Levillain           Primitive::kPrimLong);
494556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
495556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
496556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
497556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Tiny three-register-pair program exercising long constant folding
498556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * on subtraction.
499556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
500556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
501556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
502556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
503556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v0, v1) <- 3            0.      const-wide/16 v0, #+3
504556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v2, v3) <- 2            2.      const-wide/16 v2, #+2
505556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     (v4, v5) <-
506556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *       (v0, v1) - (v1, v2)    4.      sub-long v4, v0, v2
507556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return (v4, v5)          6.      return-wide v4
508556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
50996709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, LongConstantFoldingOnSubtraction) {
510556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = SIX_REGISTERS_CODE_ITEM(
511556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 0 << 8, 3,
512556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_WIDE_16 | 2 << 8, 2,
513556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::SUB_LONG | 4 << 8, 0 | 2 << 8,
514556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_WIDE | 4 << 8);
515556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
516556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
517556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
518556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  6: LongConstant [12]\n"
519556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  8: LongConstant [12]\n"
520556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: SuspendCheck\n"
521556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  18: Goto 1\n"
522556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 2\n"
523556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Sub(6, 8) [15]\n"
524556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Return(12)\n"
525556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1\n"
526556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  16: Exit\n";
527556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
52875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
52975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
530556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant [12]\n", "  6: LongConstant\n" },
531556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant [12]\n", "  8: LongConstant\n" },
5328d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  17: SuspendCheck\n",     "  17: SuspendCheck\n"
5338d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  19: LongConstant [15]\n" },
5348d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  12: Sub(6, 8) [15]\n",   removed },
535556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  15: Return(12)\n",       "  15: Return(19)\n" }
536556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
53775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
538556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
53993445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the value of the computed constant.
54075be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
541ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
54293445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsLongConstant());
54393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsLongConstant()->GetValue(), 1);
54493445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
54593445689c714e53cabf347da4321ecf3023e926cRoland Levillain
546556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
547556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  diff_t expected_dce_diff = {
548556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  6: LongConstant\n", removed },
549556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  8: LongConstant\n", removed }
550556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
55175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_dce = Patch(expected_after_cf, expected_dce_diff);
552556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
55393445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
55493445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
55575be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
55693445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
55775be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf,
55893445689c714e53cabf347da4321ecf3023e926cRoland Levillain           Primitive::kPrimLong);
559556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
560556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
561556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
562556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with jumps leading to the creation of many
563556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * blocks.
564556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
565556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * The intent of this test is to ensure that all constant expressions
566556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * are actually evaluated at compile-time, thanks to the reverse
567556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * (forward) post-order traversal of the the dominator tree.
568556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
569556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
570556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
571556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
5728d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v0 <- 1                   0.     const/4 v0, #+1
5738d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil *     v1 <- 2                   1.     const/4 v1, #+2
574556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v2 <- v0 + v1             2.     add-int v2, v0, v1
575556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L2                   4.     goto +4
5768d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil * L1: v1 <- v0 + 5              5.     add-int/lit16 v1, v0, #+5
577556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L3                   7.     goto +4
5788d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil * L2: v0 <- v2 + 4              8.     add-int/lit16 v0, v2, #+4
579556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     goto L1                  10.     goto +(-5)
5808d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil * L3: v2 <- v1 + 8             11.     add-int/lit16 v2, v1, #+8
581556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return v2                13.     return v2
582556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
58396709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, IntConstantFoldingAndJumps) {
584556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
5858d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 0 << 8 | 1 << 12,
5868d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::CONST_4 | 1 << 8 | 2 << 12,
587556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
588556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::GOTO | 4 << 8,
5898d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::ADD_INT_LIT16 | 1 << 8 | 0 << 12, 5,
590556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::GOTO | 4 << 8,
5918d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::ADD_INT_LIT16 | 0 << 8 | 2 << 12, 4,
59258554b7de4b437ddef7ff550e62c8ec0b16f9264Andreas Gampe    static_cast<uint16_t>(Instruction::GOTO | 0xFFFFFFFB << 8),
5938d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    Instruction::ADD_INT_LIT16 | 2 << 8 | 1 << 12, 8,
594556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN | 2 << 8);
595556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
596556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
597556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
5988d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  3: IntConstant [9]\n"            // v0 <- 1
5998d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  5: IntConstant [9]\n"            // v1 <- 2
6008d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  13: IntConstant [14]\n"          // const 5
6018d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  18: IntConstant [19]\n"          // const 4
6028d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  24: IntConstant [25]\n"          // const 8
603556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  30: SuspendCheck\n"
604556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  31: Goto 1\n"
605556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 3\n"
6068d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  9: Add(3, 5) [19]\n"             // v2 <- v0 + v1 = 1 + 2 = 3
60793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  11: Goto 3\n"                    // goto L2
60893445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "BasicBlock 2, pred: 3, succ: 4\n"  // L1:
6098d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  14: Add(19, 13) [25]\n"          // v1 <- v0 + 3 = 7 + 5 = 12
61093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  16: Goto 4\n"                    // goto L3
61193445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "BasicBlock 3, pred: 1, succ: 2\n"  // L2:
6128d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  19: Add(9, 18) [14]\n"           // v0 <- v2 + 2 = 3 + 4 = 7
613556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  21: SuspendCheck\n"
61493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  22: Goto 2\n"                    // goto L1
61593445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "BasicBlock 4, pred: 2, succ: 5\n"  // L3:
6168d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    "  25: Add(14, 24) [28]\n"          // v2 <- v1 + 4 = 12 + 8 = 20
61793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    "  28: Return(25)\n"                // return v2
618556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 5, pred: 4\n"
619556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  29: Exit\n";
620556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
62175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
62275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
623556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  3: IntConstant [9]\n",   "  3: IntConstant\n" },
624556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [9]\n",   "  5: IntConstant []\n" },
625556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  13: IntConstant [14]\n", "  13: IntConstant\n" },
626556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  18: IntConstant [19]\n", "  18: IntConstant\n" },
627556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  24: IntConstant [25]\n", "  24: IntConstant\n" },
6288d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  30: SuspendCheck\n",     "  30: SuspendCheck\n"
6298d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  32: IntConstant []\n"
6308d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  33: IntConstant []\n"
6318d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  34: IntConstant\n"
6328d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil                                  "  35: IntConstant [28]\n" },
6338d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: Add(3, 5) [19]\n",    removed },
6348d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  14: Add(19, 13) [25]\n", removed },
6358d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  19: Add(9, 18) [14]\n",  removed },
6368d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  25: Add(14, 24) [28]\n", removed },
637556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  28: Return(25)\n",       "  28: Return(35)\n"}
638556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
63975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
640556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
64193445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
64275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
643ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst1 = graph->GetBlocks()[4]->GetFirstInstruction()->InputAt(0);
64493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst1->IsIntConstant());
6458d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst1->AsIntConstant()->GetValue(), 20);
6468d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst2 = inst1->GetPrevious();
64793445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst2->IsIntConstant());
6488d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst2->AsIntConstant()->GetValue(), 12);
6498d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst3 = inst2->GetPrevious();
65093445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst3->IsIntConstant());
6518d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst3->AsIntConstant()->GetValue(), 7);
6528d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    HInstruction* inst4 = inst3->GetPrevious();
65393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst4->IsIntConstant());
6548d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    ASSERT_EQ(inst4->AsIntConstant()->GetValue(), 3);
65593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
65693445689c714e53cabf347da4321ecf3023e926cRoland Levillain
657556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  // Expected difference after dead code elimination.
6581c533c17baff841e383a539fdd3c0a65135181b0David Brazdil  std::string expected_after_dce =
6591c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "BasicBlock 0, succ: 1\n"
6601c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  5: IntConstant []\n"
6611c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  30: SuspendCheck\n"
6621c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  32: IntConstant []\n"
6631c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  33: IntConstant []\n"
6641c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  35: IntConstant [28]\n"
6651c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  31: Goto 1\n"
6661c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "BasicBlock 1, pred: 0, succ: 5\n"
6671c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  21: SuspendCheck\n"
6681c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  28: Return(35)\n"
6691c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "BasicBlock 5, pred: 1\n"
6701c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  29: Exit\n";
671556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
67293445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
67393445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
67475be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
67593445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
67675be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
677556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
678556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
679556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain/**
680556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * Three-register program with a constant (static) condition.
681556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *
682556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              16-bit
683556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              offset
684556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *                              ------
685556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v1 <- 1                  0.      const/4 v1, #+1
686556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- 0                  1.      const/4 v0, #+0
687556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     if v1 >= 0 goto L1       2.      if-gez v1, +3
688556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     v0 <- v1                 4.      move v0, v1
689556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain * L1: v2 <- v0 + v1            5.      add-int v2, v0, v1
690556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain *     return-void              7.      return
691556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain */
69296709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, ConstantCondition) {
693556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  const uint16_t data[] = THREE_REGISTERS_CODE_ITEM(
694556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 1 << 8 | 1 << 12,
695556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::CONST_4 | 0 << 8 | 0 << 12,
696556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::IF_GEZ | 1 << 8, 3,
697556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::MOVE | 0 << 8 | 1 << 12,
698556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::ADD_INT | 2 << 8, 0 | 1 << 8,
699556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    Instruction::RETURN_VOID);
700556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
701556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  std::string expected_before =
702556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 0, succ: 1\n"
703556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  3: IntConstant [15, 22, 8]\n"
704556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  5: IntConstant [22, 8]\n"
705556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  19: SuspendCheck\n"
706556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  20: Goto 1\n"
707556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 1, pred: 0, succ: 5, 2\n"
708556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  8: GreaterThanOrEqual(3, 5) [9]\n"
709556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  9: If(8)\n"
710556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 2, pred: 1, succ: 3\n"
711556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  12: Goto 3\n"
7128b20f88b0a8d1b374dd5eaae289d19734c77b8f8Nicolas Geoffray    "BasicBlock 3, pred: 5, 2, succ: 4\n"
7138b20f88b0a8d1b374dd5eaae289d19734c77b8f8Nicolas Geoffray    "  22: Phi(5, 3) [15]\n"
714556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  15: Add(22, 3)\n"
715556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  17: ReturnVoid\n"
716556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 4, pred: 3\n"
717556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  18: Exit\n"
718556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "BasicBlock 5, pred: 1, succ: 3\n"
719556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    "  21: Goto 3\n";
720556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
72175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  // Expected difference after constant folding.
72275be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  diff_t expected_cf_diff = {
7238d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  3: IntConstant [15, 22, 8]\n",      "  3: IntConstant [9, 15, 22]\n" },
724556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain    { "  5: IntConstant [22, 8]\n",          "  5: IntConstant [22]\n" },
7258d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  8: GreaterThanOrEqual(3, 5) [9]\n", removed },
7268d5b8b295930aaa43255c4f0b74ece3ee8b43a47David Brazdil    { "  9: If(8)\n",                        "  9: If(3)\n" }
727556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain  };
72875be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  std::string expected_after_cf = Patch(expected_before, expected_cf_diff);
729556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
73093445689c714e53cabf347da4321ecf3023e926cRoland Levillain  // Check the values of the computed constants.
73175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain  auto check_after_cf = [](HGraph* graph) {
732ec7802a102d49ab5c17495118d4fe0bcc7287bebVladimir Marko    HInstruction* inst = graph->GetBlocks()[1]->GetFirstInstruction()->InputAt(0);
73393445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_TRUE(inst->IsIntConstant());
73493445689c714e53cabf347da4321ecf3023e926cRoland Levillain    ASSERT_EQ(inst->AsIntConstant()->GetValue(), 1);
73593445689c714e53cabf347da4321ecf3023e926cRoland Levillain  };
73693445689c714e53cabf347da4321ecf3023e926cRoland Levillain
7371c533c17baff841e383a539fdd3c0a65135181b0David Brazdil  // Expected graph after dead code elimination.
7381c533c17baff841e383a539fdd3c0a65135181b0David Brazdil  std::string expected_after_dce =
7391c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "BasicBlock 0, succ: 1\n"
7401c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  19: SuspendCheck\n"
7411c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  20: Goto 1\n"
7421c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "BasicBlock 1, pred: 0, succ: 4\n"
7431c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  17: ReturnVoid\n"
7441c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "BasicBlock 4, pred: 1\n"
7451c533c17baff841e383a539fdd3c0a65135181b0David Brazdil    "  18: Exit\n";
746556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
74793445689c714e53cabf347da4321ecf3023e926cRoland Levillain  TestCode(data,
74893445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_before,
74975be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           expected_after_cf,
75093445689c714e53cabf347da4321ecf3023e926cRoland Levillain           expected_after_dce,
75175be28332b278cff9039b54bfb228ac72f539cccRoland Levillain           check_after_cf);
752556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}
753556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain
75496709f17347cb7a6aae15816244d2200ca95a649Aart Bik/**
75596709f17347cb7a6aae15816244d2200ca95a649Aart Bik * Unsigned comparisons with zero. Since these instructions are not present
75696709f17347cb7a6aae15816244d2200ca95a649Aart Bik * in the bytecode, we need to set up the graph explicitly.
75796709f17347cb7a6aae15816244d2200ca95a649Aart Bik */
75896709f17347cb7a6aae15816244d2200ca95a649Aart BikTEST_F(ConstantFoldingTest, UnsignedComparisonsWithZero) {
75996709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_ = CreateGraph(&allocator_);
76096709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HBasicBlock* entry_block = new (&allocator_) HBasicBlock(graph_);
76196709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->AddBlock(entry_block);
76296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->SetEntryBlock(entry_block);
76396709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HBasicBlock* block = new (&allocator_) HBasicBlock(graph_);
76496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->AddBlock(block);
76596709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HBasicBlock* exit_block = new (&allocator_) HBasicBlock(graph_);
76696709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->AddBlock(exit_block);
76796709f17347cb7a6aae15816244d2200ca95a649Aart Bik  graph_->SetExitBlock(exit_block);
76896709f17347cb7a6aae15816244d2200ca95a649Aart Bik  entry_block->AddSuccessor(block);
76996709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddSuccessor(exit_block);
77096709f17347cb7a6aae15816244d2200ca95a649Aart Bik
77196709f17347cb7a6aae15816244d2200ca95a649Aart Bik  // Make various unsigned comparisons with zero against a parameter.
77296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HInstruction* parameter = new (&allocator_) HParameterValue(
77396709f17347cb7a6aae15816244d2200ca95a649Aart Bik      graph_->GetDexFile(), 0, 0, Primitive::kPrimInt, true);
77496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  entry_block->AddInstruction(parameter);
77596709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HInstruction* zero = graph_->GetIntConstant(0);
77696709f17347cb7a6aae15816244d2200ca95a649Aart Bik  HInstruction* last;
77796709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HAbove(zero, parameter));
77896709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
77996709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HAbove(parameter, zero));
78096709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
78196709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HAboveOrEqual(zero, parameter));
78296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
78396709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HAboveOrEqual(parameter, zero));
78496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
78596709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HBelow(zero, parameter));
78696709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
78796709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HBelow(parameter, zero));
78896709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
78996709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HBelowOrEqual(zero, parameter));
79096709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
79196709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(last = new (&allocator_) HBelowOrEqual(parameter, zero));
79296709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HDeoptimize(last, 0));
79396709f17347cb7a6aae15816244d2200ca95a649Aart Bik
79496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  entry_block->AddInstruction(new (&allocator_) HGoto());
79596709f17347cb7a6aae15816244d2200ca95a649Aart Bik  block->AddInstruction(new (&allocator_) HReturn(zero));
79696709f17347cb7a6aae15816244d2200ca95a649Aart Bik  exit_block->AddInstruction(new (&allocator_) HExit());
79796709f17347cb7a6aae15816244d2200ca95a649Aart Bik
79896709f17347cb7a6aae15816244d2200ca95a649Aart Bik  const std::string expected_before =
79996709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 0, succ: 1\n"
80096709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  0: ParameterValue [16, 14, 12, 10, 8, 6, 4, 2]\n"
80196709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  1: IntConstant [19, 16, 14, 12, 10, 8, 6, 4, 2]\n"
80296709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  18: Goto 1\n"
80396709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 1, pred: 0, succ: 2\n"
80496709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  2: Above(1, 0) [3]\n"
80596709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  3: Deoptimize(2)\n"
80696709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  4: Above(0, 1) [5]\n"
80796709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  5: Deoptimize(4)\n"
80896709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  6: AboveOrEqual(1, 0) [7]\n"
80996709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  7: Deoptimize(6)\n"
81096709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  8: AboveOrEqual(0, 1) [9]\n"
81196709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  9: Deoptimize(8)\n"
81296709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  10: Below(1, 0) [11]\n"
81396709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  11: Deoptimize(10)\n"
81496709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  12: Below(0, 1) [13]\n"
81596709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  13: Deoptimize(12)\n"
81696709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  14: BelowOrEqual(1, 0) [15]\n"
81796709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  15: Deoptimize(14)\n"
81896709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  16: BelowOrEqual(0, 1) [17]\n"
81996709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  17: Deoptimize(16)\n"
82096709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  19: Return(1)\n"
82196709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 2, pred: 1\n"
82296709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  20: Exit\n";
82396709f17347cb7a6aae15816244d2200ca95a649Aart Bik
82496709f17347cb7a6aae15816244d2200ca95a649Aart Bik  const std::string expected_after_cf =
82596709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 0, succ: 1\n"
82696709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  0: ParameterValue [16, 10, 6, 4]\n"
82796709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  1: IntConstant [13, 3, 19, 16, 10, 6, 4]\n"
82896709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  21: IntConstant [15, 9]\n"
82996709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  18: Goto 1\n"
83096709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 1, pred: 0, succ: 2\n"
83196709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  3: Deoptimize(1)\n"
83296709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  4: Above(0, 1) [5]\n"
83396709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  5: Deoptimize(4)\n"
83496709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  6: AboveOrEqual(1, 0) [7]\n"
83596709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  7: Deoptimize(6)\n"
83696709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  9: Deoptimize(21)\n"
83796709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  10: Below(1, 0) [11]\n"
83896709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  11: Deoptimize(10)\n"
83996709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  13: Deoptimize(1)\n"
84096709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  15: Deoptimize(21)\n"
84196709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  16: BelowOrEqual(0, 1) [17]\n"
84296709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  17: Deoptimize(16)\n"
84396709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  19: Return(1)\n"
84496709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "BasicBlock 2, pred: 1\n"
84596709f17347cb7a6aae15816244d2200ca95a649Aart Bik      "  20: Exit\n";
84696709f17347cb7a6aae15816244d2200ca95a649Aart Bik
84796709f17347cb7a6aae15816244d2200ca95a649Aart Bik  const std::string expected_after_dce = expected_after_cf;
84896709f17347cb7a6aae15816244d2200ca95a649Aart Bik
84996709f17347cb7a6aae15816244d2200ca95a649Aart Bik  auto check_after_cf = [](HGraph* graph) {
85096709f17347cb7a6aae15816244d2200ca95a649Aart Bik    CHECK(graph != nullptr);
85196709f17347cb7a6aae15816244d2200ca95a649Aart Bik  };
85296709f17347cb7a6aae15816244d2200ca95a649Aart Bik
85396709f17347cb7a6aae15816244d2200ca95a649Aart Bik  TestCodeOnReadyGraph(expected_before,
85496709f17347cb7a6aae15816244d2200ca95a649Aart Bik                       expected_after_cf,
85596709f17347cb7a6aae15816244d2200ca95a649Aart Bik                       expected_after_dce,
85696709f17347cb7a6aae15816244d2200ca95a649Aart Bik                       check_after_cf);
85796709f17347cb7a6aae15816244d2200ca95a649Aart Bik}
85896709f17347cb7a6aae15816244d2200ca95a649Aart Bik
859556c3d193134f6461f3e1fe17c032b087c5931a0Roland Levillain}  // namespace art
860